Expand description
One shared, TTL-cached eth_blockNumber read for every chain watcher.
Without a shared read, every tick would cost one eth_blockNumber per
watcher — ~7 head reads per event_poll_interval against a single endpoint,
on top of each watcher’s eth_getLogs. SharedHead collapses them: the
first caller within a TTL window issues the RPC, everyone else reads the
cache.
Two properties matter:
- Monotonicity — why a stale head is safe.
SharedHeadonly ever returns a head at-or-before the true head at the call instant; it can never report a head ahead of the chain. Every consumer of the head inresumable_watcherclamps against it (resolve_persisted_start,resolve_head_window_start, and thefrom > toidle branch), so a head that lags only ever widens an already-idempotent rescan or defers work to the next tick — it can never open a gap. Note this is a property of the cache direction, not a coincidence: a cache that could run ahead would skip blocks, which is exactly the #751/#762 hazard (anchoring a durable checkpoint floor too high). The cost is bounded observation latency (≤ TTL), not correctness. - Single-flight, including failures. The mutex is held across the RPC, so
concurrent callers queue and then read the fresh entry rather than each
issuing their own read. Failures are cached for the same TTL, which is what
keeps a wedged provider from serializing timeouts: without it, N watchers
queued behind a stalled endpoint would each wait the full
chain_events::DEFAULT_RPC_CALL_TIMEOUTin turn, so the last one’s tick — and therefore its*_backoff_startedgauge — would be delayed by N × 10s. With it, one caller pays the timeout and the rest fail instantly, so every watcher enters backoff at the same moment.
Structs§
- Shared
Head - TTL-cached, single-flight
HeadSourceover one provider.
Constants§
- SNAPSHOT_
LAG_ MARGIN_ BLOCKS - How far below the reported head an enumeration snapshot pins its reads.
Traits§
- Head
Source - A source of the current chain head block number.