Add log_watcher: block-scoped log watching (closes #36)#59
Conversation
On each newHeads notification, fetch eth_getLogs scoped to the planned block range. Blocks missed across reconnects are back-filled (the gap between the last processed head and the new one), and reorgs detected via parent-hash mismatch re-fetch the replaced range. Re-announced old heights re-fetch only that height, since the new chain may be shorter than the previous head. The range planning lives in a pure planRange() function with unit tests for first-head lag, sequential heads, gaps, both reorg shapes, and the handle_reorgs=false paths. LogWatcher.pollOnce() is the pull-based API; watchLogs() is the callback loop from the issue. Also fixes a latent 0.15.2 incompatibility this feature exposed: subscription.parseBlockFromNotification used std.json.stringifyAlloc (removed in 0.15) to re-wrap the notification for parseBlockHeader. The header object is now parsed directly via the new provider.parseBlockHeaderObject, with no stringify round-trip. Verified: zig build test (0.15.2 and 0.17.0-dev), integration tests against Anvil including a new LogWatcher cursor-tracking test, docs build.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (8)
📝 WalkthroughWalkthroughThis PR introduces ChangesLog Watcher Feature
Sequence DiagramsequenceDiagram
participant Client
participant LogWatcher
participant WsClient
participant Provider
Client->>LogWatcher: pollOnce()
LogWatcher->>WsClient: wait for next newHeads event
WsClient-->>LogWatcher: BlockHeader
LogWatcher->>LogWatcher: planRange(cursor, header)
LogWatcher->>Provider: getLogs(fromBlock, toBlock, filter)
Provider-->>LogWatcher: logs[]
LogWatcher->>LogWatcher: update cursor (block number, hash)
LogWatcher-->>Client: logs[]
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
What
Implements
watchLogsfrom #36: alog_watchermodule that drives per-blocketh_getLogsfrom aWsClientnewHeadssubscription.LogWatcher.pollOnce()— pull API: blocks until the next head, returns the logs for the planned block rangewatchLogs(...)— the callback loop from the issuestart_block_lagwarm-up andhandle_reorgsopt-out per the issue'sWatchOptsDesign notes
planRange) with unit tests covering first-head lag (incl. genesis saturation), sequential heads, gaps, both reorg shapes, andhandle_reorgs = false.(block_hash, log_index)— documented in the module, README, and websockets guide.Bug fix this exposed
subscription.parseBlockFromNotificationcalledstd.json.stringifyAlloc, which doesn't exist in Zig 0.15.2 — it compiled until now only because nothing referenced it (lazy analysis). It now parses the notification object directly via a newprovider.parseBlockHeaderObject, shared withparseBlockHeader.Verification
make cion 0.15.2 andzig build teston 0.17.0-dev.813: passzig build integration-testagainst Anvil: pass, including a newLogWatchertest that mines blocks and asserts cursor trackingCloses #36
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Documentation