fix(queue): phase-spread the scheduled cron enqueue (#1948) - #1952
Conversation
The self-host cron flushed every due scheduled job with run_after=now in one Promise.all, so the top-of-hour (and top-of-6h) tick fanned out the hourly singletons, the 30-min set, and all six heavy full-sync parents in the same 2-min slot; their per-repo children then piled on together, draining the shared GitHub REST bucket and tripping the secondary rate limit. Give each scheduled job type a stable deterministic slot across a jitter window (reusing deterministicJitterMs) so the maintenance fan-out rolls out over minutes. The per-repo children inherit the offset because their index stagger is relative to when the parent runs. The every-tick sweep and its Orb-relay retry stay immediate. The enqueued job set is byte-identical; only run_after timing changes. Window is tunable via SCHEDULED_ENQUEUE_JITTER_MS.
|
Tip 🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩 ✅ Gittensory review result - approve/merge recommendedReview updated: 2026-07-01 04:14:27 UTC
✅ Suggested Action - Approve/Merge
Review summary Nits — 5 non-blocking
Review context
Contributor next steps
Signal definitions
🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1952 +/- ##
=======================================
Coverage 95.61% 95.61%
=======================================
Files 218 218
Lines 24298 24305 +7
Branches 8816 8818 +2
=======================================
+ Hits 23232 23239 +7
Misses 436 436
Partials 630 630
🚀 New features to boost your workflow:
|
Summary
The self-host cron flushed every due scheduled job with
run_after = nowin onePromise.all(src/index.ts), so at the top of the hour — and especially the top of every 6th hour — the hourly singletons, the 30-min set, and all six heavy full-sync fan-out parents became due in the same 2-min slot. Their per-repo children then piled on together, draining the shared GitHub REST bucket and tripping GitHub's secondary (burst) rate limit, which parked the queue.This phase-spreads the enqueue: each scheduled job type gets a stable, deterministic slot across a jitter window (reusing the existing
deterministicJitterMshelper), so the maintenance fan-out rolls out over minutes instead of firing in one instant. The per-repo children each parent fans out inherit the offset for free, since their own index-stagger is relative to when the parent runs. The every-tick priority jobs — the re-gate sweep and its Orb-relay retry, which drive timely merges/closes — stay immediate. The enqueued set of jobs is byte-identical; onlyrun_aftertiming changes.Advances #1948 (the phase-spread deliverable; extending maintenance-headroom backpressure to every fan-out type and fixing the per-repo
min(index*step, cap)tail clamp remain as follow-ups). Root cause and the full audit backlog are on #1936.SCHEDULED_ENQUEUE_JITTER_MS(default 5 min) makes the window operator-tunable, matching the existingQUEUE_*_JITTER_MSknobs.Scope
type(scope): short summaryConventional Commit format.CONTRIBUTING.mdand does not reintroduce GitHub Pages, VitePress,site/, orCNAME.Validation
git diff --checknpm run typechecknpm run test:coveragelocally — the changed lines and branches insrc/index.ts(the jittered enqueue ternary) andsrc/selfhost/queue-common.ts(scheduledEnqueueJitterMs/scheduledEnqueueDelaySeconds) are fully covered (both the immediate → no-delay and jittered → delayed sides).npm run test:ci(actionlint, db:migrations:check, typecheck, coverage, workers, mcp, ui:*)npm audit --audit-level=moderate— 0 vulnerabilitiesIf any required check was skipped, explain why:
ui:openapi/cf-typegen/ migration regen: this is a backend-only change with no API/schema, no Cloudflare binding (the new knob is read fromprocess.env, matching the siblingQUEUE_*_JITTER_MShelpers), and no DB change.Safety
Notes
jobCoalesceKey), backpressure gating, and terminal-state guards all behave exactly as before — a job delayed within the window is still deduped against the next tick's copy. Onlyrun_aftermoves.src/index.ts+src/selfhost/queue-common.tsand does not touch the guardedsrc/queue/**fan-out code; jittering the parents is sufficient to de-collide their children.