5.4 KiB
5.4 KiB
Tasks: enterprise-server-job-scheduler
Change ID: enterprise-server-job-scheduler
Package: @suaveplan/job-scheduler
Target path: packages/control-flow/job-scheduler
Prerequisites on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/events, @suaveplan/retry, @suaveplan/logger, @suaveplan/cron
Amended 2026-05-11: Cron parsing extracted to
@suaveplan/cron. Task §3 is replaced by a thin consumer wrapper; the bundled cron-parser is removed.
Amended 2026-05-12: Implemented at the genesis-canonical path
packages/control-flow/job-scheduler/(universal-tier control-flow primitive). The proposal'sserver/infra/job-schedulerpath was pre-reorg; flat layout per cron-sibling convention used here.
1. Scaffold
- Create directory tree (flat layout mirroring
@suaveplan/cron). package.jsonat0.1.0,"sideEffects": false, exports.+ per-feature subpaths.- Deps: workspace + catalog deps (incl.
@suaveplan/cron workspace:^). - DevDeps:
vitest,@vitest/coverage-istanbul,fast-check,@suaveplan/testing. tsconfig.lib.jsonextendingtsconfig.base.json(universal tier — nolibrary-node.json).vitest.config.tsstandalone with istanbul + 100% thresholds.- Scripts:
lint,typecheck,test,test:coverage,build,docs:check.
2. Types and errors
- All interfaces in
src/scheduler/job-scheduler.types.ts; Zod schemas insrc/scheduler/job-scheduler.schemas.ts. - Sibling
.mddocs ≥200 words per impl file. src/errors/job-scheduler-error.ts: three codes (JOB_NOT_FOUND,EXECUTION_FAILED,TIMEOUT);registerJobSchedulerErrorCodes(); eager call. Cron parse failures propagate asCRON.*codes from@suaveplan/cron.
3. Cron integration
- Consume
@suaveplan/cron:parseCron,CronExpression. No local cron-parser module. - In
schedule(cronExpr, handler, options): callparseCron(cronExpr); store the returnedCronExpression; compute first + every subsequent fire viaexpression.nextRun(clock.now(), tz). - Honour
CRON.NEXT_RUN_NOT_FOUND: drop the job after emittingjob:scheduling_exhaustedand incrementingjob_scheduler.cron_exhausted_total. Implemented insrc/scheduler/cron-rescheduler.ts.
4. Job queue
src/queue/job-queue.ts: array-backed binary min-heap byrunAt;enqueue/dequeue/peek/size/remove(jobId)/snapshot.src/queue/job-queue.test.ts: priority order, head/tail/mid removal, empty edge cases, large randomised sequence.src/queue/job-queue.md≥200 words.- Property-tested in
tests/property.test.ts(monotonic dequeue, remove-all-leaves-empty, sorted-output).
5. Job scheduler
src/scheduler/job-scheduler.ts:JobScheduler+createJobScheduler. Tick loop driven by injectedtimers.start/stop/schedule/queue/cancel/pause/resume/jobs.src/scheduler/job-dispatcher.ts: per-job dispatch + bookkeeping (separated so scheduler core stays <300 lines).src/execution/job-execution.ts: per-attempt retry/timeout/abort/event surface.src/scheduler/cron-rescheduler.ts: cron-next-fire + catchup-missed branching.src/scheduler/job-snapshot.ts:JobStatusprojection.src/scheduler/job-scheduler.test.ts+src/scheduler/job-scheduler-edge.test.ts(split for ≤500-line cap): covers immediate queue execution, cron scheduling, concurrency cap, cancel-during-run, retry, catchup, pause/resume, lifecycle idempotency.- Sibling
.mdper impl file (≥200 words, all 6 sections). - Events emitted via
EventBusLikefrom@suaveplan/types:job:start,job:complete,job:fail,job:scheduling_exhausted,job:paused,job:resumed,job:cancelled.JOB_SCHEDULER_EVENTSregistry insrc/events/events.ts. - OTel surface in
src/otel/job-scheduler-otel.ts:duration_mshistogram,runs_totalcounter,failures_totalcounter,cron_exhausted_totalcounter,queue_depthhistogram. Closedoutcome ∈ {success,error,timeout}andkind ∈ {cron,queued}labels.
6. Registry
src/registry/job-registry.ts:register/unregister/resolve/list; duplicate-name throwsJOB_SCHEDULER.JOB_NOT_FOUND.- Sibling
.md≥200 words.
7. Integration + property tests
tests/integration.test.ts: three cron jobs over 10 simulated minutes (every-1m, every-2m, every-5m) with expected counts 10/5/2;stop()drains a slow handler.tests/property.test.ts(fast-check): monotonic dequeue, enqueue+remove-all leaves empty, sorted-output property.
8. Docs + verify
- Root
README.md: quick-start, queued example, retries+timeout, FakeClock recipe, API table, relationship to@suaveplan/cron, events list, observability list. bunx turbo lint --filter=@suaveplan/job-scheduler— green.bunx turbo typecheck --filter=@suaveplan/job-scheduler— green.bunx turbo test --filter=@suaveplan/job-scheduler— 96 tests pass.bunx turbo test:coverage --filter=@suaveplan/job-scheduler— 100% statements/branches/functions/lines.bun run docs:check— 10/10 files at ≥200 words.bun scripts/publish.ts --package @suaveplan/job-scheduler(deferred to maintainer).- Update
CLAUDE.mdandMANIFEST.md(deferred to maintainer). - Archive to
openspec/archive/2026-05-12-enterprise-server-job-scheduler/(deferred to maintainer).