ADR 0002: Schedule background work with Quartz.NET, not Noundry.Jobs
- Status: Accepted, 2026-08-28
Context
Section titled “Context”Noundry.Jobs was considered for Bookend’s pipeline and housekeeping jobs. Version 1.0.0 is a helper library for standalone job scripts (JobsDb, JobsEmail, JobsFile, JobsApi conveniences for one-shot console programs). It provides no scheduler, no persistent queue, no retry or backoff and no worker model. Bookend needs durable, chained pipeline stages that survive restarts (queue and resume while the inference service is unavailable), cron-style housekeeping (watch-folder scan, document retention sweep, metering heartbeat, nightly evidence chain verifier) and misfire handling.
Decision
Section titled “Decision”Use Quartz.NET (Quartz, Quartz.Extensions.Hosting, Quartz.Serialization.SystemTextJson) hosted inside the api container with the ADO.NET persistent job store on the application’s database (PostgreSQL or SQL Server), clustered mode off (single node), misfire policy “fire now”. Quartz’s official DDL for each dialect ships as db/<dialect>/004_quartz.sql and is applied by the migrator like every other script; Quartz never executes application SQL and owns only its qrtz_* tables.
Pipeline stages are individual durable jobs chained by a stage runner; failures reschedule with exponential backoff and are surfaced through GET /v1/loans/{ref}/pipeline, whose stage status is derived from the loan’s evidence events.
Noundry.Jobs is not referenced anywhere in the solution.
Consequences
Section titled “Consequences”- One library-owned table set in the schema (
qrtz_*), granted to the application principal in002_grants.sql. - Job state is inspectable with standard Quartz tooling and survives container restarts without any in-memory queue.
- The
apiimage carries the scheduler; scaling out would require enabling Quartz clustering, which is outside the current single-node deployment target.