Skip to content

feat(bpm): defer the -transitioned publish to the end of the BPMN execution chain#6234

Merged
delchev merged 1 commit into
masterfrom
feat/transitioned-after-commit
Jul 10, 2026
Merged

feat(bpm): defer the -transitioned publish to the end of the BPMN execution chain#6234
delchev merged 1 commit into
masterfrom
feat/transitioned-after-commit

Conversation

@delchev

@delchev delchev commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

The problem

The intent setter delegates (setField/setRelationField) published the -transitioned topic inline, at the moment the status was persisted. But service tasks that follow the setter in the same synchronous Flowable chain — e.g. a number-generation delegate after an Issue transition — run milliseconds later in the same command. An asynchronous consumer of -transitioned that re-loads the source on receive (the postings glue, integrations) raced those steps: an auto-posted journal entry could catch the source's create-time UUID placeholder as its documentNumber instead of the real stamped number. Timing-dependent, unfixable by the consumer.

The fix

Process.executeAfterCommit(Runnable) (SDK) / BpmFacade.executeAfterCommit — registers a Flowable COMMITTED transaction listener via the current command's TransactionContext, so the action runs after the whole synchronous BPMN execution chain (the current service task and everything up to the next wait state) has completed and committed. Outside a BPMN command it runs the action immediately.

SetField.java.template publishes -transitioned through it. By the time any consumer reacts, every write the chain performed is committed — a consumer's re-load by id observes the completed document by construction, with no authoring-order requirement.

(Modeling-side, the intent guide now also documents the complementary convention — order the steps a posting must read before the status set, so "the transition is final" also means "the document is complete".)

Verification

  • Verified live on a generated application: issue → generateNumber → markIssued chain; the auto-posted journal entry deterministically carries the real document number (previously the UUID placeholder, timing-dependent).
  • IntentEngineIT setter assertion updated: the generated delegate wraps the publish in Process.executeAfterCommit(...).
  • Docs: engine-intent CLAUDE.md (-transitioned semantics) + intent-assistant-guide.md (postings section).

🤖 Generated with Claude Code

…cution chain

The intent setter delegates (setField/setRelationField) published the
-transitioned topic inline, while service tasks that FOLLOW the setter
in the same synchronous Flowable chain (a number-generation delegate)
ran milliseconds later - an asynchronous consumer that re-loads the
source on receive (the postings glue) raced them and could observe the
pre-chain state (an auto-posted journal entry catching the create-time
UUID placeholder as its documentNumber).

New Process.executeAfterCommit(Runnable) (SDK) / BpmFacade
.executeAfterCommit - a Flowable COMMITTED transaction listener; runs
immediately outside a BPMN command. SetField.java.template publishes
-transitioned through it, so by the time any consumer reacts, the whole
chain's writes are committed and a re-load observes them.

Verified live: issue -> generateNumber -> markIssued chain; the
auto-posted entry deterministically carries the real document number.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@delchev delchev merged commit fcbb6de into master Jul 10, 2026
10 checks passed
@delchev delchev deleted the feat/transitioned-after-commit branch July 10, 2026 13:50
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