JobRunStore — @gj-kit/nest-operations-jobs
@gj-kit/nest-operations-jobs에서 공개하는 interface입니다. package version 0.1.1의 release declaration을 그대로 표시합니다.
검증된 import 예제
섹션 제목: “검증된 import 예제”import { JobRunStore } from '@gj-kit/nest-operations-jobs';시그니처, 매개변수, 반환 타입
섹션 제목: “시그니처, 매개변수, 반환 타입”/** * 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>;}이 선언은 매개변수, optionality, 제네릭, 반환값, 공개 union/type 계약의 정본입니다. 호출 전 필요한 환경·권한·오류 경계는 패키지 Golden path와 이 subpath의 import 조건을 함께 확인하세요.
Release context
섹션 제목: “Release context”- 패키지:
@gj-kit/nest-operations-jobs - 버전:
0.1.1 - 공개 entry:
. - 소스: GitHub
구현 주석
섹션 제목: “구현 주석”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
overlapKeyat most oneRUNNINGrow exists at any instant.claimis an atomic compare-and-set, never “read, then insert if absent”. The loser returnsnullrather than throwing. The only exception convertible tonullis the overlap uniqueness violation; every other constraint violation, connection error or serialisation failure must be rethrown so the runner reportsERR_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 —
heartbeatadvances the liveness watermark to the store’s own current time and returnstrueonly while the row isRUNNING. The watermark never moves backwards. A row that is no longerRUNNINGis left untouched and answeredfalse. - S3 idempotent completion —
completewrites only on aRUNNING -> terminaltransition and returnstrue. An already-settled row is left untouched and answeredfalse. Terminal is final. - S4 atomic reap —
reapStaletransitions matching staleRUNNINGrows toTIMED_OUTin 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
claimandrecordSkippedare 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.claimmust initialise the watermark from that clock; a null watermark is never reapable and would hold the overlap key forever. - S7 input/summary round trip —
inputandsummaryare stored as JSON-round-trippable values; a value that cannot be stored raises rather than being silently dropped.