fix(cron): guard against year-rollback in croner nextRun (#30777)

* fix(cron): guard against year-rollback in croner nextRun

Croner can return a past-year timestamp for some timezone/date
combinations (e.g. Asia/Shanghai).  When nextRun returns a value at or
before nowMs, retry from the next whole second and, if still stale,
from midnight-tomorrow UTC before giving up.

Closes #30351

* googlechat: guard API calls with SSRF-safe fetch

* test: fix hoisted plugin context mock setup

---------

Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
Sid
2026-03-02 12:22:59 +08:00
committed by GitHub
parent 6fc0787bf0
commit 4691aab019
4 changed files with 142 additions and 85 deletions

View File

@@ -73,6 +73,16 @@ describe("cron schedule", () => {
expect(next).toBe(anchor + 30_000);
});
it("never returns a past timestamp for Asia/Shanghai daily schedule (#30351)", () => {
const nowMs = Date.parse("2026-03-01T00:00:00.000Z");
const next = computeNextRunAtMs(
{ kind: "cron", expr: "0 8 * * *", tz: "Asia/Shanghai" },
nowMs,
);
expect(next).toBeDefined();
expect(next!).toBeGreaterThan(nowMs);
});
describe("cron with specific seconds (6-field pattern)", () => {
// Pattern: fire at exactly second 0 of minute 0 of hour 12 every day
const dailyNoon = { kind: "cron" as const, expr: "0 0 12 * * *", tz: "UTC" };