From 78df2e89c647349d0baacfa11b2941fb2eec516f Mon Sep 17 00:00:00 2001 From: evgeniy-scherbina Date: Fri, 27 Sep 2024 15:07:27 -0400 Subject: [PATCH] fix: fix bug in evm-indexer --- go.mod | 2 +- go.sum | 4 -- server/indexer_service.go | 28 +++++++++++++ server/indexer_service_test.go | 75 ++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 server/indexer_service_test.go diff --git a/go.mod b/go.mod index b63bea5aff..d57caafd6e 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/armon/go-metrics v0.4.1 github.com/btcsuite/btcd v0.23.4 github.com/btcsuite/btcd/btcutil v1.1.3 + github.com/cenkalti/backoff/v4 v4.1.3 github.com/cometbft/cometbft v0.37.4 github.com/cometbft/cometbft-db v0.9.1 github.com/cosmos/cosmos-proto v1.0.0-beta.5 @@ -67,7 +68,6 @@ require ( github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chzyer/readline v1.5.1 // indirect diff --git a/go.sum b/go.sum index 39e3c0f5a5..85de64dcce 100644 --- a/go.sum +++ b/go.sum @@ -229,10 +229,6 @@ github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Kava-Labs/go-ethereum v1.10.27-0.20240308170502-da7973e5eee0 h1:pPFzOjEZmihLk70TQRPUCWs8uar6nfh4vZ/I1r0zeso= github.com/Kava-Labs/go-ethereum v1.10.27-0.20240308170502-da7973e5eee0/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo= -github.com/Kava-Labs/opendb v0.0.0-20240711202006-a704c1f501f7 h1:6BDmJ1buHbeJomcuZ0wqEjyF30cOZeZeNzs58JlGENc= -github.com/Kava-Labs/opendb v0.0.0-20240711202006-a704c1f501f7/go.mod h1:LbPsJiWvj90NT3Y9YV8EFPkWfvp8A15Tp88qqKa3LxA= -github.com/Kava-Labs/opendb v0.0.0-20240715194257-36fd81dc1423 h1:DviscVBwfAEruLIzNY1XowKIETXZ1F0wMq7jijYvkME= -github.com/Kava-Labs/opendb v0.0.0-20240715194257-36fd81dc1423/go.mod h1:LbPsJiWvj90NT3Y9YV8EFPkWfvp8A15Tp88qqKa3LxA= github.com/Kava-Labs/opendb v0.0.0-20240719173129-a2f11f6d7e51 h1:tMTENCeSPIJO8yCpEQbT15XYXt4EFNQUx3s334uxVts= github.com/Kava-Labs/opendb v0.0.0-20240719173129-a2f11f6d7e51/go.mod h1:LbPsJiWvj90NT3Y9YV8EFPkWfvp8A15Tp88qqKa3LxA= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= diff --git a/server/indexer_service.go b/server/indexer_service.go index 2edbc02aa5..04872e39af 100644 --- a/server/indexer_service.go +++ b/server/indexer_service.go @@ -17,6 +17,8 @@ package server import ( "context" + "errors" + "github.com/cenkalti/backoff/v4" "time" "github.com/cometbft/cometbft/libs/service" @@ -54,6 +56,11 @@ func NewEVMIndexerService( // and indexing them by events. func (eis *EVMIndexerService) OnStart() error { ctx := context.Background() + + if err := waitUntilClientReady(ctx, eis.client, backoff.NewConstantBackOff(time.Second)); err != nil { + return err + } + status, err := eis.client.Status(ctx) if err != nil { return err @@ -122,3 +129,24 @@ func (eis *EVMIndexerService) OnStart() error { } } } + +// waitUntilClientReady waits until StatusClient is ready to serve requests +func waitUntilClientReady(ctx context.Context, client rpcclient.StatusClient, b backoff.BackOff) error { + err := backoff.Retry(func() error { + status, err := client.Status(ctx) + if err != nil { + return err + } + + if status.SyncInfo.LatestBlockHeight == 0 { + return errors.New("node isn't ready, possibly in state sync process") + } + + return nil + }, b) + if err != nil { + return err + } + + return nil +} diff --git a/server/indexer_service_test.go b/server/indexer_service_test.go new file mode 100644 index 0000000000..a147f1f869 --- /dev/null +++ b/server/indexer_service_test.go @@ -0,0 +1,75 @@ +package server + +import ( + "context" + "testing" + "time" + + "github.com/cenkalti/backoff/v4" + "github.com/stretchr/testify/require" + + coretypes "github.com/cometbft/cometbft/rpc/core/types" +) + +var ( + failedResponse = &coretypes.ResultStatus{ + SyncInfo: coretypes.SyncInfo{ + LatestBlockHeight: 0, + }, + } + + successfulResponse = &coretypes.ResultStatus{ + SyncInfo: coretypes.SyncInfo{ + LatestBlockHeight: 1, + }, + } +) + +type statusClientMock struct { + // retries left before success response + retriesLeft uint +} + +func newStatusClientMock(retriesLeft uint) *statusClientMock { + return &statusClientMock{ + retriesLeft: retriesLeft, + } +} + +func (m *statusClientMock) Status(context.Context) (*coretypes.ResultStatus, error) { + if m.retriesLeft == 0 { + return successfulResponse, nil + } + + m.retriesLeft-- + return failedResponse, nil +} + +func TestWaitUntilClientReady(t *testing.T) { + for _, tc := range []struct { + desc string + retriesLeft uint + }{ + { + desc: "test case #1", + retriesLeft: 0, + }, + { + desc: "test case #2", + retriesLeft: 1, + }, + { + desc: "test case #3", + retriesLeft: 10, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + ctxb := context.Background() + mock := newStatusClientMock(tc.retriesLeft) + + err := waitUntilClientReady(ctxb, mock, backoff.NewConstantBackOff(time.Nanosecond)) + require.NoError(t, err) + require.Equal(t, uint(0), mock.retriesLeft) + }) + } +}