添加环境变量映射,支持完整性检查任务和工具类任务的执行
This commit is contained in:
@@ -129,6 +129,13 @@ class ETLScheduler:
|
||||
# ------------------------------------------------------------------ internals
|
||||
def _run_single_task(self, task_code: str, run_uuid: str, store_id: int):
|
||||
"""单个任务的抓取/清洗编排。"""
|
||||
task_code_upper = task_code.upper()
|
||||
|
||||
# 工具类任务:直接执行,不记录 cursor/run
|
||||
if task_code_upper in self.NO_DB_CONFIG_TASKS:
|
||||
self._run_utility_task(task_code_upper, store_id)
|
||||
return
|
||||
|
||||
task_cfg = self._load_task_config(task_code, store_id)
|
||||
if not task_cfg:
|
||||
self.logger.warning("任务 %s 未启用或不存在", task_code)
|
||||
@@ -183,6 +190,7 @@ class ETLScheduler:
|
||||
window_end=window.get("end"),
|
||||
run_id=run_id,
|
||||
)
|
||||
self._maybe_run_integrity_check(task_code, window)
|
||||
return
|
||||
|
||||
if self._flow_includes_fetch():
|
||||
@@ -221,6 +229,7 @@ class ETLScheduler:
|
||||
window_end=window.get("end"),
|
||||
run_id=run_id,
|
||||
)
|
||||
self._maybe_run_integrity_check(task_code, window)
|
||||
|
||||
except Exception as exc: # noqa: BLE001
|
||||
self.run_tracker.update_run(
|
||||
@@ -322,6 +331,53 @@ class ETLScheduler:
|
||||
def _flow_includes_ingest(self) -> bool:
|
||||
return self.pipeline_flow in {"INGEST_ONLY", "FULL"}
|
||||
|
||||
# 不需要数据库配置即可运行的任务(工具类/初始化类)
|
||||
NO_DB_CONFIG_TASKS = {
|
||||
# Schema 初始化任务
|
||||
"INIT_ODS_SCHEMA",
|
||||
"INIT_DWD_SCHEMA",
|
||||
"INIT_DWS_SCHEMA",
|
||||
# 质量检查任务
|
||||
"DATA_INTEGRITY_CHECK",
|
||||
"DWD_QUALITY_CHECK",
|
||||
# 工具任务
|
||||
"CHECK_CUTOFF",
|
||||
"MANUAL_INGEST",
|
||||
"ODS_JSON_ARCHIVE",
|
||||
# DWS 汇总任务
|
||||
"DWS_BUILD_ORDER_SUMMARY",
|
||||
}
|
||||
|
||||
def _run_utility_task(self, task_code: str, store_id: int):
|
||||
"""
|
||||
执行工具类任务(不记录 cursor/run,直接执行)。
|
||||
这些任务不需要游标管理和运行跟踪。
|
||||
"""
|
||||
self.logger.info("%s: 开始执行工具类任务", task_code)
|
||||
|
||||
try:
|
||||
# 创建任务实例(不需要 API client,使用 None)
|
||||
task = self.task_registry.create_task(
|
||||
task_code, self.config, self.db_ops, None, self.logger
|
||||
)
|
||||
|
||||
# 执行任务(工具类任务通常不需要 cursor_data)
|
||||
result = task.execute(None)
|
||||
|
||||
status = (result.get("status") or "").upper() if isinstance(result, dict) else "SUCCESS"
|
||||
if status == "SUCCESS":
|
||||
self.logger.info("%s: 工具类任务执行成功", task_code)
|
||||
if isinstance(result, dict):
|
||||
counts = result.get("counts", {})
|
||||
if counts:
|
||||
self.logger.info("%s: 结果统计: %s", task_code, counts)
|
||||
else:
|
||||
self.logger.warning("%s: 工具类任务执行结果: %s", task_code, status)
|
||||
|
||||
except Exception as exc:
|
||||
self.logger.error("%s: 工具类任务执行失败: %s", task_code, exc, exc_info=True)
|
||||
raise
|
||||
|
||||
def _load_task_config(self, task_code: str, store_id: int) -> dict | None:
|
||||
"""从数据库加载任务配置。"""
|
||||
sql = """
|
||||
@@ -334,6 +390,45 @@ class ETLScheduler:
|
||||
rows = self.db_conn.query(sql, (store_id, task_code))
|
||||
return rows[0] if rows else None
|
||||
|
||||
def _maybe_run_integrity_check(self, task_code: str, window: dict | None) -> None:
|
||||
if not self.config.get("integrity.auto_check", False):
|
||||
return
|
||||
if str(task_code or "").upper() != "DWD_LOAD_FROM_ODS":
|
||||
return
|
||||
if not isinstance(window, dict):
|
||||
return
|
||||
window_start = window.get("start")
|
||||
window_end = window.get("end")
|
||||
if not window_start or not window_end:
|
||||
return
|
||||
|
||||
try:
|
||||
from quality.integrity_checker import IntegrityWindow, run_integrity_window
|
||||
|
||||
include_dimensions = bool(self.config.get("integrity.include_dimensions", False))
|
||||
task_codes = str(self.config.get("integrity.ods_task_codes", "") or "").strip()
|
||||
report = run_integrity_window(
|
||||
cfg=self.config,
|
||||
window=IntegrityWindow(
|
||||
start=window_start,
|
||||
end=window_end,
|
||||
label="etl_window",
|
||||
granularity="window",
|
||||
),
|
||||
include_dimensions=include_dimensions,
|
||||
task_codes=task_codes,
|
||||
logger=self.logger,
|
||||
write_report=True,
|
||||
)
|
||||
self.logger.info(
|
||||
"Integrity check done: report=%s missing=%s errors=%s",
|
||||
report.get("report_path"),
|
||||
report.get("api_to_ods", {}).get("total_missing"),
|
||||
report.get("api_to_ods", {}).get("total_errors"),
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
self.logger.warning("Integrity check failed: %s", exc, exc_info=True)
|
||||
|
||||
def close(self):
|
||||
"""关闭连接。"""
|
||||
self.db_conn.close()
|
||||
|
||||
Reference in New Issue
Block a user