feat(messaging): a deferred announcement survives a broker outage - the durable publish - #6874
Merged
Merged
Conversation
…he durable publish (#6867) The write-attached outbox (#6854) covers an event that belongs to ONE write. Five generated announcements are deliberately DECOUPLED from any single write and stayed bare Producer.sendToTopic calls - each a live instance of #6816's loss class, where a briefly-down broker swallows the notice and every downstream reaction keyed on it silently never runs: - SetField, Writer and Numbering defer their "-transitioned"/"-updated" publish past the synchronous Flowable chain's commit, so consumers observe the whole chain's writes rather than a mid-chain snapshot - attaching the event to the write would regress exactly that; - a StepEvent moment has no entity write of its own at all; - the create-from's completion announce is ordered after the target and its items exist, across several transactions. They now publish through Producer.sendToTopicDurable: the message is recorded in the tenant's event outbox in its own short transaction and handed to the broker immediately - a healthy system publishes exactly as promptly as before - and whatever the broker refuses stays for EventOutboxRelayJob, the same at-least-once contract the write-attached events have. Ordering is untouched: the deferral points stay where they are; only the loss window closes. If even the recording fails, the message falls back to the direct publish - the caller's work has already committed and an at-most-once attempt beats none. The plumbing: DurableMessagePublisher is a small SPI in api-messaging (the module both sides already see - the SDK cannot depend on the outbox's module and the outbox already depends on messaging), EventOutbox implements it with an own-connection insert on the store, and the SDK Producer resolves it through BeanProvider. The javadoc states the rule: an announcement that belongs to one write rides that write; this is for the decoupled ones. Emission is pinned by the existing IntentEngineIT anchors, updated to the durable call; runtime by IntentEmissionCoverageIT (the workflow setters, step moments, stamped numbers and completion announces all flow through the new path) and JavaEventOutboxIT. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Part two of #6867, completing it (part one is #6869 — merge that first; this PR touches adjacent
IntentEngineITregions).The write-attached outbox (#6854) covers an event that belongs to one write. Five generated announcements are deliberately decoupled from any single write and remained bare publishes — each a live event-loss window:
SetField,Writer,NumberingProcess.executeAfterCommitso consumers observe the whole synchronous Flowable chain's writes — write-attachment would regress that ordering fixStepEventGeneratecompletion announceThey now publish through
Producer.sendToTopicDurable: recorded in the tenant's event outbox in its own short transaction, dispatched immediately, retried byEventOutboxRelayJobwhen the broker refuses — the same at-least-once contract the write-attached events have, with ordering untouched. Recording failure falls back to the direct publish (the caller's work has already committed).Plumbing:
DurableMessagePublisherSPI inapi-messaging(visible to both sides without a dependency cycle), implemented byEventOutboxwith an own-connectionEventOutboxStore.insert, resolved by the SDKProducerviaBeanProvider. The engine-java guide's doctrine line now names both rules: one-write announcements ride the write; decoupled ones use the durable publish.Verified:
IntentEngineIT56/56 (anchors updated to the durable call),IntentEmissionCoverageIT(workflow setters, step moments, stamped numbers and completion announces all flow through the new path at runtime),JavaEventOutboxIT, release-profile javadoc gate on the three modules.Closes #6867 (together with #6869).
🤖 Generated with Claude Code