feat: prepare ARR for controlled public deployment
This commit is contained in:
45
arr_mcp/gateway.py
Normal file
45
arr_mcp/gateway.py
Normal file
@@ -0,0 +1,45 @@
|
||||
"""Framework-neutral adapter for the single ARR MCP tool."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import threading
|
||||
from typing import Any, Dict, Protocol
|
||||
|
||||
from arr_ingestion.contracts import IngestionError
|
||||
from arr_ingestion.direct_contracts import DirectSubmissionReceipt
|
||||
|
||||
|
||||
class DirectResultSubmitter(Protocol):
|
||||
def submit(self, raw_request: Any) -> DirectSubmissionReceipt:
|
||||
...
|
||||
|
||||
|
||||
class DirectResultGateway:
|
||||
"""Expose one bounded command without duplicating ingestion logic."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
service: DirectResultSubmitter,
|
||||
*,
|
||||
max_concurrency: int = 2,
|
||||
) -> None:
|
||||
if (
|
||||
not isinstance(max_concurrency, int)
|
||||
or isinstance(max_concurrency, bool)
|
||||
or not 1 <= max_concurrency <= 8
|
||||
):
|
||||
raise ValueError("direct gateway concurrency is invalid")
|
||||
self._service = service
|
||||
self._slots = threading.BoundedSemaphore(max_concurrency)
|
||||
|
||||
def submit_processing_result(self, arguments: Any) -> Dict[str, Any]:
|
||||
if not self._slots.acquire(blocking=False):
|
||||
raise IngestionError(
|
||||
"DIRECT_GATEWAY_BUSY",
|
||||
"direct result gateway is busy; retry later",
|
||||
retryable=True,
|
||||
)
|
||||
try:
|
||||
return self._service.submit(arguments).to_dict()
|
||||
finally:
|
||||
self._slots.release()
|
||||
Reference in New Issue
Block a user