triedb/pathdb: improve history indexer

This commit is contained in:
Gary Rong 2026-01-28 12:06:47 +08:00
parent 8a6e026fcb
commit ecd3e2a7f1

View file

@ -461,10 +461,18 @@ const (
// to be close enough to the tip to operate in real-time mode. // to be close enough to the tip to operate in real-time mode.
syncHistoryThreshold = 6 * time.Hour syncHistoryThreshold = 6 * time.Hour
// indexerIdleTimeout is the maximum duration of inactivity allowed // indexerIdleTimeoutLive is the strict inactivity limit applied once the
// before the indexer decides it has finished its current catch-up // indexer is synchronized with the chain head.
// and exits the initial sync mode. indexerIdleTimeoutLive = 60 * time.Second
indexerIdleTimeout = 30 * time.Second
// indexerIdleTimeoutStartup is the period allowed when the indexer has
// little or no history, for Geth's initial sync procedures (e.g., beacon
// headers downloading or something else).
indexerIdleTimeoutStartup = 1 * time.Hour
// indexerIdleDecayWindow defines the progress threshold over which the
// idle timeout linearly scales from the startup period down to the live one.
indexerIdleDecayWindow = 10000
// indexerHeartbeatInterval is the frequency at which the indexer // indexerHeartbeatInterval is the frequency at which the indexer
// checks its status and schedules background indexing operations. // checks its status and schedules background indexing operations.
@ -476,6 +484,28 @@ const (
indexerHeartbeatInterval = 15 * time.Second indexerHeartbeatInterval = 15 * time.Second
) )
// getTimeout calculates a dynamic inactivity threshold based on indexing
// progress. For massive datasets, this accounts for the preparation phase
// required before active chain synchronization begins (such as beacon
// header downloading).
//
// Note: In private networks with no block, this may result in a long wait.
// In such cases, the initial sync mode is expected to be terminated by
// another condition verifying the chain head has been reached. This timeout
// primarily serves as a heuristic for the network with massive datasets.
func (i *indexIniter) getTimeout() time.Duration {
current := i.indexed.Load()
if current >= indexerIdleDecayWindow {
return indexerIdleTimeoutLive
}
progress := float64(current) / float64(indexerIdleDecayWindow)
diff := float64(indexerIdleTimeoutStartup - indexerIdleTimeoutLive)
decay := time.Duration(diff * progress)
return indexerIdleTimeoutStartup - decay
}
// checkExit reports whether the initial mode has completed. It assumes that // checkExit reports whether the initial mode has completed. It assumes that
// all local histories have been fully indexed when invoked, and determines // all local histories have been fully indexed when invoked, and determines
// whether the initial mode should exit and marking historical state access // whether the initial mode should exit and marking historical state access
@ -502,7 +532,7 @@ func (i *indexIniter) checkExit(lastEventTime time.Time) bool {
// may be syncing toward a historical block rather than the latest chain head. // may be syncing toward a historical block rather than the latest chain head.
// In this case, check whether the indexer has been idle for a while and exit // In this case, check whether the indexer has been idle for a while and exit
// the initial mode if so. // the initial mode if so.
if time.Since(lastEventTime) > indexerIdleTimeout { if time.Since(lastEventTime) > i.getTimeout() {
i.log.Info("Exit the initial mode due to inactivity", "last", i.indexed.Load(), "age", common.PrettyAge(blockTime)) i.log.Info("Exit the initial mode due to inactivity", "last", i.indexed.Load(), "age", common.PrettyAge(blockTime))
return true return true
} }