Skip to content

feat: settlement journal — lossless per-node trade/terminal record (dark)#121

Merged
emrebulutlar merged 1 commit into
mainfrom
feat/settlement-journal
Jul 9, 2026
Merged

feat: settlement journal — lossless per-node trade/terminal record (dark)#121
emrebulutlar merged 1 commit into
mainfrom
feat/settlement-journal

Conversation

@emrebulutlar

Copy link
Copy Markdown
Member

Summary

  • Adds the ME half of the Assets Engine settlement feed: a per-node, disk-backed, recorded journal of every trade + terminal status, written from the deterministic service thread (bypasses every sheddable queue — gap-free by construction, leader-independent).
  • SPSC ring + writer agent + second Archive (stream 4001, ctl port offset +10, stream ids 4010/4011, fsync-on-commit, 64MB segments) + (egressSeq, position) checkpoint sidecar per segment for retention.
  • Dark by default: SETTLEMENT_JOURNAL_ENABLED=true (+ required SETTLEMENT_JOURNAL_DIR on disk) turns it on; disabled = one volatile null-check per publish, zero behavior change.

Test plan

  • make determinism 67/0, zero golden changes (dark)
  • Full match-cluster suite 458/0
  • SettlementJournalTest: field fidelity, append order, byte-identity (pure function of append sequence), block-never-shed on full ring
  • JournalWriterIntegrationTest: append → ring → writer → real Archive → positioned replay round-trip (isolated embedded driver/ports)

🤖 Generated with Claude Code

…ark by default)

The write half of the Assets Engine settlement feed. Every replica
appends every trade and every terminal order status (>= FILLED) to a
recorded, disk-backed Aeron archive, hooked on the DETERMINISTIC
SERVICE THREAD before the sheddable Disruptor/egress machinery -- so
the journal is gap-free by construction, independent of leadership,
egress shedding, and the omsEgressQueue.

- SettlementJournal: SBE-encodes into a 64MB SPSC ring on the service
  thread; a full ring BLOCKS loudly (never sheds) -- a stalled journal
  archive degrades the node to a lagging replica instead of losing a
  settlement.
- JournalWriterAgent (own AgentRunner thread, backoff): drains the ring
  into a recorded ExclusivePublication on a SECOND Archive (stream 4001,
  control port +10, control streams 4010/4011, fileSyncLevel(1), SHARED
  threading, 64MB segments); lazy connect with retry so node boot never
  waits on it; appends an (egressSeq, position) checkpoint sidecar
  record at each segment boundary for retention.
- Bootstrap (AeronCluster): journal runtime is env-gated dark --
  SETTLEMENT_JOURNAL_ENABLED=true requires SETTLEMENT_JOURNAL_DIR (a
  disk path, never tmpfs); wired in both external- and embedded-driver
  launch paths, first-in/last-out around the cluster components.

Verified: determinism corpus 67/0 with zero golden changes (journal
dark = zero behavior change); full match-cluster suite 458/0; new
SettlementJournalTest (field fidelity, append order, pure-function
byte identity, block-never-shed backpressure) + end-to-end
JournalWriterIntegrationTest (append -> ring -> writer -> real archive
-> positioned replay reads back in order, the bridge's access pattern).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@emrebulutlar
emrebulutlar merged commit 8138432 into main Jul 9, 2026
2 checks passed
@emrebulutlar
emrebulutlar deleted the feat/settlement-journal branch July 9, 2026 23:28
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.

1 participant