feat: distributed job scheduler with lease-based worker claiming (Closes #123) - #149
Merged
elizabetheonoja-art merged 2 commits intoAug 29, 2026
Conversation
…ming Replace the single-flight queue processor with a distributed job scheduler (jobScheduler.ts) in which multiple workers claim due webhook jobs under short-lived leases. Lease fencing prevents concurrent workers/replicas from double-delivering the same job, heartbeat renewal keeps healthy long-running deliveries from being stolen, and expired leases are reclaimed by other workers for crash recovery (at-least-once on failure). Worker count is configurable via WEBHOOK_WORKER_COUNT, scheduler metrics are exposed via /metrics, and architecture/deployment/runbook docs are updated. Closes Utility-Protocol#123
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements Issue #123 — Distributed Job Scheduler with Lease-based Worker Claiming for the webhook delivery service.
The previous queue processor used a single in-process
isProcessingflag, which both limits delivery concurrency and cannot protect against duplicate delivery when the service runs multiple replicas/workers. This change replaces it with a distributed job scheduler where workers claim due jobs under short-lived leases: a lease-holding worker is the only one allowed to execute a job, so concurrent workers and replicas can never double-deliver the same webhook.Changes
New:
webhook-delivery-service/src/jobScheduler.tsLeaseStore— shared lease registry.claim()is synchronous (atomic within the event loop, serialisable against a shared store like Redis/etcd across processes) and each lease carries a monotonic fencing token. Renew/release are owner-checked.JobScheduler— runsworkerCountworker loops that poll for due jobs and claim them:submit({ id, runAt, execute, onError })registers a unit of work.ctx.reschedule(runAt)returns a job to the claimable pool at a future time — used for the webhook exponential-backoff retries.stop(),clear(), and status helpers for dashboards.Delivery integration (
delivery.ts)WEBHOOK_WORKER_COUNTfor horizontal scaling.getSchedulerStatus()exposes workers / pending count / active leases and is surfaced onGET /health.Metrics (
metrics.ts)webhook_scheduler_workers_currentwebhook_scheduler_active_leases_currentwebhook_scheduler_jobs_submitted_totalwebhook_scheduler_jobs_processed_totalwebhook_scheduler_jobs_failed_totalwebhook_scheduler_lease_reclaimed_total(crash-recovery events)Tests
tests/jobScheduler.test.ts— 15 tests covering lease store semantics (claim/take/reclaim/renew/release), exactly-once execution under competing workers, work distribution, delayed start, rescheduling, heartbeat anti-theft, expired-lease reclaim,clear(),onError, andstop().tests/webhook.test.ts— 4 integration tests proving deliveries complete exactly once under multiple workers and lease fencing prevents double execution.Docs
Updated
WEBHOOK_ARCHITECTURE.md(scheduler design section + metrics),WEBHOOK_DEPLOYMENT.md(worker concurrency / scaling),WEBHOOK_RUNBOOK.md(scheduler diagnostics and tuning), and the rootREADME.md.Verification
tsc --noEmitpasses.jobScheduler.tsat ~96% line coverage.Closes #123