@@ -242,7 +242,7 @@ async def _wait_and_cancel(
242242 if exc is not None :
243243 logger .warning (
244244 EXECUTION_SHUTDOWN_TASK_ERROR ,
245- error = ( f"Task raised during shutdown: { type (exc ).__name__ } " ) ,
245+ error = f"Task raised during shutdown: { type (exc ).__name__ } : { exc } " ,
246246 )
247247 else :
248248 tasks_completed += 1
@@ -260,41 +260,10 @@ async def _wait_and_cancel(
260260 pending ,
261261 timeout = self ._CANCEL_PROPAGATION_TIMEOUT ,
262262 )
263- self . _log_post_cancel_exceptions (cancel_done )
263+ _log_post_cancel_exceptions (cancel_done )
264264
265265 return tasks_completed , len (pending )
266266
267- def _log_post_cancel_exceptions (
268- self ,
269- tasks : set [asyncio .Task [Any ]],
270- ) -> None :
271- """Retrieve and log exceptions from post-cancel tasks.
272-
273- Retrieving the exception prevents asyncio's "Task exception was
274- never retrieved" warning. Non-cancelled tasks with exceptions
275- are logged at DEBUG.
276- """
277- for task in tasks :
278- if task .cancelled ():
279- continue
280- try :
281- exc = task .exception ()
282- except asyncio .InvalidStateError :
283- logger .debug (
284- EXECUTION_SHUTDOWN_TASK_ERROR ,
285- error = "Failed to inspect post-cancel task: InvalidStateError" ,
286- task_name = task .get_name (),
287- )
288- else :
289- if exc is not None :
290- logger .debug (
291- EXECUTION_SHUTDOWN_TASK_ERROR ,
292- error = (
293- f"Post-cancel task exception: { type (exc ).__name__ } : { exc } "
294- ),
295- task_name = task .get_name (),
296- )
297-
298267
299268class ImmediateCancelStrategy :
300269 """Immediate cancel shutdown strategy.
@@ -349,11 +318,7 @@ async def execute_shutdown(
349318 task_set ,
350319 timeout = self ._CANCEL_PROPAGATION_TIMEOUT ,
351320 )
352- # Retrieve exceptions to suppress "never retrieved" warnings.
353- for task in cancel_done :
354- if not task .cancelled ():
355- with contextlib .suppress (Exception ):
356- task .exception ()
321+ _log_post_cancel_exceptions (cancel_done )
357322
358323 cleanup_completed = await _run_cleanup (cleanup_callbacks , self ._cleanup_seconds )
359324
@@ -448,7 +413,7 @@ async def execute_shutdown(
448413 if exc is not None :
449414 logger .warning (
450415 EXECUTION_SHUTDOWN_TASK_ERROR ,
451- error = f"Task raised during shutdown: { type (exc ).__name__ } " ,
416+ error = f"Task raised during shutdown: { type (exc ).__name__ } : { exc } " ,
452417 )
453418 else :
454419 tasks_completed += 1
@@ -465,10 +430,7 @@ async def execute_shutdown(
465430 pending ,
466431 timeout = self ._CANCEL_PROPAGATION_TIMEOUT ,
467432 )
468- for task in cancel_done :
469- if not task .cancelled ():
470- with contextlib .suppress (Exception ):
471- task .exception ()
433+ _log_post_cancel_exceptions (cancel_done )
472434
473435 cleanup_completed = await _run_cleanup (cleanup_callbacks , self ._cleanup_seconds )
474436
@@ -568,7 +530,7 @@ async def execute_shutdown(
568530 if exc is not None :
569531 logger .warning (
570532 EXECUTION_SHUTDOWN_TASK_ERROR ,
571- error = f"Task raised during shutdown: { type (exc ).__name__ } " ,
533+ error = f"Task raised during shutdown: { type (exc ).__name__ } : { exc } " ,
572534 )
573535 else :
574536 tasks_suspended += 1
@@ -580,6 +542,11 @@ async def execute_shutdown(
580542 tasks_interrupted = 0
581543 for task in pending :
582544 task_id = task_to_id .get (task , "unknown" )
545+ if task_id == "unknown" :
546+ logger .debug (
547+ EXECUTION_SHUTDOWN_TASK_ERROR ,
548+ error = "Task not found in reverse map during checkpoint" ,
549+ )
583550 saved = await self ._try_checkpoint (task_id )
584551 if saved :
585552 tasks_suspended += 1
@@ -593,10 +560,7 @@ async def execute_shutdown(
593560 pending ,
594561 timeout = self ._CANCEL_PROPAGATION_TIMEOUT ,
595562 )
596- for task in cancel_done :
597- if not task .cancelled ():
598- with contextlib .suppress (Exception ):
599- task .exception ()
563+ _log_post_cancel_exceptions (cancel_done )
600564
601565 cleanup_completed = await _run_cleanup (cleanup_callbacks , self ._cleanup_seconds )
602566
@@ -628,10 +592,11 @@ async def _try_checkpoint(self, task_id: str) -> bool:
628592 return False
629593 try :
630594 saved = await self ._checkpoint_saver (task_id )
631- except Exception :
595+ except Exception as exc :
632596 logger .exception (
633597 EXECUTION_SHUTDOWN_CHECKPOINT_FAILED ,
634598 task_id = task_id ,
599+ error_type = type (exc ).__name__ ,
635600 )
636601 return False
637602 if saved :
@@ -648,7 +613,34 @@ async def _try_checkpoint(self, task_id: str) -> bool:
648613 return saved
649614
650615
651- # ── Shared cleanup helper ────────────────────────────────────────
616+ # ── Shared helpers ───────────────────────────────────────────────
617+
618+
619+ def _log_post_cancel_exceptions (tasks : set [asyncio .Task [Any ]]) -> None :
620+ """Retrieve and log exceptions from post-cancel tasks.
621+
622+ Retrieving the exception prevents asyncio's "Task exception was
623+ never retrieved" warning. Non-cancelled tasks with exceptions
624+ are logged at DEBUG.
625+ """
626+ for task in tasks :
627+ if task .cancelled ():
628+ continue
629+ try :
630+ exc = task .exception ()
631+ except asyncio .InvalidStateError :
632+ logger .debug (
633+ EXECUTION_SHUTDOWN_TASK_ERROR ,
634+ error = "Failed to inspect post-cancel task: InvalidStateError" ,
635+ task_name = task .get_name (),
636+ )
637+ else :
638+ if exc is not None :
639+ logger .debug (
640+ EXECUTION_SHUTDOWN_TASK_ERROR ,
641+ error = (f"Post-cancel task exception: { type (exc ).__name__ } : { exc } " ),
642+ task_name = task .get_name (),
643+ )
652644
653645
654646async def _run_cleanup (
0 commit comments