Skip to content

Refactor: Move in-memory store into IndexerState - #1330

Merged
DZakh merged 4 commits into
mainfrom
claude/vigilant-galileo-indd7y
Jun 17, 2026
Merged

Refactor: Move in-memory store into IndexerState#1330
DZakh merged 4 commits into
mainfrom
claude/vigilant-galileo-indd7y

Conversation

@DZakh

@DZakh DZakh commented Jun 17, 2026

Copy link
Copy Markdown
Member

Summary

Consolidates the in-memory store (entity/effect tables, batch queue, write coordination) into IndexerState and extracts write-loop logic into a new Writing module. This eliminates the intermediate Ctx wrapper and simplifies state threading throughout the codebase.

Key Changes

  • IndexerState expansion: Moved EntityTables, effectCacheInMemTable, and all write-related fields from InMemoryStore into IndexerState. Added read accessors and domain operations (queueProcessedBatch, drainBatchRun, dropCommitted, etc.) to encapsulate state mutations.

  • InMemoryStore simplification: Reduced to a thin utility module with only effect/entity table accessors (getInMemTable, getEffectInMemTable, hasEffectOutput, etc.). Removed initialization, batch queuing, and write-loop logic.

  • Writing module: New module owns the write loop (runOneWrite, runWriteLoop, schedule) and capacity/flush coordination (getChangesCount, waitForCommit, commitBatch, dropCommitted). Calls IndexerState domain operations to mutate state.

  • Ctx removal: Deleted Ctx.res (was a wrapper holding config, persistence, inMemoryStore, registrations). Callers now thread IndexerState directly or access fields via accessors.

  • ContractRegisterContext extraction: Moved contract-register handler context logic from UserContext into a new ContractRegisterContext module, keeping it independent of IndexerState so fetch-time registration doesn't pull the full state.

  • Accessor pattern: IndexerState exposes read-only accessors for all fields (e.g., config, persistence, allEntities, committedCheckpointId) and write operations through named functions (e.g., setChainManager, beginProcessing, markCommitted).

Notable Implementation Details

  • IndexerState.t remains opaque in the interface (.resi); all mutations route through explicit operations, preventing accidental direct field access.
  • Write-loop coordination (throttling, capacity checks, commit waiters) now lives in Writing, keeping IndexerState focused on state representation.
  • InMemoryStore functions that read state now take IndexerState.t instead of the old InMemoryStore.t, maintaining the same interface but operating on the consolidated state.
  • Tests updated to construct IndexerState directly instead of building Ctx + InMemoryStore.

https://claude.ai/code/session_01UnGJ5W6o9QKzV7JJz9q8Qi

claude added 4 commits June 16, 2026 14:35
Flatten the Ctx wrapper (config, persistence, inMemoryStore) directly onto
IndexerState and drop the construction-only registrations field, which is now
passed straight to ChainManager.makeFromDbState. EventProcessing and startServer
take the persistence/config they use instead of a Ctx. Delete Ctx.res.

https://claude.ai/code/session_01UnGJ5W6o9QKzV7JJz9q8Qi
Flatten the in-memory store fields (entity/effect tables, pending-write queue,
chain metadata staging) onto IndexerState and drop InMemoryStore.t. The
InMemoryStore module now holds store operations over IndexerState.t; the loop
mutex/progress counters (isProcessing, processedBatchesCount) become plain
state fields. A single onError replaces the store's separate write-error
handler, wrapping write failures with the batch-write message inline.

Extract the contractRegister context out of UserContext into
ContractRegisterContext so ChainFetcher's fetch-time registration no longer
pulls in the store, breaking the IndexerState -> ChainManager -> ChainFetcher
-> UserContext -> IndexerState cycle.

https://claude.ai/code/session_01UnGJ5W6o9QKzV7JJz9q8Qi
Move the storage write loop and its capacity/flush coordination out of
InMemoryStore into a dedicated Writing module, a peer to ChainFetching/
BatchProcessing/Rollback: runWriteLoop, schedule (formerly kick), runOneWrite,
drainBatchRun, snapshotEffects, awaitCapacity, flush, commitBatch, setChainMeta
and the commit-waiter coordination. InMemoryStore keeps the entity/effect table
primitives plus prepareRollbackDiff and setBatchDcs. Callers commit/flush/stage
through Writing; the write fiber is still kicked by data availability so the
backpressure path is unchanged.

https://claude.ai/code/session_01UnGJ5W6o9QKzV7JJz9q8Qi
Add IndexerState.resi with an abstract type t. Other modules no longer touch
fields directly: they read through accessors and change state through named
domain operations rather than raw setters — queueProcessedBatch, drainBatchRun,
takeRollback, markCommitted, beginRollbackDiff, recordWriteFailure,
begin/endWriteFiber, wakeCommitWaiters/addCommitWaiter, stageChainMeta and
takeChainMetaSnapshot. Writing keeps the async write-loop orchestration and
InMemoryStore the entity/effect table primitives, both operating on the opaque
state through these operations.

https://claude.ai/code/session_01UnGJ5W6o9QKzV7JJz9q8Qi
@DZakh
DZakh merged commit ddc4653 into main Jun 17, 2026
13 of 14 checks passed
@DZakh
DZakh deleted the claude/vigilant-galileo-indd7y branch June 17, 2026 09:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants