From 6bebf4b6bf3033e084e658846d40e92714cda336 Mon Sep 17 00:00:00 2001 From: sebasti810 Date: Fri, 19 Jul 2024 14:20:06 +0200 Subject: [PATCH] fix: 3575 --- api/rpc/client/client.go | 34 +++++++++++++++++++++++++++++----- cmd/rpc.go | 18 ++++++++++++++++-- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/api/rpc/client/client.go b/api/rpc/client/client.go index ff206d723e..1ffa9c1179 100644 --- a/api/rpc/client/client.go +++ b/api/rpc/client/client.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "time" "github.com/filecoin-project/go-jsonrpc" @@ -39,6 +40,18 @@ type Client struct { closer multiClientCloser } +type ClientOption func(*clientConfig) + +type clientConfig struct { + timeout time.Duration +} + +func WithTimeout(timeout time.Duration) ClientOption { + return func(c *clientConfig) { + c.timeout = timeout + } +} + // multiClientCloser is a wrapper struct to close clients across multiple namespaces. type multiClientCloser struct { closers []jsonrpc.ClientCloser @@ -63,22 +76,33 @@ func (c *Client) Close() { // NewClient creates a new Client with one connection per namespace with the // given token as the authorization token. -func NewClient(ctx context.Context, addr, token string) (*Client, error) { +func NewClient(ctx context.Context, addr, token string, opts ...ClientOption) (*Client, error) { + config := &clientConfig{} + for _, opt := range opts { + opt(config) + } + authHeader := http.Header{perms.AuthKey: []string{fmt.Sprintf("Bearer %s", token)}} - return newClient(ctx, addr, authHeader) + return newClient(ctx, addr, authHeader, config) } -func newClient(ctx context.Context, addr string, authHeader http.Header) (*Client, error) { - var multiCloser multiClientCloser +func newClient(ctx context.Context, addr string, authHeader http.Header, config *clientConfig) (*Client, error) { var client Client + var multiCloser multiClientCloser + + httpClient := &http.Client{ + Timeout: config.timeout, + } + for name, module := range moduleMap(&client) { - closer, err := jsonrpc.NewClient(ctx, addr, name, module, authHeader) + closer, err := jsonrpc.NewMergeClient(ctx, addr, name, []interface{}{module}, authHeader, jsonrpc.WithHTTPClient(httpClient)) if err != nil { return nil, err } multiCloser.register(closer) } + client.closer = multiCloser return &client, nil } diff --git a/cmd/rpc.go b/cmd/rpc.go index 230b51508b..5e66325bbd 100644 --- a/cmd/rpc.go +++ b/cmd/rpc.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "path/filepath" + "time" "github.com/spf13/cobra" flag "github.com/spf13/pflag" @@ -18,6 +19,7 @@ import ( var ( requestURL string authTokenFlag string + timeoutFlag time.Duration ) func RPCFlags() *flag.FlagSet { @@ -37,13 +39,20 @@ func RPCFlags() *flag.FlagSet { "Authorization token", ) + fset.DurationVar( + &timeoutFlag, + "timeout", + 0, + "Timeout for RPC requests (e.g. 30s, 1m)", + ) + storeFlag := NodeFlags().Lookup(nodeStoreFlag) fset.AddFlag(storeFlag) return fset } func InitClient(cmd *cobra.Command, _ []string) error { - if authTokenFlag == "" { + if authTokenFlag == "" { rootErrMsg := "cant access the auth token" storePath, err := getStorePath(cmd) @@ -73,7 +82,12 @@ func InitClient(cmd *cobra.Command, _ []string) error { } } - client, err := rpc.NewClient(cmd.Context(), requestURL, authTokenFlag) + var opts []rpc.ClientOption + if timeoutFlag > 0 { + opts = append(opts, rpc.WithTimeout(timeoutFlag)) + } + + client, err := rpc.NewClient(cmd.Context(), requestURL, authTokenFlag, opts...) if err != nil { return err }