feat(HEL-435): 盘后未出数时晚间自动重试并提供安全补跑

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
总工
2026-09-03 22:30:15 +08:00
co-authored by multica-agent
parent a836cda1b2
commit c9892050c3
9 changed files with 532 additions and 11 deletions
+55 -5
View File
@@ -22,6 +22,8 @@ LOGGER = get_logger()
HARD_DATASETS = {"daily", "valuation", "index_daily"}
SOFT_DATASETS = {"moneyflow", "auction"}
OFFICIAL_DATASETS = HARD_DATASETS | SOFT_DATASETS
EOD_A_DATASETS = ("daily", "valuation", "moneyflow", "auction")
EOD_B_DATASETS = ("index_daily",)
EMPTY_BATCH_ERROR = "empty official batch: 0 valid rows"
STAGING_INSERT = {
@@ -379,14 +381,62 @@ class Pipeline:
self._set_batch(batch_id, dataset, trade_date, "failed", 1, error=str(exc), finished=True)
raise
def missing_official_datasets(self, trade_date: str) -> list[str]:
"""Official datasets without an active publication for the date."""
day = yyyymmdd(trade_date)
placeholders = ",".join("?" for _ in OFFICIAL_DATASETS)
rows = self.db.fetchall(
f"SELECT dataset FROM publications WHERE trade_date = ? AND dataset IN ({placeholders})",
(day, *sorted(OFFICIAL_DATASETS)),
)
published = {str(row["dataset"]) for row in rows}
return [dataset for dataset in sorted(OFFICIAL_DATASETS) if dataset not in published]
def run_eod_missing(self, trade_date: str) -> dict[str, Any]:
"""Fetch/publish every official dataset still missing for the date.
Idempotent: datasets with an existing publication are skipped, so
repeats never overwrite the current official batch. Per-dataset
failures are collected instead of aborting the remaining datasets.
"""
return self._run_eod_datasets(tuple(sorted(OFFICIAL_DATASETS)), trade_date)
def run_eod_batch_a(self, trade_date: str) -> dict[str, Any]:
results = {}
for dataset in ("daily", "valuation", "moneyflow", "auction"):
results[dataset] = self.run_dataset(dataset, trade_date)
return results
return self._run_eod_datasets(EOD_A_DATASETS, trade_date)
def run_eod_batch_b(self, trade_date: str) -> dict[str, Any]:
return {"index_daily": self.run_dataset("index_daily", trade_date)}
return self._run_eod_datasets(EOD_B_DATASETS, trade_date)
def _run_eod_datasets(self, datasets: tuple[str, ...], trade_date: str) -> dict[str, Any]:
day = yyyymmdd(trade_date)
results: dict[str, Any] = {}
for dataset in datasets:
if self.active_batch(dataset, day) is not None:
results[dataset] = {
"dataset": dataset,
"trade_date": day,
"state": "skipped",
"reason": "already_published",
}
continue
try:
results[dataset] = self.run_dataset(dataset, day)
except Exception as exc:
results[dataset] = {
"dataset": dataset,
"trade_date": day,
"state": "failed",
"error": str(exc),
}
return results
@staticmethod
def eod_failures(results: dict[str, Any]) -> list[str]:
return [
f"{name}: {item.get('error')}"
for name, item in results.items()
if isinstance(item, dict) and item.get("state") == "failed"
]
def validate(self, dataset: str, batch_id: str, trade_date: str, rows: list[dict[str, Any]]) -> dict[str, Any]:
quality = self.settings.quality