Skip to content

Update workflow status with a final result only when status is PENDING - #467

Merged
maxdml merged 8 commits into
mainfrom
update-workflow-outcome-improvements
Aug 20, 2026
Merged

Update workflow status with a final result only when status is PENDING#467
maxdml merged 8 commits into
mainfrom
update-workflow-outcome-improvements

Conversation

@maxdml

@maxdml maxdml commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Update the workflow outcome write (updateWorkflowOutcome) to apply only while the workflow_status row is still PENDING.

Also:

  • fix DLQ error handling in await workflow result
  • fix handling of DBOSWorkflowExecutionConflictException (park the workflow)

Port of dbos-inc/dbos-transact-golang#417.

@maxdml
maxdml marked this pull request as draft July 28, 2026 17:08
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);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctly handle DLQ errors

Comment thread transact/src/main/java/dev/dbos/transact/execution/DBOSExecutor.java Outdated
@maxdml
maxdml marked this pull request as ready for review July 28, 2026 22:05
maxdml added 3 commits July 29, 2026 00: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
maxdml force-pushed the update-workflow-outcome-improvements branch from 16ace27 to 71f6937 Compare July 28, 2026 22:05
…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
maxdml marked this pull request as draft July 29, 2026 20:32
maxdml added 3 commits July 30, 2026 08:39
…me-improvements

# Conflicts:
#	transact/src/main/java/dev/dbos/transact/database/SystemDatabase.java
@maxdml
maxdml marked this pull request as ready for review August 19, 2026 23:51
@maxdml
maxdml requested a review from devhawk August 20, 2026 17:59
Comment thread transact/src/main/java/dev/dbos/transact/execution/DBOSExecutor.java Outdated

@devhawk devhawk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One outstanding request about removing the convenience overload of DBOSExecutor getResult. Otherwise looks good

@maxdml
maxdml merged commit a623ae1 into main Aug 20, 2026
23 of 24 checks passed
@maxdml
maxdml deleted the update-workflow-outcome-improvements branch August 20, 2026 22:43
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.

2 participants