Skip to content

fix(manager): ScheduleService matcher 修跨午夜 weekly tail 漏 fire#138

Open
csp0924 wants to merge 2 commits into
mainfrom
fix/schedule-cross-midnight-weekly
Open

fix(manager): ScheduleService matcher 修跨午夜 weekly tail 漏 fire#138
csp0924 wants to merge 2 commits into
mainfrom
fix/schedule-cross-midnight-weekly

Conversation

@csp0924

@csp0924 csp0924 commented May 12, 2026

Copy link
Copy Markdown
Owner

問題

Closed-loop probe 發現:matcher.matches_schedule 對 WEEKLY 跨午夜窗口判斷錯誤。matches_time 接受 start_time > end_time(跨午夜),但 weekday check 用當下 now.weekday()。例如 days_of_week=[Sunday] + 23:30-00:30,過午夜後 weekday() 已變 Monday,post-midnight tail 整段被誤判 inactive。

Sandbox 證據(sandbox/schedule_service_dst_drift_demo.py H2 scenario):61 個 polls 橫跨 Sun 23:30 → Mon 00:30、只 30 個 match(50.8% 漏 fire)。同樣 logic 也影響 ONCE rule 的 start_date / end_date post-midnight tail。

改動

  • csp_lib/manager/schedule/matcher.py:新增 _is_post_midnight_tail(rule, now_time_str) predicate;matches_schedule 加 optional now_time_str: str | None = None,post-midnight tail 時用 (now_weekday - 1) % 7 / now_date - 1 day 比對
  • csp_lib/manager/schedule/repository.pycsp_lib/manager/schedule/in_memory.py:caller 改 forward now_time
  • docs/13-Guides/Custom Repository.md:sample code 同步示範
  • 預設 now_time_str=None 保持向後相容(patch bump)

驗證

  • 新增 tests/manager/test_matcher_cross_midnight.py(WEEKLY pre/post、ONCE date range、symmetric over-correction guard、backward-compat、repository integration)
  • 全 4864 tests pass、ruff / mypy clean

跨午夜時段(start_time > end_time,如 23:30-00:30)與 WEEKLY/ONCE 規則組合時,
午夜後尾段(now_time <= end_time)的 weekday/date 在語意上應屬於前一日(起算日),
但舊版 matches_schedule 直接以呼叫當下的 now.weekday() / now.date() 比對 days_of_week
與 start_date/end_date,導致整個午夜後尾段被 silent skip(例:days_of_week=[6] Sunday
配 23:30-00:30,Mon 00:00-00:30 完全 dead)。

修法:matcher.matches_schedule 新增可選的 now_time_str 參數,偵測到跨午夜尾段時
將 now_weekday/now_date 回推一日再做型別比對。對既有呼叫端為 backward compat
(不傳 now_time_str 維持舊行為);production 端 MongoScheduleRepository 與
InMemoryScheduleRepository 已更新傳入 now_time。docs 範例同步更新。

回歸覆蓋於 tests/manager/test_matcher_cross_midnight.py:
- WEEKLY 跨午夜前/後段、對稱誤判防護
- ONCE start_date/end_date 跨午夜尾段歸屬
- backward compat: 未傳 now_time_str 維持舊行為
- 整合層:InMemoryScheduleRepository.find_active_rules 跨午夜尾段
Copilot AI review requested due to automatic review settings May 12, 2026 23:01

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

此 PR 修正 csp_lib.manager.schedule.matcher.matches_schedule 在「跨午夜(start_time > end_time)」時段的 weekday/date 歸屬判斷,避免 WEEKLY / ONCE 規則在午夜後尾段被錯誤判定為 inactive 而漏 fire;並同步更新 repository 呼叫端與補齊回歸測試。

Changes:

  • matcher.matches_schedule 新增 now_time_str(可選)並在跨午夜尾段時將 weekday/date 回推一天後再比對 WEEKLY/ONCE 條件。
  • MongoScheduleRepository / InMemoryScheduleRepository 呼叫端轉傳 now_time,讓 matcher 能判斷尾段歸屬。
  • 新增跨午夜回歸測試與更新自訂 Repository 指南範例。

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
csp_lib/manager/schedule/matcher.py 新增跨午夜尾段判斷並在 WEEKLY/ONCE 比對前回推 weekday/date。
csp_lib/manager/schedule/repository.py 轉傳 now_time 給 matcher,讓 Mongo repository 不再漏掉跨午夜尾段。
csp_lib/manager/schedule/in_memory.py 轉傳 now_time 給 matcher,讓 in-memory repository 行為與正式實作一致。
tests/manager/test_matcher_cross_midnight.py 新增 WEEKLY/ONCE 跨午夜(含對稱 guard 與整合層)回歸測試。
docs/13-Guides/Custom Repository.md 更新範例:呼叫 matches_schedule 時一併傳入 now_time

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docs/13-Guides/Custom Repository.md Outdated
if matcher.matches_time(rule, now_time)
and matcher.matches_schedule(rule, now_weekday, now_date)
# 將 now_time 一併傳入,讓 matcher 能正確處理跨午夜尾段歸屬
and matcher.matches_schedule(rule, now_weekday, now_date, now_time)
Comment thread csp_lib/manager/schedule/repository.py Outdated
continue
if not self._matches_schedule(rule, now_weekday, now_date):
# 將 now_time 一併傳入,讓 matcher 能正確處理跨午夜尾段的 weekday/date 歸屬
if not self._matches_schedule(rule, now_weekday, now_date, now_time):
Copilot review #138 建議:在 repository.py 與 docs 範例兩處呼叫 matcher.matches_schedule 時,
把第 4 個參數 now_time_str 從位置參數改為 keyword 形式,避免 signature 演進時 caller 混淆,
並讓「此參數僅用於跨午夜尾段歸屬」的意圖更顯眼。

無行為變更。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants