Update workflow status with a final result only when status is PENDING - #467
Draft
maxdml wants to merge 4 commits into
Draft
Update workflow status with a final result only when status is PENDING#467maxdml wants to merge 4 commits into
maxdml wants to merge 4 commits into
Conversation
maxdml
marked this pull request as draft
July 28, 2026 17:08
maxdml
commented
Jul 28, 2026
Comment on lines
+1264
to
+1269
| case MAX_RECOVERY_ATTEMPTS_EXCEEDED -> { | ||
| // A workflow is dead-lettered by the attempt that pushes recovery_attempts | ||
| // past maxRetries+1, so a dead-lettered row carries maxRetries+2 attempts. | ||
| int maxRetries = Math.max(0, rs.getInt("recovery_attempts") - 2); | ||
| throw new DBOSMaxRecoveryAttemptsExceededException(workflowId, maxRetries); | ||
| } |
Contributor
Author
There was a problem hiding this comment.
Correctly handle DLQ errors
maxdml
commented
Jul 28, 2026
Comment on lines
+1820
to
+1827
| // Another execution owns this workflow (a concurrent run recorded a step | ||
| // checkpoint, or the workflow is already active on this executor). Never | ||
| // persist the conflict: park the execution and deliver the recorded outcome | ||
| // through this run's own future. | ||
| logger.warn( | ||
| "Aborting duplicate execution of workflow. Waiting for the recorded outcome. workflowId {}", | ||
| workflowId); | ||
| return awaitWorkflowResult(workflowId); |
Contributor
Author
There was a problem hiding this comment.
Now park the workflow when concurrent execution is detected (typically during step checkpointing)
maxdml
marked this pull request as ready for review
July 28, 2026 22:05
The terminal-outcome write (updateWorkflowOutcome) now applies only to a PENDING row and reports whether it landed: a run owns its workflow's outcome exactly as long as the row says that run is what the workflow is doing. When the write is refused, the runner parks on awaitWorkflowResult and delivers the recorded outcome through its own handle instead of its locally computed result. A missing row surfaces as DBOSNonExistentWorkflowException. awaitWorkflowResult now throws DBOSMaxRecoveryAttemptsExceededException for a dead-lettered row instead of polling forever.
A run that observes its own cancellation now parks on the recorded outcome instead of rethrowing from its local view: normally the row is CANCELLED and awaitWorkflowResult throws DBOSAwaitedWorkflowCancelledException (the same error the handle delivered before), but a concurrent resume may have taken the workflow back, in which case the recorded outcome is the truth. Safe to park because checkWorkflow only throws own-cancellation after reading CANCELLED from the DB, so the row is never left PENDING by this path.
A run that loses the execution race (a concurrent run recorded a step checkpoint, or the workflow is already active on this executor) now parks on awaitWorkflowResult inside the task and delivers the recorded outcome through its own future, instead of completing the future exceptionally and relying on the handle's getResult conversion. The getResult conversions remain as backstops for futures produced before the park was in place.
maxdml
force-pushed
the
update-workflow-outcome-improvements
branch
from
July 28, 2026 22:05
16ace27 to
71f6937
Compare
…tcome write The PENDING-guarded outcome update now does exactly one statement and only reports whether the write landed. Runs that park on the recorded outcome know their row must already exist, so awaitWorkflowResult gains an opt-in failIfMissing that throws DBOSNonExistentWorkflowException on a missing row instead of polling forever. Tolerant callers (unchecked retrieves, debounced workflows whose rows appear later) keep the polling default.
maxdml
marked this pull request as draft
July 29, 2026 20:32
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.
Update the workflow outcome write (
updateWorkflowOutcome) to apply only while theworkflow_statusrow is still PENDING.Also:
DBOSWorkflowExecutionConflictException(park the workflow)Port of dbos-inc/dbos-transact-golang#417.