Skip to content

Commit fe31cdf

Browse files
committed
Add bg task thing
1 parent f57c31f commit fe31cdf

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

async_utils/bg_tasks.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Copyright 2020-present Michael Hall
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from __future__ import annotations
16+
17+
import asyncio
18+
from collections.abc import Coroutine, Generator
19+
from contextvars import Context
20+
from types import TracebackType
21+
from typing import Any, Self, TypeAlias, TypeVar
22+
23+
_T = TypeVar("_T")
24+
_CoroutineLike: TypeAlias = Generator[Any, None, _T] | Coroutine[Any, Any, _T]
25+
26+
27+
__all__ = ["BGTasks"]
28+
29+
30+
class BGTasks:
31+
"""An intentionally dumber task group"""
32+
33+
def __init__(self, exit_timeout: float | None) -> None:
34+
self._tasks: set[asyncio.Task[Any]] = set()
35+
self._exit_timeout: float | None = exit_timeout
36+
37+
def create_task(self, coro: _CoroutineLike[_T], *, name: str | None = None, context: Context | None = None) -> Any:
38+
t = asyncio.create_task(coro)
39+
self._tasks.add(t)
40+
t.add_done_callback(self._tasks.discard)
41+
return t
42+
43+
async def __aenter__(self: Self) -> Self:
44+
return self
45+
46+
async def __aexit__(self, exc_type: type[Exception], exc: Exception, tb: TracebackType):
47+
_done, _pending = await asyncio.wait(self._tasks, timeout=self._exit_timeout)
48+
for task in _pending:
49+
task.cancel()

0 commit comments

Comments
 (0)