From 1b35c07a562d8117e38ffcf60a94fc26651ebbd8 Mon Sep 17 00:00:00 2001 From: Aditya Vyas Date: Mon, 17 Jun 2024 12:41:34 -0400 Subject: [PATCH] Remove GetLedgerRange from meta table and use ledgerRangeGetter for getHealth and getFeeStats --- cmd/soroban-rpc/internal/db/ledger.go | 56 ------------------- cmd/soroban-rpc/internal/db/ledger_test.go | 6 -- cmd/soroban-rpc/internal/db/mocks.go | 4 -- cmd/soroban-rpc/internal/events/events.go | 3 +- cmd/soroban-rpc/internal/jsonrpc.go | 15 +++-- .../internal/methods/get_fee_stats.go | 2 +- .../methods/get_latest_ledger_test.go | 5 -- cmd/soroban-rpc/internal/methods/health.go | 2 +- 8 files changed, 13 insertions(+), 80 deletions(-) diff --git a/cmd/soroban-rpc/internal/db/ledger.go b/cmd/soroban-rpc/internal/db/ledger.go index 31e960a4..39ded8f8 100644 --- a/cmd/soroban-rpc/internal/db/ledger.go +++ b/cmd/soroban-rpc/internal/db/ledger.go @@ -5,11 +5,7 @@ import ( "fmt" sq "github.com/Masterminds/squirrel" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/xdr" - - "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/ledgerbucketwindow" ) const ( @@ -21,7 +17,6 @@ type StreamLedgerFn func(xdr.LedgerCloseMeta) error type LedgerReader interface { GetLedger(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, bool, error) StreamAllLedgers(ctx context.Context, f StreamLedgerFn) error - LedgerRangeReader } type LedgerWriter interface { @@ -73,57 +68,6 @@ func (r ledgerReader) GetLedger(ctx context.Context, sequence uint32) (xdr.Ledge } } -// GetLedgerRange pulls the min/max ledger sequence numbers from the ledgers table. -func (r ledgerReader) GetLedgerRange(ctx context.Context) (ledgerbucketwindow.LedgerRange, error) { - var ledgerRange ledgerbucketwindow.LedgerRange - // - // We use subqueries alongside a UNION ALL stitch in order to select the min - // and max from the ledger table in a single query and get around sqlite's - // limitations with parentheses (see https://stackoverflow.com/a/22609948). - // - newestQ := sq. - Select("m1.meta"). - FromSelect( - sq. - Select("meta"). - From(ledgerCloseMetaTableName). - OrderBy("sequence ASC"). - Limit(1), - "m1", - ) - sql, args, err := sq. - Select("m2.meta"). - FromSelect( - sq. - Select("meta"). - From(ledgerCloseMetaTableName). - OrderBy("sequence DESC"). - Limit(1), - "m2", - ).ToSql() - if err != nil { - return ledgerRange, errors.Wrap(err, "couldn't build ledger range query") - } - - var lcms []xdr.LedgerCloseMeta - if err = r.db.Select(ctx, &lcms, newestQ.Suffix("UNION ALL "+sql, args...)); err != nil { - return ledgerRange, errors.Wrap(err, "couldn't query ledger range") - } else if len(lcms) < 2 { - // There is almost certainly a row, but we want to avoid a race condition - // with ingestion as well as support test cases from an empty DB, so we need - // to sanity check that there is in fact a result. Note that no ledgers in - // the database isn't an error, it's just an empty range. - return ledgerRange, nil - } - - lcm1, lcm2 := lcms[0], lcms[1] - ledgerRange.FirstLedger.Sequence = lcm1.LedgerSequence() - ledgerRange.FirstLedger.CloseTime = lcm1.LedgerCloseTime() - ledgerRange.LastLedger.Sequence = lcm2.LedgerSequence() - ledgerRange.LastLedger.CloseTime = lcm2.LedgerCloseTime() - return ledgerRange, nil -} - type ledgerWriter struct { stmtCache *sq.StmtCache } diff --git a/cmd/soroban-rpc/internal/db/ledger_test.go b/cmd/soroban-rpc/internal/db/ledger_test.go index 52ca44d2..562afc0f 100644 --- a/cmd/soroban-rpc/internal/db/ledger_test.go +++ b/cmd/soroban-rpc/internal/db/ledger_test.go @@ -67,12 +67,6 @@ func assertLedgerRange(t *testing.T, reader LedgerReader, start, end uint32) { allLedgers = allLedgers[1:] } assert.Empty(t, allLedgers) - - ledgerRange, err := reader.GetLedgerRange(context.Background()) - assert.Equal(t, start, ledgerRange.FirstLedger.Sequence) - assert.Equal(t, int64(start+10), ledgerRange.FirstLedger.CloseTime) - assert.Equal(t, end, ledgerRange.LastLedger.Sequence) - assert.Equal(t, int64(end+10), ledgerRange.LastLedger.CloseTime) } func TestLedgers(t *testing.T) { diff --git a/cmd/soroban-rpc/internal/db/mocks.go b/cmd/soroban-rpc/internal/db/mocks.go index c72b7393..d2dfba4f 100644 --- a/cmd/soroban-rpc/internal/db/mocks.go +++ b/cmd/soroban-rpc/internal/db/mocks.go @@ -105,10 +105,6 @@ func (m *mockLedgerReader) StreamAllLedgers(ctx context.Context, f StreamLedgerF return nil } -func (m *mockLedgerReader) GetLedgerRange(ctx context.Context) (ledgerbucketwindow.LedgerRange, error) { - return ledgerbucketwindow.LedgerRange{}, nil -} - var _ TransactionReader = &mockTransactionHandler{} var _ TransactionWriter = &mockTransactionHandler{} var _ LedgerReader = &mockLedgerReader{} diff --git a/cmd/soroban-rpc/internal/events/events.go b/cmd/soroban-rpc/internal/events/events.go index b724fbf9..f428c0e7 100644 --- a/cmd/soroban-rpc/internal/events/events.go +++ b/cmd/soroban-rpc/internal/events/events.go @@ -1,6 +1,7 @@ package events import ( + "context" "errors" "io" "sort" @@ -267,7 +268,7 @@ func readEvents(networkPassphrase string, ledgerCloseMeta xdr.LedgerCloseMeta) ( } // GetLedgerRange returns the first and latest ledger available in the store. -func (m *MemoryStore) GetLedgerRange() (ledgerbucketwindow.LedgerRange, error) { +func (m *MemoryStore) GetLedgerRange(ctx context.Context) (ledgerbucketwindow.LedgerRange, error) { m.lock.RLock() defer m.lock.RUnlock() return m.eventsByLedger.GetLedgerRange(), nil diff --git a/cmd/soroban-rpc/internal/jsonrpc.go b/cmd/soroban-rpc/internal/jsonrpc.go index 5d5189ab..7bc948c5 100644 --- a/cmd/soroban-rpc/internal/jsonrpc.go +++ b/cmd/soroban-rpc/internal/jsonrpc.go @@ -136,10 +136,13 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler { }, } - // While we transition from in-memory to database-oriented history storage, - // the on-disk (transaction) retention window will always be larger than the - // in-memory (events) one. - var retentionWindow = cfg.TransactionLedgerRetentionWindow + // Get the largest history window + var ledgerRangeGetter db.LedgerRangeReader = params.EventStore + var retentionWindow = cfg.EventLedgerRetentionWindow + if cfg.TransactionLedgerRetentionWindow > cfg.EventLedgerRetentionWindow { + retentionWindow = cfg.TransactionLedgerRetentionWindow + ledgerRangeGetter = params.TransactionReader + } handlers := []struct { methodName string @@ -151,7 +154,7 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler { { methodName: "getHealth", underlyingHandler: methods.NewHealthCheck( - retentionWindow, params.LedgerReader, cfg.MaxHealthyLedgerLatency), + retentionWindow, ledgerRangeGetter, cfg.MaxHealthyLedgerLatency), longName: "get_health", queueLimit: cfg.RequestBacklogGetHealthQueueLimit, requestDurationLimit: cfg.MaxGetHealthExecutionDuration, @@ -232,7 +235,7 @@ func NewJSONRPCHandler(cfg *config.Config, params HandlerParams) Handler { }, { methodName: "getFeeStats", - underlyingHandler: methods.NewGetFeeStatsHandler(params.FeeStatWindows, params.LedgerReader, params.Logger), + underlyingHandler: methods.NewGetFeeStatsHandler(params.FeeStatWindows, ledgerRangeGetter, params.Logger), longName: "get_fee_stats", queueLimit: cfg.RequestBacklogGetFeeStatsTransactionQueueLimit, requestDurationLimit: cfg.MaxGetFeeStatsExecutionDuration, diff --git a/cmd/soroban-rpc/internal/methods/get_fee_stats.go b/cmd/soroban-rpc/internal/methods/get_fee_stats.go index efccdf71..61592176 100644 --- a/cmd/soroban-rpc/internal/methods/get_fee_stats.go +++ b/cmd/soroban-rpc/internal/methods/get_fee_stats.go @@ -58,7 +58,7 @@ type GetFeeStatsResult struct { } // NewGetFeeStatsHandler returns a handler obtaining fee statistics -func NewGetFeeStatsHandler(windows *feewindow.FeeWindows, reader db.LedgerReader, logger *log.Entry) jrpc2.Handler { +func NewGetFeeStatsHandler(windows *feewindow.FeeWindows, reader db.LedgerRangeReader, logger *log.Entry) jrpc2.Handler { return NewHandler(func(ctx context.Context) (GetFeeStatsResult, error) { ledgerRange, err := reader.GetLedgerRange(ctx) if err != nil { // still not fatal diff --git a/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go b/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go index 05e378ec..e961510c 100644 --- a/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go +++ b/cmd/soroban-rpc/internal/methods/get_latest_ledger_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/db" - "github.com/stellar/soroban-rpc/cmd/soroban-rpc/internal/ledgerbucketwindow" ) const ( @@ -59,10 +58,6 @@ func (ledgerReader *ConstantLedgerReader) StreamAllLedgers(ctx context.Context, return nil } -func (ledgerReader *ConstantLedgerReader) GetLedgerRange(ctx context.Context) (ledgerbucketwindow.LedgerRange, error) { - return ledgerbucketwindow.LedgerRange{}, nil -} - func createLedger(ledgerSequence uint32, protocolVersion uint32, hash byte) xdr.LedgerCloseMeta { return xdr.LedgerCloseMeta{ V: 1, diff --git a/cmd/soroban-rpc/internal/methods/health.go b/cmd/soroban-rpc/internal/methods/health.go index d013d53f..bef5e4b6 100644 --- a/cmd/soroban-rpc/internal/methods/health.go +++ b/cmd/soroban-rpc/internal/methods/health.go @@ -20,7 +20,7 @@ type HealthCheckResult struct { // NewHealthCheck returns a health check json rpc handler func NewHealthCheck( retentionWindow uint32, - reader db.LedgerReader, + reader db.LedgerRangeReader, maxHealthyLedgerLatency time.Duration, ) jrpc2.Handler { return NewHandler(func(ctx context.Context) (HealthCheckResult, error) {