Skip to content

Commit 6886f0b

Browse files
committed
fix: simplify periodic history drop
After deleting by timestamp, query MIN(blocks.number) for both FirstDatabaseIndexState and FirstDatabaseFSPEventIndexState instead of running a chain binary search. The RPC search was a leftover from when DropHistoryIteration doubled as the empty-DB bootstrap (1239e31); GetStartBlock owns that case now (7e6d5cf). The (historyEpochs+4)·rewardEpoch retention is sized so that by the time drops trim X-2 event-window logs (δ ≈ 3 epochs), continuous indexing has already covered the same range (δ ≥ 2). Contract holds at every δ on both networks.
1 parent c367984 commit 6886f0b

4 files changed

Lines changed: 14 additions & 148 deletions

File tree

cmd/indexer/main.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,6 @@ func runIndexer(
194194
historyDrop,
195195
database.HistoryDropIntervalCheck,
196196
ethClient,
197-
cfg.Indexer.StartIndex,
198197
)
199198
}
200199

internal/database/history_drop.go

Lines changed: 14 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,12 @@ func DropHistory(
2323
db *gorm.DB,
2424
intervalSeconds, checkInterval uint64,
2525
client *chain.Client,
26-
startBlockNumber uint64,
2726
) {
2827
for {
2928
logger.Infof("starting DropHistory iteration")
3029

3130
startTime := time.Now()
32-
err := dropHistoryIteration(ctx, db, intervalSeconds, client, startBlockNumber)
31+
err := dropHistoryIteration(ctx, db, intervalSeconds, client)
3332
if err == nil {
3433
duration := time.Since(startTime)
3534
logger.Infof("finished DropHistory iteration in %v", duration)
@@ -52,22 +51,15 @@ var deleteOrder = []interface{}{
5251
const deleteBatchSize = 1000
5352

5453
func dropHistoryIteration(
55-
ctx context.Context, db *gorm.DB, intervalSeconds uint64, client *chain.Client, startBlockNumber uint64,
54+
ctx context.Context, db *gorm.DB, intervalSeconds uint64, client *chain.Client,
5655
) error {
57-
lastBlockTime, lastBlockNumber, err := getBlockTimestamp(ctx, nil, client)
56+
lastBlockTime, _, err := getBlockTimestamp(ctx, nil, client)
5857
if err != nil {
5958
return errors.Wrap(err, "Failed to get the latest time")
6059
}
6160

6261
db = db.WithContext(ctx)
63-
6462
deleteStartTime := lastBlockTime - intervalSeconds
65-
deleteStartBlock, err := getNearestBlockByTimestamp(
66-
ctx, deleteStartTime, db, client, startBlockNumber, lastBlockNumber,
67-
)
68-
if err != nil {
69-
return errors.Wrap(err, "Failed to get the nearest block by timestamp")
70-
}
7163

7264
// Delete in specified order to not break foreign keys.
7365
for _, entity := range deleteOrder {
@@ -76,10 +68,19 @@ func dropHistoryIteration(
7668
}
7769
}
7870

79-
if err := updateStateIfLower(db, FirstDatabaseIndexState, deleteStartBlock, deleteStartTime); err != nil {
71+
var firstBlock Block
72+
err = db.Order("number ASC").First(&firstBlock).Error
73+
if errors.Is(err, gorm.ErrRecordNotFound) {
74+
return nil
75+
}
76+
if err != nil {
77+
return errors.Wrap(err, "find first surviving block")
78+
}
79+
80+
if err := updateStateIfLower(db, FirstDatabaseIndexState, firstBlock.Number, firstBlock.Timestamp); err != nil {
8081
return errors.Wrap(err, "Failed to update state in the DB")
8182
}
82-
if err := updateStateIfLower(db, FirstDatabaseFSPEventIndexState, deleteStartBlock, deleteStartTime); err != nil {
83+
if err := updateStateIfLower(db, FirstDatabaseFSPEventIndexState, firstBlock.Number, firstBlock.Timestamp); err != nil {
8384
return errors.Wrap(err, "Failed to update FSP event state in the DB")
8485
}
8586

@@ -157,88 +158,3 @@ func getBlockTimestamp(ctx context.Context, index *big.Int, client *chain.Client
157158

158159
return block.Time(), block.Number().Uint64(), nil
159160
}
160-
161-
func getNearestBlockByTimestamp(
162-
ctx context.Context,
163-
timestamp uint64,
164-
db *gorm.DB,
165-
client *chain.Client,
166-
startBlockNumber uint64,
167-
lastBlockNumber uint64,
168-
) (uint64, error) {
169-
// First try to find a block in the DB with a timestamp close to the requested one.
170-
// If that fails, we fall back to doing a binary search on the chain.
171-
blockNumber, err := getNearestBlockByTimestampFromDB(ctx, timestamp, db)
172-
if err != nil {
173-
logger.Debugf("failed to get the nearest block by timestamp from DB, will fall back to RPC binary search. err: %s", err)
174-
}
175-
176-
// A blocknumber of 0 means that no block was found in the DB.
177-
if blockNumber != 0 {
178-
return blockNumber, nil
179-
}
180-
181-
return chain.GetNearestBlockByTimestampFromChain(ctx, timestamp, client, startBlockNumber, lastBlockNumber)
182-
}
183-
184-
const maxBlockTimeDiff = time.Minute
185-
186-
func validateNearestDBBlockTimestamp(blockTime, timestamp uint64) (bool, error) {
187-
if blockTime < timestamp {
188-
return false, errors.Errorf(
189-
"unexpected block time %d, expected at least %d",
190-
blockTime, timestamp,
191-
)
192-
}
193-
194-
blockTimeDiff := time.Duration(blockTime-timestamp) * time.Second
195-
if blockTimeDiff > maxBlockTimeDiff {
196-
// This is expected on initial runs or whenever the DB only contains a
197-
// much newer window of blocks than the requested history-drop cutoff.
198-
// In that case we should quietly fall back to RPC binary search.
199-
return false, nil
200-
}
201-
202-
return true, nil
203-
}
204-
205-
func getNearestBlockByTimestampFromDB(ctx context.Context, timestamp uint64, db *gorm.DB) (uint64, error) {
206-
// First try to find a block in the DB with a similar timestamp.
207-
block, err := boff.RetryWithMaxElapsed(
208-
ctx,
209-
func() (*Block, error) {
210-
// First try to find a block in the DB with a similar timestamp.
211-
block := new(Block)
212-
err := db.Where("timestamp >= ?", timestamp).Order("timestamp ASC").First(block).Error
213-
214-
if err == nil {
215-
return block, nil
216-
}
217-
218-
if errors.Is(err, gorm.ErrRecordNotFound) {
219-
return nil, nil
220-
}
221-
222-
return nil, err
223-
},
224-
"getNearestBlockByTimestampFromDB",
225-
)
226-
if err != nil {
227-
return 0, errors.Wrap(err, "getNearestBlockByTimestampFromDB")
228-
}
229-
230-
// Block not found in the DB.
231-
if block == nil || block.Number == 0 {
232-
return 0, nil
233-
}
234-
235-
useBlock, err := validateNearestDBBlockTimestamp(block.Timestamp, timestamp)
236-
if err != nil {
237-
return 0, errors.Wrapf(err, "invalid DB block %d", block.Number)
238-
}
239-
if !useBlock {
240-
return 0, nil
241-
}
242-
243-
return block.Number, nil
244-
}

internal/database/history_drop_test.go

Lines changed: 0 additions & 48 deletions
This file was deleted.

internal/fsp/runtime.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ func RunIndexer(
7171
historyDropSeconds,
7272
database.HistoryDropIntervalCheck,
7373
ethClient,
74-
0,
7574
)
7675

7776
ready.SetSynced(true)

0 commit comments

Comments
 (0)