Files
wyndham-ARR/arr_web/agent_writeback_runtime.py
2026-07-31 15:11:42 +08:00

131 lines
4.5 KiB
Python

"""Production composition for authenticated Agent result callbacks."""
from __future__ import annotations
import os
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Callable, Optional
from arr_ingestion.postgres import DatabaseConfig, PostgresIngestionRepository
from arr_ingestion.service import IngestionService
from arr_ingestion.validation import DeliveryValidator, ProcessorPolicy
from arr_processing.callbacks import AgentResultWriteback
from arr_processing.config import ResultVerificationConfig
from arr_processing.errors import ProcessingTransportError
from arr_processing.postgres import PostgresProcessingState, ProcessingDatabaseConfig
from arr_processing.registration import ProcessingOutputRegistrar, RemoteFilePort
from arr_processing.remote_files import PrefixRemoteFilePort
from arr_processing.runner import ProcessingRunner, RemoteRunSnapshot
from arr_processing.policy import load_processor_policy
from arr_storage.aliyun_oss_v2 import AliyunOssConfig, AliyunOssV2Client
from arr_storage.contracts import ObjectKeyPolicy
from arr_storage.exchange import OutputExchangeConfig
from arr_storage.remote import CloudObjectBackend
from arr_storage.store import ManagedObjectStore
from arr_web.legacy_agent_services import ProcessingAgentResultCoordinator
class CallbackOnlyTransport:
"""Callbacks do not require remote Agent network authority in this process."""
@staticmethod
def _disabled() -> None:
raise ProcessingTransportError(
"PROCESSING_REMOTE_DISABLED",
retryable=False,
)
def submit(self, request: Any, idempotency_key: str) -> RemoteRunSnapshot:
del request, idempotency_key
self._disabled()
def get(self, request: Any, remote_run_id: str) -> RemoteRunSnapshot:
del request, remote_run_id
self._disabled()
def cancel(self, request: Any, remote_run_id: str) -> RemoteRunSnapshot:
del request, remote_run_id
self._disabled()
@dataclass
class AgentWritebackRuntime:
coordinator: ProcessingAgentResultCoordinator
close_callback: Optional[Callable[[], None]] = None
def close(self) -> None:
if self.close_callback is not None:
self.close_callback()
def compose_agent_writeback(
*,
object_store: ManagedObjectStore,
remote_files: RemoteFilePort,
processor_policy: ProcessorPolicy,
verification: ResultVerificationConfig,
connect: Optional[Callable[[str], Any]] = None,
) -> AgentWritebackRuntime:
processing_config = (
ProcessingDatabaseConfig("controlled")
if connect is not None
else ProcessingDatabaseConfig.from_environment()
)
ingestion_config = (
DatabaseConfig("controlled")
if connect is not None
else DatabaseConfig.from_environment()
)
state = PostgresProcessingState(processing_config, connect=connect)
runner = ProcessingRunner(
CallbackOnlyTransport(),
state,
verification.verifier(),
)
repository = PostgresIngestionRepository(ingestion_config, connect=connect)
writeback = AgentResultWriteback(
runner,
state,
ProcessingOutputRegistrar(remote_files, object_store),
IngestionService(
DeliveryValidator(object_store, processor_policy),
repository,
),
outcome_resolver=state,
)
return AgentWritebackRuntime(ProcessingAgentResultCoordinator(writeback))
def compose_oss_agent_writeback(
*,
project_root: Path,
connect: Optional[Callable[[str], Any]] = None,
) -> AgentWritebackRuntime:
oss_client = AliyunOssV2Client(AliyunOssConfig.from_environment())
try:
oss_client.assert_immutable_writes_supported()
key_policy = ObjectKeyPolicy(os.environ.get("ARR_OBJECT_PREFIX", "arr"))
object_store = ManagedObjectStore(
CloudObjectBackend(oss_client),
key_policy,
)
runtime = compose_agent_writeback(
object_store=object_store,
remote_files=PrefixRemoteFilePort(
oss_client,
OutputExchangeConfig.from_environment(),
),
processor_policy=load_processor_policy(project_root),
verification=ResultVerificationConfig.from_environment(),
connect=connect,
)
runtime.close_callback = oss_client.close
return runtime
except Exception:
try:
oss_client.close()
except Exception:
pass
raise