feat(runtime): propagate date through dispatch chain and business-date snapshot

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Misaka_Company
2026-07-29 13:10:23 +08:00
parent cda764a305
commit fcb75643d0

View File

@@ -454,14 +454,14 @@ def _web_handler(site, download_func):
焦点;交互模式置顶便于调试。顺心是 page 列表,置顶标志透传给 shunxin_download。 焦点;交互模式置顶便于调试。顺心是 page 列表,置顶标志透传给 shunxin_download。
""" """
def handler(ctx, force=False): def handler(ctx, force=False, date=None):
pg = ctx.pages_map[site] pg = ctx.pages_map[site]
if isinstance(pg, list): if isinstance(pg, list):
# 顺心双账号:置顶与否交给 shunxin_download 在逐账号循环里按 foreground 决定 # 顺心双账号:置顶与否交给 shunxin_download 在逐账号循环里按 foreground 决定
return download_func(pg, foreground=ctx.foreground, force=force) return download_func(pg, foreground=ctx.foreground, force=force, date=date)
if ctx.foreground: if ctx.foreground:
pg.bring_to_front() pg.bring_to_front()
return download_func(pg, force=force) return download_func(pg, force=force, date=date)
return handler return handler
@@ -470,11 +470,11 @@ def _site_undelivered_handler(site):
"""4 站未到:下应到+实到 → 比对写 downloads/<站>-未到数据.xlsx。 """4 站未到:下应到+实到 → 比对写 downloads/<站>-未到数据.xlsx。
任一下载失败 → 清掉旧未到文件、返回 False前端不展示陈旧未到""" 任一下载失败 → 清掉旧未到文件、返回 False前端不展示陈旧未到"""
def handler(ctx, force=False): def handler(ctx, force=False, date=None):
# 各站下载入口约定返回 True/False顺心历史返回 None视为成功与 dispatch 一致) # 各站下载入口约定返回 True/False顺心历史返回 None视为成功与 dispatch 一致)
exp_ok = TASK_HANDLERS[(site, "expected")](ctx, force) is not False exp_ok = TASK_HANDLERS[(site, "expected")](ctx, force, date) is not False
act_ok = ( act_ok = (
(TASK_HANDLERS[(site, "actual")](ctx, force) is not False) (TASK_HANDLERS[(site, "actual")](ctx, force, date) is not False)
if exp_ok if exp_ok
else False else False
) )
@@ -504,24 +504,32 @@ TASK_HANDLERS = {
("韵达", "expected"): _web_handler("韵达", yunda.yunda_expected_download), ("韵达", "expected"): _web_handler("韵达", yunda.yunda_expected_download),
("韵达", "actual"): _web_handler("韵达", yunda.yunda_actual_download), ("韵达", "actual"): _web_handler("韵达", yunda.yunda_actual_download),
("韵达", "undelivered"): _site_undelivered_handler("韵达"), ("韵达", "undelivered"): _site_undelivered_handler("韵达"),
("安能", "expected"): lambda ctx, force=False: anneng.anneng_expected_download( (
force=force "安能",
"expected",
): lambda ctx, force=False, date=None: anneng.anneng_expected_download(
force=force, date=date
), ),
("安能", "actual"): lambda ctx, force=False: anneng.anneng_actual_download( (
force=force "安能",
"actual",
): lambda ctx, force=False, date=None: anneng.anneng_actual_download(
force=force, date=date
), ),
("安能", "undelivered"): _site_undelivered_handler("安能"), ("安能", "undelivered"): _site_undelivered_handler("安能"),
("__compare__", "compare"): lambda ctx, force=False: (compare.main() or True), ("__compare__", "compare"): lambda ctx, force=False, date=None: (
compare.main() or True
),
} }
def _record_business_date(site, kind): def _record_business_date(site, kind, date=None):
"""下载成功后,把本次数据的业务日期快照写进状态库(供前端/报告显示「是哪天的数据」)。 """下载成功后,把本次数据的业务日期快照写进状态库(供前端/报告显示「是哪天的数据」)。
业务日期 = 下载当天 该数据对应的日期偏移。__compare__ 无数据概念,跳过。 有 date 用 date否则 = 下载当天 该数据对应的日期偏移。__compare__ 无数据概念,跳过。
kind → 写入: kind → 写入:
expected/actual各写自己一列(偏移各取其列) expected/actual各写自己一列。
undelivered百世直供 0)写 undelivered4 站未到由 _site_undelivered_handler undelivered百世直供当天)写 undelivered4 站未到由 _site_undelivered_handler
内部连带下了 expected+actual不经 dispatch无业务日期写入故此处一并补写 内部连带下了 expected+actual不经 dispatch无业务日期写入故此处一并补写
expected/actual/undelivered 三列——actual 用 actual 偏移、未到跟随 expected 偏移。 expected/actual/undelivered 三列——actual 用 actual 偏移、未到跟随 expected 偏移。
顺带置 ready=True让前端不必等心跳即可反映下载成功写入失败仅告警、不影响任务判定。""" 顺带置 ready=True让前端不必等心跳即可反映下载成功写入失败仅告警、不影响任务判定。"""
@@ -530,8 +538,13 @@ def _record_business_date(site, kind):
today = datetime.now().date() today = datetime.now().date()
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
def _write(k, off): def _write(k, biz_or_off):
biz = (today - timedelta(days=off)).strftime("%Y-%m-%d") # biz_or_off: int=偏移todayoffstr=已确定业务日期date
biz = (
(today - timedelta(days=biz_or_off)).strftime("%Y-%m-%d")
if isinstance(biz_or_off, int)
else biz_or_off
)
try: try:
state_store.set_data_state( state_store.set_data_state(
site, k, ready=True, generated_at=now, business_date=biz site, k, ready=True, generated_at=now, business_date=biz
@@ -539,16 +552,19 @@ def _record_business_date(site, kind):
except Exception as e: except Exception as e:
print(f">> [状态] 写业务日期失败 {site}/{k}: {e}") print(f">> [状态] 写业务日期失败 {site}/{k}: {e}")
def off(kind_key):
return state_store.get_offset(site, kind_key)
if kind == "expected": if kind == "expected":
_write("expected", state_store.get_offset(site, "expected")) _write("expected", date if date else off("expected"))
elif kind == "actual": elif kind == "actual":
_write("actual", state_store.get_offset(site, "actual")) _write("actual", date if date else off("actual"))
elif site == "百世": elif site == "百世":
_write("undelivered", 0) _write("undelivered", 0)
else: # 4 站 undelivered连带补写 expected/actual/undelivered 三列 else: # 4 站 undelivered连带补写 expected/actual/undelivered 三列
_write("expected", state_store.get_offset(site, "expected")) _write("expected", date if date else off("expected"))
_write("actual", state_store.get_offset(site, "actual")) _write("actual", date if date else off("actual"))
_write("undelivered", state_store.get_offset(site, "expected")) _write("undelivered", date if date else off("expected"))
def _persist_to_db(site, kind): def _persist_to_db(site, kind):
@@ -600,10 +616,10 @@ def dispatch_task(ctx, task_spec):
if handler is None: if handler is None:
return (state_store.TASK_FAILED, f"未知任务: {site}/{kind}") return (state_store.TASK_FAILED, f"未知任务: {site}/{kind}")
try: try:
ret = handler(ctx, bool(task_spec.get("force", False))) ret = handler(ctx, bool(task_spec.get("force", False)), task_spec.get("date"))
if ret is False: if ret is False:
return (state_store.TASK_FAILED, "任务执行失败(重试耗尽)") return (state_store.TASK_FAILED, "任务执行失败(重试耗尽)")
_record_business_date(site, kind) _record_business_date(site, kind, task_spec.get("date"))
_persist_to_db(site, kind) _persist_to_db(site, kind)
return (state_store.TASK_SUCCESS, None) return (state_store.TASK_SUCCESS, None)
except Exception as e: except Exception as e: