Repository navigation
Add startInBackground() and automation catch-up barrier - #196
Merged
vanrogu merged 3 commits intoOct 30, 2026
Merged
Conversation
…ng up at startup The automation's catch-up guard only compares the todo list's read position with the last event the automation produced, so once the EPHEMERAL todo list's projector has bookmarked its first batch, the automation works a list that does not yet reflect the rest of the history: an item resolved later by someone else is handled anyway. The test is disabled until the guard also waits for the todo list to reach the stream head. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJQ5EHaNK3gUidThN29mrz
When an automation begins working (started, restarted, promoted to leader) it now reads the stream head once and runs no round until its todo list's projector has read up to it. The guard on its own bookmark only covered what the automation itself produced, so an EPHEMERAL todo list rebuilt at startup was worked part-way through its catch-up, and an item resolved later in the history was handled anyway. AutomationDuringStartupTest is enabled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJQ5EHaNK3gUidThN29mrz
… it projects startInBackground() does everything start() does except wait for the in-memory read models: it returns with the context STARTING and completes the returned future once the context is RUNNING, or once a stop() or terminate() cut the start short. A process can then register its routes, open its HTTP server and answer liveness, startup and readiness while a long history is projected. start() keeps its behaviour, and waits for a start already under way instead of ignoring it. While STARTING, the inMemoryReadModels health check names the read models still projecting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJQ5EHaNK3gUidThN29mrz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This change adds non-blocking startup capability to bounded contexts and prevents automations from acting on incomplete todo lists during startup.
Key Changes
New
startInBackground()method:BoundedContextImplnow splits startup into two phases:beginStart()(wiring and processor initialization) andfinishStart()(waiting for ephemeral read models)startInBackground()returns immediately inSTARTINGstate while read models project in the background, allowing processes to answer health probes during long startupsstart()now waits for any in-progress background start rather than re-running startup logicstartInProgressfuture andstartGenerationcounter to handle concurrent start attempts correctlyAutomation catch-up barrier:
AutomationProcessornow captures the stream head when it begins working (start, restart, or promotion to leader) ascatchUpBarrierEPHEMERALtodo lists rebuilt from scratch at each start)EventReferencetotal order, not just position, ensuring correctness across different storage backendsRead model module refactoring:
ReadModelModule.start()now callsstartProcessors()thenawaitEphemeralReadModelsProjected()startProcessors()is public and can be called independently byBoundedContextImpl.beginStart()awaitEphemeralReadModelsProjected()accepts aBooleanSupplierto allow early termination if the start is cancelledImplementation Details
Thread.ofVirtual())BoundedContextImplprotects lifecycle state transitions and the start generation counterinMemoryReadModelsstatus whileSTARTING, showing which read models are still projectingTests Added
AutomationDuringStartupTest: Verifies automations don't act on items resolved later in history during startupBackgroundStartTest: Comprehensive tests forstartInBackground()behavior, concurrent starts, and stop/terminate interactionshttps://claude.ai/code/session_01PJQ5EHaNK3gUidThN29mrz