46 lines
1.4 KiB
Python
46 lines
1.4 KiB
Python
"""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()
|