"""Low-level helper methods for experiment sync service.""" from __future__ import annotations from .shared import Any, Dict, Experiment, ExperimentTruthNodeSync, Optional, TruthNode, and_, now_cn_aware, select class ExperimentSyncHelpersMixin: """Fetchers and sync-data mutation helpers.""" async def _get_experiment(self, experiment_id: int, tenant_id: int) -> Optional[Experiment]: result = await self.db.execute( select(Experiment).where( and_(Experiment.id == experiment_id, Experiment.tenant_id == tenant_id) ) ) return result.scalar_one_or_none() async def _get_truth_node(self, truth_node_id: int, tenant_id: int) -> Optional[TruthNode]: result = await self.db.execute( select(TruthNode).where( and_(TruthNode.id == truth_node_id, TruthNode.tenant_id == tenant_id) ) ) return result.scalar_one_or_none() async def _get_sync_record(self, sync_id: int, tenant_id: int) -> Optional[ExperimentTruthNodeSync]: result = await self.db.execute( select(ExperimentTruthNodeSync).where( and_(ExperimentTruthNodeSync.id == sync_id, ExperimentTruthNodeSync.tenant_id == tenant_id) ) ) return result.scalar_one_or_none() def _calc_confidence(self, current_score: Optional[float]) -> float: score = float(current_score or 0.0) if score > 1: score /= 100.0 return round(max(0.0, min(1.0, score)), 2) def _build_sync_data( self, experiment: Experiment, truth_node: TruthNode, sync_type: str, ) -> Dict[str, Any]: return { "sync_type": sync_type, "experiment_summary": { "id": experiment.id, "title": experiment.title, "status": experiment.status, "target_metric": experiment.target_metric, "current_score": experiment.current_score, }, "previous_truth_content": truth_node.content, } async def _apply_sync_to_truth_node( self, record: ExperimentTruthNodeSync, truth_node: TruthNode, ) -> None: content = truth_node.content if isinstance(truth_node.content, dict) else {} if not isinstance(content, dict): content = {"raw": str(truth_node.content)} sync_section = content.get("experiment_sync", {}) sync_section["last_sync"] = { "sync_id": record.id, "sync_type": record.sync_type, "confidence_score": record.confidence_score, "experiment_summary": (record.sync_data or {}).get("experiment_summary", {}), "applied_at": now_cn_aware().isoformat(), } content["experiment_sync"] = sync_section truth_node.content = content truth_node.version = int(truth_node.version or 1) + 1