fix(scheduler): drop cross-task mutex, quiet window + retry
Incident: evening full snapshot could be recorded as ok with already_completed/elapsed=0 after mutual skip with hourly sync, then next_run jumped to the next day. - Full-site snapshot never skips because another task is running - 23:00-01:00 Asia/Shanghai: defer discovery / snapshot_recent / candidate_cleanup to after 01:00; fans never defers - Skip records ok=false + skipped=true (not success / not completed) - Skip/fail reschedule soon (~5m); daily success still next snapshot_at - TaskControl return value drives next_run; system UI shows skip fields
This commit is contained in:
1 parent
39378c65b2
commit
9969e65202
10 files changed
+411
-84
No files matched your search
@@ -57,3 +57,39 @@ def day_bounds(date: str) -> tuple[float, float]:
|
||||
raise ValueError(f"日期格式必须是 YYYY-MM-DD: {date!r}")
|
||||
start = datetime.strptime(date, "%Y-%m-%d").replace(tzinfo=SHANGHAI_TZ)
|
||||
return start.timestamp(), (start + timedelta(days=1)).timestamp()
|
||||
|
||||
|
||||
# 全站快照静默窗:上海时区 [23:00, 01:00)。此间 discovery / recent / cleanup 不执行。
|
||||
SNAPSHOT_QUIET_START_HOUR = 23
|
||||
SNAPSHOT_QUIET_END_HOUR = 1
|
||||
|
||||
|
||||
def in_snapshot_quiet_window(ts: float | None = None) -> bool:
|
||||
"""是否处于全站快照静默窗 [23:00, 01:00)(上海时区,跨日)。"""
|
||||
dt = shanghai_datetime(ts)
|
||||
return dt.hour >= SNAPSHOT_QUIET_START_HOUR or dt.hour < SNAPSHOT_QUIET_END_HOUR
|
||||
|
||||
|
||||
def next_after_snapshot_quiet_window(ts: float) -> float:
|
||||
"""若 ``ts`` 落在静默窗内,推到窗结束后的 01:00;否则原样返回。"""
|
||||
if not in_snapshot_quiet_window(ts):
|
||||
return ts
|
||||
dt = shanghai_datetime(ts)
|
||||
if dt.hour >= SNAPSHOT_QUIET_START_HOUR:
|
||||
target = (dt + timedelta(days=1)).replace(
|
||||
hour=SNAPSHOT_QUIET_END_HOUR, minute=0, second=0, microsecond=0,
|
||||
)
|
||||
else:
|
||||
target = dt.replace(
|
||||
hour=SNAPSHOT_QUIET_END_HOUR, minute=0, second=0, microsecond=0,
|
||||
)
|
||||
if target.timestamp() <= ts:
|
||||
target += timedelta(days=1)
|
||||
return target.timestamp()
|
||||
|
||||
|
||||
def interval_next_run(now: float, interval: float) -> float:
|
||||
"""``now + interval``,若落入静默窗则推到 01:00 之后。"""
|
||||
if interval <= 0:
|
||||
raise ValueError("interval 必须大于 0")
|
||||
return next_after_snapshot_quiet_window(now + interval)
|
||||
Reference in new issue
Block a user