File tree Expand file tree Collapse file tree 2 files changed +19
-3
lines changed
Expand file tree Collapse file tree 2 files changed +19
-3
lines changed Original file line number Diff line number Diff line change 99__author__ = "Michael Hall"
1010__license__ = "Apache-2.0"
1111__copyright__ = "Copyright 2020-Present Michael Hall"
12- __version__ = "2025.07.08b "
12+ __version__ = "2025.07.11b "
1313
1414import os
1515import sys
Original file line number Diff line number Diff line change 1515from __future__ import annotations
1616
1717import asyncio
18+ import time
1819from collections .abc import Coroutine
1920from contextvars import Context
2021
@@ -48,7 +49,10 @@ class BGTasks:
4849 Parameters
4950 ----------
5051 exit_timeout: int | None
51- Optionally, the number of seconds to wait before timing out tasks.
52+ Optionally, the number of seconds to wait before sending a
53+ cancellation to pending tasks. This does not guarantee that after
54+ the timeout the context manager will exit immediately,
55+ as tasks may catch cancellation.
5256
5357 In applications that care about graceful shutdown, this should
5458 usually not be set. When not provided, the context manager
@@ -99,8 +103,20 @@ async def __aenter__(self: t.Self) -> t.Self:
99103 return self
100104
101105 async def __aexit__ (self , * _dont_care : object ) -> None :
106+ start = time .monotonic ()
107+ pending : set [asyncio .Task [t .Any ]] = set ()
102108 while tsks := self ._tasks .copy ():
109+ if self ._etime :
110+ max_sleep = start - time .monotonic () + self ._etime
111+ if max_sleep <= 0 :
112+ break
113+
103114 _done , pending = await asyncio .wait (tsks , timeout = self ._etime )
115+ await asyncio .sleep (0 )
116+
117+ if pending :
104118 for task in pending :
105119 task .cancel ()
106- await asyncio .sleep (0 )
120+ # This wait is required in case tasks catch cancelation and
121+ # do further cleanup
122+ await asyncio .wait (pending )
You can’t perform that action at this time.
0 commit comments