Skip to content

Commit

Permalink
Limit concurrent calls per user instead of globally
Browse files Browse the repository at this point in the history
  • Loading branch information
justvanrossum committed Nov 23, 2023
1 parent 0541def commit 4eb5d6a
Showing 1 changed file with 6 additions and 9 deletions.
15 changes: 6 additions & 9 deletions src/fontra_rcjk/client_async.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import asyncio
import logging
from collections import defaultdict
from contextlib import asynccontextmanager

import aiohttp
Expand All @@ -10,19 +9,20 @@

logger = logging.getLogger(__name__)

MAX_CONCURRENT_CALLS = 140 # MySQL's default max connections is 151
MAX_CONCURRENT_CALLS = 60 # Per client connection


class ConcurrentCallLimiter:
def __init__(self):
def __init__(self, label):
self.label = label
self.num_calls_in_progress = 0
self.event_queue = []

@asynccontextmanager
async def limit(self):
if self.num_calls_in_progress >= MAX_CONCURRENT_CALLS:
if not self.event_queue:
logger.info("limiting concurrent API calls")
logger.info(f"limiting concurrent API calls ({self.label})")
event = asyncio.Event()
self.event_queue.append(event)
await event.wait()
Expand All @@ -36,10 +36,7 @@ async def limit(self):
event = self.event_queue.pop(0)
event.set()
if not self.event_queue:
logger.info("done limiting concurrent API calls")


call_limiters = defaultdict(ConcurrentCallLimiter)
logger.info(f"done limiting concurrent API calls ({self.label})")


class RCJKClientAsync(RCJKClient):
Expand All @@ -49,7 +46,7 @@ def _connect(self):
pass

async def connect(self):
self._call_limiter = call_limiters[self._host]
self._call_limiter = ConcurrentCallLimiter(self._username)
self._session = aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False))
session = await self._session.__aenter__()
assert session is self._session
Expand Down

0 comments on commit 4eb5d6a

Please sign in to comment.