-
Notifications
You must be signed in to change notification settings - Fork 28
Add chains mapping in event context #775
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds a new per-chain readiness type and threads a Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant GS as GlobalState
participant EP as EventProcessing
participant CM as ChainMap/Fetchers
participant UC as UserContext
participant H as Handler
GS->>EP: processEventBatch(~items, ~chainFetchers, ...)
EP->>CM: computeChainsState(chainFetchers)
CM-->>EP: chains (map chainId -> {isReady})
note right of EP: New — per-chain readiness derived
EP->>EP: preloadBatchOrThrow(..., ~chains)
EP->>EP: runBatchHandlersOrThrow(..., ~chains)
EP->>EP: runEventHandlerOrThrow(item, ..., ~chains)
EP->>UC: build handler context(..., chains)
UC-->>H: handler receives context with chains
H->>H: read context.chains[chainId].isReady
H-->>EP: handler result
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
scenarios/test_codegen/test/EventOriginDetection_test.res(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{res,resi}
📄 CodeRabbit inference engine (.cursor/rules/rescript.mdc)
**/*.{res,resi}: Never use[| item |]to create an array. Use[ item ]instead.
Must always use=for setting value to a field. Use:=only for ref values created usingreffunction.
ReScript has record types which require a type definition before hand. You can access record fields by dot likefoo.myField.
It's also possible to define an inline object, it'll have quoted fields in this case.
Use records when working with structured data, and objects to conveniently pass payload data between functions.
Never use %raw to access object fields if you know the type.
Files:
scenarios/test_codegen/test/EventOriginDetection_test.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript .res modules directly; compiled .js artifacts can be ignored
Files:
scenarios/test_codegen/test/EventOriginDetection_test.res
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
scenarios/test_codegen/test/EventOriginDetection_test.res (1)
180-357: Consider extracting a test helper to reduce duplication.The three async tests share substantial setup code (creating config, stores, managers, event logs, and items). Extracting a helper function would improve maintainability and make the test intent clearer.
Example helper:
let makeTestEventBatch = (~chainId, ~progressBlockNumber, ~isProgressAtHead) => { let config = RegisterHandlers.registerAllHandlers() let inMemoryStore = InMemoryStore.make() let loadManager = LoadManager.make() let emptyEventLog: Types.eventLog<Types.Gravatar.EmptyEvent.eventArgs> = { params: (), chainId: chainId, srcAddress: "0xabc0000000000000000000000000000000000000"->Address.Evm.fromStringOrThrow, logIndex: 1, transaction: MockEvents.tx1, block: MockEvents.block1, } let item = Internal.Event({ timestamp: emptyEventLog.block.timestamp, chain: ChainMap.Chain.makeUnsafe(~chainId), blockNumber: emptyEventLog.block.number, logIndex: emptyEventLog.logIndex, eventConfig: (Types.Gravatar.EmptyEvent.register() :> Internal.eventConfig), event: emptyEventLog->Internal.fromGenericEvent, }) let progressedChains = [{ chainId: chainId, batchSize: 1, progressBlockNumber: progressBlockNumber, isProgressAtHead: isProgressAtHead, totalEventsProcessed: 1, }] (config, inMemoryStore, loadManager, item, progressedChains) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
scenarios/test_codegen/src/EventHandlers.res(1 hunks)scenarios/test_codegen/test/EventOriginDetection_test.res(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- scenarios/test_codegen/src/EventHandlers.res
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{res,resi}
📄 CodeRabbit inference engine (.cursor/rules/rescript.mdc)
**/*.{res,resi}: Never use[| item |]to create an array. Use[ item ]instead.
Must always use=for setting value to a field. Use:=only for ref values created usingreffunction.
ReScript has record types which require a type definition before hand. You can access record fields by dot likefoo.myField.
It's also possible to define an inline object, it'll have quoted fields in this case.
Use records when working with structured data, and objects to conveniently pass payload data between functions.
Never use %raw to access object fields if you know the type.
Files:
scenarios/test_codegen/test/EventOriginDetection_test.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript .res modules directly; compiled .js artifacts can be ignored
Files:
scenarios/test_codegen/test/EventOriginDetection_test.res
🔇 Additional comments (2)
scenarios/test_codegen/test/EventOriginDetection_test.res (2)
4-174: LGTM! Comprehensive coverage of allChainsEventsProcessedToEndblock.The test suite thoroughly validates the function across single-chain, multi-chain, edge cases (empty map, exceeded end block), and various progress states. The tests are clear and well-structured.
180-293: LGTM! These tests now exercise the real processEventBatch code path.Unlike the previous version that duplicated the conditional logic, these tests actually invoke
EventProcessing.processEventBatchand verify that it correctly passeseventOriginto handlers based onchainFetchersstate. This gives us confidence that the wiring is correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
scenarios/test_codegen/test/EventOriginDetection_test.res(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{res,resi}
📄 CodeRabbit inference engine (.cursor/rules/rescript.mdc)
**/*.{res,resi}: Never use[| item |]to create an array. Use[ item ]instead.
Must always use=for setting value to a field. Use:=only for ref values created usingreffunction.
ReScript has record types which require a type definition before hand. You can access record fields by dot likefoo.myField.
It's also possible to define an inline object, it'll have quoted fields in this case.
Use records when working with structured data, and objects to conveniently pass payload data between functions.
Never use %raw to access object fields if you know the type.
Files:
scenarios/test_codegen/test/EventOriginDetection_test.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript .res modules directly; compiled .js artifacts can be ignored
Files:
scenarios/test_codegen/test/EventOriginDetection_test.res
🧠 Learnings (1)
📚 Learning: 2025-09-04T14:42:53.500Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: .cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-09-04T14:42:53.500Z
Learning: Applies to src/**/*.ts : For multichain support, prefix all entity IDs with event.chainId (e.g., `${event.chainId}-${originalId}`), never hardcode chainId=1, pass chainId into helpers, and use chain-specific Bundle IDs like `${chainId}-1`
Applied to files:
scenarios/test_codegen/test/EventOriginDetection_test.res
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
scenarios/test_codegen/test/EventOriginDetection_test.res (1)
180-357: Previous review concerns have been addressed.All chain ID mismatches flagged in prior reviews have been corrected:
- Lines 180-236: chainId=54321 used consistently across chainFetchers, event, item.chain, and progressedChains
- Lines 238-293: chainId=54321 used consistently
- Lines 295-357: chainId=1 used consistently in multi-chain scenario
Additionally, tests now call the real
EventProcessing.processEventBatchand assert on the actualeventOrigincaptured viaEventHandlers.lastEmptyEventOrigin, rather than duplicating the conditional logic.Optional: Consider adding multi-chain Live test for completeness.
Current coverage includes single-chain Historical, single-chain Live, and multi-chain Historical scenarios. Adding a test where all chains in a multi-chain setup have reached their end blocks (expecting Live) would provide more comprehensive coverage.
Example test structure:
Async.it("should pass Live in multi-chain when all chains reached end", async () => { EventHandlers.lastEmptyEventOrigin := None // Setup: both chains have reached their end blocks let chainFetcher1 = { "committedProgressBlockNumber": 1000, "fetchState": {"endBlock": Some(1000)}, }->Utils.magic let chainFetcher2 = { "committedProgressBlockNumber": 2000, "fetchState": {"endBlock": Some(2000)}, }->Utils.magic let chainFetchers = ChainMap.fromArrayUnsafe([ (ChainMap.Chain.makeUnsafe(~chainId=1), chainFetcher1), (ChainMap.Chain.makeUnsafe(~chainId=2), chainFetcher2), ]) // ... rest of test setup and assertions expecting Live })
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
scenarios/test_codegen/test/EventOriginDetection_test.res(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{res,resi}
📄 CodeRabbit inference engine (.cursor/rules/rescript.mdc)
**/*.{res,resi}: Never use[| item |]to create an array. Use[ item ]instead.
Must always use=for setting value to a field. Use:=only for ref values created usingreffunction.
ReScript has record types which require a type definition before hand. You can access record fields by dot likefoo.myField.
It's also possible to define an inline object, it'll have quoted fields in this case.
Use records when working with structured data, and objects to conveniently pass payload data between functions.
Never use %raw to access object fields if you know the type.
Files:
scenarios/test_codegen/test/EventOriginDetection_test.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript .res modules directly; compiled .js artifacts can be ignored
Files:
scenarios/test_codegen/test/EventOriginDetection_test.res
🧠 Learnings (1)
📚 Learning: 2025-09-04T14:42:53.500Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: .cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-09-04T14:42:53.500Z
Learning: Applies to src/**/*.ts : For multichain support, prefix all entity IDs with event.chainId (e.g., `${event.chainId}-${originalId}`), never hardcode chainId=1, pass chainId into helpers, and use chain-specific Bundle IDs like `${chainId}-1`
Applied to files:
scenarios/test_codegen/test/EventOriginDetection_test.res
🔇 Additional comments (1)
scenarios/test_codegen/test/EventOriginDetection_test.res (1)
3-174: Comprehensive test coverage for allChainsEventsProcessedToEndblock.The test suite thoroughly validates edge cases including:
- All chains reached end block
- Partial completion in multi-chain scenarios
- Live mode (no end block set)
- Progress below/at/above end block
- Empty chainFetchers map
Test logic is correct and assertions align with expected behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
scenarios/test_codegen/test/EventOriginDetection_test.res (2)
176-357: Consider adding test coverage for additional scenarios.While the current tests cover the core cases, consider adding tests for:
Live mode with no endBlock: Verify handlers receive
Livewhen a chain hasfetchState.endBlock = None(this case is tested in the helper function tests at lines 57-70 but not in the processEventBatch integration tests).Progress exceeds endBlock: Verify handlers receive
LivewhencommittedProgressBlockNumberexceedsendBlock(covered in helper tests at lines 86-99 but not in processEventBatch tests).Multi-chain all complete → Live: Add the inverse of the test at lines 295-357 where ALL chains have reached their end block in a multi-chain setup, verifying handlers receive
Live.These additions would ensure the integration tests have the same coverage as the unit tests for the helper function.
180-357: Optional: Extract shared test setup into a helper function.The three processEventBatch tests duplicate setup code for
config,inMemoryStore,loadManager, and event/item construction. Consider extracting a helper function like:let makeTestContext = () => { let config = RegisterHandlers.registerAllHandlers() let inMemoryStore = InMemoryStore.make() let loadManager = LoadManager.make() (config, inMemoryStore, loadManager) } let makeEmptyEvent = (~chainId) => { let emptyEventLog: Types.eventLog<Types.Gravatar.EmptyEvent.eventArgs> = { params: (), chainId, srcAddress: "0xabc0000000000000000000000000000000000000"->Address.Evm.fromStringOrThrow, logIndex: 1, transaction: MockEvents.tx1, block: MockEvents.block1, } Internal.Event({ timestamp: emptyEventLog.block.timestamp, chain: ChainMap.Chain.makeUnsafe(~chainId), blockNumber: emptyEventLog.block.number, logIndex: emptyEventLog.logIndex, eventConfig: (Types.Gravatar.EmptyEvent.register() :> Internal.eventConfig), event: emptyEventLog->Internal.fromGenericEvent, }) }This would reduce duplication and make the tests more maintainable, though the current approach is acceptable.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
scenarios/test_codegen/test/EventOriginDetection_test.res(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{res,resi}
📄 CodeRabbit inference engine (.cursor/rules/rescript.mdc)
**/*.{res,resi}: Never use[| item |]to create an array. Use[ item ]instead.
Must always use=for setting value to a field. Use:=only for ref values created usingreffunction.
ReScript has record types which require a type definition before hand. You can access record fields by dot likefoo.myField.
It's also possible to define an inline object, it'll have quoted fields in this case.
Use records when working with structured data, and objects to conveniently pass payload data between functions.
Never use %raw to access object fields if you know the type.
Files:
scenarios/test_codegen/test/EventOriginDetection_test.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript .res modules directly; compiled .js artifacts can be ignored
Files:
scenarios/test_codegen/test/EventOriginDetection_test.res
🔇 Additional comments (2)
scenarios/test_codegen/test/EventOriginDetection_test.res (2)
4-174: Comprehensive coverage of the helper function.The test suite thoroughly exercises
allChainsEventsProcessedToEndblockacross all relevant scenarios: single-chain (complete, incomplete, no endBlock, progress below/at/exceeds endBlock), multi-chain (partial/full completion), and edge cases (empty map). The logic and assertions are correct.
180-357: Past chain ID mismatches have been fixed.All the chain ID mismatches flagged in previous reviews have been resolved:
- Lines 180-236:
item.chainnow useschainId=54321, matchingchainFetchers- Lines 238-293:
item.chainnow useschainId=54321, matchingchainFetchers- Lines 295-357:
event.chainId,item.chain, andprogressedChains[0].chainIdall usechainId=1, matchingchainFetchersThe tests now correctly exercise the real
processEventBatchcode path and verify handlers receive the expectedeventOrigin.
|
I think it should be done similarly to @JonoPrest What do you think? |
|
Even though the solution with |
|
Well done @Segfaultd on navigating the ReSscript code 👏🏼 Generally with API level features like this we first discuss the API before implementing, because people have different ideas. I tend to agree with Dmitry that it would be nice to have a unified API to expose more metadata than just whether it is syncing at the head for a given chain. If we just want the single field so long though, I would suggest using a boolean rather than enum/string union. Since there's only 2 options and its nicer to just say |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
codegenerator/cli/npm/envio/src/Internal.res (1)
57-62: Consider adding inline documentation forisReady.The types are correctly defined with appropriate
@genTypeannotation. However, consider adding a doc comment explaining whenisReadyistrue(live indexing after sync completes) vsfalse(historical sync in progress).Example:
@genType type chainInfo = { + // true when the chain has completed initial sync and is processing live events + // false during historical synchronization isReady: bool, }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
scenarios/test_codegen/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (13)
codegenerator/cli/npm/envio/src/Internal.gen.ts(1 hunks)codegenerator/cli/npm/envio/src/Internal.res(1 hunks)codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs(1 hunks)codegenerator/cli/templates/dynamic/codegen/src/Types.res.hbs(3 hunks)codegenerator/cli/templates/static/codegen/src/EventProcessing.res(14 hunks)codegenerator/cli/templates/static/codegen/src/UserContext.res(3 hunks)codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.res(2 hunks)scenarios/test_codegen/src/EventHandlers.res(1 hunks)scenarios/test_codegen/test/EventOriginDetection_test.res(1 hunks)scenarios/test_codegen/test/EventOrigin_test.res(1 hunks)scenarios/test_codegen/test/Mock_test.res(1 hunks)scenarios/test_codegen/test/schema_types/BigDecimal_test.res(1 hunks)scenarios/test_codegen/test/schema_types/Timestamp_test.res(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- codegenerator/cli/templates/static/codegen/src/UserContext.res
🧰 Additional context used
📓 Path-based instructions (3)
codegenerator/cli/templates/{static,dynamic}/codegen/src/**/*
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Edit template versions under codegenerator/cli/templates/static/codegen/src or codegenerator/cli/templates/dynamic/codegen/src instead of editing generated/src
Files:
codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbscodegenerator/cli/templates/dynamic/codegen/src/Types.res.hbscodegenerator/cli/templates/static/codegen/src/globalState/GlobalState.rescodegenerator/cli/templates/static/codegen/src/EventProcessing.res
**/*.{res,resi}
📄 CodeRabbit inference engine (.cursor/rules/rescript.mdc)
**/*.{res,resi}: Never use[| item |]to create an array. Use[ item ]instead.
Must always use=for setting value to a field. Use:=only for ref values created usingreffunction.
ReScript has record types which require a type definition before hand. You can access record fields by dot likefoo.myField.
It's also possible to define an inline object, it'll have quoted fields in this case.
Use records when working with structured data, and objects to conveniently pass payload data between functions.
Never use %raw to access object fields if you know the type.
Files:
codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.resscenarios/test_codegen/test/EventOriginDetection_test.rescodegenerator/cli/npm/envio/src/Internal.resscenarios/test_codegen/src/EventHandlers.resscenarios/test_codegen/test/schema_types/Timestamp_test.resscenarios/test_codegen/test/schema_types/BigDecimal_test.resscenarios/test_codegen/test/EventOrigin_test.rescodegenerator/cli/templates/static/codegen/src/EventProcessing.resscenarios/test_codegen/test/Mock_test.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript .res modules directly; compiled .js artifacts can be ignored
Files:
codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.resscenarios/test_codegen/test/EventOriginDetection_test.rescodegenerator/cli/npm/envio/src/Internal.resscenarios/test_codegen/src/EventHandlers.resscenarios/test_codegen/test/schema_types/Timestamp_test.resscenarios/test_codegen/test/schema_types/BigDecimal_test.resscenarios/test_codegen/test/EventOrigin_test.rescodegenerator/cli/templates/static/codegen/src/EventProcessing.resscenarios/test_codegen/test/Mock_test.res
🧠 Learnings (1)
📚 Learning: 2025-09-04T14:42:53.500Z
Learnt from: CR
PR: enviodev/hyperindex#0
File: .cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-09-04T14:42:53.500Z
Learning: Applies to src/**/*.ts : For multichain support, prefix all entity IDs with event.chainId (e.g., `${event.chainId}-${originalId}`), never hardcode chainId=1, pass chainId into helpers, and use chain-specific Bundle IDs like `${chainId}-1`
Applied to files:
scenarios/test_codegen/test/EventOriginDetection_test.res
🔇 Additional comments (8)
scenarios/test_codegen/test/schema_types/BigDecimal_test.res (1)
42-43: LGTM!The chains initialization and propagation through
UserContext.getHandlerContextis correct. SettingisReady: falseappropriately simulates historical indexing mode for this test scenario.Also applies to: 52-52
codegenerator/cli/npm/envio/src/Internal.gen.ts (1)
45-45: LGTM!The generated TypeScript type correctly mirrors the ReScript
chainInfodefinition with appropriate readonly modifier for immutability.scenarios/test_codegen/test/schema_types/Timestamp_test.res (1)
34-35: LGTM!Chains initialization follows the same correct pattern as other test files, appropriately simulating historical indexing mode.
Also applies to: 44-44
scenarios/test_codegen/test/Mock_test.res (1)
13-15: LGTM!Chains state correctly simulates historical indexing with clear documentation. The propagation to
runBatchHandlersOrThrowis correct.Also applies to: 24-24
codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs (1)
408-410: LGTM!Chains state correctly simulates live mode (
isReady: true) forprocessEvents. The chain ID is properly converted to string for the dictionary key, and chains are consistently passed through both preload and handler phases.Also applies to: 417-417, 425-425
scenarios/test_codegen/test/EventOrigin_test.res (1)
1-53: Excellent test coverage!This test suite comprehensively validates the chains functionality:
- Unit tests for
chainInfotype with both boolean states- Multi-chain dictionary behavior
- Integration test confirming handler context accessibility
The tests properly cover type validation, dictionary operations, and end-to-end integration.
scenarios/test_codegen/src/EventHandlers.res (1)
144-160: LGTM!The handler correctly accesses and logs the chains state. The mutable reference enables test verification, and the logging provides clear visibility into chain readiness during processing.
codegenerator/cli/npm/envio/src/Internal.res (1)
65-68: LGTM!The
handlerContextextension correctly includes thechainsfield while preserving theprivatemodifier to prevent unsafe manual construction. The structure properly supports per-chain readiness tracking.
codegenerator/cli/templates/static/codegen/src/EventProcessing.res
Outdated
Show resolved
Hide resolved
codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.res
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, this API looks good to me. I left a few comments, keen to merge after they are fixed 🫡
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
codegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbs (1)
82-92: Template duplication is necessary but creates maintenance burden.The
chainsproperty definition is duplicated here (identical to lines 27-37) due to the template's conditional structure. While this duplication is unavoidable given the{{#if preload_handlers}}and{{#unless preload_handlers}}blocks, be aware that any future changes to thechainstype must be synchronized across both locations.Consider adding a code comment above both blocks referencing each other to remind maintainers to keep them in sync:
+ // Note: This chains property is duplicated at line 27 (or line 82) - keep both in sync /** * Per-chain state information accessible in event handlers and block handlers.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
codegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbs(2 hunks)codegenerator/cli/templates/static/codegen/src/EventProcessing.res(14 hunks)codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.res(1 hunks)scenarios/test_codegen/src/EventHandlers.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- codegenerator/cli/templates/static/codegen/src/EventProcessing.res
- codegenerator/cli/templates/static/codegen/src/globalState/GlobalState.res
🧰 Additional context used
📓 Path-based instructions (2)
scenarios/test_codegen/**/*.ts
📄 CodeRabbit inference engine (scenarios/test_codegen/.cursor/rules/hyperindex.mdc)
scenarios/test_codegen/**/*.ts: After changing any TypeScript files, run: pnpm tsc --noEmit to ensure successful compilation
When updating existing entities in handlers, always use the spread operator to create updated objects before persisting
For any external call (e.g., fetch), wrap it in an Effect via experimental_createEffect and consume via context.effect
Use !context.isPreload to skip logic that should not run during preload
In TypeScript, set relationship fields using *_id properties (e.g., token_id) rather than object references
Always cast timestamps from events to BigInt (e.g., BigInt(event.block.timestamp))
When matching addresses in configuration objects within code, ensure keys are lowercase and compare using address.toLowerCase()
Use string | undefined for optional string fields instead of string | null
Always normalize token amounts to a standard decimal (e.g., 18) before addition across tokens; use helpers like normalizeAmountToUSD()
Files:
scenarios/test_codegen/src/EventHandlers.ts
codegenerator/cli/templates/{static,dynamic}/codegen/src/**/*
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Edit template versions under codegenerator/cli/templates/static/codegen/src or codegenerator/cli/templates/dynamic/codegen/src instead of editing generated/src
Files:
codegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbs
🔇 Additional comments (1)
scenarios/test_codegen/src/EventHandlers.ts (1)
174-185: LGTM! Type assertion correctly validates chains field structure.The compile-time type check confirms that
context.chainshas the expected shape ({ [chainId: string]: { readonly isReady: boolean } }), which aligns with the chainInfo type introduced in this PR. The assertion follows the established pattern used for other type validations in this test file.
codegenerator/cli/templates/static/codegen/src/EventProcessing.res
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, let's wait for the tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
codegenerator/cli/templates/static/codegen/src/EventProcessing.res (2)
9-24: Chains readiness computation looks good; consider centralizing readiness and keying helpers
- Logic aligns with intended semantics and prior feedback.
- Suggest exposing a ChainFetcher.isReady (or similar) helper to avoid direct field access to timestampCaughtUpToHeadOrEndblock and keep invariants local.
- Minor: use Utils.Dict.setByInt for consistent int-to-string dict keying across the codebase.
337-341: No missing~chainspropagation;computeChainsStateusage is isolated
- All call sites for
preloadBatchOrThrow,runBatchHandlersOrThrow, andprocessEventBatchinclude~chains.computeChainsStateis only invoked inprocessEventBatch; no duplication inGlobalState.- Optional: add a comment clarifying that
chainsis a per-batch snapshot and not live-updating mid-batch.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
codegenerator/cli/templates/static/codegen/src/EventProcessing.res(14 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{res,resi}
📄 CodeRabbit inference engine (.cursor/rules/rescript.mdc)
**/*.{res,resi}: Never use[| item |]to create an array. Use[ item ]instead.
Must always use=for setting value to a field. Use:=only for ref values created usingreffunction.
ReScript has record types which require a type definition before hand. You can access record fields by dot likefoo.myField.
It's also possible to define an inline object, it'll have quoted fields in this case.
Use records when working with structured data, and objects to conveniently pass payload data between functions.
Never use %raw to access object fields if you know the type.
Files:
codegenerator/cli/templates/static/codegen/src/EventProcessing.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript .res modules directly; compiled .js artifacts can be ignored
Files:
codegenerator/cli/templates/static/codegen/src/EventProcessing.res
codegenerator/cli/templates/{static,dynamic}/codegen/src/**/*
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Edit template versions under codegenerator/cli/templates/static/codegen/src or codegenerator/cli/templates/dynamic/codegen/src instead of editing generated/src
Files:
codegenerator/cli/templates/static/codegen/src/EventProcessing.res
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_and_test
🔇 Additional comments (4)
codegenerator/cli/templates/static/codegen/src/EventProcessing.res (4)
107-130: Threadingchainsinto handler context is correctParameter added and passed to UserContext.getHandlerContext consistently.
159-204:runHandlerOrThrow: correct propagation ofchainsfor both Block and Event pathsLooks consistent and safe.
220-272: Preload path correctly includeschainsin preloader contextsBoth Event and Block preload contexts carry
chains. Good.
289-301: Batch handlers:chainscorrectly threadedConsistent with single-item path.
Add per-chain state tracking to handler context
Introduction
Add per-chain state tracking to handler contexts, allowing event handlers to distinguish between chains that are still syncing historical data versus chains that have caught up to head.
Problem / Issue
Event handlers need visibility into which chains are actively syncing versus which chains have caught up and are processing live events. This is critical for:
Previously, handlers had no way to determine the indexing state of individual chains.
Solution
Introduced a
chainsfield in handler and loader contexts that provides per-chain state tracking:"1"for Ethereum mainnet)chainInfoobject withisReady: booleanisReady: false- Chain is syncing historical dataisReady: true- Chain has reached its end block and is processing live eventsThis allows handlers to check individual chain states and make granular decisions in multichain scenarios.
Key changes:
Core Type Definitions (
Internal.res)type chainInfo = {isReady: bool}andtype chains = dict<chainInfo>handlerContextto includechains: chainsfieldEvent Processing Logic (
EventProcessing.res)computeChainsStatefunction that returns dict of per-chain stateshasProcessedToEndblockfor each chain independently~chainsparameter through all processing functionsUser Context (
UserContext.res)chainstocontextParamsfor proper context initializationchainsfield via proxy handlers for user access incontext.chainsCode Generation Templates
chains: Internal.chainsTypeScript Integration
chainInfoas{ readonly isReady: boolean }Handler usage examples:
TypeScript example:
Test Coverage
Unit Tests:
Integration Tests:
Benefits
References
Summary by CodeRabbit
New Features
Tests
Chores