@adonis-agora/durable 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 +29 -0
- package/dist/assets/dashboard.html +446 -0
- package/dist/commands/main.d.ts +15 -0
- package/dist/commands/main.d.ts.map +1 -0
- package/dist/commands/main.js +15 -0
- package/dist/commands/main.js.map +1 -0
- package/dist/commands/retry.d.ts +16 -0
- package/dist/commands/retry.d.ts.map +1 -0
- package/dist/commands/retry.js +34 -0
- package/dist/commands/retry.js.map +1 -0
- package/dist/commands/runs.d.ts +17 -0
- package/dist/commands/runs.d.ts.map +1 -0
- package/dist/commands/runs.js +40 -0
- package/dist/commands/runs.js.map +1 -0
- package/dist/commands/work.d.ts +18 -0
- package/dist/commands/work.d.ts.map +1 -0
- package/dist/commands/work.js +58 -0
- package/dist/commands/work.js.map +1 -0
- package/dist/configure.d.ts +15 -0
- package/dist/configure.d.ts.map +1 -0
- package/dist/configure.js +26 -0
- package/dist/configure.js.map +1 -0
- package/dist/providers/dashboard_provider.d.ts +27 -0
- package/dist/providers/dashboard_provider.d.ts.map +1 -0
- package/dist/providers/dashboard_provider.js +94 -0
- package/dist/providers/dashboard_provider.js.map +1 -0
- package/dist/providers/durable_provider.d.ts +36 -0
- package/dist/providers/durable_provider.d.ts.map +1 -0
- package/dist/providers/durable_provider.js +113 -0
- package/dist/providers/durable_provider.js.map +1 -0
- package/dist/src/admission-redis/index.d.ts +2 -0
- package/dist/src/admission-redis/index.d.ts.map +1 -0
- package/dist/src/admission-redis/index.js +2 -0
- package/dist/src/admission-redis/index.js.map +1 -0
- package/dist/src/admission-redis/redis-admission-backend.d.ts +83 -0
- package/dist/src/admission-redis/redis-admission-backend.d.ts.map +1 -0
- package/dist/src/admission-redis/redis-admission-backend.js +200 -0
- package/dist/src/admission-redis/redis-admission-backend.js.map +1 -0
- package/dist/src/admission.d.ts +49 -0
- package/dist/src/admission.d.ts.map +1 -0
- package/dist/src/admission.js +30 -0
- package/dist/src/admission.js.map +1 -0
- package/dist/src/backoff.d.ts +5 -0
- package/dist/src/backoff.d.ts.map +1 -0
- package/dist/src/backoff.js +11 -0
- package/dist/src/backoff.js.map +1 -0
- package/dist/src/checkpoints.d.ts +42 -0
- package/dist/src/checkpoints.d.ts.map +1 -0
- package/dist/src/checkpoints.js +57 -0
- package/dist/src/checkpoints.js.map +1 -0
- package/dist/src/codec-state-store.d.ts +60 -0
- package/dist/src/codec-state-store.d.ts.map +1 -0
- package/dist/src/codec-state-store.js +129 -0
- package/dist/src/codec-state-store.js.map +1 -0
- package/dist/src/commands/index.d.ts +3 -0
- package/dist/src/commands/index.d.ts.map +1 -0
- package/dist/src/commands/index.js +3 -0
- package/dist/src/commands/index.js.map +1 -0
- package/dist/src/commands/runs.d.ts +24 -0
- package/dist/src/commands/runs.d.ts.map +1 -0
- package/dist/src/commands/runs.js +39 -0
- package/dist/src/commands/runs.js.map +1 -0
- package/dist/src/commands/worker.d.ts +61 -0
- package/dist/src/commands/worker.d.ts.map +1 -0
- package/dist/src/commands/worker.js +74 -0
- package/dist/src/commands/worker.js.map +1 -0
- package/dist/src/completion.d.ts +15 -0
- package/dist/src/completion.d.ts.map +1 -0
- package/dist/src/completion.js +10 -0
- package/dist/src/completion.js.map +1 -0
- package/dist/src/dashboard/define_config.d.ts +48 -0
- package/dist/src/dashboard/define_config.d.ts.map +1 -0
- package/dist/src/dashboard/define_config.js +57 -0
- package/dist/src/dashboard/define_config.js.map +1 -0
- package/dist/src/dashboard/handlers.d.ts +47 -0
- package/dist/src/dashboard/handlers.d.ts.map +1 -0
- package/dist/src/dashboard/handlers.js +163 -0
- package/dist/src/dashboard/handlers.js.map +1 -0
- package/dist/src/dashboard/html.d.ts +7 -0
- package/dist/src/dashboard/html.d.ts.map +1 -0
- package/dist/src/dashboard/html.js +24 -0
- package/dist/src/dashboard/html.js.map +1 -0
- package/dist/src/dashboard/index.d.ts +8 -0
- package/dist/src/dashboard/index.d.ts.map +1 -0
- package/dist/src/dashboard/index.js +6 -0
- package/dist/src/dashboard/index.js.map +1 -0
- package/dist/src/define_config.d.ts +72 -0
- package/dist/src/define_config.d.ts.map +1 -0
- package/dist/src/define_config.js +8 -0
- package/dist/src/define_config.js.map +1 -0
- package/dist/src/diagnostics-bridge.d.ts +22 -0
- package/dist/src/diagnostics-bridge.d.ts.map +1 -0
- package/dist/src/diagnostics-bridge.js +25 -0
- package/dist/src/diagnostics-bridge.js.map +1 -0
- package/dist/src/duration.d.ts +6 -0
- package/dist/src/duration.d.ts.map +1 -0
- package/dist/src/duration.js +39 -0
- package/dist/src/duration.js.map +1 -0
- package/dist/src/engine.d.ts +583 -0
- package/dist/src/engine.d.ts.map +1 -0
- package/dist/src/engine.js +1894 -0
- package/dist/src/engine.js.map +1 -0
- package/dist/src/entities.d.ts +44 -0
- package/dist/src/entities.d.ts.map +1 -0
- package/dist/src/entities.js +64 -0
- package/dist/src/entities.js.map +1 -0
- package/dist/src/errors.d.ts +68 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +102 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/event-accumulators.d.ts +39 -0
- package/dist/src/event-accumulators.d.ts.map +1 -0
- package/dist/src/event-accumulators.js +70 -0
- package/dist/src/event-accumulators.js.map +1 -0
- package/dist/src/events.d.ts +9 -0
- package/dist/src/events.d.ts.map +1 -0
- package/dist/src/events.js +35 -0
- package/dist/src/events.js.map +1 -0
- package/dist/src/index.d.ts +36 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +37 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces.d.ts +909 -0
- package/dist/src/interfaces.d.ts.map +1 -0
- package/dist/src/interfaces.js +2 -0
- package/dist/src/interfaces.js.map +1 -0
- package/dist/src/metrics.d.ts +44 -0
- package/dist/src/metrics.d.ts.map +1 -0
- package/dist/src/metrics.js +78 -0
- package/dist/src/metrics.js.map +1 -0
- package/dist/src/otel/durable-metrics.d.ts +42 -0
- package/dist/src/otel/durable-metrics.d.ts.map +1 -0
- package/dist/src/otel/durable-metrics.js +75 -0
- package/dist/src/otel/durable-metrics.js.map +1 -0
- package/dist/src/otel/durable-otel.d.ts +20 -0
- package/dist/src/otel/durable-otel.d.ts.map +1 -0
- package/dist/src/otel/durable-otel.js +74 -0
- package/dist/src/otel/durable-otel.js.map +1 -0
- package/dist/src/otel/index.d.ts +4 -0
- package/dist/src/otel/index.d.ts.map +1 -0
- package/dist/src/otel/index.js +4 -0
- package/dist/src/otel/index.js.map +1 -0
- package/dist/src/otel/traceparent.d.ts +17 -0
- package/dist/src/otel/traceparent.d.ts.map +1 -0
- package/dist/src/otel/traceparent.js +21 -0
- package/dist/src/otel/traceparent.js.map +1 -0
- package/dist/src/pollers.d.ts +33 -0
- package/dist/src/pollers.d.ts.map +1 -0
- package/dist/src/pollers.js +76 -0
- package/dist/src/pollers.js.map +1 -0
- package/dist/src/protocol.d.ts +17 -0
- package/dist/src/protocol.d.ts.map +1 -0
- package/dist/src/protocol.js +47 -0
- package/dist/src/protocol.js.map +1 -0
- package/dist/src/queue.d.ts +113 -0
- package/dist/src/queue.d.ts.map +1 -0
- package/dist/src/queue.js +128 -0
- package/dist/src/queue.js.map +1 -0
- package/dist/src/remote-step-factory.d.ts +15 -0
- package/dist/src/remote-step-factory.d.ts.map +1 -0
- package/dist/src/remote-step-factory.js +12 -0
- package/dist/src/remote-step-factory.js.map +1 -0
- package/dist/src/remote-workflow-executor.d.ts +24 -0
- package/dist/src/remote-workflow-executor.d.ts.map +1 -0
- package/dist/src/remote-workflow-executor.js +70 -0
- package/dist/src/remote-workflow-executor.js.map +1 -0
- package/dist/src/scheduler.d.ts +67 -0
- package/dist/src/scheduler.d.ts.map +1 -0
- package/dist/src/scheduler.js +111 -0
- package/dist/src/scheduler.js.map +1 -0
- package/dist/src/search-attributes.d.ts +48 -0
- package/dist/src/search-attributes.d.ts.map +1 -0
- package/dist/src/search-attributes.js +98 -0
- package/dist/src/search-attributes.js.map +1 -0
- package/dist/src/singleton-gate.d.ts +44 -0
- package/dist/src/singleton-gate.d.ts.map +1 -0
- package/dist/src/singleton-gate.js +90 -0
- package/dist/src/singleton-gate.js.map +1 -0
- package/dist/src/step-logger.d.ts +9 -0
- package/dist/src/step-logger.d.ts.map +1 -0
- package/dist/src/step-logger.js +89 -0
- package/dist/src/step-logger.js.map +1 -0
- package/dist/src/stores/factory.d.ts +42 -0
- package/dist/src/stores/factory.d.ts.map +1 -0
- package/dist/src/stores/factory.js +29 -0
- package/dist/src/stores/factory.js.map +1 -0
- package/dist/src/stores/lucid-helpers.d.ts +11 -0
- package/dist/src/stores/lucid-helpers.d.ts.map +1 -0
- package/dist/src/stores/lucid-helpers.js +38 -0
- package/dist/src/stores/lucid-helpers.js.map +1 -0
- package/dist/src/stores/lucid-mappers.d.ts +58 -0
- package/dist/src/stores/lucid-mappers.d.ts.map +1 -0
- package/dist/src/stores/lucid-mappers.js +174 -0
- package/dist/src/stores/lucid-mappers.js.map +1 -0
- package/dist/src/stores/lucid-schema.d.ts +28 -0
- package/dist/src/stores/lucid-schema.d.ts.map +1 -0
- package/dist/src/stores/lucid-schema.js +115 -0
- package/dist/src/stores/lucid-schema.js.map +1 -0
- package/dist/src/stores/lucid.d.ts +69 -0
- package/dist/src/stores/lucid.d.ts.map +1 -0
- package/dist/src/stores/lucid.js +342 -0
- package/dist/src/stores/lucid.js.map +1 -0
- package/dist/src/telescope/dashboard.d.ts +15 -0
- package/dist/src/telescope/dashboard.d.ts.map +1 -0
- package/dist/src/telescope/dashboard.js +113 -0
- package/dist/src/telescope/dashboard.js.map +1 -0
- package/dist/src/telescope/data-providers.d.ts +20 -0
- package/dist/src/telescope/data-providers.d.ts.map +1 -0
- package/dist/src/telescope/data-providers.js +322 -0
- package/dist/src/telescope/data-providers.js.map +1 -0
- package/dist/src/telescope/extension.d.ts +22 -0
- package/dist/src/telescope/extension.d.ts.map +1 -0
- package/dist/src/telescope/extension.js +38 -0
- package/dist/src/telescope/extension.js.map +1 -0
- package/dist/src/telescope/index.d.ts +5 -0
- package/dist/src/telescope/index.d.ts.map +1 -0
- package/dist/src/telescope/index.js +4 -0
- package/dist/src/telescope/index.js.map +1 -0
- package/dist/src/telescope/telescope-sdk.d.ts +123 -0
- package/dist/src/telescope/telescope-sdk.d.ts.map +1 -0
- package/dist/src/telescope/telescope-sdk.js +12 -0
- package/dist/src/telescope/telescope-sdk.js.map +1 -0
- package/dist/src/test-helpers.d.ts +11 -0
- package/dist/src/test-helpers.d.ts.map +1 -0
- package/dist/src/test-helpers.js +12 -0
- package/dist/src/test-helpers.js.map +1 -0
- package/dist/src/testing/in-memory-state-store.d.ts +64 -0
- package/dist/src/testing/in-memory-state-store.d.ts.map +1 -0
- package/dist/src/testing/in-memory-state-store.js +259 -0
- package/dist/src/testing/in-memory-state-store.js.map +1 -0
- package/dist/src/testing/in-memory-transport.d.ts +25 -0
- package/dist/src/testing/in-memory-transport.d.ts.map +1 -0
- package/dist/src/testing/in-memory-transport.js +49 -0
- package/dist/src/testing/in-memory-transport.js.map +1 -0
- package/dist/src/testing-kit/admission-backend-conformance.d.ts +18 -0
- package/dist/src/testing-kit/admission-backend-conformance.d.ts.map +1 -0
- package/dist/src/testing-kit/admission-backend-conformance.js +81 -0
- package/dist/src/testing-kit/admission-backend-conformance.js.map +1 -0
- package/dist/src/testing-kit/assertions.d.ts +10 -0
- package/dist/src/testing-kit/assertions.d.ts.map +1 -0
- package/dist/src/testing-kit/assertions.js +41 -0
- package/dist/src/testing-kit/assertions.js.map +1 -0
- package/dist/src/testing-kit/harness.d.ts +28 -0
- package/dist/src/testing-kit/harness.d.ts.map +1 -0
- package/dist/src/testing-kit/harness.js +42 -0
- package/dist/src/testing-kit/harness.js.map +1 -0
- package/dist/src/testing-kit/index.d.ts +8 -0
- package/dist/src/testing-kit/index.d.ts.map +1 -0
- package/dist/src/testing-kit/index.js +8 -0
- package/dist/src/testing-kit/index.js.map +1 -0
- package/dist/src/testing-kit/replay.d.ts +22 -0
- package/dist/src/testing-kit/replay.d.ts.map +1 -0
- package/dist/src/testing-kit/replay.js +38 -0
- package/dist/src/testing-kit/replay.js.map +1 -0
- package/dist/src/testing-kit/state-store-conformance.d.ts +51 -0
- package/dist/src/testing-kit/state-store-conformance.d.ts.map +1 -0
- package/dist/src/testing-kit/state-store-conformance.js +430 -0
- package/dist/src/testing-kit/state-store-conformance.js.map +1 -0
- package/dist/src/testing-kit/steps.d.ts +5 -0
- package/dist/src/testing-kit/steps.d.ts.map +1 -0
- package/dist/src/testing-kit/steps.js +15 -0
- package/dist/src/testing-kit/steps.js.map +1 -0
- package/dist/src/testing-kit/transport-conformance.d.ts +16 -0
- package/dist/src/testing-kit/transport-conformance.d.ts.map +1 -0
- package/dist/src/testing-kit/transport-conformance.js +64 -0
- package/dist/src/testing-kit/transport-conformance.js.map +1 -0
- package/dist/src/tokens.d.ts +18 -0
- package/dist/src/tokens.d.ts.map +1 -0
- package/dist/src/tokens.js +18 -0
- package/dist/src/tokens.js.map +1 -0
- package/dist/src/transport-pool.d.ts +30 -0
- package/dist/src/transport-pool.d.ts.map +1 -0
- package/dist/src/transport-pool.js +82 -0
- package/dist/src/transport-pool.js.map +1 -0
- package/dist/src/transports/db-helpers.d.ts +10 -0
- package/dist/src/transports/db-helpers.d.ts.map +1 -0
- package/dist/src/transports/db-helpers.js +33 -0
- package/dist/src/transports/db-helpers.js.map +1 -0
- package/dist/src/transports/db-schema.d.ts +28 -0
- package/dist/src/transports/db-schema.d.ts.map +1 -0
- package/dist/src/transports/db-schema.js +98 -0
- package/dist/src/transports/db-schema.js.map +1 -0
- package/dist/src/transports/db.d.ts +81 -0
- package/dist/src/transports/db.d.ts.map +1 -0
- package/dist/src/transports/db.js +340 -0
- package/dist/src/transports/db.js.map +1 -0
- package/dist/src/transports/factory.d.ts +79 -0
- package/dist/src/transports/factory.d.ts.map +1 -0
- package/dist/src/transports/factory.js +57 -0
- package/dist/src/transports/factory.js.map +1 -0
- package/dist/src/transports/queue-mock-adapter.d.ts +39 -0
- package/dist/src/transports/queue-mock-adapter.d.ts.map +1 -0
- package/dist/src/transports/queue-mock-adapter.js +86 -0
- package/dist/src/transports/queue-mock-adapter.js.map +1 -0
- package/dist/src/transports/queue.d.ts +84 -0
- package/dist/src/transports/queue.d.ts.map +1 -0
- package/dist/src/transports/queue.js +210 -0
- package/dist/src/transports/queue.js.map +1 -0
- package/dist/src/workflow-ctx.d.ts +64 -0
- package/dist/src/workflow-ctx.d.ts.map +1 -0
- package/dist/src/workflow-ctx.js +457 -0
- package/dist/src/workflow-ctx.js.map +1 -0
- package/dist/src/workflow-ref.d.ts +34 -0
- package/dist/src/workflow-ref.d.ts.map +1 -0
- package/dist/src/workflow-ref.js +28 -0
- package/dist/src/workflow-ref.js.map +1 -0
- package/dist/stubs/config/durable.stub +49 -0
- package/dist/stubs/config/durable_dashboard.stub +17 -0
- package/dist/stubs/database/migrations/create_durable_tables.stub +87 -0
- package/dist/stubs/database/migrations/create_durable_transport_tables.stub +75 -0
- package/dist/stubs/main.d.ts +3 -0
- package/dist/stubs/main.d.ts.map +1 -0
- package/dist/stubs/main.js +4 -0
- package/dist/stubs/main.js.map +1 -0
- package/package.json +154 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { AttributeFilter, AttributeOp, RunQuery, WorkflowRun } from './interfaces.js';
|
|
2
|
+
import type { SearchAttributes } from './interfaces.js';
|
|
3
|
+
/**
|
|
4
|
+
* Does a run's search attributes satisfy EVERY filter (AND)? A missing key never matches (so `ne`
|
|
5
|
+
* on an absent key is false too — the attribute simply isn't there to compare). Empty/undefined
|
|
6
|
+
* filters match everything. Shared by every store so typed/range queries behave identically across
|
|
7
|
+
* adapters (applied in-process after the coarse workflow/status/tag filters).
|
|
8
|
+
*/
|
|
9
|
+
export declare function matchesAttributes(attributes: SearchAttributes | undefined, filters: AttributeFilter[] | undefined): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Apply a query's attribute predicates then its `offset`/`limit`, in-process — for store adapters
|
|
12
|
+
* that can't express typed/range predicates in SQL. Pass rows already coarse-filtered (workflow /
|
|
13
|
+
* status / tag) and sorted newest-first; this filters by `attributes` and paginates. Only call it
|
|
14
|
+
* when `query.attributes` is set (otherwise let the DB do `LIMIT`/`OFFSET`).
|
|
15
|
+
*/
|
|
16
|
+
export declare function applyAttributeQuery(rows: WorkflowRun[], query: RunQuery): WorkflowRun[];
|
|
17
|
+
/**
|
|
18
|
+
* One normalized row of the `durable_run_attributes` side-table: a single (key → value) pair of a
|
|
19
|
+
* run's search attributes, split into typed columns so SQL can index/range-scan it. Exactly one of
|
|
20
|
+
* `strValue`/`numValue` is set per row (booleans normalize to a string `"true"`/`"false"` so `eq`/`ne`
|
|
21
|
+
* still match). NULL for the column that doesn't apply, which keeps `(key, numValue)` /
|
|
22
|
+
* `(key, strValue)` indexes selective.
|
|
23
|
+
*/
|
|
24
|
+
export interface RunAttributeRow {
|
|
25
|
+
runId: string;
|
|
26
|
+
key: string;
|
|
27
|
+
strValue: string | null;
|
|
28
|
+
numValue: number | null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Explode a run's search attributes into normalized side-table rows (one per key). Used by SQL stores
|
|
32
|
+
* to maintain `durable_run_attributes` on every create/update and by the in-memory store's index, so
|
|
33
|
+
* attribute predicates can be pushed DOWN into a join/EXISTS instead of scanned in-process. Numbers go
|
|
34
|
+
* to `numValue`; strings to `strValue`; booleans to `strValue` as `"true"`/`"false"` (matching how the
|
|
35
|
+
* in-process `compare` treats `eq`/`ne` on booleans). Returns `[]` for a run with no attributes.
|
|
36
|
+
*/
|
|
37
|
+
export declare function normalizeAttributeRows(runId: string, attributes: SearchAttributes | undefined): RunAttributeRow[];
|
|
38
|
+
/** SQL comparison operator for an {@link AttributeOp} (used to build pushdown predicates). */
|
|
39
|
+
export declare function sqlComparator(op: AttributeOp): string;
|
|
40
|
+
/**
|
|
41
|
+
* Which side-table column an attribute filter compares against: numeric operands (and range ops on
|
|
42
|
+
* numbers) hit `numValue`; everything else hits `strValue` (booleans are stored as `"true"`/`"false"`).
|
|
43
|
+
* Keeping this in core means every SQL adapter pushes predicates down identically.
|
|
44
|
+
*/
|
|
45
|
+
export declare function attributeColumnFor(filter: AttributeFilter): 'numValue' | 'strValue';
|
|
46
|
+
/** The literal a side-table predicate compares against (booleans → `"true"`/`"false"` strings). */
|
|
47
|
+
export declare function attributeOperand(filter: AttributeFilter): string | number;
|
|
48
|
+
//# sourceMappingURL=search-attributes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-attributes.d.ts","sourceRoot":"","sources":["../../src/search-attributes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC3F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAoBxD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,gBAAgB,GAAG,SAAS,EACxC,OAAO,EAAE,eAAe,EAAE,GAAG,SAAS,GACrC,OAAO,CAIT;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,QAAQ,GAAG,WAAW,EAAE,CAKvF;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,gBAAgB,GAAG,SAAS,GACvC,eAAe,EAAE,CAanB;AAED,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAerD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,UAAU,GAAG,UAAU,CAEnF;AAED,mGAAmG;AACnG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,GAAG,MAAM,CAGzE"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Compare one attribute value against a filter operand. Range ops need both sides comparable. */
|
|
2
|
+
function compare(actual, op, expected) {
|
|
3
|
+
switch (op) {
|
|
4
|
+
case 'eq':
|
|
5
|
+
return actual === expected;
|
|
6
|
+
case 'ne':
|
|
7
|
+
return actual !== expected;
|
|
8
|
+
case 'gt':
|
|
9
|
+
return actual != null && actual > expected;
|
|
10
|
+
case 'gte':
|
|
11
|
+
return actual != null && actual >= expected;
|
|
12
|
+
case 'lt':
|
|
13
|
+
return actual != null && actual < expected;
|
|
14
|
+
case 'lte':
|
|
15
|
+
return actual != null && actual <= expected;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Does a run's search attributes satisfy EVERY filter (AND)? A missing key never matches (so `ne`
|
|
20
|
+
* on an absent key is false too — the attribute simply isn't there to compare). Empty/undefined
|
|
21
|
+
* filters match everything. Shared by every store so typed/range queries behave identically across
|
|
22
|
+
* adapters (applied in-process after the coarse workflow/status/tag filters).
|
|
23
|
+
*/
|
|
24
|
+
export function matchesAttributes(attributes, filters) {
|
|
25
|
+
if (!filters?.length)
|
|
26
|
+
return true;
|
|
27
|
+
if (!attributes)
|
|
28
|
+
return false;
|
|
29
|
+
return filters.every((f) => f.key in attributes && compare(attributes[f.key], f.op, f.value));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Apply a query's attribute predicates then its `offset`/`limit`, in-process — for store adapters
|
|
33
|
+
* that can't express typed/range predicates in SQL. Pass rows already coarse-filtered (workflow /
|
|
34
|
+
* status / tag) and sorted newest-first; this filters by `attributes` and paginates. Only call it
|
|
35
|
+
* when `query.attributes` is set (otherwise let the DB do `LIMIT`/`OFFSET`).
|
|
36
|
+
*/
|
|
37
|
+
export function applyAttributeQuery(rows, query) {
|
|
38
|
+
const filtered = rows.filter((r) => matchesAttributes(r.searchAttributes, query.attributes));
|
|
39
|
+
const offset = query.offset ?? 0;
|
|
40
|
+
const limit = query.limit ?? filtered.length;
|
|
41
|
+
return filtered.slice(offset, offset + limit);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Explode a run's search attributes into normalized side-table rows (one per key). Used by SQL stores
|
|
45
|
+
* to maintain `durable_run_attributes` on every create/update and by the in-memory store's index, so
|
|
46
|
+
* attribute predicates can be pushed DOWN into a join/EXISTS instead of scanned in-process. Numbers go
|
|
47
|
+
* to `numValue`; strings to `strValue`; booleans to `strValue` as `"true"`/`"false"` (matching how the
|
|
48
|
+
* in-process `compare` treats `eq`/`ne` on booleans). Returns `[]` for a run with no attributes.
|
|
49
|
+
*/
|
|
50
|
+
export function normalizeAttributeRows(runId, attributes) {
|
|
51
|
+
if (!attributes)
|
|
52
|
+
return [];
|
|
53
|
+
const out = [];
|
|
54
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
55
|
+
if (typeof value === 'number') {
|
|
56
|
+
out.push({ runId, key, strValue: null, numValue: value });
|
|
57
|
+
}
|
|
58
|
+
else if (typeof value === 'boolean') {
|
|
59
|
+
out.push({ runId, key, strValue: value ? 'true' : 'false', numValue: null });
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
out.push({ runId, key, strValue: value, numValue: null });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
/** SQL comparison operator for an {@link AttributeOp} (used to build pushdown predicates). */
|
|
68
|
+
export function sqlComparator(op) {
|
|
69
|
+
switch (op) {
|
|
70
|
+
case 'eq':
|
|
71
|
+
return '=';
|
|
72
|
+
case 'ne':
|
|
73
|
+
return '<>';
|
|
74
|
+
case 'gt':
|
|
75
|
+
return '>';
|
|
76
|
+
case 'gte':
|
|
77
|
+
return '>=';
|
|
78
|
+
case 'lt':
|
|
79
|
+
return '<';
|
|
80
|
+
case 'lte':
|
|
81
|
+
return '<=';
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Which side-table column an attribute filter compares against: numeric operands (and range ops on
|
|
86
|
+
* numbers) hit `numValue`; everything else hits `strValue` (booleans are stored as `"true"`/`"false"`).
|
|
87
|
+
* Keeping this in core means every SQL adapter pushes predicates down identically.
|
|
88
|
+
*/
|
|
89
|
+
export function attributeColumnFor(filter) {
|
|
90
|
+
return typeof filter.value === 'number' ? 'numValue' : 'strValue';
|
|
91
|
+
}
|
|
92
|
+
/** The literal a side-table predicate compares against (booleans → `"true"`/`"false"` strings). */
|
|
93
|
+
export function attributeOperand(filter) {
|
|
94
|
+
if (typeof filter.value === 'boolean')
|
|
95
|
+
return filter.value ? 'true' : 'false';
|
|
96
|
+
return filter.value;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=search-attributes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-attributes.js","sourceRoot":"","sources":["../../src/search-attributes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { SingletonConfig } from './engine.js';
|
|
2
|
+
import type { StateStore, WorkflowRun } from './interfaces.js';
|
|
3
|
+
export interface SingletonGateDeps {
|
|
4
|
+
store: Pick<StateStore, 'listRuns' | 'updateRun'>;
|
|
5
|
+
clock: () => number;
|
|
6
|
+
/** Hand a gated run to the run dispatcher (fire-and-forget, like the engine's other dispatches). */
|
|
7
|
+
dispatch: (runId: string) => void;
|
|
8
|
+
/** Resolve a settled run's singleton config from the engine's workflow registry. */
|
|
9
|
+
configFor: (run: WorkflowRun) => SingletonConfig | undefined;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Per-key serialization for singleton workflows — start-time back-pressure, FIFO race-free
|
|
13
|
+
* admission, and notify-on-release wakeups. Extracted from {@link WorkflowEngine} so the whole
|
|
14
|
+
* singleton feature lives in one place instead of being smeared across `start`, `execute`, both run
|
|
15
|
+
* loops, and `cancel`.
|
|
16
|
+
*/
|
|
17
|
+
export declare class SingletonGate {
|
|
18
|
+
private readonly deps;
|
|
19
|
+
constructor(deps: SingletonGateDeps);
|
|
20
|
+
/** The tag a singleton run carries, so the gate can find others sharing its key. */
|
|
21
|
+
tag(cfg: SingletonConfig, input: unknown): string;
|
|
22
|
+
/** Next wake time for a gated run: the base retry delay jittered to avoid a wakeup stampede. */
|
|
23
|
+
retryWakeAt(): number;
|
|
24
|
+
/**
|
|
25
|
+
* Reject a start that would grow the same-key backlog past `limit + maxQueueDepth` (counting
|
|
26
|
+
* `pending`/`running`/`suspended` runs sharing the key in one scan). No-op when no `maxQueueDepth`
|
|
27
|
+
* is configured.
|
|
28
|
+
*/
|
|
29
|
+
assertCapacity(workflow: string, cfg: SingletonConfig, input: unknown): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Whether `run` may run now under its key: it's among the `limit` oldest in-flight (running or
|
|
32
|
+
* suspended) runs sharing the key, by `(createdAt, id)` order. A consistent store gives every
|
|
33
|
+
* instance the same ordering, so admission is race-free + FIFO.
|
|
34
|
+
*/
|
|
35
|
+
admit(run: WorkflowRun, cfg: SingletonConfig): Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* Notify-on-release: a singleton run settled (freeing a slot), so dispatch the oldest gated
|
|
38
|
+
* (`suspended` + same tag) waiters now instead of waiting for their ~1s retry timer. Each re-checks
|
|
39
|
+
* admission in the executor and runs only if it actually wins a slot, so FIFO/race-free guarantees
|
|
40
|
+
* hold; the durable timer remains the cross-instance/crash fallback.
|
|
41
|
+
*/
|
|
42
|
+
wakeNext(settled: WorkflowRun): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=singleton-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"singleton-gate.d.ts","sourceRoot":"","sources":["../../src/singleton-gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAU/D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,WAAW,CAAC,CAAC;IAClD,KAAK,EAAE,MAAM,MAAM,CAAC;IACpB,oGAAoG;IACpG,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,oFAAoF;IACpF,SAAS,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,eAAe,GAAG,SAAS,CAAC;CAC9D;AAED;;;;;GAKG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,iBAAiB;IAEpD,oFAAoF;IACpF,GAAG,CAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM;IAIjD,gGAAgG;IAChG,WAAW,IAAI,MAAM;IAQrB;;;;OAIG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAa3F;;;;OAIG;IACG,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IAcrE;;;;;OAKG;IACG,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAmBpD"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { SingletonQueueFullError } from './errors.js';
|
|
2
|
+
const SINGLETON_RETRY_MS = 1000;
|
|
3
|
+
/**
|
|
4
|
+
* Max jitter (ms, each direction) added to {@link SINGLETON_RETRY_MS} so a queue of N gated runs
|
|
5
|
+
* doesn't wake in lockstep and stampede the admission scan. Each retry picks an independent offset
|
|
6
|
+
* in `[-SINGLETON_RETRY_JITTER_MS, +SINGLETON_RETRY_JITTER_MS]`.
|
|
7
|
+
*/
|
|
8
|
+
const SINGLETON_RETRY_JITTER_MS = 250;
|
|
9
|
+
/**
|
|
10
|
+
* Per-key serialization for singleton workflows — start-time back-pressure, FIFO race-free
|
|
11
|
+
* admission, and notify-on-release wakeups. Extracted from {@link WorkflowEngine} so the whole
|
|
12
|
+
* singleton feature lives in one place instead of being smeared across `start`, `execute`, both run
|
|
13
|
+
* loops, and `cancel`.
|
|
14
|
+
*/
|
|
15
|
+
export class SingletonGate {
|
|
16
|
+
deps;
|
|
17
|
+
constructor(deps) {
|
|
18
|
+
this.deps = deps;
|
|
19
|
+
}
|
|
20
|
+
/** The tag a singleton run carries, so the gate can find others sharing its key. */
|
|
21
|
+
tag(cfg, input) {
|
|
22
|
+
return `singleton:${cfg.key(input)}`;
|
|
23
|
+
}
|
|
24
|
+
/** Next wake time for a gated run: the base retry delay jittered to avoid a wakeup stampede. */
|
|
25
|
+
retryWakeAt() {
|
|
26
|
+
return (this.deps.clock() +
|
|
27
|
+
SINGLETON_RETRY_MS +
|
|
28
|
+
Math.floor((Math.random() * 2 - 1) * SINGLETON_RETRY_JITTER_MS));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Reject a start that would grow the same-key backlog past `limit + maxQueueDepth` (counting
|
|
32
|
+
* `pending`/`running`/`suspended` runs sharing the key in one scan). No-op when no `maxQueueDepth`
|
|
33
|
+
* is configured.
|
|
34
|
+
*/
|
|
35
|
+
async assertCapacity(workflow, cfg, input) {
|
|
36
|
+
if (cfg.maxQueueDepth == null)
|
|
37
|
+
return;
|
|
38
|
+
const cap = (cfg.limit ?? 1) + cfg.maxQueueDepth;
|
|
39
|
+
const queued = await this.deps.store.listRuns({
|
|
40
|
+
tag: this.tag(cfg, input),
|
|
41
|
+
workflow,
|
|
42
|
+
statuses: ['pending', 'running', 'suspended'],
|
|
43
|
+
});
|
|
44
|
+
if (queued.length >= cap) {
|
|
45
|
+
throw new SingletonQueueFullError(workflow, cfg.key(input), cfg.maxQueueDepth);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Whether `run` may run now under its key: it's among the `limit` oldest in-flight (running or
|
|
50
|
+
* suspended) runs sharing the key, by `(createdAt, id)` order. A consistent store gives every
|
|
51
|
+
* instance the same ordering, so admission is race-free + FIFO.
|
|
52
|
+
*/
|
|
53
|
+
async admit(run, cfg) {
|
|
54
|
+
// ONE scan for both in-flight statuses; the total `(createdAt, id)` sort makes admission order
|
|
55
|
+
// independent of the store's row order, preserving the FIFO + race-free-across-instances contract.
|
|
56
|
+
const inflight = (await this.deps.store.listRuns({
|
|
57
|
+
tag: this.tag(cfg, run.input),
|
|
58
|
+
workflow: run.workflow,
|
|
59
|
+
statuses: ['running', 'suspended'],
|
|
60
|
+
})).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id));
|
|
61
|
+
const idx = inflight.findIndex((r) => r.id === run.id);
|
|
62
|
+
return idx >= 0 && idx < (cfg.limit ?? 1);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Notify-on-release: a singleton run settled (freeing a slot), so dispatch the oldest gated
|
|
66
|
+
* (`suspended` + same tag) waiters now instead of waiting for their ~1s retry timer. Each re-checks
|
|
67
|
+
* admission in the executor and runs only if it actually wins a slot, so FIFO/race-free guarantees
|
|
68
|
+
* hold; the durable timer remains the cross-instance/crash fallback.
|
|
69
|
+
*/
|
|
70
|
+
async wakeNext(settled) {
|
|
71
|
+
const cfg = this.deps.configFor(settled);
|
|
72
|
+
if (!cfg)
|
|
73
|
+
return;
|
|
74
|
+
const tag = settled.tags?.find((t) => t.startsWith('singleton:'));
|
|
75
|
+
if (!tag)
|
|
76
|
+
return;
|
|
77
|
+
const gated = (await this.deps.store.listRuns({ tag, workflow: settled.workflow, statuses: ['suspended'] })).sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id));
|
|
78
|
+
for (const next of gated.slice(0, cfg.limit ?? 1)) {
|
|
79
|
+
// Clear the durable retry timer as we hand the run over, so the timer poller can't also pick it
|
|
80
|
+
// up and double-dispatch. Only for runs that carry a wakeAt; dispatch after the clear commits.
|
|
81
|
+
if (next.wakeAt != null) {
|
|
82
|
+
await this.deps.store
|
|
83
|
+
.updateRun(next.id, { wakeAt: undefined, updatedAt: new Date() })
|
|
84
|
+
.catch(() => undefined);
|
|
85
|
+
}
|
|
86
|
+
this.deps.dispatch(next.id);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=singleton-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"singleton-gate.js","sourceRoot":"","sources":["../../src/singleton-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { StepEvent, StepLogger } from './interfaces.js';
|
|
2
|
+
/**
|
|
3
|
+
* A {@link StepLogger} that appends to `events`, stamping each line with `now()`. Shared by the
|
|
4
|
+
* local-step path (`ctx.step`) and the remote-worker path (`runStepHandler`) so a step records
|
|
5
|
+
* the same {@link StepEvent} shape wherever it runs — the TypeScript twin of the Python SDK's
|
|
6
|
+
* `StepContext`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createStepLogger(events: StepEvent[], now: () => number): StepLogger;
|
|
9
|
+
//# sourceMappingURL=step-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-logger.d.ts","sourceRoot":"","sources":["../../src/step-logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAoB,MAAM,iBAAiB,CAAC;AAW/E;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,MAAM,MAAM,GAAG,UAAU,CAwEnF"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/** Attach the elapsed `durationMs` (from `start`) to `data`, unless the caller already set one. */
|
|
2
|
+
function withDuration(start, now, data) {
|
|
3
|
+
if (data && typeof data === 'object' && 'durationMs' in data) {
|
|
4
|
+
return data;
|
|
5
|
+
}
|
|
6
|
+
const base = data && typeof data === 'object' ? data : {};
|
|
7
|
+
return { ...base, durationMs: now() - start };
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A {@link StepLogger} that appends to `events`, stamping each line with `now()`. Shared by the
|
|
11
|
+
* local-step path (`ctx.step`) and the remote-worker path (`runStepHandler`) so a step records
|
|
12
|
+
* the same {@link StepEvent} shape wherever it runs — the TypeScript twin of the Python SDK's
|
|
13
|
+
* `StepContext`.
|
|
14
|
+
*/
|
|
15
|
+
export function createStepLogger(events, now) {
|
|
16
|
+
// The sub-process a `subProcess(...)` body is currently inside; debug/info/warn/error emitted while
|
|
17
|
+
// inside get tagged with its id, so the dashboard groups that log trail under the sub-process.
|
|
18
|
+
let currentSub;
|
|
19
|
+
const push = (level, message, data) => events.push({
|
|
20
|
+
at: now(),
|
|
21
|
+
level,
|
|
22
|
+
message,
|
|
23
|
+
...(currentSub ? { subId: currentSub.id } : {}),
|
|
24
|
+
...(data === undefined ? {} : { data }),
|
|
25
|
+
});
|
|
26
|
+
const subEvent = (e) => events.push({
|
|
27
|
+
at: now(),
|
|
28
|
+
level: e.status === 'failed' ? 'error' : e.status === 'skipped' ? 'warn' : 'info',
|
|
29
|
+
message: e.message ?? e.phase ?? e.name,
|
|
30
|
+
subId: e.id,
|
|
31
|
+
name: e.name,
|
|
32
|
+
...(e.group === undefined ? {} : { group: e.group }),
|
|
33
|
+
...(e.phase === undefined ? {} : { phase: e.phase }),
|
|
34
|
+
...(e.status === undefined ? {} : { status: e.status }),
|
|
35
|
+
...(e.data === undefined ? {} : { data: e.data }),
|
|
36
|
+
});
|
|
37
|
+
const subProcess = async (name, body, opts) => {
|
|
38
|
+
const id = opts?.id ?? globalThis.crypto.randomUUID();
|
|
39
|
+
const group = opts?.group;
|
|
40
|
+
const start = now();
|
|
41
|
+
const prevSub = currentSub;
|
|
42
|
+
currentSub = { id };
|
|
43
|
+
let terminal = false;
|
|
44
|
+
const emit = (status, message, data) => {
|
|
45
|
+
if (terminal)
|
|
46
|
+
return;
|
|
47
|
+
terminal = true;
|
|
48
|
+
subEvent({ id, name, group, status, message, data: withDuration(start, now, data) });
|
|
49
|
+
};
|
|
50
|
+
const handle = {
|
|
51
|
+
phase: (phase, data) => {
|
|
52
|
+
if (!terminal)
|
|
53
|
+
subEvent({ id, name, group, phase, data });
|
|
54
|
+
return handle;
|
|
55
|
+
},
|
|
56
|
+
skip: (reason, data) => emit('skipped', reason, data),
|
|
57
|
+
fail: (reason, data) => emit('failed', reason, data),
|
|
58
|
+
};
|
|
59
|
+
try {
|
|
60
|
+
const result = await body(handle);
|
|
61
|
+
emit('ok'); // no-op if the body already called skip()/fail()
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
emit('failed', err instanceof Error ? err.message : String(err));
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
currentSub = prevSub;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
return {
|
|
73
|
+
debug: (m, d) => push('debug', m, d),
|
|
74
|
+
info: (m, d) => push('info', m, d),
|
|
75
|
+
warn: (m, d) => push('warn', m, d),
|
|
76
|
+
error: (m, d) => push('error', m, d),
|
|
77
|
+
sub: (name, status, message, data) => events.push({
|
|
78
|
+
at: now(),
|
|
79
|
+
level: status === 'failed' ? 'error' : status === 'skipped' ? 'warn' : 'info',
|
|
80
|
+
message: message ?? name,
|
|
81
|
+
name,
|
|
82
|
+
status,
|
|
83
|
+
...(data === undefined ? {} : { data }),
|
|
84
|
+
}),
|
|
85
|
+
subEvent,
|
|
86
|
+
subProcess,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=step-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step-logger.js","sourceRoot":"","sources":["../../src/step-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { StateStore } from '../interfaces.js';
|
|
2
|
+
import type { TransportContext } from '../transports/factory.js';
|
|
3
|
+
/**
|
|
4
|
+
* The runtime context a {@link StoreFactory} thunk receives when the durable provider builds the
|
|
5
|
+
* configured state store at boot. Shares {@link TransportContext} so a driver can resolve a peer's
|
|
6
|
+
* service (the Lucid `db`) from the booted application if it needs to.
|
|
7
|
+
*/
|
|
8
|
+
export type StoreContext = TransportContext;
|
|
9
|
+
/**
|
|
10
|
+
* A configured state store: a thunk the durable provider calls at boot to build the {@link StateStore}.
|
|
11
|
+
* Each factory lazily imports its peer dependency (`@adonisjs/lucid`) inside the thunk, so the driver
|
|
12
|
+
* is only loaded when it is actually selected — keeping that package optional.
|
|
13
|
+
*/
|
|
14
|
+
export type StoreFactory = (ctx: StoreContext) => Promise<StateStore>;
|
|
15
|
+
/** Options for the Lucid-backed persistent store. */
|
|
16
|
+
export interface LucidStoreConfig {
|
|
17
|
+
/** Lucid connection name to use. Defaults to the `Database` default connection. */
|
|
18
|
+
connection?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The store factory namespace used in `config/durable.ts`:
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { defineConfig, stores } from '@adonis-agora/durable'
|
|
25
|
+
*
|
|
26
|
+
* export default defineConfig({
|
|
27
|
+
* store: 'lucid',
|
|
28
|
+
* stores: {
|
|
29
|
+
* lucid: stores.lucid({ connection: 'pg' }),
|
|
30
|
+
* },
|
|
31
|
+
* })
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* Each factory returns a {@link StoreFactory} — a lazy thunk. Calling it in the config file costs
|
|
35
|
+
* nothing; the peer dependency is only imported when the provider builds the selected store at boot.
|
|
36
|
+
* Omit `store` entirely to use the in-process `InMemoryStateStore` (single-process, no extra infra).
|
|
37
|
+
*/
|
|
38
|
+
export declare const stores: {
|
|
39
|
+
/** Persist runs/checkpoints/timers/signals in SQL via `@adonisjs/lucid`. */
|
|
40
|
+
lucid(config?: LucidStoreConfig): StoreFactory;
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/stores/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAE5C;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,YAAY,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtE,qDAAqD;AACrD,MAAM,WAAW,gBAAgB;IAC/B,mFAAmF;IACnF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,MAAM;IACjB,4EAA4E;mBAC9D,gBAAgB,GAAQ,YAAY;CAUnD,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The store factory namespace used in `config/durable.ts`:
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* import { defineConfig, stores } from '@adonis-agora/durable'
|
|
6
|
+
*
|
|
7
|
+
* export default defineConfig({
|
|
8
|
+
* store: 'lucid',
|
|
9
|
+
* stores: {
|
|
10
|
+
* lucid: stores.lucid({ connection: 'pg' }),
|
|
11
|
+
* },
|
|
12
|
+
* })
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Each factory returns a {@link StoreFactory} — a lazy thunk. Calling it in the config file costs
|
|
16
|
+
* nothing; the peer dependency is only imported when the provider builds the selected store at boot.
|
|
17
|
+
* Omit `store` entirely to use the in-process `InMemoryStateStore` (single-process, no extra infra).
|
|
18
|
+
*/
|
|
19
|
+
export const stores = {
|
|
20
|
+
/** Persist runs/checkpoints/timers/signals in SQL via `@adonisjs/lucid`. */
|
|
21
|
+
lucid(config = {}) {
|
|
22
|
+
return async () => {
|
|
23
|
+
const db = (await import('@adonisjs/lucid/services/db')).default;
|
|
24
|
+
const { LucidStateStore } = await import('./lucid.js');
|
|
25
|
+
return new LucidStateStore(db, config.connection !== undefined ? { connectionName: config.connection } : {});
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../src/stores/factory.ts"],"names":[],"mappings":"AAuBA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,4EAA4E;IAC5E,KAAK,CAAC,SAA2B,EAAE;QACjC,OAAO,KAAK,IAAI,EAAE;YAChB,MAAM,EAAE,GAAG,CAAC,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC,CAAC,OAAO,CAAC;YACjE,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;YACvD,OAAO,IAAI,eAAe,CACxB,EAAE,EACF,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAC7E,CAAC;QACJ,CAAC,CAAC;IACJ,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Database } from '@adonisjs/lucid/database';
|
|
2
|
+
/**
|
|
3
|
+
* Build a standalone Lucid `Database` pointed at an in-memory SQLite (`better-sqlite3`) — the
|
|
4
|
+
* "using Lucid outside an app" pattern. We construct `Database(config, logger, emitter)` directly
|
|
5
|
+
* (the same three args Lucid's provider passes) so the store can be exercised against real SQL with
|
|
6
|
+
* no AdonisJS app boot.
|
|
7
|
+
*/
|
|
8
|
+
export declare function makeMemoryDb(): Database;
|
|
9
|
+
/** A fresh in-memory db with the durable tables already created. */
|
|
10
|
+
export declare function makeStoreDb(): Promise<Database>;
|
|
11
|
+
//# sourceMappingURL=lucid-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lucid-helpers.d.ts","sourceRoot":"","sources":["../../../src/stores/lucid-helpers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGpD;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,QAAQ,CAwBvC;AAED,oEAAoE;AACpE,wBAAsB,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC,CAIrD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Emitter } from '@adonisjs/core/events';
|
|
2
|
+
import { Logger } from '@adonisjs/core/logger';
|
|
3
|
+
import { Database } from '@adonisjs/lucid/database';
|
|
4
|
+
import { createDurableTables } from './lucid-schema.js';
|
|
5
|
+
/**
|
|
6
|
+
* Build a standalone Lucid `Database` pointed at an in-memory SQLite (`better-sqlite3`) — the
|
|
7
|
+
* "using Lucid outside an app" pattern. We construct `Database(config, logger, emitter)` directly
|
|
8
|
+
* (the same three args Lucid's provider passes) so the store can be exercised against real SQL with
|
|
9
|
+
* no AdonisJS app boot.
|
|
10
|
+
*/
|
|
11
|
+
export function makeMemoryDb() {
|
|
12
|
+
const logger = new Logger({ enabled: false });
|
|
13
|
+
// Database needs an Emitter; in standalone use a minimal app stand-in is enough (the emitter only
|
|
14
|
+
// fans out `db:query` events, which we don't subscribe to here).
|
|
15
|
+
const emitter = new Emitter(undefined);
|
|
16
|
+
const db = new Database({
|
|
17
|
+
connection: 'sqlite',
|
|
18
|
+
connections: {
|
|
19
|
+
sqlite: {
|
|
20
|
+
client: 'better-sqlite3',
|
|
21
|
+
connection: { filename: ':memory:' },
|
|
22
|
+
useNullAsDefault: true,
|
|
23
|
+
// A `:memory:` SQLite db is per-connection: a pool of N would give N independent empty
|
|
24
|
+
// databases. Pin the pool to a single connection so every query (and the schema we create)
|
|
25
|
+
// hits the same in-memory db.
|
|
26
|
+
pool: { min: 1, max: 1 },
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
}, logger, emitter);
|
|
30
|
+
return db;
|
|
31
|
+
}
|
|
32
|
+
/** A fresh in-memory db with the durable tables already created. */
|
|
33
|
+
export async function makeStoreDb() {
|
|
34
|
+
const db = makeMemoryDb();
|
|
35
|
+
await createDurableTables(db);
|
|
36
|
+
return db;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=lucid-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lucid-helpers.js","sourceRoot":"","sources":["../../../src/stores/lucid-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD;;;;;GAKG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,kGAAkG;IAClG,iEAAiE;IACjE,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,SAAkB,CAAC,CAAC;IAChD,MAAM,EAAE,GAAG,IAAI,QAAQ,CACrB;QACE,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE;YACX,MAAM,EAAE;gBACN,MAAM,EAAE,gBAAgB;gBACxB,UAAU,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE;gBACpC,gBAAgB,EAAE,IAAI;gBACtB,uFAAuF;gBACvF,2FAA2F;gBAC3F,8BAA8B;gBAC9B,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;aACzB;SACF;KACF,EACD,MAAM,EACN,OAAO,CACR,CAAC;IACF,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;IAC1B,MAAM,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAC9B,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { StepCheckpoint, WorkflowRun } from '../interfaces.js';
|
|
2
|
+
/**
|
|
3
|
+
* Row shapes as they live in the durable tables: snake_case columns, JSON payloads stored as TEXT
|
|
4
|
+
* (we (de)serialize them here rather than relying on a driver's JSON column type, so the schema is
|
|
5
|
+
* portable across SQLite / Postgres / MySQL). Timestamps are epoch-ms numbers.
|
|
6
|
+
*
|
|
7
|
+
* NOTE: drivers can return numeric columns as strings (e.g. `bigInteger` over some dialects) and
|
|
8
|
+
* booleans/ints loosely typed, so every read goes through the guarded coercers below — never trust a
|
|
9
|
+
* raw row field's static type.
|
|
10
|
+
*/
|
|
11
|
+
export interface RunRow {
|
|
12
|
+
id: string;
|
|
13
|
+
workflow: string;
|
|
14
|
+
workflow_version: string;
|
|
15
|
+
status: string;
|
|
16
|
+
input: string | null;
|
|
17
|
+
output: string | null;
|
|
18
|
+
error: string | null;
|
|
19
|
+
wake_at: number | string | null;
|
|
20
|
+
locked_by: string | null;
|
|
21
|
+
locked_until: number | string | null;
|
|
22
|
+
recovery_attempts: number | string | null;
|
|
23
|
+
tags: string | null;
|
|
24
|
+
search_attributes: string | null;
|
|
25
|
+
priority: number | string | null;
|
|
26
|
+
created_at: number | string;
|
|
27
|
+
updated_at: number | string;
|
|
28
|
+
}
|
|
29
|
+
export interface CheckpointRow {
|
|
30
|
+
run_id: string;
|
|
31
|
+
seq: number | string;
|
|
32
|
+
name: string;
|
|
33
|
+
kind: string;
|
|
34
|
+
step_id: string;
|
|
35
|
+
status: string;
|
|
36
|
+
input: string | null;
|
|
37
|
+
output: string | null;
|
|
38
|
+
error: string | null;
|
|
39
|
+
events: string | null;
|
|
40
|
+
attempts: number | string;
|
|
41
|
+
worker_group: string | null;
|
|
42
|
+
wake_at: number | string | null;
|
|
43
|
+
enqueued_at: number | string | null;
|
|
44
|
+
started_at: number | string;
|
|
45
|
+
finished_at: number | string;
|
|
46
|
+
}
|
|
47
|
+
export declare function runToRow(run: WorkflowRun): RunRow;
|
|
48
|
+
/**
|
|
49
|
+
* Map a run patch to a column patch using presence (`'x' in patch`) semantics for nullable fields, so
|
|
50
|
+
* a patch can CLEAR a column (e.g. `{ error: undefined }` on completion → NULL), matching the
|
|
51
|
+
* in-memory store's `{ ...existing, ...patch }` semantics. The two required Date fields use a
|
|
52
|
+
* defined-guard since they're never cleared.
|
|
53
|
+
*/
|
|
54
|
+
export declare function runPatchToRow(patch: Partial<WorkflowRun>): Partial<RunRow>;
|
|
55
|
+
export declare function rowToRun(row: RunRow): WorkflowRun;
|
|
56
|
+
export declare function checkpointToRow(cp: StepCheckpoint): CheckpointRow;
|
|
57
|
+
export declare function rowToCheckpoint(row: CheckpointRow): StepCheckpoint;
|
|
58
|
+
//# sourceMappingURL=lucid-mappers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lucid-mappers.d.ts","sourceRoot":"","sources":["../../../src/stores/lucid-mappers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAwB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE1F;;;;;;;;GAQG;AACH,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACrC,iBAAiB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC1C,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACjC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;CAC9B;AA4BD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAmBjD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAkB1E;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CA4BjD;AAID,wBAAgB,eAAe,CAAC,EAAE,EAAE,cAAc,GAAG,aAAa,CAmBjE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAwBlE"}
|