Как реализовать отложенный callback для корутины?

Подскажите, как реализовать callback для coroutine?

Минимально-рабочая конструкция, которой удалось достичь

def ratelimit(fn, max_limit=1, timeout=2):
    ctx = contextvars.ContextVar(
        'ratelimit-semaphore',
        default=asyncio.Semaphore(max_limit)
    )

    def callback(a, sem):
        async def _():
            await asyncio.sleep(timeout)
            sem.release()

        current_loop = asyncio.get_running_loop()
        current_loop.create_task(_())

    def _():
        async def wrapper(*args, **kwargs):
            loop = kwargs.get('loop', asyncio.get_running_loop())
            assert isinstance(loop, asyncio.AbstractEventLoop)
            sem = ctx.get()
            await sem.acquire()

            task = loop.create_task(fn(*args, **kwargs), name=repr(fn.__name__))
            task.add_done_callback(functools.partial(callback, sem=sem))

            return await task
        return wrapper
    return _()

Увы, если loop был завершен - вызов коллбека не происходит


Ответы (0 шт):