"""One-call direct structured-result orchestration owned by ARR.""" from __future__ import annotations from typing import Any, Protocol from arr_ingestion.contracts import IngestionError from arr_ingestion.direct_contracts import ( DirectSubmissionReceipt, DirectSubmissionRequest, ReceivedDirectSubmission, SubmissionGrant, VerifiedDirectSubmission, ) class DirectSubmissionRepository(Protocol): def assert_ready(self) -> None: ... def issue_grant( self, job_id: str, attempt_no: int, *, ttl_seconds: int, ) -> SubmissionGrant: ... def receive( self, request: DirectSubmissionRequest, ) -> ReceivedDirectSubmission: ... def commit( self, verified: VerifiedDirectSubmission, ) -> DirectSubmissionReceipt: ... def reject( self, submission: ReceivedDirectSubmission, failure_code: str, ) -> None: ... def expire_stale(self, *, limit: int) -> int: ... class DirectSubmissionValidator(Protocol): def validate( self, submission: ReceivedDirectSubmission, ) -> VerifiedDirectSubmission: ... _RETRYABLE_VALIDATION_CODES = frozenset( { "ARTIFACT_NOT_FOUND", "ARTIFACT_UNREADABLE", "DIRECT_REPLAY_UNAVAILABLE", "OBJECT_STORE_UNAVAILABLE", } ) class DirectSubmissionService: """Persist, replay, and atomically commit one complete structured payload.""" def __init__( self, validator: DirectSubmissionValidator, repository: DirectSubmissionRepository, ) -> None: self._validator = validator self._repository = repository def issue_grant( self, job_id: str, attempt_no: int, *, ttl_seconds: int = 900, ) -> SubmissionGrant: return self._repository.issue_grant( job_id, attempt_no, ttl_seconds=ttl_seconds, ) def assert_ready(self) -> None: self._repository.assert_ready() def submit(self, raw_request: Any) -> DirectSubmissionReceipt: request = DirectSubmissionRequest.from_dict(raw_request) submission = self._repository.receive(request) if submission.receipt is not None: return submission.receipt try: verified = self._validator.validate(submission) except IngestionError as error: if ( not error.retryable and error.code not in _RETRYABLE_VALIDATION_CODES ): self._repository.reject(submission, error.code) raise return self._repository.commit(verified) def expire_stale(self, *, limit: int = 100) -> int: if ( not isinstance(limit, int) or isinstance(limit, bool) or not 1 <= limit <= 1000 ): raise IngestionError( "DIRECT_SUBMISSION_INVALID", "direct submission expiry limit is invalid", ) return self._repository.expire_stale(limit=limit)