adispatchd 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +195 -2
- package/dist/api/errors.d.ts +27 -0
- package/dist/api/errors.js +80 -0
- package/dist/api/errors.js.map +1 -0
- package/dist/api/index.d.ts +10 -0
- package/dist/api/index.js +11 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/logs.d.ts +30 -0
- package/dist/api/logs.js +88 -0
- package/dist/api/logs.js.map +1 -0
- package/dist/api/serialize.d.ts +65 -0
- package/dist/api/serialize.js +135 -0
- package/dist/api/serialize.js.map +1 -0
- package/dist/api/server.d.ts +89 -0
- package/dist/api/server.js +751 -0
- package/dist/api/server.js.map +1 -0
- package/dist/api/sse.d.ts +90 -0
- package/dist/api/sse.js +225 -0
- package/dist/api/sse.js.map +1 -0
- package/dist/app.d.ts +173 -0
- package/dist/app.js +488 -0
- package/dist/app.js.map +1 -0
- package/dist/cli/config-validate.d.ts +6 -0
- package/dist/cli/config-validate.js +39 -0
- package/dist/cli/config-validate.js.map +1 -0
- package/dist/cli/control.d.ts +31 -0
- package/dist/cli/control.js +186 -0
- package/dist/cli/control.js.map +1 -0
- package/dist/cli/http-client.d.ts +57 -0
- package/dist/cli/http-client.js +174 -0
- package/dist/cli/http-client.js.map +1 -0
- package/dist/cli/index.d.ts +14 -0
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init-templates.d.ts +20 -0
- package/dist/cli/init-templates.js +275 -0
- package/dist/cli/init-templates.js.map +1 -0
- package/dist/cli/init.d.ts +16 -0
- package/dist/cli/init.js +107 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +25 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/program.d.ts +102 -0
- package/dist/cli/program.js +133 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/service.d.ts +27 -0
- package/dist/cli/service.js +252 -0
- package/dist/cli/service.js.map +1 -0
- package/dist/cli/start.d.ts +22 -0
- package/dist/cli/start.js +133 -0
- package/dist/cli/start.js.map +1 -0
- package/dist/cli/workflow-dry-run.d.ts +13 -0
- package/dist/cli/workflow-dry-run.js +144 -0
- package/dist/cli/workflow-dry-run.js.map +1 -0
- package/dist/config/field-catalog.d.ts +33 -0
- package/dist/config/field-catalog.js +172 -0
- package/dist/config/field-catalog.js.map +1 -0
- package/dist/config/filter-schema.d.ts +15 -0
- package/dist/config/filter-schema.js +110 -0
- package/dist/config/filter-schema.js.map +1 -0
- package/dist/config/index.d.ts +15 -0
- package/dist/config/index.js +16 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/issues.d.ts +27 -0
- package/dist/config/issues.js +37 -0
- package/dist/config/issues.js.map +1 -0
- package/dist/config/loader.d.ts +32 -0
- package/dist/config/loader.js +250 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/manager.d.ts +153 -0
- package/dist/config/manager.js +276 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/model.d.ts +334 -0
- package/dist/config/model.js +2 -0
- package/dist/config/model.js.map +1 -0
- package/dist/config/normalize.d.ts +20 -0
- package/dist/config/normalize.js +200 -0
- package/dist/config/normalize.js.map +1 -0
- package/dist/config/parameters.d.ts +37 -0
- package/dist/config/parameters.js +71 -0
- package/dist/config/parameters.js.map +1 -0
- package/dist/config/public.d.ts +6 -0
- package/dist/config/public.js +18 -0
- package/dist/config/public.js.map +1 -0
- package/dist/config/schemas.d.ts +538 -0
- package/dist/config/schemas.js +321 -0
- package/dist/config/schemas.js.map +1 -0
- package/dist/config/snapshot.d.ts +38 -0
- package/dist/config/snapshot.js +57 -0
- package/dist/config/snapshot.js.map +1 -0
- package/dist/config/validate.d.ts +33 -0
- package/dist/config/validate.js +346 -0
- package/dist/config/validate.js.map +1 -0
- package/dist/core/clock.d.ts +59 -0
- package/dist/core/clock.js +133 -0
- package/dist/core/clock.js.map +1 -0
- package/dist/core/duration.d.ts +19 -0
- package/dist/core/duration.js +93 -0
- package/dist/core/duration.js.map +1 -0
- package/dist/core/errors.d.ts +62 -0
- package/dist/core/errors.js +72 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/ids.d.ts +57 -0
- package/dist/core/ids.js +88 -0
- package/dist/core/ids.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logger.d.ts +100 -0
- package/dist/core/logger.js +207 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/paths.d.ts +84 -0
- package/dist/core/paths.js +138 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/template.d.ts +136 -0
- package/dist/core/template.js +261 -0
- package/dist/core/template.js.map +1 -0
- package/dist/core/types.d.ts +544 -0
- package/dist/core/types.js +172 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/worker-protocol.d.ts +102 -0
- package/dist/core/worker-protocol.js +75 -0
- package/dist/core/worker-protocol.js.map +1 -0
- package/dist/executors/classify.d.ts +25 -0
- package/dist/executors/classify.js +54 -0
- package/dist/executors/classify.js.map +1 -0
- package/dist/executors/dispatcher.d.ts +35 -0
- package/dist/executors/dispatcher.js +68 -0
- package/dist/executors/dispatcher.js.map +1 -0
- package/dist/executors/env.d.ts +43 -0
- package/dist/executors/env.js +66 -0
- package/dist/executors/env.js.map +1 -0
- package/dist/executors/event-parser.d.ts +41 -0
- package/dist/executors/event-parser.js +106 -0
- package/dist/executors/event-parser.js.map +1 -0
- package/dist/executors/index.d.ts +12 -0
- package/dist/executors/index.js +13 -0
- package/dist/executors/index.js.map +1 -0
- package/dist/executors/log-capture.d.ts +57 -0
- package/dist/executors/log-capture.js +155 -0
- package/dist/executors/log-capture.js.map +1 -0
- package/dist/executors/process-identity.d.ts +124 -0
- package/dist/executors/process-identity.js +283 -0
- package/dist/executors/process-identity.js.map +1 -0
- package/dist/executors/shell-executor.d.ts +35 -0
- package/dist/executors/shell-executor.js +478 -0
- package/dist/executors/shell-executor.js.map +1 -0
- package/dist/executors/stream-redactor.d.ts +40 -0
- package/dist/executors/stream-redactor.js +89 -0
- package/dist/executors/stream-redactor.js.map +1 -0
- package/dist/executors/workspace.d.ts +10 -0
- package/dist/executors/workspace.js +47 -0
- package/dist/executors/workspace.js.map +1 -0
- package/dist/filters/evaluate.d.ts +77 -0
- package/dist/filters/evaluate.js +187 -0
- package/dist/filters/evaluate.js.map +1 -0
- package/dist/filters/fields.d.ts +35 -0
- package/dist/filters/fields.js +75 -0
- package/dist/filters/fields.js.map +1 -0
- package/dist/filters/index.d.ts +11 -0
- package/dist/filters/index.js +12 -0
- package/dist/filters/index.js.map +1 -0
- package/dist/filters/iso-date.d.ts +10 -0
- package/dist/filters/iso-date.js +42 -0
- package/dist/filters/iso-date.js.map +1 -0
- package/dist/filters/predicate.d.ts +24 -0
- package/dist/filters/predicate.js +178 -0
- package/dist/filters/predicate.js.map +1 -0
- package/dist/filters/priority.d.ts +51 -0
- package/dist/filters/priority.js +91 -0
- package/dist/filters/priority.js.map +1 -0
- package/dist/filters/pushdown.d.ts +12 -0
- package/dist/filters/pushdown.js +52 -0
- package/dist/filters/pushdown.js.map +1 -0
- package/dist/filters/shell-check.d.ts +110 -0
- package/dist/filters/shell-check.js +304 -0
- package/dist/filters/shell-check.js.map +1 -0
- package/dist/identities/github-app.d.ts +55 -0
- package/dist/identities/github-app.js +160 -0
- package/dist/identities/github-app.js.map +1 -0
- package/dist/identities/index.d.ts +6 -0
- package/dist/identities/index.js +7 -0
- package/dist/identities/index.js.map +1 -0
- package/dist/identities/jwt.d.ts +24 -0
- package/dist/identities/jwt.js +56 -0
- package/dist/identities/jwt.js.map +1 -0
- package/dist/lifecycle/context.d.ts +106 -0
- package/dist/lifecycle/context.js +170 -0
- package/dist/lifecycle/context.js.map +1 -0
- package/dist/lifecycle/engine.d.ts +185 -0
- package/dist/lifecycle/engine.js +551 -0
- package/dist/lifecycle/engine.js.map +1 -0
- package/dist/lifecycle/errors.d.ts +48 -0
- package/dist/lifecycle/errors.js +71 -0
- package/dist/lifecycle/errors.js.map +1 -0
- package/dist/lifecycle/index.d.ts +9 -0
- package/dist/lifecycle/index.js +9 -0
- package/dist/lifecycle/index.js.map +1 -0
- package/dist/lifecycle/performers.d.ts +66 -0
- package/dist/lifecycle/performers.js +179 -0
- package/dist/lifecycle/performers.js.map +1 -0
- package/dist/notifications/index.d.ts +6 -0
- package/dist/notifications/index.js +7 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/service.d.ts +115 -0
- package/dist/notifications/service.js +364 -0
- package/dist/notifications/service.js.map +1 -0
- package/dist/persistence/actions.d.ts +101 -0
- package/dist/persistence/actions.js +196 -0
- package/dist/persistence/actions.js.map +1 -0
- package/dist/persistence/blocks.d.ts +85 -0
- package/dist/persistence/blocks.js +140 -0
- package/dist/persistence/blocks.js.map +1 -0
- package/dist/persistence/cron-firings.d.ts +55 -0
- package/dist/persistence/cron-firings.js +70 -0
- package/dist/persistence/cron-firings.js.map +1 -0
- package/dist/persistence/database.d.ts +60 -0
- package/dist/persistence/database.js +124 -0
- package/dist/persistence/database.js.map +1 -0
- package/dist/persistence/errors.d.ts +39 -0
- package/dist/persistence/errors.js +67 -0
- package/dist/persistence/errors.js.map +1 -0
- package/dist/persistence/events.d.ts +72 -0
- package/dist/persistence/events.js +83 -0
- package/dist/persistence/events.js.map +1 -0
- package/dist/persistence/index.d.ts +18 -0
- package/dist/persistence/index.js +19 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/instance-lock.d.ts +26 -0
- package/dist/persistence/instance-lock.js +117 -0
- package/dist/persistence/instance-lock.js.map +1 -0
- package/dist/persistence/lock-keys.d.ts +16 -0
- package/dist/persistence/lock-keys.js +41 -0
- package/dist/persistence/lock-keys.js.map +1 -0
- package/dist/persistence/notifications.d.ts +113 -0
- package/dist/persistence/notifications.js +213 -0
- package/dist/persistence/notifications.js.map +1 -0
- package/dist/persistence/persistence.d.ts +46 -0
- package/dist/persistence/persistence.js +42 -0
- package/dist/persistence/persistence.js.map +1 -0
- package/dist/persistence/retention.d.ts +46 -0
- package/dist/persistence/retention.js +68 -0
- package/dist/persistence/retention.js.map +1 -0
- package/dist/persistence/runs.d.ts +215 -0
- package/dist/persistence/runs.js +417 -0
- package/dist/persistence/runs.js.map +1 -0
- package/dist/persistence/schema.d.ts +16 -0
- package/dist/persistence/schema.js +183 -0
- package/dist/persistence/schema.js.map +1 -0
- package/dist/persistence/sqlite.d.ts +49 -0
- package/dist/persistence/sqlite.js +131 -0
- package/dist/persistence/sqlite.js.map +1 -0
- package/dist/runs/controller.d.ts +307 -0
- package/dist/runs/controller.js +1078 -0
- package/dist/runs/controller.js.map +1 -0
- package/dist/runs/errors.d.ts +20 -0
- package/dist/runs/errors.js +26 -0
- package/dist/runs/errors.js.map +1 -0
- package/dist/runs/event-bus.d.ts +106 -0
- package/dist/runs/event-bus.js +105 -0
- package/dist/runs/event-bus.js.map +1 -0
- package/dist/runs/execution.d.ts +39 -0
- package/dist/runs/execution.js +146 -0
- package/dist/runs/execution.js.map +1 -0
- package/dist/runs/index.d.ts +12 -0
- package/dist/runs/index.js +13 -0
- package/dist/runs/index.js.map +1 -0
- package/dist/runs/retention.d.ts +64 -0
- package/dist/runs/retention.js +232 -0
- package/dist/runs/retention.js.map +1 -0
- package/dist/runs/workspace.d.ts +20 -0
- package/dist/runs/workspace.js +51 -0
- package/dist/runs/workspace.js.map +1 -0
- package/dist/scheduler/checks.d.ts +41 -0
- package/dist/scheduler/checks.js +111 -0
- package/dist/scheduler/checks.js.map +1 -0
- package/dist/scheduler/cron.d.ts +32 -0
- package/dist/scheduler/cron.js +83 -0
- package/dist/scheduler/cron.js.map +1 -0
- package/dist/scheduler/dry-run.d.ts +42 -0
- package/dist/scheduler/dry-run.js +167 -0
- package/dist/scheduler/dry-run.js.map +1 -0
- package/dist/scheduler/errors.d.ts +22 -0
- package/dist/scheduler/errors.js +22 -0
- package/dist/scheduler/errors.js.map +1 -0
- package/dist/scheduler/format.d.ts +3 -0
- package/dist/scheduler/format.js +73 -0
- package/dist/scheduler/format.js.map +1 -0
- package/dist/scheduler/index.d.ts +13 -0
- package/dist/scheduler/index.js +14 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/scheduler/planner.d.ts +88 -0
- package/dist/scheduler/planner.js +255 -0
- package/dist/scheduler/planner.js.map +1 -0
- package/dist/scheduler/scheduler.d.ts +160 -0
- package/dist/scheduler/scheduler.js +680 -0
- package/dist/scheduler/scheduler.js.map +1 -0
- package/dist/scheduler/state.d.ts +26 -0
- package/dist/scheduler/state.js +25 -0
- package/dist/scheduler/state.js.map +1 -0
- package/dist/scheduler/types.d.ts +197 -0
- package/dist/scheduler/types.js +3 -0
- package/dist/scheduler/types.js.map +1 -0
- package/dist/service/index.d.ts +6 -0
- package/dist/service/index.js +7 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/install.d.ts +93 -0
- package/dist/service/install.js +250 -0
- package/dist/service/install.js.map +1 -0
- package/dist/service/unit.d.ts +50 -0
- package/dist/service/unit.js +171 -0
- package/dist/service/unit.js.map +1 -0
- package/dist/sources/github/adapter.d.ts +99 -0
- package/dist/sources/github/adapter.js +336 -0
- package/dist/sources/github/adapter.js.map +1 -0
- package/dist/sources/github/fields.d.ts +8 -0
- package/dist/sources/github/fields.js +72 -0
- package/dist/sources/github/fields.js.map +1 -0
- package/dist/sources/github/http.d.ts +100 -0
- package/dist/sources/github/http.js +288 -0
- package/dist/sources/github/http.js.map +1 -0
- package/dist/sources/github/index.d.ts +6 -0
- package/dist/sources/github/index.js +7 -0
- package/dist/sources/github/index.js.map +1 -0
- package/dist/sources/github/pushdown.d.ts +14 -0
- package/dist/sources/github/pushdown.js +47 -0
- package/dist/sources/github/pushdown.js.map +1 -0
- package/dist/sources/github/refs.d.ts +17 -0
- package/dist/sources/github/refs.js +61 -0
- package/dist/sources/github/refs.js.map +1 -0
- package/dist/sources/index.d.ts +6 -0
- package/dist/sources/index.js +7 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/ui/index.d.ts +12 -0
- package/dist/ui/index.js +28 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/public/app.css +239 -0
- package/dist/ui/public/favicon.svg +1 -0
- package/dist/ui/public/index.html +27 -0
- package/dist/ui/public/js/client/api.js +68 -0
- package/dist/ui/public/js/client/app.js +146 -0
- package/dist/ui/public/js/client/dom.js +34 -0
- package/dist/ui/public/js/client/page.js +9 -0
- package/dist/ui/public/js/client/pages/actions.js +35 -0
- package/dist/ui/public/js/client/pages/blocked.js +58 -0
- package/dist/ui/public/js/client/pages/config.js +126 -0
- package/dist/ui/public/js/client/pages/dashboard.js +175 -0
- package/dist/ui/public/js/client/pages/run.js +367 -0
- package/dist/ui/public/js/client/pages/runs.js +72 -0
- package/dist/ui/public/js/client/pages/views.js +80 -0
- package/dist/ui/public/js/client/pages/workflows.js +291 -0
- package/dist/ui/public/js/client/types.js +1 -0
- package/dist/ui/public/js/client/ui.js +152 -0
- package/dist/ui/public/js/shared/dom.js +77 -0
- package/dist/ui/public/js/shared/events.js +88 -0
- package/dist/ui/public/js/shared/format.js +213 -0
- package/dist/ui/public/js/shared/logs.js +136 -0
- package/dist/ui/public/js/shared/params.js +90 -0
- package/dist/ui/public/js/shared/route.js +36 -0
- package/dist/ui/public/js/shared/sort.js +70 -0
- package/dist/ui/public/js/shared/sse.js +193 -0
- package/dist/ui/public/js/shared/throttle.js +65 -0
- package/dist/views/index.d.ts +6 -0
- package/dist/views/index.js +7 -0
- package/dist/views/index.js.map +1 -0
- package/dist/views/service.d.ts +131 -0
- package/dist/views/service.js +264 -0
- package/dist/views/service.js.map +1 -0
- package/docs/api.md +239 -0
- package/docs/configuration-reference.md +1785 -0
- package/docs/cron-semantics.md +96 -0
- package/docs/manual-tests/github-fixture/config.yaml +30 -0
- package/docs/manual-tests/github-fixture/helpers.sh +93 -0
- package/docs/manual-tests/github-fixture/identities.yaml +18 -0
- package/docs/manual-tests/github-fixture/scripts/test-worker.sh +100 -0
- package/docs/manual-tests/github-fixture/sources.yaml +13 -0
- package/docs/manual-tests/github-fixture/views/dependencies.yaml +17 -0
- package/docs/manual-tests/github-fixture/views/needs-maintainer.yaml +17 -0
- package/docs/manual-tests/github-fixture/workflows/coder-test.yaml +76 -0
- package/docs/manual-tests/github-fixture/workflows/commenter-test.yaml +63 -0
- package/docs/manual-tests/github-fixture/workflows/reviewer-test.yaml +60 -0
- package/docs/manual-tests/github.md +1308 -0
- package/docs/manual-tests/process-supervision.md +64 -0
- package/docs/manual-tests/systemd.md +68 -0
- package/docs/operations.md +271 -0
- package/docs/worker-protocol.md +145 -0
- package/examples/config/config.yaml +35 -0
- package/examples/config/identities.yaml +18 -0
- package/examples/config/sources.yaml +13 -0
- package/examples/config/views/needs-maintainer.yaml +15 -0
- package/examples/config/workflows/coder-project-a.yaml +86 -0
- package/examples/config/workflows/deploy.yaml +15 -0
- package/examples/config/workflows/nightly-maintenance.yaml +13 -0
- package/package.json +75 -4
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs and active locks (Spec §7, §8, §11, §12).
|
|
3
|
+
*
|
|
4
|
+
* The state machine from core (`canTransition`, `RUN_STATUS_TRANSITIONS`) is
|
|
5
|
+
* enforced here. Every terminal status is reached only through `finalizing`:
|
|
6
|
+
* {@link RunRepository.beginFinalization} persists the
|
|
7
|
+
* {@link FinalizationTarget}, updates the technical-failure counter and (if
|
|
8
|
+
* the limit is reached) creates the retry block – all in one transaction;
|
|
9
|
+
* {@link RunRepository.finish} then moves to exactly the persisted target and
|
|
10
|
+
* releases the lock in the same transaction.
|
|
11
|
+
*/
|
|
12
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
13
|
+
import { type BusinessResult, type Clock, type FinalizationTarget, type LifecycleStatus, type ProcessStartIdentity, type TechnicalStatus, type TerminalStatus, type TriggerType } from '../core/index.js';
|
|
14
|
+
import type { BlockRecord, BlockRepository } from './blocks.js';
|
|
15
|
+
import { type EventRepository } from './events.js';
|
|
16
|
+
/** A persisted run. JSON columns are parsed. */
|
|
17
|
+
export interface RunRecord {
|
|
18
|
+
id: string;
|
|
19
|
+
workflowId: string;
|
|
20
|
+
triggerType: TriggerType;
|
|
21
|
+
sourceId: string | null;
|
|
22
|
+
sourceItemKey: string | null;
|
|
23
|
+
sourceUrl: string | null;
|
|
24
|
+
/** See `lockKeyFor` for semantics. */
|
|
25
|
+
lockKey: string;
|
|
26
|
+
/** Cron slot (ISO) for scheduled runs. */
|
|
27
|
+
scheduledFor: string | null;
|
|
28
|
+
/** Workflow configuration snapshot taken at reservation (Spec §12, §19). */
|
|
29
|
+
configSnapshot: unknown;
|
|
30
|
+
parameters: Record<string, unknown> | null;
|
|
31
|
+
/** Identity ID used by the run, if any. */
|
|
32
|
+
identity: string | null;
|
|
33
|
+
/** Executed command (as JSON, e.g. `{command, args}`), for diagnostics. */
|
|
34
|
+
command: unknown;
|
|
35
|
+
status: TechnicalStatus;
|
|
36
|
+
/** Persisted finalization target (set when entering `finalizing`). */
|
|
37
|
+
finalStatus: TerminalStatus | null;
|
|
38
|
+
businessResult: BusinessResult;
|
|
39
|
+
finalReason: string | null;
|
|
40
|
+
exitCode: number | null;
|
|
41
|
+
pid: number | null;
|
|
42
|
+
processStartIdentity: ProcessStartIdentity | null;
|
|
43
|
+
workspacePath: string | null;
|
|
44
|
+
/** Last worker `status` event message. */
|
|
45
|
+
statusMessage: string | null;
|
|
46
|
+
/** Parsed worker result file (if valid). */
|
|
47
|
+
result: unknown;
|
|
48
|
+
/** Technical error diagnostics (no secrets). */
|
|
49
|
+
error: unknown;
|
|
50
|
+
lifecycleStatus: LifecycleStatus | null;
|
|
51
|
+
/** Failure-counting period at finalization. */
|
|
52
|
+
blockGeneration: number | null;
|
|
53
|
+
/** True if this run's outcome incremented the technical-failure counter. */
|
|
54
|
+
countedTechnicalFailure: boolean;
|
|
55
|
+
createdAt: string;
|
|
56
|
+
startedAt: string | null;
|
|
57
|
+
finalizingAt: string | null;
|
|
58
|
+
finishedAt: string | null;
|
|
59
|
+
updatedAt: string;
|
|
60
|
+
}
|
|
61
|
+
/** Input for {@link RunRepository.reserve}. */
|
|
62
|
+
export interface ReserveRunInput {
|
|
63
|
+
/** Run ID; generated via `createRunId` if omitted. */
|
|
64
|
+
id?: string;
|
|
65
|
+
workflowId: string;
|
|
66
|
+
triggerType: TriggerType;
|
|
67
|
+
sourceId?: string | null;
|
|
68
|
+
/** `sourceItemKey(sourceId, itemId)`; required for `source` runs, optional for manual runs. */
|
|
69
|
+
sourceItemKey?: string | null;
|
|
70
|
+
sourceUrl?: string | null;
|
|
71
|
+
/** Cron slot; required for `schedule` runs without item. */
|
|
72
|
+
scheduledFor?: Date | string | null;
|
|
73
|
+
configSnapshot: unknown;
|
|
74
|
+
parameters?: Record<string, unknown> | null;
|
|
75
|
+
identity?: string | null;
|
|
76
|
+
command?: unknown;
|
|
77
|
+
workspacePath?: string | null;
|
|
78
|
+
/**
|
|
79
|
+
* Also refuse (atomically) if an active retry block exists for the run's
|
|
80
|
+
* block scope. Scheduler: `true`; manual starts: `false` (Spec §7, §11).
|
|
81
|
+
*/
|
|
82
|
+
failIfBlocked?: boolean;
|
|
83
|
+
}
|
|
84
|
+
/** Mutable non-status fields. `undefined` = unchanged. */
|
|
85
|
+
export interface RunUpdate {
|
|
86
|
+
pid?: number | null;
|
|
87
|
+
processStartIdentity?: ProcessStartIdentity | null;
|
|
88
|
+
workspacePath?: string | null;
|
|
89
|
+
statusMessage?: string | null;
|
|
90
|
+
lifecycleStatus?: LifecycleStatus | null;
|
|
91
|
+
exitCode?: number | null;
|
|
92
|
+
result?: unknown;
|
|
93
|
+
error?: unknown;
|
|
94
|
+
configSnapshot?: unknown;
|
|
95
|
+
identity?: string | null;
|
|
96
|
+
command?: unknown;
|
|
97
|
+
startedAt?: Date | string | null;
|
|
98
|
+
}
|
|
99
|
+
/** Retry-block policy applied in {@link RunRepository.beginFinalization}. */
|
|
100
|
+
export interface BlockPolicy {
|
|
101
|
+
/** Block when the consecutive technical failures reach this number (≥ 1). */
|
|
102
|
+
maxTechnicalFailures: number;
|
|
103
|
+
/** Block reason; default describes the count and the final reason. */
|
|
104
|
+
reason?: string;
|
|
105
|
+
}
|
|
106
|
+
/** Options for {@link RunRepository.beginFinalization}. */
|
|
107
|
+
export interface BeginFinalizationOptions {
|
|
108
|
+
update?: RunUpdate;
|
|
109
|
+
blockPolicy?: BlockPolicy;
|
|
110
|
+
}
|
|
111
|
+
/** Outcome of {@link RunRepository.beginFinalization}. */
|
|
112
|
+
export interface FinalizationResult {
|
|
113
|
+
run: RunRecord;
|
|
114
|
+
/** True if the target is a technical failure (counted). */
|
|
115
|
+
technicalFailure: boolean;
|
|
116
|
+
/** Counter value after applying this outcome. */
|
|
117
|
+
consecutiveTechnicalFailures: number;
|
|
118
|
+
/** Block created in this transaction (caller emits `retry_block_created`). */
|
|
119
|
+
blockCreated: BlockRecord | null;
|
|
120
|
+
}
|
|
121
|
+
/** Query for {@link RunRepository.list}. */
|
|
122
|
+
export interface RunListQuery {
|
|
123
|
+
workflowId?: string;
|
|
124
|
+
statuses?: readonly TechnicalStatus[];
|
|
125
|
+
triggerType?: TriggerType;
|
|
126
|
+
sourceItemKey?: string;
|
|
127
|
+
businessResult?: 'success' | 'failure';
|
|
128
|
+
/** Only runs created before this time (exclusive). */
|
|
129
|
+
createdBefore?: Date | string;
|
|
130
|
+
/** Default 50, max 500. */
|
|
131
|
+
limit?: number;
|
|
132
|
+
offset?: number;
|
|
133
|
+
}
|
|
134
|
+
/** A page of runs, newest first. */
|
|
135
|
+
export interface RunPage {
|
|
136
|
+
runs: RunRecord[];
|
|
137
|
+
total: number;
|
|
138
|
+
}
|
|
139
|
+
/** An active reservation. */
|
|
140
|
+
export interface LockRecord {
|
|
141
|
+
workflowId: string;
|
|
142
|
+
lockKey: string;
|
|
143
|
+
runId: string;
|
|
144
|
+
sourceItemKey: string | null;
|
|
145
|
+
acquiredAt: string;
|
|
146
|
+
}
|
|
147
|
+
/** Repository for `runs` and `locks`. */
|
|
148
|
+
export declare class RunRepository {
|
|
149
|
+
private readonly db;
|
|
150
|
+
private readonly clock;
|
|
151
|
+
private readonly events;
|
|
152
|
+
private readonly blocks;
|
|
153
|
+
constructor(db: DatabaseSync, clock: Clock, events: EventRepository, blocks: BlockRepository);
|
|
154
|
+
/**
|
|
155
|
+
* Atomically reserve a run: check + create the lock `(workflowId, lockKey)`
|
|
156
|
+
* and insert the run in status `reserved`. Throws {@link LockConflictError}
|
|
157
|
+
* if an active run holds the lock, {@link BlockedError} with `failIfBlocked`.
|
|
158
|
+
*/
|
|
159
|
+
reserve(input: ReserveRunInput): RunRecord;
|
|
160
|
+
/**
|
|
161
|
+
* Non-final transition (e.g. `reserved → starting`, `starting → running`,
|
|
162
|
+
* `→ cancelling`, `→ recovery_pending`). `finalizing` and terminal statuses
|
|
163
|
+
* must go through {@link beginFinalization} / {@link finish}.
|
|
164
|
+
*/
|
|
165
|
+
transition(runId: string, to: TechnicalStatus, options?: {
|
|
166
|
+
expectedFrom?: TechnicalStatus;
|
|
167
|
+
update?: RunUpdate;
|
|
168
|
+
}): RunRecord;
|
|
169
|
+
/**
|
|
170
|
+
* `X → finalizing`: persist the {@link FinalizationTarget}, apply the
|
|
171
|
+
* outcome to the technical-failure counter and – if `blockPolicy` is given
|
|
172
|
+
* and the limit is reached and no block is active – create the retry block,
|
|
173
|
+
* all in one transaction (Spec §11 "important order").
|
|
174
|
+
*/
|
|
175
|
+
beginFinalization(runId: string, target: FinalizationTarget, options?: BeginFinalizationOptions): FinalizationResult;
|
|
176
|
+
/**
|
|
177
|
+
* `finalizing → <persisted target status>`: sets `finished_at` and releases
|
|
178
|
+
* the lock in the same transaction.
|
|
179
|
+
*/
|
|
180
|
+
finish(runId: string, options?: {
|
|
181
|
+
update?: RunUpdate;
|
|
182
|
+
}): RunRecord;
|
|
183
|
+
/** Update non-status fields (pid, start identity, lifecycle status, ...). */
|
|
184
|
+
update(runId: string, update: RunUpdate): RunRecord;
|
|
185
|
+
/** Run by ID or `null`. */
|
|
186
|
+
get(runId: string): RunRecord | null;
|
|
187
|
+
/** Run by ID; throws {@link NotFoundError}. */
|
|
188
|
+
require(runId: string): RunRecord;
|
|
189
|
+
/** All runs in active (non-terminal) states, oldest first (recovery, dashboard). */
|
|
190
|
+
listActive(workflowId?: string): RunRecord[];
|
|
191
|
+
/** Number of active runs (all triggers incl. manual), optionally per workflow (Spec §7 concurrency). */
|
|
192
|
+
countActive(workflowId?: string): number;
|
|
193
|
+
/** Run history with filter and paging, newest first. */
|
|
194
|
+
list(query?: RunListQuery): RunPage;
|
|
195
|
+
/** Latest run (by creation) for an item key, across workflows unless `workflowId` is given. */
|
|
196
|
+
lastRunForItem(itemKey: string, options?: {
|
|
197
|
+
workflowId?: string;
|
|
198
|
+
finishedOnly?: boolean;
|
|
199
|
+
}): RunRecord | null;
|
|
200
|
+
/** Latest run per item key (views: `run.last_*`, Spec §17). Keys without runs are absent. */
|
|
201
|
+
lastRunsForItems(itemKeys: readonly string[], options?: {
|
|
202
|
+
workflowId?: string;
|
|
203
|
+
finishedOnly?: boolean;
|
|
204
|
+
}): Map<string, RunRecord>;
|
|
205
|
+
/** Active lock for `(workflowId, lockKey)` or `null`. */
|
|
206
|
+
activeLock(workflowId: string, lockKey: string): LockRecord | null;
|
|
207
|
+
/** Active run of a workflow for a source item (scheduler step 4), or `null`. */
|
|
208
|
+
activeRunForItem(workflowId: string, itemKey: string): RunRecord | null;
|
|
209
|
+
/** All active locks. */
|
|
210
|
+
listLocks(): LockRecord[];
|
|
211
|
+
private assertTransition;
|
|
212
|
+
private applyUpdate;
|
|
213
|
+
}
|
|
214
|
+
/** The persisted finalization target of a run, or `null` before `finalizing`. */
|
|
215
|
+
export declare function finalizationTarget(run: RunRecord): FinalizationTarget | null;
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import { ACTIVE_STATUSES, canTransition, createRunId, isTechnicalFailure, isTerminalStatus, } from '../core/index.js';
|
|
2
|
+
import { BlockedError, InvalidTransitionError, LockConflictError, NotFoundError } from './errors.js';
|
|
3
|
+
import { RUN_STATUS_EVENT } from './events.js';
|
|
4
|
+
import { lockKeyFor } from './lock-keys.js';
|
|
5
|
+
import { all, fromJson, get, iso, num, placeholders, run, str, toJson, transaction } from './sqlite.js';
|
|
6
|
+
const ACTIVE_SQL = `(${ACTIVE_STATUSES.map((s) => `'${s}'`).join(', ')})`;
|
|
7
|
+
/** Repository for `runs` and `locks`. */
|
|
8
|
+
export class RunRepository {
|
|
9
|
+
db;
|
|
10
|
+
clock;
|
|
11
|
+
events;
|
|
12
|
+
blocks;
|
|
13
|
+
constructor(db, clock, events, blocks) {
|
|
14
|
+
this.db = db;
|
|
15
|
+
this.clock = clock;
|
|
16
|
+
this.events = events;
|
|
17
|
+
this.blocks = blocks;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Atomically reserve a run: check + create the lock `(workflowId, lockKey)`
|
|
21
|
+
* and insert the run in status `reserved`. Throws {@link LockConflictError}
|
|
22
|
+
* if an active run holds the lock, {@link BlockedError} with `failIfBlocked`.
|
|
23
|
+
*/
|
|
24
|
+
reserve(input) {
|
|
25
|
+
if (input.triggerType === 'source' && !input.sourceItemKey) {
|
|
26
|
+
throw new TypeError('Source-triggered runs require sourceItemKey');
|
|
27
|
+
}
|
|
28
|
+
const id = input.id ?? createRunId({ clock: this.clock });
|
|
29
|
+
const lockKey = lockKeyFor({
|
|
30
|
+
triggerType: input.triggerType,
|
|
31
|
+
runId: id,
|
|
32
|
+
sourceItemKey: input.sourceItemKey ?? null,
|
|
33
|
+
scheduledFor: input.scheduledFor ?? null,
|
|
34
|
+
});
|
|
35
|
+
const itemKey = input.sourceItemKey ?? null;
|
|
36
|
+
return transaction(this.db, () => {
|
|
37
|
+
const holder = this.activeLock(input.workflowId, lockKey);
|
|
38
|
+
if (holder)
|
|
39
|
+
throw new LockConflictError(input.workflowId, lockKey, holder.runId);
|
|
40
|
+
if (input.failIfBlocked) {
|
|
41
|
+
const block = this.blocks.activeFor(input.workflowId, itemKey);
|
|
42
|
+
if (block)
|
|
43
|
+
throw new BlockedError(input.workflowId, itemKey, block.id);
|
|
44
|
+
}
|
|
45
|
+
const now = this.clock.now().toISOString();
|
|
46
|
+
try {
|
|
47
|
+
run(this.db, `INSERT INTO runs (id, workflow_id, trigger_type, source_id, source_item_key, source_url, lock_key, scheduled_for,
|
|
48
|
+
config_snapshot, parameters_json, identity, command, status, workspace_path, created_at, updated_at)
|
|
49
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'reserved', ?, ?, ?)`, [
|
|
50
|
+
id,
|
|
51
|
+
input.workflowId,
|
|
52
|
+
input.triggerType,
|
|
53
|
+
input.sourceId ?? null,
|
|
54
|
+
itemKey,
|
|
55
|
+
input.sourceUrl ?? null,
|
|
56
|
+
lockKey,
|
|
57
|
+
input.scheduledFor ? iso(input.scheduledFor) : null,
|
|
58
|
+
JSON.stringify(input.configSnapshot ?? null),
|
|
59
|
+
toJson(input.parameters ?? undefined),
|
|
60
|
+
input.identity ?? null,
|
|
61
|
+
toJson(input.command),
|
|
62
|
+
input.workspacePath ?? null,
|
|
63
|
+
now,
|
|
64
|
+
now,
|
|
65
|
+
]);
|
|
66
|
+
run(this.db, 'INSERT INTO locks (workflow_id, lock_key, run_id, source_item_key, acquired_at) VALUES (?, ?, ?, ?, ?)', [
|
|
67
|
+
input.workflowId,
|
|
68
|
+
lockKey,
|
|
69
|
+
id,
|
|
70
|
+
itemKey,
|
|
71
|
+
now,
|
|
72
|
+
]);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
// Defensive: unique constraints are the final arbiter.
|
|
76
|
+
if (err instanceof Error && /UNIQUE constraint failed: (locks|runs)\.(workflow_id|lock_key)/.test(err.message)) {
|
|
77
|
+
const h = this.activeLock(input.workflowId, lockKey);
|
|
78
|
+
throw new LockConflictError(input.workflowId, lockKey, h?.runId ?? 'unknown');
|
|
79
|
+
}
|
|
80
|
+
throw err;
|
|
81
|
+
}
|
|
82
|
+
this.events.append(id, RUN_STATUS_EVENT, { from: null, to: 'reserved' });
|
|
83
|
+
return this.require(id);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Non-final transition (e.g. `reserved → starting`, `starting → running`,
|
|
88
|
+
* `→ cancelling`, `→ recovery_pending`). `finalizing` and terminal statuses
|
|
89
|
+
* must go through {@link beginFinalization} / {@link finish}.
|
|
90
|
+
*/
|
|
91
|
+
transition(runId, to, options = {}) {
|
|
92
|
+
if (to === 'finalizing' || isTerminalStatus(to)) {
|
|
93
|
+
throw new InvalidTransitionError(`Use beginFinalization()/finish() to move to '${to}'`, { runId, to });
|
|
94
|
+
}
|
|
95
|
+
return transaction(this.db, () => {
|
|
96
|
+
const current = this.require(runId);
|
|
97
|
+
this.assertTransition(current, to, options.expectedFrom);
|
|
98
|
+
const extra = options.update ? { ...options.update } : {};
|
|
99
|
+
if (to === 'running' && extra.startedAt === undefined && current.startedAt === null) {
|
|
100
|
+
extra.startedAt = this.clock.now();
|
|
101
|
+
}
|
|
102
|
+
this.applyUpdate(runId, extra, { status: to });
|
|
103
|
+
this.events.append(runId, RUN_STATUS_EVENT, { from: current.status, to });
|
|
104
|
+
return this.require(runId);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* `X → finalizing`: persist the {@link FinalizationTarget}, apply the
|
|
109
|
+
* outcome to the technical-failure counter and – if `blockPolicy` is given
|
|
110
|
+
* and the limit is reached and no block is active – create the retry block,
|
|
111
|
+
* all in one transaction (Spec §11 "important order").
|
|
112
|
+
*/
|
|
113
|
+
beginFinalization(runId, target, options = {}) {
|
|
114
|
+
validateTarget(target);
|
|
115
|
+
if (options.blockPolicy && !(Number.isInteger(options.blockPolicy.maxTechnicalFailures) && options.blockPolicy.maxTechnicalFailures >= 1)) {
|
|
116
|
+
throw new TypeError('blockPolicy.maxTechnicalFailures must be an integer ≥ 1');
|
|
117
|
+
}
|
|
118
|
+
return transaction(this.db, () => {
|
|
119
|
+
const current = this.require(runId);
|
|
120
|
+
this.assertTransition(current, 'finalizing');
|
|
121
|
+
const technicalFailure = isTechnicalFailure(target.status);
|
|
122
|
+
const effect = technicalFailure
|
|
123
|
+
? 'increment'
|
|
124
|
+
: target.status === 'completed' && target.businessResult === 'success'
|
|
125
|
+
? 'reset'
|
|
126
|
+
: 'none';
|
|
127
|
+
const counter = this.blocks.applyOutcome(current.workflowId, current.sourceItemKey, effect);
|
|
128
|
+
const now = this.clock.now().toISOString();
|
|
129
|
+
this.applyUpdate(runId, options.update ?? {}, {
|
|
130
|
+
status: 'finalizing',
|
|
131
|
+
final_status: target.status,
|
|
132
|
+
business_result: target.businessResult,
|
|
133
|
+
final_reason: target.reason,
|
|
134
|
+
finalizing_at: now,
|
|
135
|
+
block_generation: counter.generation,
|
|
136
|
+
counted_technical_failure: technicalFailure ? 1 : 0,
|
|
137
|
+
});
|
|
138
|
+
let blockCreated = null;
|
|
139
|
+
const policy = options.blockPolicy;
|
|
140
|
+
if (technicalFailure &&
|
|
141
|
+
policy &&
|
|
142
|
+
counter.consecutive >= policy.maxTechnicalFailures &&
|
|
143
|
+
!this.blocks.isBlocked(current.workflowId, current.sourceItemKey)) {
|
|
144
|
+
blockCreated = this.blocks.create({
|
|
145
|
+
workflowId: current.workflowId,
|
|
146
|
+
itemKey: current.sourceItemKey,
|
|
147
|
+
reason: policy.reason ??
|
|
148
|
+
`${counter.consecutive} consecutive technical failures (last: ${target.status}: ${target.reason})`,
|
|
149
|
+
runId,
|
|
150
|
+
failureCount: counter.consecutive,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
this.events.append(runId, RUN_STATUS_EVENT, {
|
|
154
|
+
from: current.status,
|
|
155
|
+
to: 'finalizing',
|
|
156
|
+
target: { status: target.status, businessResult: target.businessResult, reason: target.reason },
|
|
157
|
+
...(blockCreated ? { blockId: blockCreated.id } : {}),
|
|
158
|
+
});
|
|
159
|
+
return {
|
|
160
|
+
run: this.require(runId),
|
|
161
|
+
technicalFailure,
|
|
162
|
+
consecutiveTechnicalFailures: counter.consecutive,
|
|
163
|
+
blockCreated,
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* `finalizing → <persisted target status>`: sets `finished_at` and releases
|
|
169
|
+
* the lock in the same transaction.
|
|
170
|
+
*/
|
|
171
|
+
finish(runId, options = {}) {
|
|
172
|
+
return transaction(this.db, () => {
|
|
173
|
+
const current = this.require(runId);
|
|
174
|
+
const target = finalizationTarget(current);
|
|
175
|
+
if (current.status !== 'finalizing' || !target) {
|
|
176
|
+
throw new InvalidTransitionError(`Run '${runId}' is not finalizing (status '${current.status}')`, {
|
|
177
|
+
runId,
|
|
178
|
+
from: current.status,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
if (!canTransition('finalizing', target.status, target)) {
|
|
182
|
+
throw new InvalidTransitionError(`Invalid final status '${target.status}'`, { runId, to: target.status });
|
|
183
|
+
}
|
|
184
|
+
this.applyUpdate(runId, options.update ?? {}, { status: target.status, finished_at: this.clock.now().toISOString() });
|
|
185
|
+
run(this.db, 'DELETE FROM locks WHERE run_id = ?', [runId]);
|
|
186
|
+
this.events.append(runId, RUN_STATUS_EVENT, { from: 'finalizing', to: target.status });
|
|
187
|
+
return this.require(runId);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/** Update non-status fields (pid, start identity, lifecycle status, ...). */
|
|
191
|
+
update(runId, update) {
|
|
192
|
+
return transaction(this.db, () => {
|
|
193
|
+
this.require(runId);
|
|
194
|
+
this.applyUpdate(runId, update, {});
|
|
195
|
+
return this.require(runId);
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
/** Run by ID or `null`. */
|
|
199
|
+
get(runId) {
|
|
200
|
+
const row = get(this.db, 'SELECT * FROM runs WHERE id = ?', [runId]);
|
|
201
|
+
return row ? toRun(row) : null;
|
|
202
|
+
}
|
|
203
|
+
/** Run by ID; throws {@link NotFoundError}. */
|
|
204
|
+
require(runId) {
|
|
205
|
+
const r = this.get(runId);
|
|
206
|
+
if (!r)
|
|
207
|
+
throw new NotFoundError('run', runId);
|
|
208
|
+
return r;
|
|
209
|
+
}
|
|
210
|
+
/** All runs in active (non-terminal) states, oldest first (recovery, dashboard). */
|
|
211
|
+
listActive(workflowId) {
|
|
212
|
+
const params = [];
|
|
213
|
+
let sql = `SELECT * FROM runs WHERE status IN ${ACTIVE_SQL}`;
|
|
214
|
+
if (workflowId !== undefined) {
|
|
215
|
+
sql += ' AND workflow_id = ?';
|
|
216
|
+
params.push(workflowId);
|
|
217
|
+
}
|
|
218
|
+
return all(this.db, `${sql} ORDER BY created_at ASC, id ASC`, params).map(toRun);
|
|
219
|
+
}
|
|
220
|
+
/** Number of active runs (all triggers incl. manual), optionally per workflow (Spec §7 concurrency). */
|
|
221
|
+
countActive(workflowId) {
|
|
222
|
+
const row = workflowId === undefined
|
|
223
|
+
? get(this.db, `SELECT COUNT(*) AS n FROM runs WHERE status IN ${ACTIVE_SQL}`)
|
|
224
|
+
: get(this.db, `SELECT COUNT(*) AS n FROM runs WHERE status IN ${ACTIVE_SQL} AND workflow_id = ?`, [workflowId]);
|
|
225
|
+
return Number(row?.n ?? 0);
|
|
226
|
+
}
|
|
227
|
+
/** Run history with filter and paging, newest first. */
|
|
228
|
+
list(query = {}) {
|
|
229
|
+
const where = [];
|
|
230
|
+
const params = [];
|
|
231
|
+
if (query.workflowId !== undefined) {
|
|
232
|
+
where.push('workflow_id = ?');
|
|
233
|
+
params.push(query.workflowId);
|
|
234
|
+
}
|
|
235
|
+
if (query.statuses && query.statuses.length > 0) {
|
|
236
|
+
where.push(`status IN (${placeholders(query.statuses.length)})`);
|
|
237
|
+
params.push(...query.statuses);
|
|
238
|
+
}
|
|
239
|
+
if (query.triggerType !== undefined) {
|
|
240
|
+
where.push('trigger_type = ?');
|
|
241
|
+
params.push(query.triggerType);
|
|
242
|
+
}
|
|
243
|
+
if (query.sourceItemKey !== undefined) {
|
|
244
|
+
where.push('source_item_key = ?');
|
|
245
|
+
params.push(query.sourceItemKey);
|
|
246
|
+
}
|
|
247
|
+
if (query.businessResult !== undefined) {
|
|
248
|
+
where.push('business_result = ?');
|
|
249
|
+
params.push(query.businessResult);
|
|
250
|
+
}
|
|
251
|
+
if (query.createdBefore !== undefined) {
|
|
252
|
+
where.push('created_at < ?');
|
|
253
|
+
params.push(iso(query.createdBefore));
|
|
254
|
+
}
|
|
255
|
+
const clause = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
|
|
256
|
+
const limit = Math.min(Math.max(1, query.limit ?? 50), 500);
|
|
257
|
+
const offset = Math.max(0, query.offset ?? 0);
|
|
258
|
+
const total = Number(get(this.db, `SELECT COUNT(*) AS n FROM runs ${clause}`, params)?.n ?? 0);
|
|
259
|
+
const runs = all(this.db, `SELECT * FROM runs ${clause} ORDER BY created_at DESC, id DESC LIMIT ? OFFSET ?`, [
|
|
260
|
+
...params,
|
|
261
|
+
limit,
|
|
262
|
+
offset,
|
|
263
|
+
]).map(toRun);
|
|
264
|
+
return { runs, total };
|
|
265
|
+
}
|
|
266
|
+
/** Latest run (by creation) for an item key, across workflows unless `workflowId` is given. */
|
|
267
|
+
lastRunForItem(itemKey, options = {}) {
|
|
268
|
+
return this.lastRunsForItems([itemKey], options).get(itemKey) ?? null;
|
|
269
|
+
}
|
|
270
|
+
/** Latest run per item key (views: `run.last_*`, Spec §17). Keys without runs are absent. */
|
|
271
|
+
lastRunsForItems(itemKeys, options = {}) {
|
|
272
|
+
const result = new Map();
|
|
273
|
+
const unique = [...new Set(itemKeys)];
|
|
274
|
+
for (let i = 0; i < unique.length; i += 500) {
|
|
275
|
+
const chunk = unique.slice(i, i + 500);
|
|
276
|
+
const params = [...chunk];
|
|
277
|
+
let filter = '';
|
|
278
|
+
if (options.workflowId !== undefined) {
|
|
279
|
+
filter += ' AND workflow_id = ?';
|
|
280
|
+
params.push(options.workflowId);
|
|
281
|
+
}
|
|
282
|
+
if (options.finishedOnly)
|
|
283
|
+
filter += ' AND finished_at IS NOT NULL';
|
|
284
|
+
const order = options.finishedOnly ? 'finished_at DESC, id DESC' : 'created_at DESC, id DESC';
|
|
285
|
+
const rows = all(this.db, `SELECT * FROM (
|
|
286
|
+
SELECT *, ROW_NUMBER() OVER (PARTITION BY source_item_key ORDER BY ${order}) AS rn
|
|
287
|
+
FROM runs WHERE source_item_key IN (${placeholders(chunk.length)})${filter}
|
|
288
|
+
) WHERE rn = 1`, params);
|
|
289
|
+
for (const row of rows)
|
|
290
|
+
result.set(String(row.source_item_key), toRun(row));
|
|
291
|
+
}
|
|
292
|
+
return result;
|
|
293
|
+
}
|
|
294
|
+
/** Active lock for `(workflowId, lockKey)` or `null`. */
|
|
295
|
+
activeLock(workflowId, lockKey) {
|
|
296
|
+
const row = get(this.db, 'SELECT * FROM locks WHERE workflow_id = ? AND lock_key = ?', [workflowId, lockKey]);
|
|
297
|
+
return row ? toLock(row) : null;
|
|
298
|
+
}
|
|
299
|
+
/** Active run of a workflow for a source item (scheduler step 4), or `null`. */
|
|
300
|
+
activeRunForItem(workflowId, itemKey) {
|
|
301
|
+
const lock = this.activeLock(workflowId, lockKeyFor({ triggerType: 'source', runId: '', sourceItemKey: itemKey }));
|
|
302
|
+
return lock ? this.get(lock.runId) : null;
|
|
303
|
+
}
|
|
304
|
+
/** All active locks. */
|
|
305
|
+
listLocks() {
|
|
306
|
+
return all(this.db, 'SELECT * FROM locks ORDER BY acquired_at ASC').map(toLock);
|
|
307
|
+
}
|
|
308
|
+
assertTransition(current, to, expectedFrom) {
|
|
309
|
+
if (expectedFrom !== undefined && current.status !== expectedFrom) {
|
|
310
|
+
throw new InvalidTransitionError(`Run '${current.id}' is in status '${current.status}', expected '${expectedFrom}'`, { runId: current.id, from: current.status, expectedFrom, to });
|
|
311
|
+
}
|
|
312
|
+
if (!canTransition(current.status, to)) {
|
|
313
|
+
throw new InvalidTransitionError(`Invalid run transition '${current.status}' → '${to}'`, {
|
|
314
|
+
runId: current.id,
|
|
315
|
+
from: current.status,
|
|
316
|
+
to,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
applyUpdate(runId, update, columns) {
|
|
321
|
+
const set = { ...columns };
|
|
322
|
+
if (update.pid !== undefined)
|
|
323
|
+
set.pid = update.pid;
|
|
324
|
+
if (update.processStartIdentity !== undefined)
|
|
325
|
+
set.process_start_identity = toJson(update.processStartIdentity ?? undefined);
|
|
326
|
+
if (update.workspacePath !== undefined)
|
|
327
|
+
set.workspace_path = update.workspacePath;
|
|
328
|
+
if (update.statusMessage !== undefined)
|
|
329
|
+
set.status_message = update.statusMessage;
|
|
330
|
+
if (update.lifecycleStatus !== undefined)
|
|
331
|
+
set.lifecycle_status = update.lifecycleStatus;
|
|
332
|
+
if (update.exitCode !== undefined)
|
|
333
|
+
set.exit_code = update.exitCode;
|
|
334
|
+
if (update.result !== undefined)
|
|
335
|
+
set.result_json = toJson(update.result ?? undefined);
|
|
336
|
+
if (update.error !== undefined)
|
|
337
|
+
set.error_json = toJson(update.error ?? undefined);
|
|
338
|
+
if (update.configSnapshot !== undefined)
|
|
339
|
+
set.config_snapshot = JSON.stringify(update.configSnapshot);
|
|
340
|
+
if (update.identity !== undefined)
|
|
341
|
+
set.identity = update.identity;
|
|
342
|
+
if (update.command !== undefined)
|
|
343
|
+
set.command = toJson(update.command ?? undefined);
|
|
344
|
+
if (update.startedAt !== undefined)
|
|
345
|
+
set.started_at = update.startedAt === null ? null : iso(update.startedAt);
|
|
346
|
+
set.updated_at = this.clock.now().toISOString();
|
|
347
|
+
const keys = Object.keys(set);
|
|
348
|
+
run(this.db, `UPDATE runs SET ${keys.map((k) => `${k} = ?`).join(', ')} WHERE id = ?`, [
|
|
349
|
+
...keys.map((k) => set[k] ?? null),
|
|
350
|
+
runId,
|
|
351
|
+
]);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/** The persisted finalization target of a run, or `null` before `finalizing`. */
|
|
355
|
+
export function finalizationTarget(run) {
|
|
356
|
+
if (run.finalStatus === null)
|
|
357
|
+
return null;
|
|
358
|
+
return { status: run.finalStatus, businessResult: run.businessResult, reason: run.finalReason ?? '' };
|
|
359
|
+
}
|
|
360
|
+
function validateTarget(target) {
|
|
361
|
+
if (!isTerminalStatus(target.status)) {
|
|
362
|
+
throw new InvalidTransitionError(`Finalization target '${String(target.status)}' is not terminal`, { target });
|
|
363
|
+
}
|
|
364
|
+
if (target.status === 'completed') {
|
|
365
|
+
if (target.businessResult !== 'success' && target.businessResult !== 'failure') {
|
|
366
|
+
throw new InvalidTransitionError('Target `completed` requires businessResult success|failure', { target });
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
else if (target.businessResult !== null) {
|
|
370
|
+
throw new InvalidTransitionError(`Target '${target.status}' requires businessResult null`, { target });
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
function toRun(row) {
|
|
374
|
+
return {
|
|
375
|
+
id: String(row.id),
|
|
376
|
+
workflowId: String(row.workflow_id),
|
|
377
|
+
triggerType: row.trigger_type,
|
|
378
|
+
sourceId: str(row.source_id),
|
|
379
|
+
sourceItemKey: str(row.source_item_key),
|
|
380
|
+
sourceUrl: str(row.source_url),
|
|
381
|
+
lockKey: String(row.lock_key),
|
|
382
|
+
scheduledFor: str(row.scheduled_for),
|
|
383
|
+
configSnapshot: fromJson(row.config_snapshot),
|
|
384
|
+
parameters: fromJson(row.parameters_json),
|
|
385
|
+
identity: str(row.identity),
|
|
386
|
+
command: fromJson(row.command),
|
|
387
|
+
status: row.status,
|
|
388
|
+
finalStatus: str(row.final_status) ?? null,
|
|
389
|
+
businessResult: str(row.business_result) ?? null,
|
|
390
|
+
finalReason: str(row.final_reason),
|
|
391
|
+
exitCode: num(row.exit_code),
|
|
392
|
+
pid: num(row.pid),
|
|
393
|
+
processStartIdentity: fromJson(row.process_start_identity),
|
|
394
|
+
workspacePath: str(row.workspace_path),
|
|
395
|
+
statusMessage: str(row.status_message),
|
|
396
|
+
result: fromJson(row.result_json),
|
|
397
|
+
error: fromJson(row.error_json),
|
|
398
|
+
lifecycleStatus: str(row.lifecycle_status) ?? null,
|
|
399
|
+
blockGeneration: num(row.block_generation),
|
|
400
|
+
countedTechnicalFailure: Number(row.counted_technical_failure) === 1,
|
|
401
|
+
createdAt: String(row.created_at),
|
|
402
|
+
startedAt: str(row.started_at),
|
|
403
|
+
finalizingAt: str(row.finalizing_at),
|
|
404
|
+
finishedAt: str(row.finished_at),
|
|
405
|
+
updatedAt: String(row.updated_at),
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
function toLock(row) {
|
|
409
|
+
return {
|
|
410
|
+
workflowId: String(row.workflow_id),
|
|
411
|
+
lockKey: String(row.lock_key),
|
|
412
|
+
runId: String(row.run_id),
|
|
413
|
+
sourceItemKey: str(row.source_item_key),
|
|
414
|
+
acquiredAt: String(row.acquired_at),
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
//# sourceMappingURL=runs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/persistence/runs.ts"],"names":[],"mappings":"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"}
|