Skip to content

Commit

Permalink
fix: lazy load version in client/rpc
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias committed Aug 17, 2023
1 parent 7d43260 commit c0beb79
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 38 deletions.
76 changes: 45 additions & 31 deletions client/rpc/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"os"
"path/filepath"
"strings"
"sync"
"time"

"github.com/blang/semver/v4"
Expand Down Expand Up @@ -42,12 +43,13 @@ var ErrApiNotFound = errors.New("ipfs api address could not be found")
// For interface docs see
// https://godoc.org/github.com/ipfs/interface-go-ipfs-core#CoreAPI
type HttpApi struct {
url string
httpcli http.Client
Headers http.Header
applyGlobal func(*requestBuilder)
ipldDecoder *legacy.Decoder
remoteVersion *semver.Version
url string
httpcli http.Client
Headers http.Header
applyGlobal func(*requestBuilder)
ipldDecoder *legacy.Decoder
versionOnce sync.Once
version *semver.Version
}

// NewLocalApi tries to construct new HttpApi instance communicating with local
Expand Down Expand Up @@ -158,9 +160,7 @@ func NewURLApiWithClient(url string, c *http.Client) (*HttpApi, error) {
return fmt.Errorf("unexpected redirect")
}

var err error
api.remoteVersion, err = api.getRemoteVersion()
return api, err
return api, nil
}

func (api *HttpApi) WithOptions(opts ...caopts.ApiOption) (iface.CoreAPI, error) {
Expand All @@ -169,14 +169,19 @@ func (api *HttpApi) WithOptions(opts ...caopts.ApiOption) (iface.CoreAPI, error)
return nil, err
}

subApi := *api
subApi.applyGlobal = func(req *requestBuilder) {
if options.Offline {
req.Option("offline", options.Offline)
}
subApi := &HttpApi{
url: api.url,
httpcli: api.httpcli,
Headers: api.Headers,
applyGlobal: func(req *requestBuilder) {
if options.Offline {
req.Option("offline", options.Offline)
}
},
ipldDecoder: api.ipldDecoder,
}

return &subApi, nil
return subApi, nil
}

func (api *HttpApi) Request(command string, args ...string) RequestBuilder {
Expand Down Expand Up @@ -238,25 +243,34 @@ func (api *HttpApi) Routing() iface.RoutingAPI {
return (*RoutingAPI)(api)
}

func (api *HttpApi) getRemoteVersion() (*semver.Version, error) {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second*30))
defer cancel()
func (api *HttpApi) loadRemoteVersion() error {
if api.version == nil {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second*30))
defer cancel()

resp, err := api.Request("version").Send(ctx)
if err != nil {
return nil, err
}
if resp.Error != nil {
return nil, resp.Error
}
defer resp.Close()
resp, err := api.Request("version").Send(ctx)
if err != nil {
return err
}
if resp.Error != nil {
return resp.Error
}
defer resp.Close()
var out ipfs.VersionInfo
dec := json.NewDecoder(resp.Output)
if err := dec.Decode(&out); err != nil {
return err
}

var out ipfs.VersionInfo
remoteVersion, err := semver.New(out.Version)
if err != nil {
return err
}

dec := json.NewDecoder(resp.Output)
if err := dec.Decode(&out); err != nil {
return nil, err
api.versionOnce.Do(func() {
api.version = remoteVersion
})
}

return semver.New(out.Version)
return nil
}
27 changes: 21 additions & 6 deletions client/rpc/requestbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ type RequestBuilder interface {

// requestBuilder is an IPFS commands request builder.
type requestBuilder struct {
command string
args []string
opts map[string]string
headers map[string]string
body io.Reader
command string
args []string
opts map[string]string
headers map[string]string
body io.Reader
buildError error

shell *HttpApi
}
Expand Down Expand Up @@ -61,7 +62,17 @@ func (r *requestBuilder) Body(body io.Reader) RequestBuilder {
func (r *requestBuilder) FileBody(body io.Reader) RequestBuilder {
pr, _ := files.NewReaderPathFile("/dev/stdin", io.NopCloser(body), nil)
d := files.NewMapDirectory(map[string]files.Node{"": pr})
r.body = files.NewMultiFileReader(d, false, r.shell.remoteVersion.LT(ipfs.EncodedAbsolutePathVersion))

err := r.shell.loadRemoteVersion()
if err != nil {
// Unfortunately, we cannot return an error here. Changing this API is also
// not the best since we would otherwise have an inconsistent RequestBuilder.
// We save the error and return it when calling [requestBuilder.Send].
r.buildError = err
return r
}

r.body = files.NewMultiFileReader(d, false, r.shell.version.LT(ipfs.EncodedAbsolutePathVersion))

return r
}
Expand Down Expand Up @@ -98,6 +109,10 @@ func (r *requestBuilder) Header(name, value string) RequestBuilder {

// Send sends the request and return the response.
func (r *requestBuilder) Send(ctx context.Context) (*Response, error) {
if r.buildError != nil {
return nil, r.buildError
}

r.shell.applyGlobal(r)

req := NewRequest(ctx, r.shell.url, r.command, r.args...)
Expand Down
2 changes: 1 addition & 1 deletion client/rpc/unixfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, f files.Node, opts ...caopts.Unix
}

d := files.NewMapDirectory(map[string]files.Node{"": f}) // unwrapped on the other side
req.Body(files.NewMultiFileReader(d, false, api.remoteVersion.LT(ipfs.EncodedAbsolutePathVersion)))
req.Body(files.NewMultiFileReader(d, false, api.version.LT(ipfs.EncodedAbsolutePathVersion)))

var out addEvent
resp, err := req.Send(ctx)
Expand Down

0 comments on commit c0beb79

Please sign in to comment.