diff --git a/bioengine/_version.py b/bioengine/_version.py index 83f80f7..af6c015 100644 --- a/bioengine/_version.py +++ b/bioengine/_version.py @@ -13,4 +13,4 @@ Must stay in lock-step with ``pyproject.toml``'s ``version`` field. The ``version-check.yml`` CI workflow enforces the match. """ -__version__ = "0.11.25" +__version__ = "0.11.26" diff --git a/bioengine/apps/proxy_deployment.py b/bioengine/apps/proxy_deployment.py index e97b659..705719b 100644 --- a/bioengine/apps/proxy_deployment.py +++ b/bioengine/apps/proxy_deployment.py @@ -428,6 +428,26 @@ async def deployment_function(*args, context: Dict[str, Any], **kwargs) -> Any: # Semaphore bounds concurrency for both WebSocket and WebRTC entry paths — # they share this single wrapper, so a long-running call from either # transport consumes one slot until it returns. + # + # Fail fast instead of queueing unboundedly when at capacity: a + # blocked caller still holds its decoded payload (e.g. an inference + # image) in this actor's memory while it waits, so an open-ended + # backlog grows proxy memory without limit. Because we reject rather + # than await, the semaphore never accumulates waiters — so + # ``.locked()`` means "no free slot", and there is no ``await`` + # between this check and the acquire below, making the decision + # race-free. + if self.service_semaphore.locked(): + logger.warning( + f"⚠️ '{self.application_id}' at capacity " + f"({self.max_ongoing_requests} concurrent requests); " + f"rejecting '{method_name}'." + ) + raise RuntimeError( + f"Application '{self.application_id}' has reached its maximum " + f"of {self.max_ongoing_requests} concurrent requests. Please " + f"try again in a moment." + ) async with self.service_semaphore: try: await self._check_permissions(context, method_name=method_name) diff --git a/pyproject.toml b/pyproject.toml index 12eb65a..80fcbbd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "bioengine" -version = "0.11.25" +version = "0.11.26" description = "BioEngine — CLI and SDK for deploying and calling AI model services on BioEngine workers" requires-python = ">=3.11" authors = [