2022-09-05 12:54:02 +00:00
|
|
|
"""
|
|
|
|
Some useful helpers for working in async contexts.
|
|
|
|
"""
|
|
|
|
|
2022-09-04 22:30:40 +00:00
|
|
|
from asyncio import get_running_loop
|
|
|
|
from functools import partial, wraps
|
|
|
|
from time import time
|
|
|
|
|
|
|
|
from async_lru import alru_cache
|
|
|
|
|
|
|
|
|
|
|
|
def run_in_executor(f):
|
|
|
|
"""
|
2022-09-05 12:54:02 +00:00
|
|
|
Decorator to make blocking a function call asyncio compatible.
|
2022-09-04 22:30:40 +00:00
|
|
|
https://stackoverflow.com/questions/41063331/how-to-use-asyncio-with-existing-blocking-library/
|
2022-09-05 13:02:15 +00:00
|
|
|
https://stackoverflow.com/a/53719009
|
2022-09-04 22:30:40 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
@wraps(f)
|
2022-09-05 13:02:15 +00:00
|
|
|
async def wrapper(*args, **kwargs):
|
2022-09-04 22:30:40 +00:00
|
|
|
loop = get_running_loop()
|
2022-09-05 13:02:15 +00:00
|
|
|
return await loop.run_in_executor(
|
2022-09-04 22:30:40 +00:00
|
|
|
None,
|
|
|
|
partial(f, *args, **kwargs),
|
|
|
|
)
|
|
|
|
|
2022-09-05 13:02:15 +00:00
|
|
|
return wrapper
|
2022-09-04 22:30:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
def get_ttl_hash(seconds: int = 20) -> int:
|
|
|
|
"""
|
2022-09-05 12:54:02 +00:00
|
|
|
Return the same value within `seconds` time period.
|
2022-09-04 22:30:40 +00:00
|
|
|
https://stackoverflow.com/a/55900800
|
|
|
|
"""
|
2022-09-05 12:54:02 +00:00
|
|
|
|
2022-09-04 22:30:40 +00:00
|
|
|
return round(time() / seconds)
|
|
|
|
|
|
|
|
|
|
|
|
def timed_alru_cache(**decorator_kwargs):
|
2022-09-05 12:54:02 +00:00
|
|
|
"""
|
|
|
|
Decorator which adds an (unused) param `ttl_hash`
|
|
|
|
and the `@alru_cache` annotation to a function.
|
|
|
|
"""
|
|
|
|
|
2022-09-04 22:30:40 +00:00
|
|
|
def decorate(f):
|
|
|
|
@alru_cache(**decorator_kwargs)
|
|
|
|
@wraps(f)
|
|
|
|
async def wrapper(ttl_hash: int, *args, **kwargs):
|
|
|
|
del ttl_hash
|
|
|
|
|
|
|
|
return await f(*args, **kwargs)
|
|
|
|
|
|
|
|
return wrapper
|
|
|
|
|
|
|
|
return decorate
|