feat(V2): ClientRegistry lazy con lock per chiave
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
"""Cache lazy di client exchange, una istanza per (exchange, env)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections import defaultdict
|
||||
from collections.abc import Awaitable, Callable
|
||||
from typing import Any, Literal
|
||||
|
||||
Environment = Literal["testnet", "mainnet"]
|
||||
Builder = Callable[[str, Environment], Awaitable[Any]]
|
||||
|
||||
|
||||
class ClientRegistry:
|
||||
def __init__(self, *, builder: Builder) -> None:
|
||||
self._builder = builder
|
||||
self._clients: dict[tuple[str, Environment], Any] = {}
|
||||
self._locks: dict[tuple[str, Environment], asyncio.Lock] = defaultdict(
|
||||
asyncio.Lock
|
||||
)
|
||||
|
||||
async def get(self, exchange: str, env: Environment) -> Any:
|
||||
key = (exchange, env)
|
||||
if key in self._clients:
|
||||
return self._clients[key]
|
||||
async with self._locks[key]:
|
||||
if key in self._clients: # double-check
|
||||
return self._clients[key]
|
||||
client = await self._builder(exchange, env)
|
||||
self._clients[key] = client
|
||||
return client
|
||||
|
||||
async def aclose(self) -> None:
|
||||
for client in self._clients.values():
|
||||
close = getattr(client, "aclose", None)
|
||||
if close is None:
|
||||
continue
|
||||
try:
|
||||
await close()
|
||||
except Exception:
|
||||
pass
|
||||
self._clients.clear()
|
||||
Reference in New Issue
Block a user