Skip to content

[refactor][P2] timex/cron WrapSchedule 破坏 Schedule 的零值哨兵契约——不可满足表达式经包装后从「放弃」变成「过去时刻热循环」 #383

Closed

Description

@zy84338719

来源:2026-11-11 全矩阵深度代码审查(6 路并行扫描约 24 万行 Go)。判定已复核;行号基于 2026-11-11 的 main,动手前请核对现场。
归档索引:#372(本仓重构 backlog)

位置

pkg/timex/cron/cron.go:517-519(对照 :142-149、:157-166,已人工复核)

证据

func (w WrapSchedule) Next(t time.Time) time.Time {
    return w.Schedule.Next(t).Add(w.Delay)   // 零值也 Add
}

SpecSchedule.Next 契约明文「返回值保证严格晚于入参(除非返回零值 time.Time 表示放弃)」,并警告「调用方消费 Next 前应判 IsZero」;但包装器对零值直接 Add——time.Time{}.Add(delay) 是公元 1 年 + delay 的非零具体时刻。0 0 31 2 *(2 月永无 31 日,#185 记录的形态)包一层 WrapSchedule 后:消费方 IsZero 判定失效,time.Until 为极大负值 → 立即触发、prev 停在远古 → SpecSchedule.next 再从远古扫 5 年 → 调度器热转。哨兵语义只覆盖了内层,组合子把它漏掉了。

建议

WrapSchedule.Next 对 next.IsZero() 短路直返零值(哨兵穿透包装器);同检 DelaySchedule/RandomDelaySchedule 是否需要同样约定并在 Next 的 godoc 写明零值穿透契约,用例钉住「不可满足 spec + Wrap → 仍返回零值」。

Activity

  1. moved this from Todo to In Progress in oekit Issue 大盘on Nov 12, 2026
  2. added a commit that references this issue on Nov 12, 2026
  3. moved this from In Progress to Done in oekit Issue 大盘on Nov 12, 2026
  4. zy84338719 commented on Nov 12, 2026

    @zy84338719
    ContributorAuthor

    已合入修复 ✅(无 SemVer 发布:本次改动不发版本)

    变更内容

    WrapSchedule.Next 零值哨兵穿透——不可满足表达式经包装后仍返回零值 time.Time,热循环消除

    合入:PR #421(https://github.com/oekit/pkg/pull/421),merge commit 63917515,2026-11-12T17:10:03Z

    CI:link ✅ / Lint & Test / Test ✅ / Lint & Test / Lint ✅ / Zero Third-Party Deps ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    refactor重构机会(代码审查产出)

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions