Skip to content

Job System

Praxrr runs background work through a SQLite-backed job queue and a timer-driven job dispatcher. Handlers register via side-effect imports; scheduling lives in schedule.ts and is separate from sync-module trigger logic in $sync/processor.ts.

Jobs are stored in the app database (job_queue table) via jobQueueQueries:

Field Purpose
jobType Discriminator for handler lookup
runAt ISO timestamp when the job becomes due
payload Typed JSON per job type
source schedule, manual, or system
dedupeKey Prevents duplicate scheduled jobs for the same logical work
cooldownUntil Optional cooldown passed through on reschedule
status queued, running, success, failed, cancelled

Run history is recorded in job_run_history for debugging and UI display.

Defined in queueTypes.ts:

Type Typical payload
arr.sync.qualityProfiles { instanceId }
arr.sync.delayProfiles { instanceId }
arr.sync.mediaManagement { instanceId }
arr.sync.metadataProfiles { instanceId }
arr.sync { instanceId, sections? } (legacy combined)
arr.pull.startup { enqueuedAt? }
arr.upgrade { instanceId }
arr.rename { instanceId }
pcd.sync { databaseId }
trashguide.sync { sourceId, trigger }
backup.create / backup.cleanup {}
logs.cleanup {}
config-health.snapshot {}
config-health.cleanup {}

config-health.snapshot runs a chunked, instance-ordered sweep of enabled sync-capable Arr instances. It scores each instance and appends the report to config_health_snapshots. Scheduled sweeps persist their cursor between chunks and schedule the next interval after the terminal chunk; a manual run does not make itself recurring.

Snapshot insertion is the primary-operation boundary. Only after the insert succeeds does the handler read the adjacent persisted predecessor and evaluate a possible health.degraded event. Assessment, state claim or re-arm, rendering, notification manager, provider, history, and secondary logging failures are contained by that post-insert boundary. They do not undo the snapshot, fail sibling instances, change sweep progress, or activate the snapshot handler’s failure backoff.

config-health.cleanup prunes snapshots by retention age and then caps the rows that remain. The scheduled job recurs daily; a manual run performs one cleanup only. Both Config Health jobs cancel when Config Health scoring is disabled.

JobDispatcher in dispatcher.ts:

  1. Queries the next queued job and sets a timer for runAt
  2. On wake, claims due jobs in a loop (claimNextDue)
  3. Looks up the handler in jobQueueRegistry
  4. Executes the handler and records run history
  5. On rescheduleAt in the handler result, reschedules instead of marking finished

There is no central retry policy — handlers return rescheduleAt and optional cooldownUntil when they want deferred retry.

Handlers self-register when imported. dispatcher.ts imports ./handlers/index.ts, which side-effect imports:

  • arrSync.ts, arrPullStartup.ts, arrUpgrade.ts, arrRename.ts
  • pcdSync.ts, trashGuideSync.ts
  • backupCreate.ts, backupCleanup.ts, logsCleanup.ts

Adding a job type requires a handler file, registry entry, and queue type definition.

schedule.ts functions upsert scheduled jobs with dedupe keys such as arr.sync.qualityProfiles:{instanceId} or pcd.sync:{databaseId}. Cron-based Arr sync schedules read sync config from arrSyncQueries and compute next run times.

scheduleAllJobs() runs during initializeJobs() after recovering interrupted running jobs back to queued.

initializeJobs() in init.ts:

  1. jobQueueQueries.recoverRunning() — reset stuck running jobs
  2. scheduleAllJobs() — refresh scheduled work for instances and databases
  3. jobDispatcher.start() — begin the claim loop

Sync execution is triggered by arr.sync.* jobs and by direct calls from triggerSyncs() after PCD pulls or changes. Sync scheduling in $sync/ evaluates cron triggers and enqueues jobs — do not conflate that module with jobs/schedule.ts persistence mechanics.

  • packages/praxrr-app/src/lib/server/jobs/dispatcher.ts
  • packages/praxrr-app/src/lib/server/jobs/init.ts
  • packages/praxrr-app/src/lib/server/jobs/schedule.ts
  • packages/praxrr-app/src/lib/server/jobs/queueTypes.ts
  • packages/praxrr-app/src/lib/server/jobs/handlers/
  • packages/praxrr-app/src/lib/server/jobs/handlers/configHealthSnapshot.ts
  • packages/praxrr-app/src/lib/server/jobs/handlers/configHealthCleanup.ts