Repository navigation
[Fix-18721][Master] Keep workflow finish retryable after transaction rollback - #18722
Conversation
|
Could we simplify The flow could be:
The database-operation logs can stay inside For this scope, I do not think an additional This is deliberately a narrower contract, not an equivalent refactor: it would not retain the additional guarantees for an enclosing |
|
Thanks, I've simplified the implementation around the current event-dispatch path as suggested. Shared state, metrics, and finalize publication now follow a successful return from |
| final WorkflowExecutionStatus originState = workflowInstance.getState(); | ||
| workflowInstance.setState(workflowInstanceToUpdate.getState()); | ||
| workflowInstance.setEndTime(workflowInstanceToUpdate.getEndTime()); | ||
| log.info("Success set WorkflowExecuteRunnable: {} state from: {} to {}", | ||
| workflowInstance.getName(), originState.name(), workflowInstance.getState().name()); | ||
| try { | ||
| WorkflowInstanceMetrics.recordWorkflowInstanceFinish(workflowInstance.getState(), | ||
| workflowInstance.getWorkflowDefinitionCode()); | ||
| } catch (Exception ex) { | ||
| // Metrics must not prevent releasing a workflow whose transaction has already committed. | ||
| log.warn("Record completion metric failed for workflow: {}", workflowExecution.getName(), ex); | ||
| } |
There was a problem hiding this comment.
NIT: We can use another PR to simplify this. Since most of the state changes here involve updating the database and updating memory, we can move the memory updates into a separate method, similar to the implementation for task instance updates.
At the same time, exception handling can be placed in recordWorkflowInstanceFinish; I believe that any exceptions that occur while recording metrics should not affect the upper layers.
Was this PR generated or assisted by AI?
YES. AI assisted with the investigation, code changes, regression tests, and this description. I reviewed the proposed approach and the reported test results.
Purpose of the pull request
Fixes #18721.
If serial-command cleanup or a pre-commit callback fails after the workflow update, the transaction rolls back but the shared workflow instance already has a final state. The Master then skips the retried finish event, and a following SERIAL_WAIT instance can remain blocked.
This change keeps the shared instance unchanged until the transaction commits, so a rollback leaves it ready for retry.
Brief change log
afterCommitcallback throws, useafterCompletionto finish only when the transaction committed and completion has not already been attempted.Verify this pull request
Added
WorkflowFinishPersistenceRecoveryTestCaseusing the existing Master integration test framework and H2.beforeCommit, then checks rollback, retry, and repeated events. These cases use real handlers and transactions with a mocked execution graph and event bus.The original reproduction fails on unmodified production code: the database rolls back while the shared instance stays final. It passes with this change.
Focused clean builds passed 35 selected cases in both Surefire executions on JDK 8 and JDK 11. An earlier JDK 11 build passed 53 cases covering transaction callback boundaries and related workflow regressions with the same production change. These selections overlap; they are not a single full-suite run. Spotless checks and JaCoCo were enabled, and
spotless:applywas run before testing.To run the full workflow-finish and related regression selection:
./mvnw -B -ntp -pl dolphinscheduler-master -am \ -Dtest=WorkflowFinishPersistenceRecoveryTestCase,WorkflowStartSerialStrategyTestCase,WorkflowInstanceMetricsTestCase,WorkflowBackfillTestCase,WorkflowStartSubWorkflowTestCase \ -Dsurefire.failIfNoSpecifiedTests=false clean testThe tests inject exceptions into real H2 transactions; they do not simulate a database-server outage. The full project test suite was not run.
Pull Request Notice
Pull Request Notice