From a4837d54d1ad38c5c6b127670c18a9ef123b0ff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=E1=BA=A3i=20Nam?= Date: Thu, 9 May 2024 10:58:42 +0700 Subject: [PATCH] feat: add timeout when connect to rpc (#115) * feat: add timeout when connect to rpc * chore: fix golangci-lint --- internal/app/app.go | 6 ++++-- pkg/evmclient/client.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/internal/app/app.go b/internal/app/app.go index 7aaba98..d458fa6 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -56,7 +56,8 @@ func NewListener(c *cli.Context) (*listener.Listener, error) { } wsRPC := c.String(wsRPCFlag.Name) l.Infow("Connect to node websocket rpc", "rpc", wsRPC) - wsEVMClient, err := evmclient.DialContext(context.Background(), wsRPC, httpClient) + wsEVMClient, err := evmclient.DialContextWithTimeout( + context.Background(), wsRPC, httpClient, defaultRequestTimeout) if err != nil { l.Errorw("Fail to connect to node", "rpc", wsRPC, "error", err) @@ -65,7 +66,8 @@ func NewListener(c *cli.Context) (*listener.Listener, error) { httpRPC := c.String(httpRPCFlag.Name) l.Infow("Connect to node http rpc", "rpc", httpRPC) - httpEVMClient, err := evmclient.DialContext(context.Background(), httpRPC, httpClient) + httpEVMClient, err := evmclient.DialContextWithTimeout( + context.Background(), httpRPC, httpClient, defaultRequestTimeout) if err != nil { l.Errorw("Fail to connect to node", "rpc", httpRPC, "error", err) diff --git a/pkg/evmclient/client.go b/pkg/evmclient/client.go index 260e4d4..9d21bef 100644 --- a/pkg/evmclient/client.go +++ b/pkg/evmclient/client.go @@ -2,8 +2,10 @@ package evmclient import ( "context" + "errors" "math/big" "net/http" + "time" "github.com/KyberNetwork/evmlistener/pkg/common" "github.com/KyberNetwork/evmlistener/pkg/evmclient/ftmclient" @@ -99,6 +101,36 @@ func DialContext(ctx context.Context, rawurl string, httpClient *http.Client) (* return client, nil } +func DialContextWithTimeout( + ctx context.Context, + rawurl string, + httpClient *http.Client, + timeout time.Duration, +) (*Client, error) { + type dialContextResponse struct { + client *Client + err error + } + + ch := make(chan dialContextResponse, 1) + go func() { + client, err := DialContext(ctx, rawurl, httpClient) + ch <- dialContextResponse{ + client: client, + err: err, + } + }() + + select { + case res := <-ch: + return res.client, res.err + case <-ctx.Done(): + return nil, ctx.Err() + case <-time.After(timeout): + return nil, errors.New("timeout when dial RPC") + } +} + func (c *Client) ChainID(ctx context.Context) (*big.Int, error) { return new(big.Int).SetUint64(c.chainID), nil }