I have a list of awaitables that I want to pass to the asyncio.AbstractEventLoop but I need to throttle the requests to a third party API.
Another solution - using bounded semaphores - by a coworker, mentor, and friend, is the following:
import asyncio
class AsyncLeakyBucket(object):
def __init__(self, max_tasks: float, time_period: float = 60, loop: asyncio.events=None):
self._delay_time = time_period / max_tasks
self._sem = asyncio.BoundedSemaphore(max_tasks)
self._loop = loop or asyncio.get_event_loop()
self._loop.create_task(self._leak_sem())
async def _leak_sem(self):
"""
Background task that leaks semaphore releases based on the desired rate of tasks per time_period
"""
while True:
await asyncio.sleep(self._delay_time)
try:
self._sem.release()
except ValueError:
pass
async def __aenter__(self) -> None:
await self._sem.acquire()
async def __aexit__(self, exc_type, exc, tb) -> None:
pass
Can still be used with the same async with bucket code as in @Martijn's answer