70 lines
2.2 KiB
Python
70 lines
2.2 KiB
Python
"""Small active Web mutation ports for ARR2.0."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import threading
|
|
from dataclasses import dataclass
|
|
from datetime import date
|
|
from typing import Any, Dict, Protocol
|
|
|
|
from arr_web.contracts import PortalError
|
|
from monthly_reports.service import MonthlyReportService, RunRequest
|
|
|
|
|
|
class UploadCoordinator(Protocol):
|
|
def submit(self, original_filename: str, payload: bytes) -> Dict[str, Any]:
|
|
...
|
|
|
|
|
|
class MonthlyCoordinator(Protocol):
|
|
def generate(self, month_key: str, as_of_date: date) -> Dict[str, Any]:
|
|
...
|
|
|
|
|
|
class UnavailableUploadCoordinator:
|
|
def submit(self, original_filename: str, payload: bytes) -> Dict[str, Any]:
|
|
raise PortalError(
|
|
"PROCESSING_GATEWAY_UNAVAILABLE",
|
|
"文件接收服务尚未完成生产接线",
|
|
503,
|
|
)
|
|
|
|
|
|
class UnavailableMonthlyCoordinator:
|
|
def generate(self, month_key: str, as_of_date: date) -> Dict[str, Any]:
|
|
raise PortalError(
|
|
"MONTHLY_GENERATOR_UNAVAILABLE",
|
|
"月报生成服务暂不可用",
|
|
503,
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class ProgramMonthlyCoordinator:
|
|
"""Run the deterministic monthly database program."""
|
|
|
|
service: MonthlyReportService
|
|
|
|
def __post_init__(self) -> None:
|
|
self._lock = threading.Lock()
|
|
|
|
def generate(self, month_key: str, as_of_date: date) -> Dict[str, Any]:
|
|
year, month = (int(part) for part in month_key.split("-"))
|
|
request = RunRequest(year, month, as_of_date)
|
|
try:
|
|
request.validate()
|
|
except Exception:
|
|
raise PortalError("MONTHLY_REQUEST_INVALID", "月报日期范围无效") from None
|
|
if not self._lock.acquire(blocking=False):
|
|
raise PortalError("MONTHLY_ALREADY_RUNNING", "该服务正在生成月报", 409)
|
|
try:
|
|
result = self.service.run(request)
|
|
finally:
|
|
self._lock.release()
|
|
payload = result.to_dict()
|
|
if result.status != "success":
|
|
error = payload.get("errors", [{}])[0]
|
|
code = str(error.get("code") or "MONTHLY_GENERATION_FAILED")
|
|
raise PortalError(code, "月报生成未完成", 422)
|
|
return payload
|