from __future__ import annotations from dataclasses import asdict, dataclass from datetime import datetime, timezone from typing import Any, Callable from uuid import uuid4 JsonLike = dict[str, Any] @dataclass class BatchRuntimeJob: job_id: str job_type: str question_id: str slice_window: str requested_outputs: list[str] reason: list[str] created_at: str def to_dict(self) -> JsonLike: return asdict(self) @dataclass class BatchRuntimeResult: job_id: str status: str execution_mode: str run_ids: JsonLike error_message: str | None = None def to_dict(self) -> JsonLike: return asdict(self) def enqueue_refresh_and_answer_job( *, question_id: str, slice_window: str, requested_outputs: list[str], reason: list[str], ) -> BatchRuntimeJob: return BatchRuntimeJob( job_id=uuid4().hex, job_type="refresh_and_answer", question_id=question_id, slice_window=slice_window, requested_outputs=list(requested_outputs), reason=list(reason), created_at=datetime.now(timezone.utc).isoformat(), ) def run_refresh_and_answer_job( job: BatchRuntimeJob, *, refresh_executor: Callable[[], JsonLike] | None = None, feature_executor: Callable[[], JsonLike] | None = None, risk_executor: Callable[[], JsonLike] | None = None, should_refresh: bool = False, ) -> BatchRuntimeResult: run_ids: JsonLike = {} try: if should_refresh and refresh_executor is not None: refresh_result = refresh_executor() run_ids["refresh_run_id"] = refresh_result.get("run_id") or refresh_result.get("refresh_run_id") elif should_refresh: run_ids["refresh_run_id"] = None run_ids["refresh_note"] = "refresh_requested_but_executor_missing" else: run_ids["refresh_note"] = "refresh_skipped_by_policy" if feature_executor is not None and "feature_store" in job.requested_outputs: feature_result = feature_executor() run_ids["feature_run_id"] = feature_result.get("run_id") if risk_executor is not None and "risk_store" in job.requested_outputs: risk_result = risk_executor() run_ids["risk_run_id"] = risk_result.get("run_id") return BatchRuntimeResult( job_id=job.job_id, status="success", execution_mode="batch_runtime_executed", run_ids=run_ids, ) except Exception as exc: return BatchRuntimeResult( job_id=job.job_id, status="failed", execution_mode="batch_runtime_failed", run_ids=run_ids, error_message=str(exc), )