feat: add an interval scheduler for auto scan and sync#67
Merged
Conversation
Scan and sync were only triggerable manually (#53). Adds an internal cron + table model so the product does background work. - Schema: DirectoryConnection.autoSyncIntervalMinutes (per connection) and Company.scanIntervalMinutes + lastScanAt (per company), with a migration. null disables; values are integers >= 5 minutes. - lib/scheduler.runDueSchedules: enqueues a SyncJob for every connection whose interval has elapsed (SCIM excluded, it is push-based), starts a scan for every due company that has providers configured (lastScanAt stamped up front), then drains the sync queue. - POST /api/cron: tick endpoint authenticated with CRON_SECRET (timing-safe), meant to be hit by an external cron. Returns 503 when unconfigured. - Config endpoints: PATCH /api/directory/:id (auto-sync interval, SCIM rejected) and PATCH /api/company (scan interval), both admin + scoped. - docs/scheduler.md and CRON_SECRET in .env.example. - Unit tests for isDue, runDueSchedules, the cron auth, and both config endpoints. Closes #53
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.
What
Adds interval-based scheduling so exposure scans and directory syncs run in the background, not only on manual POST. Closes #53.
Design
"Internal cron + table", no dedicated worker and no heavy dependency: schedule state lives in the DB and a single tick endpoint advances it; an external cron calls the endpoint.
How
DirectoryConnection.autoSyncIntervalMinutes(per connection),Company.scanIntervalMinutes+lastScanAt(per company).nulldisables; values are integers ≥ 5 minutes. Migration included.lib/scheduler.runDueSchedules: enqueues aSyncJobfor each connection whose interval has elapsed (SCIM excluded, it is push-based), starts a scan for each due company that has providers configured (lastScanAtstamped up front to avoid double-trigger), then drains the sync queue viaprocessSyncJobs(Move sync out of the request cycle: jobs + retry #54 retry/backoff).POST /api/cron: tick endpoint,CRON_SECRETbearer (timing-safe compare), 503 when unconfigured. Seedocs/scheduler.mdfor cron setup.PATCH /api/directory/:id(auto-sync interval, rejects SCIM) andPATCH /api/company(scan interval), both admin + company-scoped.Tests
isDue,runDueSchedules(due/not-due enqueue, scan only with providers, queue drain), cron auth (503/401/200), and both config endpoints (validation, scoping, SCIM rejection, null disable).Notes
prisma validatepasses, client generates.prisma migrate deployon deploy.Closes #53
🤖 Generated with Claude Code