Skip to content

JobRunStore — @gj-kit/nest-operations-jobs

A public interface from @gj-kit/nest-operations-jobs/core. The signature below is taken directly from the 0.1.1 release declaration.

import { JobRunStore } from '@gj-kit/nest-operations-jobs/core';
/**
* Persistence port for job runs. The library owns no schema; a host maps these
* five operations onto its own table.
*
* The concurrency obligations below are part of the contract, and
* `jobRunStoreContractCases()` from the `./testing` subpath checks them.
*
* - **S1 single-claimer** — for one `overlapKey` at most one `RUNNING` row exists
* at any instant. `claim` is an atomic compare-and-set, never "read, then
* insert if absent". The loser returns `null` rather than throwing. The only
* exception convertible to `null` is the overlap uniqueness violation; every
* other constraint violation, connection error or serialisation failure must
* be rethrown so the runner reports `ERR_JOB_STORE`. Implement with a
* **partial** unique index (`WHERE status = 'RUNNING'`) and narrow the caught
* violation by constraint name — swallowing every uniqueness violation turns a
* permanently blocked job into a stream of green SKIPPED responses.
* - **S2 monotonic heartbeat** — `heartbeat` advances the liveness watermark to
* the store's own current time and returns `true` only while the row is
* `RUNNING`. The watermark never moves backwards. A row that is no longer
* `RUNNING` is left untouched and answered `false`.
* - **S3 idempotent completion** — `complete` writes only on a
* `RUNNING -> terminal` transition and returns `true`. An already-settled row
* is left untouched and answered `false`. Terminal is final.
* - **S4 atomic reap** — `reapStale` transitions matching stale `RUNNING` rows to
* `TIMED_OUT` in a single statement and returns only the count it actually
* moved, so two concurrent reapers never double-count. Releasing the overlap
* key is immediate.
* - **S5 run id uniqueness** — ids returned by `claim` and `recordSkipped` are
* globally unique and immutable for the row's lifetime.
* - **S6 clock axis split** — recording instants (`startedAt`, `at`,
* `finishedAt`) come from the runner's injected clock and are stored verbatim.
* Liveness instants (the heartbeat watermark and the stale cutoff) come from
* the store's own clock only. `claim` must initialise the watermark from that
* clock; a null watermark is never reapable and would hold the overlap key
* forever.
* - **S7 input/summary round trip** — `input` and `summary` are stored as
* JSON-round-trippable values; a value that cannot be stored raises rather
* than being silently dropped.
*/
interface JobRunStore {
/** Atomically take the overlap key. `null` means another run holds it. */
claim(request: JobRunClaimRequest): Promise<JobRunClaim | null>;
/** `false` means the run is no longer RUNNING and the claim is gone. */
heartbeat(request: JobRunHeartbeatRequest): Promise<boolean>;
/** `false` means the run was already settled; the stored outcome is unchanged. */
complete(request: JobRunCompleteRequest): Promise<boolean>;
/** Record a run that never executed. Returns the new run's id. */
recordSkipped(request: JobRunSkippedRequest): Promise<JobRunClaim>;
/** Abandon stale RUNNING rows as TIMED_OUT. Returns how many this call moved. */
reapStale(request: JobRunReapRequest): Promise<number>;
}

This declaration is the source of truth for parameters, optionality, generics, return values, and public union/type contracts. Check the package golden path and this subpath’s import conditions for required environment, permission, and error boundaries before calling it.

  • Package: @gj-kit/nest-operations-jobs
  • Version: 0.1.1
  • Public entry: ./core
  • Source: GitHub