4949import org .apache .commons .lang3 .StringUtils ;
5050
5151import java .util .List ;
52+ import java .util .function .Consumer ;
5253
5354import lombok .extern .slf4j .Slf4j ;
5455
@@ -125,39 +126,43 @@ public void onFatalEvent(final IWorkflowExecution workflowExecution,
125126 private void persistentTaskInstanceFatalEventToDB (final ITaskExecution taskExecution ,
126127 final TaskFatalLifecycleEvent taskFatalEvent ) {
127128 final TaskInstance taskInstance = taskExecution .getTaskInstance ();
128- taskInstance .setState (TaskExecutionStatus .FAILURE );
129- taskInstance .setEndTime (taskFatalEvent .getEndTime ());
130- taskInstanceDao .updateById (taskInstance );
129+ persistTaskInstanceUpdate (taskInstance , instance -> {
130+ instance .setState (TaskExecutionStatus .FAILURE );
131+ instance .setEndTime (taskFatalEvent .getEndTime ());
132+ });
131133 }
132134
133135 @ Override
134136 public void onDispatchedEvent (final IWorkflowExecution workflowExecution ,
135137 final ITaskExecution taskExecution ,
136138 final TaskDispatchedLifecycleEvent taskDispatchedEvent ) {
137139 final TaskInstance taskInstance = taskExecution .getTaskInstance ();
138- taskInstance .setState (DISPATCH );
139- taskInstance .setHost (taskDispatchedEvent .getExecutorHost ());
140- taskInstanceDao .updateById (taskInstance );
140+ persistTaskInstanceUpdate (taskInstance , instance -> {
141+ instance .setState (DISPATCH );
142+ instance .setHost (taskDispatchedEvent .getExecutorHost ());
143+ });
141144 }
142145
143146 @ Override
144147 public void onRuntimeContextChangedEvent (final IWorkflowExecution workflowExecution ,
145148 final ITaskExecution taskExecution ,
146149 final TaskRuntimeContextChangedEvent taskRuntimeContextChangedEvent ) {
147150 final TaskInstance taskInstance = taskExecution .getTaskInstance ();
148- if (StringUtils .isNotEmpty (taskRuntimeContextChangedEvent .getRuntimeContext ())) {
149- taskInstance .setAppLink (taskRuntimeContextChangedEvent .getRuntimeContext ());
150- }
151- taskInstanceDao .updateById (taskInstance );
151+ persistTaskInstanceUpdate (taskInstance , instance -> {
152+ if (StringUtils .isNotEmpty (taskRuntimeContextChangedEvent .getRuntimeContext ())) {
153+ instance .setAppLink (taskRuntimeContextChangedEvent .getRuntimeContext ());
154+ }
155+ });
152156 }
153157
154158 protected void persistentTaskInstanceStartedEventToDB (final ITaskExecution taskExecution ,
155159 final TaskRunningLifecycleEvent taskRunningEvent ) {
156160 final TaskInstance taskInstance = taskExecution .getTaskInstance ();
157- taskInstance .setState (TaskExecutionStatus .RUNNING_EXECUTION );
158- taskInstance .setStartTime (taskRunningEvent .getStartTime ());
159- taskInstance .setLogPath (taskRunningEvent .getLogPath ());
160- taskInstanceDao .updateById (taskInstance );
161+ persistTaskInstanceUpdate (taskInstance , instance -> {
162+ instance .setState (TaskExecutionStatus .RUNNING_EXECUTION );
163+ instance .setStartTime (taskRunningEvent .getStartTime ());
164+ instance .setLogPath (taskRunningEvent .getLogPath ());
165+ });
161166 }
162167
163168 @ Override
@@ -173,8 +178,7 @@ public void onPausedEvent(final IWorkflowExecution workflowExecution,
173178 private void persistentTaskInstancePausedEventToDB (final ITaskExecution taskExecution ,
174179 final TaskPausedLifecycleEvent taskPausedEvent ) {
175180 final TaskInstance taskInstance = taskExecution .getTaskInstance ();
176- taskInstance .setState (TaskExecutionStatus .PAUSE );
177- taskInstanceDao .updateById (taskInstance );
181+ persistTaskInstanceUpdate (taskInstance , instance -> instance .setState (TaskExecutionStatus .PAUSE ));
178182 }
179183
180184 @ Override
@@ -190,9 +194,10 @@ public void onKilledEvent(final IWorkflowExecution workflowExecution,
190194 private void persistentTaskInstanceKilledEventToDB (final ITaskExecution taskExecution ,
191195 final TaskKilledLifecycleEvent taskKilledEvent ) {
192196 final TaskInstance taskInstance = taskExecution .getTaskInstance ();
193- taskInstance .setState (TaskExecutionStatus .KILL );
194- taskInstance .setEndTime (taskKilledEvent .getEndTime ());
195- taskInstanceDao .updateById (taskInstance );
197+ persistTaskInstanceUpdate (taskInstance , instance -> {
198+ instance .setState (TaskExecutionStatus .KILL );
199+ instance .setEndTime (taskKilledEvent .getEndTime ());
200+ });
196201
197202 }
198203
@@ -223,9 +228,10 @@ public void onFailedEvent(final IWorkflowExecution workflowExecution,
223228 private void persistentTaskInstanceFailedEventToDB (final ITaskExecution taskExecution ,
224229 final TaskFailedLifecycleEvent taskFailedEvent ) {
225230 final TaskInstance taskInstance = taskExecution .getTaskInstance ();
226- taskInstance .setState (TaskExecutionStatus .FAILURE );
227- taskInstance .setEndTime (taskFailedEvent .getEndTime ());
228- taskInstanceDao .updateById (taskInstance );
231+ persistTaskInstanceUpdate (taskInstance , instance -> {
232+ instance .setState (TaskExecutionStatus .FAILURE );
233+ instance .setEndTime (taskFailedEvent .getEndTime ());
234+ });
229235 }
230236
231237 @ Override
@@ -247,24 +253,32 @@ protected void mergeTaskVarPoolToWorkflow(final IWorkflowExecution workflowExecu
247253 workflowInstance .setVarPool (VarPoolUtils .serializeVarPool (finalVarPool ));
248254 }
249255
256+ /**
257+ * Persist an event's fields before applying them to the shared instance, so a failed update remains retryable.
258+ * The updater must only assign the event's fields and must be safe to apply to both instances. Compute merged
259+ * values before calling this method; do not publish events or mutate nested objects in the updater.
260+ */
261+ protected void persistTaskInstanceUpdate (final TaskInstance taskInstance ,
262+ final Consumer <TaskInstance > updater ) {
263+ final TaskInstance taskInstanceToUpdate = new TaskInstance ();
264+ BeanUtils .copyProperties (taskInstance , taskInstanceToUpdate );
265+ updater .accept (taskInstanceToUpdate );
266+ taskInstanceDao .updateById (taskInstanceToUpdate );
267+ updater .accept (taskInstance );
268+ }
269+
250270 protected void persistentTaskInstanceSuccessEventToDB (final ITaskExecution taskExecution ,
251271 final TaskSuccessLifecycleEvent taskSuccessEvent ) {
252272 final TaskInstance taskInstance = taskExecution .getTaskInstance ();
253273 final List <Property > finalVarPool = VarPoolUtils .mergeVarPoolJsonString (taskInstance .getVarPool (),
254274 JSONUtils .toJsonString (taskSuccessEvent .getVarPool ()));
255275 final String serializedFinalVarPool = VarPoolUtils .serializeVarPool (finalVarPool );
256276
257- // Keep the shared state retryable if persisting the success result throws.
258- final TaskInstance taskInstanceToUpdate = new TaskInstance ();
259- BeanUtils .copyProperties (taskInstance , taskInstanceToUpdate );
260- taskInstanceToUpdate .setState (TaskExecutionStatus .SUCCESS );
261- taskInstanceToUpdate .setEndTime (taskSuccessEvent .getEndTime ());
262- taskInstanceToUpdate .setVarPool (serializedFinalVarPool );
263- taskInstanceDao .updateById (taskInstanceToUpdate );
264-
265- taskInstance .setState (TaskExecutionStatus .SUCCESS );
266- taskInstance .setEndTime (taskSuccessEvent .getEndTime ());
267- taskInstance .setVarPool (serializedFinalVarPool );
277+ persistTaskInstanceUpdate (taskInstance , instance -> {
278+ instance .setState (TaskExecutionStatus .SUCCESS );
279+ instance .setEndTime (taskSuccessEvent .getEndTime ());
280+ instance .setVarPool (serializedFinalVarPool );
281+ });
268282 }
269283
270284 /**
0 commit comments