@@ -247,13 +247,18 @@ impl<T: 'static + AsLogicalPlan, U: 'static + AsExecutionPlan>
247247 // subscribers (e.g. SpiceAI's QueryHandle) who receive the
248248 // Completed event can immediately read the Successful status
249249 // without hitting a retry/polling loop.
250- if let Err ( e) = self . state . task_manager . succeed_job ( & job_id) . await {
251- error ! ( "Fail to invoke succeed_job for job {job_id} due to {e:?}" ) ;
250+ match self . state . task_manager . succeed_job ( & job_id) . await {
251+ Ok ( ( ) ) => {
252+ // Broadcast job completed state after status is persisted
253+ self . broadcast_job_state ( JobStateEvent :: completed ( & job_id) ) ;
254+ }
255+ Err ( e) => {
256+ error ! (
257+ "Fail to invoke succeed_job for job {job_id} due to {e:?}"
258+ ) ;
259+ }
252260 }
253261
254- // Broadcast job completed state after status is persisted
255- self . broadcast_job_state ( JobStateEvent :: completed ( & job_id) ) ;
256-
257262 self . state . clean_up_successful_job ( job_id) ;
258263 }
259264 QueryStageSchedulerEvent :: JobRunningFailed {
@@ -283,15 +288,17 @@ impl<T: 'static + AsLogicalPlan, U: 'static + AsExecutionPlan>
283288 ) )
284289 . await ?;
285290 }
291+ // Broadcast job failed state after status is persisted
292+ self . broadcast_job_state ( JobStateEvent :: failed (
293+ & job_id,
294+ & fail_message,
295+ ) ) ;
286296 }
287297 Err ( e) => {
288298 error ! ( "Fail to invoke abort_job for job {job_id} due to {e:?}" ) ;
289299 }
290300 }
291301
292- // Broadcast job failed state after status is persisted
293- self . broadcast_job_state ( JobStateEvent :: failed ( & job_id, & fail_message) ) ;
294-
295302 self . state . clean_up_failed_job ( job_id) ;
296303 }
297304 QueryStageSchedulerEvent :: JobUpdated ( job_id) => {
@@ -306,23 +313,23 @@ impl<T: 'static + AsLogicalPlan, U: 'static + AsExecutionPlan>
306313 info ! ( "Job {job_id} Cancelled" ) ;
307314
308315 // Persist terminal status before broadcasting so subscribers
309- // can immediately read the Cancelled status on receipt of the event.
316+ // can immediately read the terminal status on receipt of the event.
317+ // Note: cancel_job routes to abort_job, persisting a Failed status.
310318 match self . state . task_manager . cancel_job ( & job_id) . await {
311319 Ok ( ( running_tasks, _pending_tasks) ) => {
312320 event_sender
313321 . post_event ( QueryStageSchedulerEvent :: CancelTasks (
314322 running_tasks,
315323 ) )
316324 . await ?;
325+ // Broadcast cancelled state after status is persisted
326+ self . broadcast_job_state ( JobStateEvent :: cancelled ( & job_id) ) ;
317327 }
318328 Err ( e) => {
319329 error ! ( "Fail to invoke cancel_job for job {job_id} due to {e:?}" ) ;
320330 }
321331 }
322332
323- // Broadcast cancelled state after status is persisted
324- self . broadcast_job_state ( JobStateEvent :: cancelled ( & job_id) ) ;
325-
326333 self . state . clean_up_failed_job ( job_id) ;
327334 }
328335 QueryStageSchedulerEvent :: TaskUpdating ( executor_id, tasks_status) => {
0 commit comments