Skip to content

Instantly share code, notes, and snippets.

@Olegt0rr
Created February 1, 2024 07:56
Show Gist options
  • Save Olegt0rr/bf850cdbb8954c5d0a04228ca676ee76 to your computer and use it in GitHub Desktop.
Save Olegt0rr/bf850cdbb8954c5d0a04228ca676ee76 to your computer and use it in GitHub Desktop.
import asyncio
from collections import defaultdict
from collections.abc import AsyncIterator, Hashable
from contextlib import asynccontextmanager
from typing import Self
class IDLock:
"""Asyncio Lock synced to some id."""
def __init__(self: Self) -> None:
self._lock_dict: dict[Hashable, asyncio.Lock] = defaultdict(asyncio.Lock)
@asynccontextmanager
async def ctx(self: Self, any_id: Hashable) -> AsyncIterator[None]:
"""Lock for any id.
Usage:
lock = IDLock() # once per app, not per request!
# once per request
async with lock.ctx(user_id):
...
"""
lock = self._lock_dict[any_id]
try:
async with lock:
yield
finally:
if not lock._waiters and any_id in self._lock_dict: # noqa till issue:
# https://github.com/python/typeshed/issues/11314
# is not imported to pyCharm
del self._lock_dict[any_id]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment