Repository navigation
intent: a timed wait step - kind: wait, args: { after: PT10S, next: ... } - so an expected wait is a loop, not a retry (#8040) - #8045
Merged
Conversation
….. } - so an expected wait is a loop, not a retry (#8040) A wait could only park until an entity event, so a model waiting for a state it expects to change (a remote export, a released resource) polled through retry: - the delegate threw "not yet", and every check became a failed job with an ERROR and a stack trace, spending the retry budget a real failure of the check should have had. A wait may now declare `after: <ISO-8601 duration>` instead of an entity event. It renders as a timer intermediate catch event with no <message> and no wait listener, and needs no trigger entity: a check produces the state, a decision routes on it, the timed wait loops back. - IntentParser: `after` is a wait arg; it must be a positive ISO-8601 duration and excludes onCreate/onUpdate/onTransition, via and when, each refusal naming the step. A wait with neither form names both. - ProcessWaitSupport.isTimed: waits() generates no listener for it and eventKind() reads it as not an event wait. - BpmnIntentGenerator: the timer catch event; the definitions-level message loop skips it. Event waits generate byte-identically. - intent-assistant-guide: the timed form, the polling loop, and that retry: is for unexpected failures. Verified: engine-intent unit suite (1775) green, incl. the new WaitTimerIntentTest cases, GlueWaitsTest, TimedWaitBpmnTest and TimedWaitEngineTest (the generated loop on a live Flowable engine: parks at the wait, polls twice, completes, no dead letter, no ERROR); IntentEngineIT and IntentEmissionCoverageIT green, the latter now publishing a timed-wait poll and asserting it completes after three checks; formatter:validate with the cache wiped; release javadoc on engine-intent. Co-Authored-By: Claude Opus 5.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.
Cause
A
waitstep could only park until an entity event (onCreate/onUpdate/onTransition); the DSL's only timers were a user task's boundarytimeout:/expire:. A model waiting for a state it expects to change (a remote export, a released resource) therefore polled throughretry:: the delegate threw "not yet" andretry: { count: 60, every: PT10S }paced the next check. Every expected "not yet" became a failed job - an ERROR with a stack trace, a failure count, an exhausted budget that reads as a technical failure - and a genuinely failing check had no retries of its own left.Change
A
waitmay declareafter: <ISO-8601 duration>instead of an entity event:IntentParser):afterjoins the wait's args. It must be a positive ISO-8601 duration (PT0S,PT-10S,10sare refused). It excludesonCreate/onUpdate/onTransition,viaandwhen- each refusal names the step. A timed wait needs no trigger entity. A wait with neither form gets the existing message, extended to nameafter:(the existing substring is kept, so no existing test changed).BpmnIntentGenerator): a timed wait renders as<intermediateCatchEvent><timerEventDefinition><timeDuration>PT10S</timeDuration></timerEventDefinition></intermediateCatchEvent>; the definitions-level<message>loop skips it.ProcessWaitSupport.isTimed):waits()generates no wait listener for it;eventKind()reads it as not an event wait.TimedWaitBpmnTestpins the message definition and catch event of an event wait beside a timed one).intent-assistant-guide.md: the timed form and the polling loop, and thatretry:is for unexpected failures, not an expected wait..claude/docs/intent-dsl-features.md: a construct paragraph.Verification
engine-intentunit suite: 1775 tests, green, including:WaitTimerIntentTest:aTimedWaitParses(the issue's YAML), invalid / zero / negative duration, a period (P1D),after+ event,after+via/when, neither form, no trigger entity needed;GlueWaitsTest.aTimedWaitGeneratesNoListener(and the event wait beside it unchanged);TimedWaitBpmnTest: the timer catch event, no<message>, the loopexportDone -> pause -> checkExportwired, an event wait's message unchanged;TimedWaitEngineTest: the generated BPMN on a live in-memory Flowable engine (async executor on) - the check answers RUNNING twice then DONE; the instance's active activity ispausewhile parked on one timer job; it completes throughpublishafter 3 checks and 2 pauses, with no dead-letter job and no ERROR logged.IntentEngineIT(83) andIntentEmissionCoverageITgreen. The latter now generates, compiles and publishes aRenditionPollprocess with a timed wait (after: PT1S) and a custom checker. It asserts the timer catch event and the absence of a wait listener, then that the record reachesDONEwith the instance's history showing exactly 3 checks.mvn -T 1C formatter:validatewith the formatter cache wiped; release-profile javadoc onengine-intent.Not verified: PostgreSQL leg locally (the change emits no SQL); the editor diagram renders a timed wait with the same wait shape (no change made there).
Out of scope per the issue: durations from config/fields, a loop-budget construct, boundary timers on service tasks, docs-site and specification text (proposal: IntentFile/intent-specification#136).
Fixes #8040
🤖 Generated with Claude Code