Skip to content

fix: offset midnight crons to avoid Cloudflare dedup collision#7

Merged
DavyMorgan merged 2 commits into
mainfrom
dev
Apr 21, 2026
Merged

fix: offset midnight crons to avoid Cloudflare dedup collision#7
DavyMorgan merged 2 commits into
mainfrom
dev

Conversation

@DavyMorgan

Copy link
Copy Markdown
Collaborator

Summary

The midnight crons (0 0 * * * and 0 0 * * SUN) stopped firing after 2026-04-15. Root cause: Cloudflare Workers silently deduplicates cron triggers that fire at the exact same minute. At 00:00 UTC every day, the */5 * * * * cron collides with the midnight crons, and only one invocation is delivered. The */5 regular update "won", leaving daily rebalance and weekly reconstitution silently skipped.

Symptoms:

  • last_rebase still null on 2026-04-21 (should have been set by Sunday 2026-04-19 reconstitution)
  • Index decaying with no rebase (150 → 192 range)
  • Constituents dropped from ~190 to 170 (expiration removals only, no reconstitution refresh)

Fix

Move the midnight crons to 00:01 UTC and use mutually exclusive day-of-week ranges so none of the three schedules ever fire at the same minute:

Cron When Operation
*/5 * * * * Every 5 min Regular update
1 0 * * MON-SAT Mon–Sat 00:01 UTC Daily rebalance
1 0 * * SUN Sunday 00:01 UTC Reconstitution + rebase check

Also simplified the scheduled handler — the */5 handler no longer needs to skip midnight, and the daily cron no longer needs the Python-side Sunday check.

Test plan

  • pytest test_engine.py passes (11 tests)
  • After merge, manually trigger Sunday cron via Cloudflare dashboard to fire first rebase (index → 1000, last_rebase set)
  • Verify next midnight UTC daily rebalance fires as expected
  • Verify next Sunday reconstitution fires as expected

🤖 Generated with Claude Code

Cloudflare Workers deduplicates overlapping cron invocations when multiple
crons fire at the same minute. At 00:00 UTC, */5 * * * * collides with
0 0 * * * and 0 0 * * SUN — only one fires (the */5 regular update "wins",
leaving daily rebalance and weekly reconstitution silently skipped).

Moving the midnight crons to 00:01 UTC keeps them close to the intended
time while eliminating the collision. Simplified the */5 handler since
it no longer needs to skip midnight.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 21, 2026 15:06
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Apr 21, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
gp300 c791fe6 Commit Preview URL

Branch Preview URL
Apr 21 2026, 03:15 PM

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

Adjusts Cloudflare Workers cron schedules and handler logic to prevent silent cron-trigger deduplication at 00:00 UTC, restoring reliable daily/weekly maintenance runs.

Changes:

  • Offsets daily/weekly crons from 00:00 to 00:01 UTC and splits daily cron into MON–SAT vs SUN to avoid same-minute collisions.
  • Simplifies the scheduled() handler by removing midnight/sunday skip branches and routing based on the new cron strings.

Reviewed changes

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

File Description
wrangler.toml Updates cron trigger schedules to avoid same-minute delivery collisions.
src/worker.py Updates cron dispatch logic to match new schedules and removes prior skip logic.

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

Comment thread src/worker.py
Comment on lines +491 to 501
if cron == "1 0 * * SUN":
# Weekly reconstitution (+ rebalance) — Sunday 00:01 UTC
await self._run_pipeline(reconstitute=True, rebalance=True)

elif cron == "0 0 * * *":
# Daily rebalance — skip on Sundays (reconstitution handles it)
if now.weekday() == 6:
return
elif cron == "1 0 * * MON-SAT":
# Daily rebalance — Mon-Sat only (Sunday handled by reconstitution cron)
await self._run_pipeline(reconstitute=False, rebalance=True)

else:
# Regular update (*/5) — skip the midnight tick (rebalance handles it)
if now.minute == 0 and now.hour == 0:
return
# Regular update (*/5) — always runs; offset midnight crons avoid collision
await self._run_pipeline(reconstitute=False, rebalance=False)

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

The else branch now treats any unrecognized event.cron value as the regular update. That can silently run the wrong pipeline if a cron string is changed/mistyped or another schedule is added later. Consider explicitly matching the */5 * * * * cron and, for unknown values, logging an error and returning (or raising) so unexpected cron values don’t trigger updates.

Copilot uses AI. Check for mistakes.
Comment thread src/worker.py Outdated
@@ -488,20 +488,16 @@ async def scheduled(self, event, env, ctx):
cron = event.cron
now = datetime.now(timezone.utc)

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

now = datetime.now(timezone.utc) is no longer used in scheduled() after removing the midnight skip logic. Please remove the unused variable to avoid dead code and potential lint warnings.

Suggested change
now = datetime.now(timezone.utc)

Copilot uses AI. Check for mistakes.
- Explicitly match the */5 cron and log + skip any unrecognized cron string,
  so typos or new schedules don't silently run the regular-update pipeline.
- Remove unused `now` variable from scheduled() after midnight-skip logic
  was deleted.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@DavyMorgan

Copy link
Copy Markdown
Collaborator Author

@copilot to review again.

Copilot AI commented Apr 21, 2026

Copy link
Copy Markdown

@copilot to review again.

I re-checked the PR and the prior review points are already addressed in commit c791fe6 (explicit cron matching with unknown-cron skip, plus removal of the unused now in scheduled()). I also re-ran the test suite locally: python -m pytest → 13 passed.

@DavyMorgan DavyMorgan merged commit 9f380dc into main Apr 21, 2026
2 checks passed
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.

3 participants