@adonis-agora/durable 0.49.0 → 0.50.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/CHANGELOG.md +261 -0
- package/README.md +53 -22
- package/dist/assets/spa/assets/index-DupjrK7N.js +16 -0
- package/dist/assets/spa/assets/index-DupjrK7N.js.map +1 -0
- package/dist/assets/spa/index.html +1 -1
- package/dist/commands/durable_worker.d.ts.map +1 -1
- package/dist/commands/durable_worker.js +9 -8
- package/dist/commands/durable_worker.js.map +1 -1
- package/dist/configure.d.ts.map +1 -1
- package/dist/configure.js +1 -0
- package/dist/configure.js.map +1 -1
- package/dist/providers/dashboard_provider.d.ts +2 -0
- package/dist/providers/dashboard_provider.d.ts.map +1 -1
- package/dist/providers/dashboard_provider.js +50 -6
- package/dist/providers/dashboard_provider.js.map +1 -1
- package/dist/providers/durable_provider.d.ts.map +1 -1
- package/dist/providers/durable_provider.js +143 -34
- package/dist/providers/durable_provider.js.map +1 -1
- package/dist/src/admission-redis/redis-admission-backend.d.ts.map +1 -1
- package/dist/src/admission-redis/redis-admission-backend.js +3 -1
- package/dist/src/admission-redis/redis-admission-backend.js.map +1 -1
- package/dist/src/ambient-step.d.ts +24 -0
- package/dist/src/ambient-step.d.ts.map +1 -0
- package/dist/src/ambient-step.js +42 -0
- package/dist/src/ambient-step.js.map +1 -0
- package/dist/src/base-workflow.d.ts +10 -1
- package/dist/src/base-workflow.d.ts.map +1 -1
- package/dist/src/base-workflow.js.map +1 -1
- package/dist/src/codec-state-store.d.ts +28 -2
- package/dist/src/codec-state-store.d.ts.map +1 -1
- package/dist/src/codec-state-store.js +61 -3
- package/dist/src/codec-state-store.js.map +1 -1
- package/dist/src/commands/worker.d.ts +4 -1
- package/dist/src/commands/worker.d.ts.map +1 -1
- package/dist/src/commands/worker.js +27 -3
- package/dist/src/commands/worker.js.map +1 -1
- package/dist/src/config_types.d.ts +6 -0
- package/dist/src/config_types.d.ts.map +1 -1
- package/dist/src/control-plane-redis/redis-control-plane.d.ts.map +1 -1
- package/dist/src/control-plane-redis/redis-control-plane.js +22 -6
- package/dist/src/control-plane-redis/redis-control-plane.js.map +1 -1
- package/dist/src/control-planes/factory.d.ts +6 -0
- package/dist/src/control-planes/factory.d.ts.map +1 -1
- package/dist/src/control-planes/factory.js +1 -0
- package/dist/src/control-planes/factory.js.map +1 -1
- package/dist/src/dashboard/gateway-adapter.d.ts +15 -5
- package/dist/src/dashboard/gateway-adapter.d.ts.map +1 -1
- package/dist/src/dashboard/gateway-adapter.js +71 -7
- package/dist/src/dashboard/gateway-adapter.js.map +1 -1
- package/dist/src/dashboard/handlers.d.ts +53 -1
- package/dist/src/dashboard/handlers.d.ts.map +1 -1
- package/dist/src/dashboard/handlers.js +200 -20
- package/dist/src/dashboard/handlers.js.map +1 -1
- package/dist/src/dashboard/index.d.ts +2 -2
- package/dist/src/dashboard/index.d.ts.map +1 -1
- package/dist/src/dashboard/index.js +2 -2
- package/dist/src/dashboard/index.js.map +1 -1
- package/dist/src/dashboard/openapi.d.ts.map +1 -1
- package/dist/src/dashboard/openapi.js +71 -1
- package/dist/src/dashboard/openapi.js.map +1 -1
- package/dist/src/define_config.d.ts +122 -8
- package/dist/src/define_config.d.ts.map +1 -1
- package/dist/src/define_config.js.map +1 -1
- package/dist/src/diagnostics-bridge.d.ts +16 -3
- package/dist/src/diagnostics-bridge.d.ts.map +1 -1
- package/dist/src/diagnostics-bridge.js +9 -3
- package/dist/src/diagnostics-bridge.js.map +1 -1
- package/dist/src/discovery-roots.d.ts +92 -0
- package/dist/src/discovery-roots.d.ts.map +1 -0
- package/dist/src/discovery-roots.js +150 -0
- package/dist/src/discovery-roots.js.map +1 -0
- package/dist/src/engine.d.ts +418 -20
- package/dist/src/engine.d.ts.map +1 -1
- package/dist/src/engine.js +1523 -159
- package/dist/src/engine.js.map +1 -1
- package/dist/src/entities.d.ts +36 -1
- package/dist/src/entities.d.ts.map +1 -1
- package/dist/src/entities.js +65 -4
- package/dist/src/entities.js.map +1 -1
- package/dist/src/errors.d.ts +36 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +44 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/event-trigger-bridge.d.ts +8 -0
- package/dist/src/event-trigger-bridge.d.ts.map +1 -1
- package/dist/src/event-trigger-bridge.js +24 -3
- package/dist/src/event-trigger-bridge.js.map +1 -1
- package/dist/src/handshake/announced.d.ts +27 -0
- package/dist/src/handshake/announced.d.ts.map +1 -1
- package/dist/src/handshake/announced.js +62 -0
- package/dist/src/handshake/announced.js.map +1 -1
- package/dist/src/handshake/directory.d.ts +92 -0
- package/dist/src/handshake/directory.d.ts.map +1 -0
- package/dist/src/handshake/directory.js +139 -0
- package/dist/src/handshake/directory.js.map +1 -0
- package/dist/src/hooks/barrel-sources.d.ts +28 -0
- package/dist/src/hooks/barrel-sources.d.ts.map +1 -0
- package/dist/src/hooks/barrel-sources.js +92 -0
- package/dist/src/hooks/barrel-sources.js.map +1 -0
- package/dist/src/hooks/steps.d.ts +12 -3
- package/dist/src/hooks/steps.d.ts.map +1 -1
- package/dist/src/hooks/steps.js +7 -11
- package/dist/src/hooks/steps.js.map +1 -1
- package/dist/src/hooks/workflows.d.ts +12 -3
- package/dist/src/hooks/workflows.d.ts.map +1 -1
- package/dist/src/hooks/workflows.js +7 -13
- package/dist/src/hooks/workflows.js.map +1 -1
- package/dist/src/index.d.ts +12 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +12 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/interfaces.d.ts +309 -21
- package/dist/src/interfaces.d.ts.map +1 -1
- package/dist/src/interfaces.js +10 -0
- package/dist/src/interfaces.js.map +1 -1
- package/dist/src/metrics.d.ts.map +1 -1
- package/dist/src/metrics.js +5 -0
- package/dist/src/metrics.js.map +1 -1
- package/dist/src/namespaces.d.ts +17 -0
- package/dist/src/namespaces.d.ts.map +1 -0
- package/dist/src/namespaces.js +24 -0
- package/dist/src/namespaces.js.map +1 -0
- package/dist/src/otel/durable-metrics.d.ts.map +1 -1
- package/dist/src/otel/durable-metrics.js +5 -0
- package/dist/src/otel/durable-metrics.js.map +1 -1
- package/dist/src/otel/durable-otel.d.ts.map +1 -1
- package/dist/src/otel/durable-otel.js +5 -0
- package/dist/src/otel/durable-otel.js.map +1 -1
- package/dist/src/pollers.d.ts +10 -1
- package/dist/src/pollers.d.ts.map +1 -1
- package/dist/src/pollers.js +15 -5
- package/dist/src/pollers.js.map +1 -1
- package/dist/src/protocol.d.ts +12 -0
- package/dist/src/protocol.d.ts.map +1 -1
- package/dist/src/protocol.js +27 -1
- package/dist/src/protocol.js.map +1 -1
- package/dist/src/remote-event.d.ts +6 -0
- package/dist/src/remote-event.d.ts.map +1 -0
- package/dist/src/remote-event.js +19 -0
- package/dist/src/remote-event.js.map +1 -0
- package/dist/src/remote-workflow-executor.d.ts +34 -12
- package/dist/src/remote-workflow-executor.d.ts.map +1 -1
- package/dist/src/remote-workflow-executor.js +42 -40
- package/dist/src/remote-workflow-executor.js.map +1 -1
- package/dist/src/run-detail-summary.d.ts +90 -3
- package/dist/src/run-detail-summary.d.ts.map +1 -1
- package/dist/src/run-detail-summary.js +360 -2
- package/dist/src/run-detail-summary.js.map +1 -1
- package/dist/src/run-facets.d.ts +48 -0
- package/dist/src/run-facets.d.ts.map +1 -0
- package/dist/src/run-facets.js +100 -0
- package/dist/src/run-facets.js.map +1 -0
- package/dist/src/run-gateway/interface.d.ts +27 -1
- package/dist/src/run-gateway/interface.d.ts.map +1 -1
- package/dist/src/run-gateway/proxy-run-gateway.d.ts +32 -4
- package/dist/src/run-gateway/proxy-run-gateway.d.ts.map +1 -1
- package/dist/src/run-gateway/proxy-run-gateway.js +101 -5
- package/dist/src/run-gateway/proxy-run-gateway.js.map +1 -1
- package/dist/src/run-gateway/run-request-responder.d.ts +18 -5
- package/dist/src/run-gateway/run-request-responder.d.ts.map +1 -1
- package/dist/src/run-gateway/run-request-responder.js +155 -32
- package/dist/src/run-gateway/run-request-responder.js.map +1 -1
- package/dist/src/run-gateway/store-run-gateway.d.ts +23 -1
- package/dist/src/run-gateway/store-run-gateway.d.ts.map +1 -1
- package/dist/src/run-gateway/store-run-gateway.js +38 -0
- package/dist/src/run-gateway/store-run-gateway.js.map +1 -1
- package/dist/src/search-attributes-schema.d.ts +44 -0
- package/dist/src/search-attributes-schema.d.ts.map +1 -0
- package/dist/src/search-attributes-schema.js +51 -0
- package/dist/src/search-attributes-schema.js.map +1 -0
- package/dist/src/singleton-admission.d.ts +75 -0
- package/dist/src/singleton-admission.d.ts.map +1 -0
- package/dist/src/singleton-admission.js +156 -0
- package/dist/src/singleton-admission.js.map +1 -0
- package/dist/src/singleton-gate.d.ts +23 -8
- package/dist/src/singleton-gate.d.ts.map +1 -1
- package/dist/src/singleton-gate.js +59 -12
- package/dist/src/singleton-gate.js.map +1 -1
- package/dist/src/standard-schema.d.ts +83 -0
- package/dist/src/standard-schema.d.ts.map +1 -0
- package/dist/src/standard-schema.js +31 -0
- package/dist/src/standard-schema.js.map +1 -0
- package/dist/src/step-discovery.d.ts +21 -11
- package/dist/src/step-discovery.d.ts.map +1 -1
- package/dist/src/step-discovery.js +86 -45
- package/dist/src/step-discovery.js.map +1 -1
- package/dist/src/step-ref.d.ts +38 -12
- package/dist/src/step-ref.d.ts.map +1 -1
- package/dist/src/step-ref.js +5 -13
- package/dist/src/step-ref.js.map +1 -1
- package/dist/src/stores/factory.d.ts +6 -0
- package/dist/src/stores/factory.d.ts.map +1 -1
- package/dist/src/stores/factory.js +4 -1
- package/dist/src/stores/factory.js.map +1 -1
- package/dist/src/stores/lucid-helpers.d.ts +2 -0
- package/dist/src/stores/lucid-helpers.d.ts.map +1 -1
- package/dist/src/stores/lucid-helpers.js +7 -0
- package/dist/src/stores/lucid-helpers.js.map +1 -1
- package/dist/src/stores/lucid-mappers.d.ts +25 -0
- package/dist/src/stores/lucid-mappers.d.ts.map +1 -1
- package/dist/src/stores/lucid-mappers.js +81 -18
- package/dist/src/stores/lucid-mappers.js.map +1 -1
- package/dist/src/stores/lucid-schema.d.ts +59 -1
- package/dist/src/stores/lucid-schema.d.ts.map +1 -1
- package/dist/src/stores/lucid-schema.js +271 -25
- package/dist/src/stores/lucid-schema.js.map +1 -1
- package/dist/src/stores/lucid.d.ts +61 -2
- package/dist/src/stores/lucid.d.ts.map +1 -1
- package/dist/src/stores/lucid.js +346 -41
- package/dist/src/stores/lucid.js.map +1 -1
- package/dist/src/telescope/dashboard.d.ts.map +1 -1
- package/dist/src/telescope/dashboard.js +30 -1
- package/dist/src/telescope/dashboard.js.map +1 -1
- package/dist/src/telescope/data-providers.d.ts +19 -1
- package/dist/src/telescope/data-providers.d.ts.map +1 -1
- package/dist/src/telescope/data-providers.js +119 -3
- package/dist/src/telescope/data-providers.js.map +1 -1
- package/dist/src/telescope/extension.d.ts.map +1 -1
- package/dist/src/telescope/extension.js +2 -1
- package/dist/src/telescope/extension.js.map +1 -1
- package/dist/src/telescope/index.d.ts +1 -1
- package/dist/src/telescope/index.d.ts.map +1 -1
- package/dist/src/telescope/index.js +1 -1
- package/dist/src/telescope/index.js.map +1 -1
- package/dist/src/testing/in-memory-state-store.d.ts +44 -15
- package/dist/src/testing/in-memory-state-store.d.ts.map +1 -1
- package/dist/src/testing/in-memory-state-store.js +204 -41
- package/dist/src/testing/in-memory-state-store.js.map +1 -1
- package/dist/src/testing-kit/checkpoint-aggregation-contract.d.ts +16 -0
- package/dist/src/testing-kit/checkpoint-aggregation-contract.d.ts.map +1 -0
- package/dist/src/testing-kit/checkpoint-aggregation-contract.js +228 -0
- package/dist/src/testing-kit/checkpoint-aggregation-contract.js.map +1 -0
- package/dist/src/testing-kit/state-store-conformance.d.ts.map +1 -1
- package/dist/src/testing-kit/state-store-conformance.js +355 -3
- package/dist/src/testing-kit/state-store-conformance.js.map +1 -1
- package/dist/src/transport-pool.d.ts +15 -1
- package/dist/src/transport-pool.d.ts.map +1 -1
- package/dist/src/transport-pool.js +50 -4
- package/dist/src/transport-pool.js.map +1 -1
- package/dist/src/transports/adaptive-concurrency.d.ts +168 -0
- package/dist/src/transports/adaptive-concurrency.d.ts.map +1 -0
- package/dist/src/transports/adaptive-concurrency.js +353 -0
- package/dist/src/transports/adaptive-concurrency.js.map +1 -0
- package/dist/src/transports/bullmq/adaptive-concurrency.d.ts +1 -143
- package/dist/src/transports/bullmq/adaptive-concurrency.d.ts.map +1 -1
- package/dist/src/transports/bullmq/adaptive-concurrency.js +3 -311
- package/dist/src/transports/bullmq/adaptive-concurrency.js.map +1 -1
- package/dist/src/transports/bullmq/bullmq-transport.d.ts +49 -1
- package/dist/src/transports/bullmq/bullmq-transport.d.ts.map +1 -1
- package/dist/src/transports/bullmq/bullmq-transport.js +330 -38
- package/dist/src/transports/bullmq/bullmq-transport.js.map +1 -1
- package/dist/src/transports/bullmq/deps.d.ts +18 -2
- package/dist/src/transports/bullmq/deps.d.ts.map +1 -1
- package/dist/src/transports/bullmq/deps.js +44 -2
- package/dist/src/transports/bullmq/deps.js.map +1 -1
- package/dist/src/transports/db-helpers.d.ts +39 -0
- package/dist/src/transports/db-helpers.d.ts.map +1 -1
- package/dist/src/transports/db-helpers.js +73 -0
- package/dist/src/transports/db-helpers.js.map +1 -1
- package/dist/src/transports/db-remote.d.ts +53 -0
- package/dist/src/transports/db-remote.d.ts.map +1 -0
- package/dist/src/transports/db-remote.js +147 -0
- package/dist/src/transports/db-remote.js.map +1 -0
- package/dist/src/transports/db-schema.d.ts +44 -1
- package/dist/src/transports/db-schema.d.ts.map +1 -1
- package/dist/src/transports/db-schema.js +227 -88
- package/dist/src/transports/db-schema.js.map +1 -1
- package/dist/src/transports/db.d.ts +189 -6
- package/dist/src/transports/db.d.ts.map +1 -1
- package/dist/src/transports/db.js +1291 -137
- package/dist/src/transports/db.js.map +1 -1
- package/dist/src/transports/event-emitter.d.ts +8 -0
- package/dist/src/transports/event-emitter.d.ts.map +1 -1
- package/dist/src/transports/event-emitter.js +36 -3
- package/dist/src/transports/event-emitter.js.map +1 -1
- package/dist/src/transports/factory.d.ts +110 -5
- package/dist/src/transports/factory.d.ts.map +1 -1
- package/dist/src/transports/factory.js +56 -9
- package/dist/src/transports/factory.js.map +1 -1
- package/dist/src/transports/queue-mock-adapter.d.ts +7 -2
- package/dist/src/transports/queue-mock-adapter.d.ts.map +1 -1
- package/dist/src/transports/queue-mock-adapter.js +18 -2
- package/dist/src/transports/queue-mock-adapter.js.map +1 -1
- package/dist/src/transports/queue-remote.d.ts +146 -0
- package/dist/src/transports/queue-remote.d.ts.map +1 -0
- package/dist/src/transports/queue-remote.js +398 -0
- package/dist/src/transports/queue-remote.js.map +1 -0
- package/dist/src/transports/queue.d.ts +159 -6
- package/dist/src/transports/queue.d.ts.map +1 -1
- package/dist/src/transports/queue.js +747 -37
- package/dist/src/transports/queue.js.map +1 -1
- package/dist/src/transports/task-failure.d.ts +31 -0
- package/dist/src/transports/task-failure.d.ts.map +1 -0
- package/dist/src/transports/task-failure.js +50 -0
- package/dist/src/transports/task-failure.js.map +1 -0
- package/dist/src/workflow-als.d.ts +1 -1
- package/dist/src/workflow-als.d.ts.map +1 -1
- package/dist/src/workflow-ctx.d.ts +10 -0
- package/dist/src/workflow-ctx.d.ts.map +1 -1
- package/dist/src/workflow-ctx.js +97 -15
- package/dist/src/workflow-ctx.js.map +1 -1
- package/dist/src/workflow-discovery.d.ts +32 -41
- package/dist/src/workflow-discovery.d.ts.map +1 -1
- package/dist/src/workflow-discovery.js +65 -88
- package/dist/src/workflow-discovery.js.map +1 -1
- package/dist/src/workflow-ref.d.ts +24 -0
- package/dist/src/workflow-ref.d.ts.map +1 -1
- package/dist/src/workflow-ref.js.map +1 -1
- package/dist/stubs/config/durable.stub +6 -0
- package/dist/stubs/config/durable_dashboard.stub +7 -3
- package/dist/stubs/database/migrations/create_durable_tables.stub +2 -1
- package/dist/stubs/database/migrations/create_durable_transport_messages.stub +43 -0
- package/dist/stubs/database/migrations/create_durable_transport_tables.stub +12 -9
- package/dist/stubs/database/migrations/create_durable_transport_worker_keys.stub +1 -1
- package/dist/stubs/make/workflow/main.stub +1 -1
- package/package.json +6 -4
- package/skills/durable-cluster/SKILL.md +80 -11
- package/skills/durable-determinism/SKILL.md +11 -5
- package/skills/durable-reliability/SKILL.md +77 -37
- package/skills/durable-setup/SKILL.md +51 -22
- package/skills/durable-transports-stores/SKILL.md +130 -19
- package/skills/durable-workflows/SKILL.md +71 -18
- package/dist/assets/spa/assets/index-DdB9zxuX.js +0 -16
- package/dist/assets/spa/assets/index-DdB9zxuX.js.map +0 -1
package/dist/src/engine.d.ts
CHANGED
|
@@ -2,16 +2,31 @@ import { type AdmissionBackend } from './admission.js';
|
|
|
2
2
|
import { type ConcurrencyConfig, type ConcurrencyQuota } from './concurrency.js';
|
|
3
3
|
import { type EntityConfig } from './entities.js';
|
|
4
4
|
import { type EventBatchConfig } from './event-accumulators.js';
|
|
5
|
-
import
|
|
5
|
+
import { type AnnouncedWorkflow } from './handshake/announced.js';
|
|
6
|
+
import { type WorkflowDirectory } from './handshake/directory.js';
|
|
7
|
+
import type { ControlPlane, EngineListener, GroupHealth, NamedTransport, RunDispatcher, RunFacetQuery, RunFacetRow, RunQuery, RunResult, RunScope, RunStatus, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, ScopedRetentionPolicy, SearchAttributes, SearchAttributesSchema, SignalWaiter, StateStore, StepCheckpoint, StepError, StepInterceptor, Transport, UpdateResult, UpdateValidator, WorkflowCtx, WorkflowExecutor, WorkflowRun } from './interfaces.js';
|
|
6
8
|
import { type OnErrorRoute } from './on-error.js';
|
|
9
|
+
import { type StepHandler } from './protocol.js';
|
|
7
10
|
import type { QueueConfig } from './queue.js';
|
|
11
|
+
import { type FanPage, type FanPageQuery, type RunDetail, type RunDetailOptions } from './run-detail-summary.js';
|
|
8
12
|
import { type ScheduledWorkflow } from './scheduler.js';
|
|
9
13
|
import { ScheduleClient } from './schedules.js';
|
|
14
|
+
import { type StandardSchemaV1 } from './standard-schema.js';
|
|
10
15
|
import type { NormalizedEventTrigger } from './workflow-events.js';
|
|
11
16
|
import { type WorkflowClass, type WorkflowInputOf, type WorkflowRef } from './workflow-ref.js';
|
|
12
17
|
type WorkflowFn = (ctx: WorkflowCtx, input: unknown) => Promise<unknown>;
|
|
13
18
|
/** Options for {@link WorkflowEngine.start}. */
|
|
14
19
|
export interface StartOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Pin the run to this registered version of the workflow instead of the newest one. Resolved
|
|
22
|
+
* against the name@version registry ({@link WorkflowEngine.register}, `registerRemote`,
|
|
23
|
+
* {@link WorkflowEngine.remote}); a version that is not registered throws before any run row is
|
|
24
|
+
* created and never falls back to the newest (a caller that asked for `name@3` and silently got
|
|
25
|
+
* `name@4` could not tell). Not honoured by convention routing (an unregistered name routed to a
|
|
26
|
+
* live worker group), which invents its version: a pinned start there throws instead. Absent →
|
|
27
|
+
* the newest registered version, as before.
|
|
28
|
+
*/
|
|
29
|
+
version?: string | undefined;
|
|
15
30
|
/** Run-scoped tags, merged with the workflow's static `workflow` config `tags` onto the run. */
|
|
16
31
|
tags?: string[] | undefined;
|
|
17
32
|
/** Typed, queryable run data stamped on the run (e.g. `{ amount: 200, tier: 'pro' }`). */
|
|
@@ -90,8 +105,9 @@ export interface StalledRunInfo {
|
|
|
90
105
|
/**
|
|
91
106
|
* Serialize runs of a workflow that share a key — a durable, FIFO mutex (e.g. one pipeline per base).
|
|
92
107
|
* Excess runs are admitted in creation order, `limit` at a time; the rest wait (suspended) and retry
|
|
93
|
-
* admission on a timer until a slot frees.
|
|
94
|
-
*
|
|
108
|
+
* admission on a timer until a slot frees. The store claims slots atomically
|
|
109
|
+
* ({@link StateStore.tryAdmitSingleton}) and records them durably on the run, so concurrent
|
|
110
|
+
* replicas can't over-admit and a later (or same-millisecond) start can't displace a holder.
|
|
95
111
|
*/
|
|
96
112
|
export interface SingletonConfig {
|
|
97
113
|
/** Derive the serialization key from the workflow input. */
|
|
@@ -102,7 +118,7 @@ export interface SingletonConfig {
|
|
|
102
118
|
* Max GATED (waiting-for-admission) runs allowed to queue behind the `limit` in-flight ones. When
|
|
103
119
|
* set, `start` rejects with {@link SingletonQueueFullError} once in-flight + gated reaches
|
|
104
120
|
* `limit + maxQueueDepth` — back-pressure against an unbounded same-key backlog. Omit for the
|
|
105
|
-
* default unbounded queue. Counts `pending`/`running`/`suspended` runs sharing the key.
|
|
121
|
+
* default unbounded queue. Counts `pending`/`running`/`suspended`/`blocked` runs sharing the key.
|
|
106
122
|
*/
|
|
107
123
|
maxQueueDepth?: number;
|
|
108
124
|
}
|
|
@@ -135,12 +151,17 @@ export interface WorkflowEngineDeps {
|
|
|
135
151
|
* (`runPending` / `recoverIncomplete` / `resumeDueTimers` / `sweepTimeouts`) only act on runs in
|
|
136
152
|
* this namespace, and `resume` of a foreign run throws {@link NamespaceMismatch}.
|
|
137
153
|
*
|
|
138
|
-
*
|
|
154
|
+
* **`undefined` here makes this engine an operator**: it drives, recovers and resumes runs of EVERY
|
|
139
155
|
* namespace (the store's poll filters no-op on `undefined`) and leaves its transports on their bare
|
|
140
156
|
* prefix. That is what lets one control plane serve many tenant pools — the queue a step lands on
|
|
141
157
|
* is derived from the RUN's namespace, not this engine's. Set a value to scope the instance to one
|
|
142
158
|
* pool instead, so ONE state store can be shared across non-interchangeable pools (e.g. local dev
|
|
143
159
|
* vs a cluster). `'default'` and `''` are the bare pool, byte-identical to a single-pool deployment.
|
|
160
|
+
*
|
|
161
|
+
* The AdonisJS provider maps `config/durable.ts` onto this: an absent `namespace` is `'default'` on
|
|
162
|
+
* a `standalone` engine (it drives only the default pool, legacy rows included), and stays
|
|
163
|
+
* `undefined` — the operator — only on a `role: 'control-plane'` engine. Constructing the engine by
|
|
164
|
+
* hand keeps the raw meaning above.
|
|
144
165
|
*/
|
|
145
166
|
namespace?: string | undefined;
|
|
146
167
|
/** Recovery lease duration in ms — how long this instance owns a run it picked up. Default 30s. */
|
|
@@ -168,6 +189,7 @@ export interface WorkflowEngineDeps {
|
|
|
168
189
|
* advances), so it's a safe self-heal, not a retry that can double-dispatch. The primary event path
|
|
169
190
|
* still wins first for a healthy run (it re-drives long before this fires), so this only ever fires
|
|
170
191
|
* for a genuinely-orphaned run. Default 5min; set `0` to disable (the prior wake-forever behavior).
|
|
192
|
+
* A non-finite or negative value falls back to the default.
|
|
171
193
|
*/
|
|
172
194
|
reconcileMs?: number | undefined;
|
|
173
195
|
/**
|
|
@@ -178,6 +200,14 @@ export interface WorkflowEngineDeps {
|
|
|
178
200
|
* falls back to the default. Default 500.
|
|
179
201
|
*/
|
|
180
202
|
timerBatchSize?: number | undefined;
|
|
203
|
+
/**
|
|
204
|
+
* How long (ms) a BUFFERED event that no `waitForEvent` claimed is kept (see
|
|
205
|
+
* {@link WorkflowEngine.publishEvent}'s buffering). Default `undefined`: kept until consumed, like a
|
|
206
|
+
* buffered signal. When set, a `waitForEvent` skips (and removes) a candidate older than this, and
|
|
207
|
+
* the worker tick's retention phase deletes expired rows across every name in bounded batches
|
|
208
|
+
* (through {@link StateStore.pruneBufferedEvents}, when the store has it).
|
|
209
|
+
*/
|
|
210
|
+
eventBufferTtlMs?: number | undefined;
|
|
181
211
|
/**
|
|
182
212
|
* Opt-in self-heal window (ms) for a remote step with NO `timeoutMs` whose dispatched job was LOST —
|
|
183
213
|
* the worker crashed mid-step leaving no result, or the transport dropped the job (a Redis
|
|
@@ -193,12 +223,33 @@ export interface WorkflowEngineDeps {
|
|
|
193
223
|
* survive a lost dispatch. {@link WorkflowEngine.redispatchPending} is the manual counterpart.
|
|
194
224
|
*/
|
|
195
225
|
remoteRedispatchMs?: number | undefined;
|
|
226
|
+
/**
|
|
227
|
+
* Minimum gap (ms) between two persisted heartbeats of one step (see `persistHeartbeat`). Default
|
|
228
|
+
* 10s: beats can arrive every few seconds from a hot loop, and liveness observability must not
|
|
229
|
+
* become a per-item UPDATE storm. It is also how stale a beat persisted by ANOTHER instance can be
|
|
230
|
+
* when a step's dispatcher reads it, so the dispatcher allows this much extra silence once it sees
|
|
231
|
+
* beats landing elsewhere. Mostly a testing knob.
|
|
232
|
+
*/
|
|
233
|
+
heartbeatPersistThrottleMs?: number | undefined;
|
|
196
234
|
/**
|
|
197
235
|
* Max times {@link remoteRedispatchMs} re-dispatches one lost remote step before giving up and
|
|
198
236
|
* failing it as a {@link RemoteStepError} (`code: 'remote_step_lost'`), so the run fails / dead-letters
|
|
199
237
|
* instead of re-dispatching forever. Default 10. Ignored when `remoteRedispatchMs` is unset.
|
|
200
238
|
*/
|
|
201
239
|
remoteRedispatchMax?: number | undefined;
|
|
240
|
+
/**
|
|
241
|
+
* Opt-in liveness window (ms) for a remote workflow TURN. A dispatched turn whose decision has not
|
|
242
|
+
* landed, and whose worker has sent no run-scoped {@link Heartbeat}, within this window is presumed
|
|
243
|
+
* lost: the timer poller re-drives the run by dispatching a fresh turn (new `taskId`, same history —
|
|
244
|
+
* the worker's replay is deterministic), and a late decision for the old turn is dropped. Each
|
|
245
|
+
* run-scoped beat pushes the deadline forward (throttled to one write per half window), so a worker
|
|
246
|
+
* still replaying a long turn is never re-driven. For an INLINE executor (one that returns its
|
|
247
|
+
* decision in-process) a lapsed window releases the run lease and leaves the run to crash recovery
|
|
248
|
+
* instead of failing it. A `RemoteWorkflowExecutor`'s own `timeoutMs` is the per-workflow version of
|
|
249
|
+
* this window; when both are set the shorter wins. Unset (the default) waits for the decision with
|
|
250
|
+
* no deadline.
|
|
251
|
+
*/
|
|
252
|
+
remoteAdvanceSilenceMs?: number | undefined;
|
|
202
253
|
/**
|
|
203
254
|
* Build the public callback URL for a `ctx.webhook()` token (e.g.
|
|
204
255
|
* ``(t) => `https://api.example.com/durable/webhooks/${t}` ``). Populates
|
|
@@ -264,6 +315,14 @@ export interface WorkflowEngineDeps {
|
|
|
264
315
|
* rule matching a run wins, since every rule is applied.
|
|
265
316
|
*/
|
|
266
317
|
retentionPolicies?: ScopedRetentionPolicy[] | undefined;
|
|
318
|
+
/**
|
|
319
|
+
* The fleet-default dead-letter workflow: a run that goes `dead` (past `maxRecoveryAttempts`) is
|
|
320
|
+
* handed to it — started with a {@link DeadLetter} input under the run id `dlq:<deadRunId>`, in the
|
|
321
|
+
* dead run's namespace. A workflow's own `deadLetterWorkflow` (register option / static config)
|
|
322
|
+
* wins. Idempotent by that run id, so a run dead-lettered twice is handled once. A handler run
|
|
323
|
+
* (`dlq:…`) that itself goes dead is not routed again.
|
|
324
|
+
*/
|
|
325
|
+
deadLetterWorkflow?: WorkflowRef | undefined;
|
|
267
326
|
/**
|
|
268
327
|
* How long an in-flight run must sit untouched — with the stranded signature (a wake-forever
|
|
269
328
|
* suspension, or an old pending remote step whose worker heartbeat is silent) — before the
|
|
@@ -307,7 +366,7 @@ export interface WorkflowEngineDeps {
|
|
|
307
366
|
* How long (ms) a run parked `blocked` (no capable/compatible worker, design §7.5) waits before the
|
|
308
367
|
* blocked-recovery poll re-drives it to re-check the live fleet. Default 5000. The run proceeds the
|
|
309
368
|
* moment a capable+compatible worker appears on the next poll; a lower value trades broker SCANs for
|
|
310
|
-
* faster pickup.
|
|
369
|
+
* faster pickup. A non-finite or sub-1 value falls back to the default.
|
|
311
370
|
*/
|
|
312
371
|
blockedPollMs?: number | undefined;
|
|
313
372
|
/**
|
|
@@ -350,11 +409,21 @@ export declare class WorkflowEngine {
|
|
|
350
409
|
/** Whether the worker tick fires {@link schedules} (the `persistedSchedules` option). */
|
|
351
410
|
readonly persistedSchedulesEnabled: boolean;
|
|
352
411
|
private readonly leaseMs;
|
|
412
|
+
/**
|
|
413
|
+
* The engine clock when this instance was constructed. Every lease THIS incarnation writes ends at
|
|
414
|
+
* or after `bootedAt + leaseMs`; a lease held under {@link instanceId} that ends before that was
|
|
415
|
+
* written by a previous process that ran under the same id (a pod restarted after a crash) — see
|
|
416
|
+
* {@link selfReclaimable}.
|
|
417
|
+
*/
|
|
418
|
+
private readonly bootedAt;
|
|
353
419
|
private readonly maxRecoveryAttempts?;
|
|
354
420
|
private readonly reconcileMs;
|
|
421
|
+
private readonly heartbeatPersistThrottleMs;
|
|
355
422
|
private readonly timerBatchSize;
|
|
423
|
+
private readonly eventBufferTtlMs;
|
|
356
424
|
private readonly remoteRedispatchMs;
|
|
357
425
|
private readonly remoteRedispatchMax;
|
|
426
|
+
private readonly remoteAdvanceSilenceMs;
|
|
358
427
|
private readonly webhookUrl?;
|
|
359
428
|
private readonly traceparent?;
|
|
360
429
|
private readonly context?;
|
|
@@ -400,7 +469,10 @@ export declare class WorkflowEngine {
|
|
|
400
469
|
private readonly accumulators;
|
|
401
470
|
/** In-flight remote steps awaiting a worker result, keyed by stepId. */
|
|
402
471
|
private readonly pending;
|
|
403
|
-
/**
|
|
472
|
+
/** Each run's step results waiting to be settled on this instance — see {@link completeRemoteResult}. */
|
|
473
|
+
private readonly resultQueues;
|
|
474
|
+
/** Per-step "reset the liveness timer" callbacks, called with the beat's worker timestamp when a
|
|
475
|
+
* heartbeat arrives. */
|
|
404
476
|
private readonly heartbeatResets;
|
|
405
477
|
private readonly listeners;
|
|
406
478
|
/** Step interceptors (onion middleware around real local-step execution), first = outermost. */
|
|
@@ -411,6 +483,8 @@ export declare class WorkflowEngine {
|
|
|
411
483
|
private readonly enqueuedListeners;
|
|
412
484
|
/** Notified when a run is dead-lettered (moved to `dead`) — a hook for a DLQ handler. */
|
|
413
485
|
private readonly deadListeners;
|
|
486
|
+
/** The fleet-default dead-letter workflow's name — see {@link WorkflowEngineDeps.deadLetterWorkflow}. */
|
|
487
|
+
private readonly deadLetterWorkflow;
|
|
414
488
|
/** Validators gating `engine.update`, keyed by `<workflow>:<updateName>`. */
|
|
415
489
|
private readonly updateValidators;
|
|
416
490
|
/** Runs being cancelled WITH saga compensation — see `cancel({ compensate: true })`. */
|
|
@@ -433,6 +507,20 @@ export declare class WorkflowEngine {
|
|
|
433
507
|
* writes. `settleRun` checks this and degrades to an echo; `execute`'s finally clears the mark.
|
|
434
508
|
*/
|
|
435
509
|
private readonly leaseLostRuns;
|
|
510
|
+
/**
|
|
511
|
+
* The lease handle of each execution in flight in this process, by run id. A path that gives the run
|
|
512
|
+
* lease away mid-execution on purpose (a remote turn suspending on its dispatched decision, see
|
|
513
|
+
* {@link releaseTurnLease}) flags it, so the execution's renew loop stops renewing and never reads its
|
|
514
|
+
* own release as a takeover: a late `false` renew would otherwise fence whoever applies the decision.
|
|
515
|
+
*/
|
|
516
|
+
private readonly executionLeases;
|
|
517
|
+
/** Stable decision handler subscribed on every remote executor's transport (see registerRemote). */
|
|
518
|
+
private readonly decisionHandler;
|
|
519
|
+
/** Earliest clock time an awaited turn's deadline is worth reading again (`runId` → clock ms), the
|
|
520
|
+
* read throttle for {@link rearmDecisionDeadline}. */
|
|
521
|
+
private readonly decisionDeadlineRearms;
|
|
522
|
+
/** Whether any registered remote executor carries its own turn window (`decisionTimeoutMs`). */
|
|
523
|
+
private anyDecisionTimeout;
|
|
436
524
|
/**
|
|
437
525
|
* The in-process execution gate, by run id: the execution of the run currently in flight in THIS
|
|
438
526
|
* process (`tail`), and at most one resume queued behind it (`queued`). See {@link resumeRun}.
|
|
@@ -456,6 +544,10 @@ export declare class WorkflowEngine {
|
|
|
456
544
|
*/
|
|
457
545
|
private readonly postSettle;
|
|
458
546
|
private draining;
|
|
547
|
+
/** Shutdown wait already spent before/alongside {@link drain} (see {@link beginDrain}). */
|
|
548
|
+
private drainSpentMs;
|
|
549
|
+
/** Re-arms the deadline of every {@link drain} currently waiting, when more wait is reported. */
|
|
550
|
+
private readonly drainRearms;
|
|
459
551
|
constructor(deps: WorkflowEngineDeps);
|
|
460
552
|
/**
|
|
461
553
|
* Register a **durable entity** (a virtual object): a keyed actor whose `handlers` run **serialized
|
|
@@ -511,6 +603,18 @@ export declare class WorkflowEngine {
|
|
|
511
603
|
/** Send an operation to an entity (fire-and-forget). Ordered + exactly-once per key. */
|
|
512
604
|
signalEntity(name: string, key: string, op: string, arg?: unknown): Promise<void>;
|
|
513
605
|
/** Read an entity's current durable state (published after each op), or undefined if it has none yet. */
|
|
606
|
+
/**
|
|
607
|
+
* The entity lost-wake reconcile: wake (start, if need be) every entity that has ops sitting in its
|
|
608
|
+
* buffer, up to `limit` of them. A workflow-side send stores the op and THEN wakes the entity, so a
|
|
609
|
+
* process that dies in between leaves the op buffered while the entity sleeps; this pass is what
|
|
610
|
+
* applies it. Idempotent — a wake carries a no-op nudge, and the entity reads its buffer in arrival
|
|
611
|
+
* order, consuming each op once (an op with a stable id is skipped if already applied). The worker
|
|
612
|
+
* tick runs it, throttled to one pass a minute. Returns how many entities were woken. A no-op on a
|
|
613
|
+
* store without `listBufferedSignalTokens`.
|
|
614
|
+
*/
|
|
615
|
+
reconcileEntityWakes(limit?: number): Promise<number>;
|
|
616
|
+
/** {@link reconcileEntityWakes}, at most once a minute — the worker tick's entry point. */
|
|
617
|
+
sweepEntityWakes(now?: number): Promise<number>;
|
|
514
618
|
getEntityState<S = unknown>(name: string, key: string): Promise<S | undefined>;
|
|
515
619
|
/**
|
|
516
620
|
* Be notified when a run is enqueued on ANOTHER instance (via the control plane), so a worker can
|
|
@@ -532,6 +636,10 @@ export declare class WorkflowEngine {
|
|
|
532
636
|
concurrency?: ConcurrencyConfig | undefined;
|
|
533
637
|
executionTimeout?: string | number | undefined;
|
|
534
638
|
validateInput?: ((input: unknown) => void | Promise<void>) | undefined;
|
|
639
|
+
/** Standard Schema validated at start, before `validateInput` — see `RegisteredWorkflow.inputSchema`. */
|
|
640
|
+
inputSchema?: StandardSchemaV1 | undefined;
|
|
641
|
+
/** Typed/validated `searchAttributes` shape — see `RegisteredWorkflow.searchAttributesSchema`. */
|
|
642
|
+
searchAttributesSchema?: SearchAttributesSchema | undefined;
|
|
535
643
|
onEvent?: string[] | undefined;
|
|
536
644
|
eventBatch?: EventBatchConfig | undefined;
|
|
537
645
|
requires?: string[] | undefined;
|
|
@@ -539,6 +647,8 @@ export declare class WorkflowEngine {
|
|
|
539
647
|
origin?: string | undefined;
|
|
540
648
|
/** Handler workflows a matching failure is routed to — see {@link OnErrorRoute}. */
|
|
541
649
|
onError?: OnErrorRoute[] | undefined;
|
|
650
|
+
/** Where a `dead` run of this workflow is handed (overrides the engine's default). */
|
|
651
|
+
deadLetterWorkflow?: WorkflowRef | undefined;
|
|
542
652
|
}): void;
|
|
543
653
|
/**
|
|
544
654
|
* Register a workflow whose body runs in another SDK (e.g. Python). The engine owns the run exactly
|
|
@@ -554,18 +664,37 @@ export declare class WorkflowEngine {
|
|
|
554
664
|
concurrency?: ConcurrencyConfig;
|
|
555
665
|
executionTimeout?: string | number;
|
|
556
666
|
validateInput?: (input: unknown) => void | Promise<void>;
|
|
667
|
+
/** Standard Schema validated at start, before `validateInput` — see `RegisteredWorkflow.inputSchema`. */
|
|
668
|
+
inputSchema?: StandardSchemaV1;
|
|
557
669
|
requires?: string[];
|
|
558
670
|
/** Handler workflows a matching failure is routed to — see {@link OnErrorRoute}. */
|
|
559
671
|
onError?: OnErrorRoute[];
|
|
672
|
+
/** Where a `dead` run of this workflow is handed (overrides the engine's default). */
|
|
673
|
+
deadLetterWorkflow?: WorkflowRef;
|
|
560
674
|
}): void;
|
|
561
675
|
/**
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
*
|
|
565
|
-
*
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
676
|
+
* Register a workflow whose body runs in another SDK, routed to worker `group` — {@link
|
|
677
|
+
* registerRemote} with the executor built for you over this engine's primary transport. `version`
|
|
678
|
+
* defaults to `'1'`; register `name` at a version explicitly to pin starts to it
|
|
679
|
+
* ({@link StartOptions.version}).
|
|
680
|
+
*/
|
|
681
|
+
remote(name: string, opts: Omit<Parameters<WorkflowEngine['registerRemote']>[2], 'executor'> & {
|
|
682
|
+
version?: string | undefined;
|
|
683
|
+
}): void;
|
|
684
|
+
/**
|
|
685
|
+
* Convention-dispatch resolution: when `name` isn't locally registered but a LIVE worker group for
|
|
686
|
+
* it exists, auto-register a remote workflow routed to that group so its runs advance over the
|
|
687
|
+
* broker like any `registerRemote`'d one. Always on — the queue name IS the routing, exactly as the
|
|
688
|
+
* aviary engine does — so a Python/NestJS/thin-worker workflow is reached by NAME with no
|
|
689
|
+
* `registerRemote` boilerplate. Returns whether `name` is registered (and routable for `namespace`)
|
|
690
|
+
* afterwards. A no-op (returns `false`) when no transport is wired (nothing to route over) or no
|
|
691
|
+
* matching worker group is live (then `start`/`resume` throws `is not registered`).
|
|
692
|
+
*
|
|
693
|
+
* TENANT-AWARE, per run: the group is the one the RUN's namespace routes to,
|
|
694
|
+
* `<name>@<namespace>` (bare for an absent/`default` namespace) — the token a tenant worker
|
|
695
|
+
* (`partition: <tenant>`) serves, and the same rule steps follow ({@link stepGroup}). So an operator
|
|
696
|
+
* starting a tenant's run reaches the tenant's live `<name>@<tenant>` group, not the bare one, and a
|
|
697
|
+
* convention workflow is re-checked for the namespace of every start.
|
|
569
698
|
*/
|
|
570
699
|
private ensureConventionWorkflow;
|
|
571
700
|
/**
|
|
@@ -579,7 +708,7 @@ export declare class WorkflowEngine {
|
|
|
579
708
|
private readonly heartbeatPersists;
|
|
580
709
|
/**
|
|
581
710
|
* Persist a worker heartbeat on its step's checkpoint (see {@link StepCheckpoint.lastHeartbeatAt}),
|
|
582
|
-
* best-effort and THROTTLED per step (≥10s between writes) — beats may arrive every few seconds
|
|
711
|
+
* best-effort and THROTTLED per step (≥ `heartbeatPersistThrottleMs`, default 10s, between writes) — beats may arrive every few seconds
|
|
583
712
|
* from a hot batch loop, and liveness observability must not turn into a per-item UPDATE storm.
|
|
584
713
|
* One exemption: a beat CARRYING progress punches through when the last persisted one had none —
|
|
585
714
|
* the automatic pickup beat lands first (no payload) and must not shadow the handler's first real
|
|
@@ -596,6 +725,22 @@ export declare class WorkflowEngine {
|
|
|
596
725
|
* never defer (in-process transports, or a broker transport left eager).
|
|
597
726
|
*/
|
|
598
727
|
startConsumers(): void;
|
|
728
|
+
/**
|
|
729
|
+
* Serve a step body by name on this engine's primary transport — the same
|
|
730
|
+
* `transport.handle(name, fn)` the provider calls for every `stepsPath` handler. It makes the
|
|
731
|
+
* engine a {@link import('./step-discovery.js').StepServer}, so app code can serve steps from an
|
|
732
|
+
* extra directory without reaching for the (provider-private) transport:
|
|
733
|
+
*
|
|
734
|
+
* ```ts
|
|
735
|
+
* // start/durable.ts (a preload)
|
|
736
|
+
* import engine from '@adonis-agora/durable/services/main'
|
|
737
|
+
* import { registerStepsFromDir } from '@adonis-agora/durable'
|
|
738
|
+
* await registerStepsFromDir(engine, app.makePath('app/engine/steps'))
|
|
739
|
+
* ```
|
|
740
|
+
*
|
|
741
|
+
* Throws when no transport is wired or the wired one can't serve handlers (no `handle`).
|
|
742
|
+
*/
|
|
743
|
+
handle(name: string, fn: StepHandler): void;
|
|
599
744
|
/** Subscribe to lifecycle events. Returns an unsubscribe function. */
|
|
600
745
|
subscribe(listener: EngineListener): () => void;
|
|
601
746
|
/**
|
|
@@ -628,6 +773,15 @@ export declare class WorkflowEngine {
|
|
|
628
773
|
*/
|
|
629
774
|
onDead(listener: (run: WorkflowRun) => void): () => void;
|
|
630
775
|
private notifyDead;
|
|
776
|
+
/**
|
|
777
|
+
* Hand a `dead` run to its dead-letter workflow, when one is configured: the workflow's own
|
|
778
|
+
* `deadLetterWorkflow`, else the engine's default. Started as `dlq:<runId>` (idempotent: a run
|
|
779
|
+
* dead-lettered twice is handled once; the dashboard links the pair by that id) in the dead run's
|
|
780
|
+
* namespace, with a {@link DeadLetter} input. Tracked, so a drain waits for the start; a failure
|
|
781
|
+
* (e.g. the handler is not registered here) is warned, never thrown into recovery. A handler run
|
|
782
|
+
* that itself goes dead is not routed again — no `dlq:dlq:…` chain.
|
|
783
|
+
*/
|
|
784
|
+
private routeDeadLetter;
|
|
631
785
|
/** Emit a locally-produced lifecycle event: deliver to subscribers AND broadcast it on the
|
|
632
786
|
* control plane so other instances (e.g. a dashboard pod) can live-tail this run. */
|
|
633
787
|
private emit;
|
|
@@ -681,6 +835,20 @@ export declare class WorkflowEngine {
|
|
|
681
835
|
runValueFacets(axis: RunValueAxis, query: RunFacetQuery, opts?: RunValueFacetOptions): Promise<RunValueFacetRow[]>;
|
|
682
836
|
/** List a run's step checkpoints (its timeline). Part of the engine's read API; see {@link listRuns}. */
|
|
683
837
|
listCheckpoints(runId: string): Promise<StepCheckpoint[]>;
|
|
838
|
+
/**
|
|
839
|
+
* How the runs matching `query` split across `(status, origin)`, in one aggregate when the store
|
|
840
|
+
* has {@link StateStore.runFacets} (else counted over a listing). Part of the engine's read API.
|
|
841
|
+
*/
|
|
842
|
+
runFacets(query: RunFacetQuery): Promise<RunFacetRow[]>;
|
|
843
|
+
/**
|
|
844
|
+
* A run's detail (see `loadRunDetail`), built from the store's checkpoint aggregates when it has
|
|
845
|
+
* `checkpointStats` + `queryCheckpoints` — a summarized detail then reads a few rows per wide fan
|
|
846
|
+
* instead of the whole history, and carries an `etag` that `options.ifNoneMatch` can match.
|
|
847
|
+
*/
|
|
848
|
+
getRunDetail(runId: string, options?: RunDetailOptions): Promise<RunDetail | null>;
|
|
849
|
+
/** One page of a summarized fan's members (see `loadFanMembers`), versioned like {@link getRunDetail}. */
|
|
850
|
+
getFanMembers(runId: string, group: string, query: FanPageQuery): Promise<FanPage | null>;
|
|
851
|
+
private detailSource;
|
|
684
852
|
/**
|
|
685
853
|
* Hard-delete a run and its whole child subtree from the store, returning the number of runs
|
|
686
854
|
* removed (0 if `runId` is unknown). Children are collected BEFORE this run's checkpoints are
|
|
@@ -720,6 +888,21 @@ export declare class WorkflowEngine {
|
|
|
720
888
|
* parents.
|
|
721
889
|
*/
|
|
722
890
|
sweepRetention(now?: number): Promise<number>;
|
|
891
|
+
/**
|
|
892
|
+
* The {@link eventBufferTtlMs} prune: delete buffered events older than the TTL, a bounded batch
|
|
893
|
+
* at a time, through the store's `pruneBufferedEvents`. Runs in {@link sweepRetention}'s pass.
|
|
894
|
+
* Best-effort — a failure is warned and retried on the next pass.
|
|
895
|
+
*/
|
|
896
|
+
private pruneExpiredBufferedEvents;
|
|
897
|
+
/**
|
|
898
|
+
* Delete the runs `rootIds` and their child subtrees: the ids are collected children-first (the
|
|
899
|
+
* edge is read from the parent's checkpoints, so before anything is deleted), deleted in one
|
|
900
|
+
* {@link deleteRunIds} batch, then each one's token-keyed buffered signals are swept like
|
|
901
|
+
* {@link deleteRun} does. Returns how many runs were deleted.
|
|
902
|
+
*/
|
|
903
|
+
private deleteRunTrees;
|
|
904
|
+
/** Bulk-delete through the store's `deleteRuns`, or one `deleteRun` per id when it has none. */
|
|
905
|
+
private deleteRunIds;
|
|
723
906
|
deleteRun(runId: string): Promise<number>;
|
|
724
907
|
/**
|
|
725
908
|
* Sweep a deleted run's token-keyed buffered signals — they are not run-scoped rows, so the store's
|
|
@@ -807,7 +990,15 @@ export declare class WorkflowEngine {
|
|
|
807
990
|
private recheckStepFans;
|
|
808
991
|
/** {@link StateStore.countCheckpoints} of `pending` steps, or a JS count on a store without it. */
|
|
809
992
|
private countPendingSteps;
|
|
810
|
-
/**
|
|
993
|
+
/**
|
|
994
|
+
* Track an in-flight execution so {@link drain} can wait for it.
|
|
995
|
+
*
|
|
996
|
+
* The bookkeeping chain must not re-raise: `p.finally(...)` returns a NEW promise that rejects
|
|
997
|
+
* whenever `p` does, and nothing awaits it. So a turn whose store write failed (a dropped
|
|
998
|
+
* connection, a missing table) became a process-level unhandled rejection even though the caller
|
|
999
|
+
* awaiting `p` handled the very same error — fatal under Node's default `--unhandled-rejections`.
|
|
1000
|
+
* The rejection is reported once, to the caller that owns `p`.
|
|
1001
|
+
*/
|
|
811
1002
|
private track;
|
|
812
1003
|
/**
|
|
813
1004
|
* Track a post-settle side effect (parent notify, singleton wake) so {@link drain} waits for it,
|
|
@@ -822,8 +1013,14 @@ export declare class WorkflowEngine {
|
|
|
822
1013
|
* (and their per-run lock loops) start nothing once this is called, and {@link runOne} refuses
|
|
823
1014
|
* broker-delivered runs. Runs already started finish. {@link drain} calls it first; the worker loop
|
|
824
1015
|
* calls it the moment a stop is requested, so a tick still in flight stops leasing a backlog.
|
|
1016
|
+
*
|
|
1017
|
+
* `spentMs` is wait time ALREADY spent on this shutdown (the worker loop waiting for its in-flight
|
|
1018
|
+
* tick). It is deducted from the budget of a later {@link drain}, so that wait plus the drain stay
|
|
1019
|
+
* within one `drainTimeoutMs`; a drain already waiting is shortened. Only time actually spent
|
|
1020
|
+
* waiting is charged, and reports add up. Non-finite or negative values are ignored, so one bad
|
|
1021
|
+
* report can't turn every later drain into a 0 ms wait.
|
|
825
1022
|
*/
|
|
826
|
-
beginDrain(): void;
|
|
1023
|
+
beginDrain(spentMs?: number): void;
|
|
827
1024
|
/** True once {@link beginDrain} (or {@link drain}) has been called. */
|
|
828
1025
|
isDraining(): boolean;
|
|
829
1026
|
/**
|
|
@@ -844,8 +1041,14 @@ export declare class WorkflowEngine {
|
|
|
844
1041
|
* process is going away, so a held lease would only delay the next pod's `recoverIncomplete` until
|
|
845
1042
|
* expiry; after release the next pod replays deterministically (a pending step re-dispatches the same
|
|
846
1043
|
* `stepId`, idempotent by the durable contract; a completed step short-circuits).
|
|
1044
|
+
*
|
|
1045
|
+
* `timeoutMs` is the TOTAL shutdown budget: wait already reported through {@link beginDrain}
|
|
1046
|
+
* (`spentMs`) is deducted, so a worker that first waited for its in-flight tick drains only for
|
|
1047
|
+
* what is left. With nothing reported, the full `timeoutMs` applies.
|
|
847
1048
|
*/
|
|
848
1049
|
drain(timeoutMs?: number): Promise<void>;
|
|
1050
|
+
/** The {@link drain} wait loop, bounded by `timer`. */
|
|
1051
|
+
private drainUntil;
|
|
849
1052
|
/**
|
|
850
1053
|
* Best-effort release of the recovery locks still held by in-flight executions. Called on `drain()`
|
|
851
1054
|
* return so a shutting-down process hands off fast. Never throws (swallowed per-run).
|
|
@@ -862,6 +1065,33 @@ export declare class WorkflowEngine {
|
|
|
862
1065
|
* replay from their checkpoints, so only the work that had not finished runs again.
|
|
863
1066
|
*/
|
|
864
1067
|
recoverIncomplete(nowMs?: number): Promise<RunResult[]>;
|
|
1068
|
+
/**
|
|
1069
|
+
* Whether a lease held under this engine's own {@link instanceId} was left behind by a previous
|
|
1070
|
+
* process that ran under the same id, rather than held by this one. Both must hold:
|
|
1071
|
+
* - nothing in this process executes the run: no execution in its run gate and no execution lease
|
|
1072
|
+
* tracked for it;
|
|
1073
|
+
* - the lease was written before this engine booted: every lease this process writes (acquire or
|
|
1074
|
+
* renew) ends at `clock() + leaseMs >= bootedAt + leaseMs`, so an earlier end proves an earlier
|
|
1075
|
+
* writer. This also covers the brief windows where a path of this process holds the lease
|
|
1076
|
+
* without having entered the run gate yet (a sweep between `tryLockRun` and the resume).
|
|
1077
|
+
*
|
|
1078
|
+
* Sound only when no two LIVE processes share an instance id — the documented requirement.
|
|
1079
|
+
*/
|
|
1080
|
+
private selfReclaimable;
|
|
1081
|
+
/**
|
|
1082
|
+
* Release a lease this instance's previous incarnation left on `listed` (see {@link selfReclaimable}),
|
|
1083
|
+
* so the recovery sweep can take the run like any orphan. The release runs inside the run's
|
|
1084
|
+
* in-process gate, so a resume landing meanwhile here queues behind it instead of executing on the
|
|
1085
|
+
* lease being given up; the run is re-read there and only released if it is still a stale `running`
|
|
1086
|
+
* self-lease. Returns whether the lease was released.
|
|
1087
|
+
*/
|
|
1088
|
+
private releaseStaleSelfLease;
|
|
1089
|
+
/**
|
|
1090
|
+
* The remote step this run dispatched and still awaits a result for, if any — the durable marker
|
|
1091
|
+
* that tells {@link recoverIncomplete} "this run's work is on the transport, not in a crashed
|
|
1092
|
+
* process". A `pending` remote checkpoint is written before the dispatch and settled by the result.
|
|
1093
|
+
*/
|
|
1094
|
+
private inFlightRemoteStep;
|
|
865
1095
|
/**
|
|
866
1096
|
* Per-recovery bookkeeping (called once the lease is held): count the attempt, or — past
|
|
867
1097
|
* `maxRecoveryAttempts` — move a poison pill to the `dead` dead-letter state. Returns a terminal
|
|
@@ -904,8 +1134,9 @@ export declare class WorkflowEngine {
|
|
|
904
1134
|
* Explicitly re-dispatch every remote step of `runId` stuck `pending` — the OPERATOR escape hatch for
|
|
905
1135
|
* a run whose dispatched step job was LOST (worker crashed with no result, or a transport that dropped
|
|
906
1136
|
* the job). No automatic recovery re-drives these: a reconcile re-drive re-suspends a still-pending
|
|
907
|
-
* step by design (unless `remoteRedispatchMs` is set), `recoverIncomplete`
|
|
908
|
-
*
|
|
1137
|
+
* step by design (unless `remoteRedispatchMs` is set), `recoverIncomplete` parks a run with an
|
|
1138
|
+
* in-flight `pending` remote step back to `suspended` instead of re-driving it, and `requeue` just
|
|
1139
|
+
* replays back to the pending guard. This re-enqueues the same `stepId` so the
|
|
909
1140
|
* (idempotent) step re-runs and its result resumes the run. Safe to call on a healthy run — it re-runs
|
|
910
1141
|
* only in-flight `pending` remote steps, which are idempotent by the durable contract. Returns the
|
|
911
1142
|
* run's current status (with the count re-dispatched), or null if the run is unknown.
|
|
@@ -946,6 +1177,12 @@ export declare class WorkflowEngine {
|
|
|
946
1177
|
/**
|
|
947
1178
|
* Resume each run only if this instance can acquire its recovery lease — so when several
|
|
948
1179
|
* replicas recover or poll at once, each run is picked up by exactly one of them.
|
|
1180
|
+
*
|
|
1181
|
+
* A run this instance cannot resume is SKIPPED (and logged), never allowed to abort the batch: a
|
|
1182
|
+
* leased batch is a mixed bag during a rolling deploy (a pod without a run's workflow throws for
|
|
1183
|
+
* it by design) and a store hiccup can fail one row, but the rest of the batch is runs it can drive
|
|
1184
|
+
* — and every caller is a recovery/poll sweep. The skipped run stays locked only until its lease
|
|
1185
|
+
* expires, then another instance (or a later tick) picks it up.
|
|
949
1186
|
*/
|
|
950
1187
|
private resumeLeased;
|
|
951
1188
|
/**
|
|
@@ -1021,6 +1258,13 @@ export declare class WorkflowEngine {
|
|
|
1021
1258
|
* side's write, and the destructive `take*` ops arbitrate so a signal is never delivered twice.
|
|
1022
1259
|
*/
|
|
1023
1260
|
signal(token: string, payload: unknown): Promise<RunResult | null>;
|
|
1261
|
+
/**
|
|
1262
|
+
* Wake the run parked on `token` with `payload`, if there is one; otherwise do nothing — unlike
|
|
1263
|
+
* {@link signal}, it never buffers. For a wake-up whose real payload is ALREADY buffered on the
|
|
1264
|
+
* token (an entity op, see `Entities.kick`): a run that isn't parked reads that buffer at its next
|
|
1265
|
+
* wait, so there is nothing to keep.
|
|
1266
|
+
*/
|
|
1267
|
+
private wakeSignalWaiter;
|
|
1024
1268
|
/**
|
|
1025
1269
|
* Ensure a run exists for `runId`, then deliver a signal to it — atomically race-free thanks to
|
|
1026
1270
|
* signal buffering: if the run is new (or busy / not yet waiting), the signal is buffered and
|
|
@@ -1131,6 +1375,21 @@ export declare class WorkflowEngine {
|
|
|
1131
1375
|
* the full listing for a store without one.
|
|
1132
1376
|
*/
|
|
1133
1377
|
countRuns(query: Omit<RunQuery, 'page' | 'size'>): Promise<number>;
|
|
1378
|
+
/**
|
|
1379
|
+
* Every workflow the live fleet can execute in this engine's partition: what workers DECLARE in
|
|
1380
|
+
* their descriptors, plus the live routing tokens no descriptor explains (a worker too old to
|
|
1381
|
+
* describe itself). Each entry says which kind of evidence it rests on. See
|
|
1382
|
+
* {@link workflowDirectory} for why the list is the length it is.
|
|
1383
|
+
*/
|
|
1384
|
+
announcedWorkflows(): Promise<AnnouncedWorkflow[]>;
|
|
1385
|
+
/**
|
|
1386
|
+
* {@link announcedWorkflows}, plus why it is empty when it is: no transport here can read the fleet
|
|
1387
|
+
* (`supported: false`), nothing is live, or workers are live only on OTHER partitions
|
|
1388
|
+
* (`otherPartitions`), which otherwise reads exactly like an empty fleet. Two live reads, neither
|
|
1389
|
+
* retained: the descriptor advertisement and the heartbeat keyspace. Only the BullMQ transport reads
|
|
1390
|
+
* them today.
|
|
1391
|
+
*/
|
|
1392
|
+
workflowDirectory(): Promise<WorkflowDirectory>;
|
|
1134
1393
|
/** The worker groups this engine dispatches to: every registered remote workflow's group, plus any
|
|
1135
1394
|
* `extra` the caller declares. Local-step groups (a group consumed by in-process `@DurableStep`
|
|
1136
1395
|
* workers, e.g. `pipeline`) aren't derivable from registrations — pass them via `extra` so a group
|
|
@@ -1140,7 +1399,7 @@ export declare class WorkflowEngine {
|
|
|
1140
1399
|
* (so a registered group with backlog and ZERO workers still reports — the alert case) UNION the
|
|
1141
1400
|
* groups discovered from live heartbeats (so a local-step group like `pipeline`, not derivable
|
|
1142
1401
|
* from registrations, shows once its workers beat). Empty when no transport can introspect health
|
|
1143
|
-
* (only the BullMQ
|
|
1402
|
+
* (only the BullMQ, queue and db transports implement `groupHealth`). */
|
|
1144
1403
|
workerHealth(extra?: string[]): Promise<GroupHealth[]>;
|
|
1145
1404
|
/**
|
|
1146
1405
|
* Persist a streamed local-step lifecycle event from a remote workflow worker (see
|
|
@@ -1231,7 +1490,101 @@ export declare class WorkflowEngine {
|
|
|
1231
1490
|
* fallback is disabled (`reconcileMs: 0`). See {@link WorkflowEngineDeps.reconcileMs}.
|
|
1232
1491
|
*/
|
|
1233
1492
|
private reconcileWakeAt;
|
|
1493
|
+
/**
|
|
1494
|
+
* The result of a turn the singleton gate denied. The store already parked the run `suspended` on
|
|
1495
|
+
* its retry timer INSIDE the admission claim (or left it alone, when a concurrent cancel had
|
|
1496
|
+
* settled it), so report what is persisted rather than writing over it.
|
|
1497
|
+
*/
|
|
1498
|
+
/**
|
|
1499
|
+
* A run's first execution: `pending` -> `running`. A singleton run not yet admitted is stamped
|
|
1500
|
+
* {@link SINGLETON_TRACKED_TAG} in the same write, BEFORE it competes for a slot, so a run this
|
|
1501
|
+
* replica is about to admit or deny is never mistaken for a holder admitted by a replica older than
|
|
1502
|
+
* 0.51 (see `legacySingletonHolders`).
|
|
1503
|
+
*/
|
|
1504
|
+
private markStarted;
|
|
1505
|
+
private singletonWaitResult;
|
|
1234
1506
|
private runRemoteExecution;
|
|
1507
|
+
/**
|
|
1508
|
+
* Apply a remote workflow turn's {@link WorkflowDecision}: persist the local steps it ran, then settle
|
|
1509
|
+
* (completed/failed/cancelled) or dispatch its blocking ops and suspend (continue). Shared by the
|
|
1510
|
+
* INLINE advance path ({@link runRemoteExecution}, under the execution's lease) and the dispatched
|
|
1511
|
+
* path ({@link completeRemoteDecision}, which holds the lease itself and has already checked that
|
|
1512
|
+
* this is the decision of the turn the run awaits).
|
|
1513
|
+
*/
|
|
1514
|
+
private applyDecision;
|
|
1515
|
+
/**
|
|
1516
|
+
* The dispatched-turn path of {@link runRemoteExecution}: SUSPEND, then ENQUEUE. The engine mints a
|
|
1517
|
+
* globally unique turn `taskId`, records it on the run as the awaited marker, and releases the lease,
|
|
1518
|
+
* all BEFORE the turn is enqueued, so a worker's decision, however fast and on whichever replica it
|
|
1519
|
+
* lands, always finds both its marker and a free lease (see {@link completeRemoteDecision}). The
|
|
1520
|
+
* deadline is the turn's liveness window ({@link decisionWindowMs}); when it lapses with no decision
|
|
1521
|
+
* and no run-scoped heartbeat, the timer poller re-drives the run, which dispatches a fresh turn.
|
|
1522
|
+
*/
|
|
1523
|
+
private dispatchRemoteTurn;
|
|
1524
|
+
/**
|
|
1525
|
+
* The turn could not be enqueued (the transport cannot carry workflow turns, or the broker refused the
|
|
1526
|
+
* write): fail the run, as an advance that throws does — but only while it still awaits THIS turn, so
|
|
1527
|
+
* a cancel or a re-drive that landed meanwhile wins.
|
|
1528
|
+
*/
|
|
1529
|
+
private failUndispatchedTurn;
|
|
1530
|
+
/**
|
|
1531
|
+
* Give the run lease away mid-execution on purpose: stop the execution's renew loop from renewing it
|
|
1532
|
+
* (or reading the release as a takeover), then release it. Owner-scoped, so a lease another instance
|
|
1533
|
+
* already holds is left alone.
|
|
1534
|
+
*/
|
|
1535
|
+
private releaseTurnLease;
|
|
1536
|
+
/**
|
|
1537
|
+
* The liveness window of a dispatched turn: the engine's `remoteAdvanceSilenceMs` and the executor's
|
|
1538
|
+
* own `decisionTimeoutMs` (a `RemoteWorkflowExecutor`'s `timeoutMs`), the shorter of the two when both
|
|
1539
|
+
* are set. `undefined` = no deadline: the run waits for its decision.
|
|
1540
|
+
*/
|
|
1541
|
+
private decisionWindowMs;
|
|
1542
|
+
/**
|
|
1543
|
+
* Await an INLINE advance, rejecting with {@link RemoteWorkflowTimeout} once `silenceMs` passes with
|
|
1544
|
+
* neither a decision nor a run-scoped heartbeat for `runId`. Each beat rearms the window. The beat
|
|
1545
|
+
* hook is registered before this returns, so a beat can't slip in unseen.
|
|
1546
|
+
*/
|
|
1547
|
+
private awaitTurnWithSilence;
|
|
1548
|
+
/** Whether `run` is awaiting exactly `decision`'s turn (and so may still apply it). */
|
|
1549
|
+
private awaitsDecision;
|
|
1550
|
+
/**
|
|
1551
|
+
* Apply a remote workflow-turn {@link WorkflowDecision} durably, on WHICHEVER replica consumes it: the
|
|
1552
|
+
* dispatching replica may be gone, or a point-to-point decisions queue handed the decision to a
|
|
1553
|
+
* sibling. The durable twin of {@link completeRemoteResult} for a workflow TURN: look the run up by
|
|
1554
|
+
* `decision.runId`, check that it still awaits this `taskId` (a stale, duplicate, foreign or
|
|
1555
|
+
* superseded decision is dropped, so a decision applies at most once), lease it, and apply it.
|
|
1556
|
+
* Serialized with this replica's own executions of the run through the run gate.
|
|
1557
|
+
*/
|
|
1558
|
+
private completeRemoteDecision;
|
|
1559
|
+
/**
|
|
1560
|
+
* Run `fn` in the run's in-process execution gate (see {@link resumeRun}): after the execution in
|
|
1561
|
+
* flight here, before any resume that lands later. A resume already queued (not started) runs first.
|
|
1562
|
+
*/
|
|
1563
|
+
private serializeOnRun;
|
|
1564
|
+
/** {@link completeRemoteDecision} inside the run gate: lease, re-check, claim the turn, apply. */
|
|
1565
|
+
private applyRemoteDecision;
|
|
1566
|
+
/**
|
|
1567
|
+
* Acquire the run lease to apply `decision`. The dispatcher released it before enqueueing, so this
|
|
1568
|
+
* normally succeeds at once; another replica may still hold it briefly (its wake found the turn in
|
|
1569
|
+
* flight and is releasing), so retry until the lease frees, the run stops awaiting this turn, or one
|
|
1570
|
+
* lease window passes (a crashed holder's lease expires within it). A lease THIS instance holds is
|
|
1571
|
+
* reused: we are inside the run gate, so no execution of it is running here.
|
|
1572
|
+
*/
|
|
1573
|
+
private leaseForDecision;
|
|
1574
|
+
/**
|
|
1575
|
+
* A run-scoped heartbeat for a run awaiting a dispatched turn's decision: push its re-drive deadline
|
|
1576
|
+
* (`wakeAt`) forward so a worker still replaying the turn is not re-driven. The durable counterpart
|
|
1577
|
+
* of an inline advance's in-memory rearm, and the run-scoped sibling of {@link rearmStepLease}.
|
|
1578
|
+
*
|
|
1579
|
+
* Throttled the same way: a renewal buys at most one window, so it is only worth a write once the
|
|
1580
|
+
* window is half spent. A beat that finds more than half of it left writes nothing and records the
|
|
1581
|
+
* half-spent mark, so later beats skip even the read until then. That bounds the cost at one read and
|
|
1582
|
+
* one write per half window per awaited turn, whatever the beat cadence. The mark is in memory only
|
|
1583
|
+
* (cold on another replica, which re-derives the same answer from the run's `wakeAt`). Best-effort:
|
|
1584
|
+
* it runs inside the transport's serial beat handler, so a store error is swallowed, and the mark only
|
|
1585
|
+
* moves after a write commits, so the next beat retries.
|
|
1586
|
+
*/
|
|
1587
|
+
private rearmDecisionDeadline;
|
|
1235
1588
|
/**
|
|
1236
1589
|
* A polyglot workflow's re-emitted `call` whose checkpoint already exists: decide whether the step is
|
|
1237
1590
|
* still out for delivery, or whether its dispatch was LOST and has to be re-driven. Returns the
|
|
@@ -1314,6 +1667,22 @@ export declare class WorkflowEngine {
|
|
|
1314
1667
|
* {@link redriveLostCall}). A terminal turn (completed/failed/cancelled) applies its commands only to
|
|
1315
1668
|
* record what already ran, and must never dispatch anything new. */
|
|
1316
1669
|
private applyCommands;
|
|
1670
|
+
/**
|
|
1671
|
+
* Whether a compensating cancel is pending for this run, consuming the in-memory flag. The intent
|
|
1672
|
+
* lives in TWO places: the in-memory `cancelRequested` fast path (same pod, same boot), and the
|
|
1673
|
+
* DURABLE buffered `cancel:<id>` marker `cancel()` persisted — so a crash or a cross-pod handoff
|
|
1674
|
+
* mid-cancellation can't silently forget the cancel. The marker is peeked (take + re-buffer), not
|
|
1675
|
+
* consumed: it must survive a crash mid-unwind; {@link compensateAndCancel} drains it once
|
|
1676
|
+
* `cancelled` is durably recorded.
|
|
1677
|
+
*/
|
|
1678
|
+
private takeCancelIntent;
|
|
1679
|
+
/**
|
|
1680
|
+
* Undo the registered saga compensations in reverse and settle the run `cancelled`. Shared by EVERY
|
|
1681
|
+
* exit of a turn with a compensating cancel pending — the body returned, suspended, hit
|
|
1682
|
+
* continue-as-new or threw — so the cancel is never lost because the body didn't stop at a
|
|
1683
|
+
* suspension point.
|
|
1684
|
+
*/
|
|
1685
|
+
private compensateAndCancel;
|
|
1317
1686
|
/** The run body, lease held + renewed by {@link execute}. */
|
|
1318
1687
|
private runExecution;
|
|
1319
1688
|
/**
|
|
@@ -1459,7 +1828,36 @@ export declare class WorkflowEngine {
|
|
|
1459
1828
|
*/
|
|
1460
1829
|
/** {@link StateStore.saveCheckpointIfPending}, or a plain save on a store without it. */
|
|
1461
1830
|
private savePendingCheckpoint;
|
|
1831
|
+
/**
|
|
1832
|
+
* Settle a durable step result and (barrier permitting) resume its run in the background.
|
|
1833
|
+
*
|
|
1834
|
+
* One run's results are settled in batches: the first starts a batch, and the ones that arrive
|
|
1835
|
+
* while it is being written (with `resultConcurrency > 1`) form the next, up to
|
|
1836
|
+
* {@link RESULT_BATCH_MAX}. A batch of several claims its checkpoints with one
|
|
1837
|
+
* {@link StateStore.saveCheckpointsIfPending} call, asks each step fan's barrier once, and resumes
|
|
1838
|
+
* the run at most once; a batch of one takes the single-result path unchanged. A result resolves
|
|
1839
|
+
* only once its own write committed, so the transport acknowledges nothing that is not durable.
|
|
1840
|
+
*/
|
|
1462
1841
|
private completeRemoteResult;
|
|
1842
|
+
/** Settle `queue` (one run's queued results) batch by batch until it is empty, then retire it. */
|
|
1843
|
+
private drainResultQueue;
|
|
1844
|
+
/** The single-result path: settle `result`, then resume its run unless its fan is still running. */
|
|
1845
|
+
private completeOneRemoteResult;
|
|
1846
|
+
private resumeInBackground;
|
|
1847
|
+
/**
|
|
1848
|
+
* Settle a batch of one run's step results; per result, `true` (settled or dropped) or the error
|
|
1849
|
+
* that kept it from settling, which the transport then redelivers. Same outcome per result as
|
|
1850
|
+
* {@link completeOneRemoteResult} on each in turn, with one resume for the batch: that resume
|
|
1851
|
+
* replays every write of the batch, so a second would only replay it again.
|
|
1852
|
+
*/
|
|
1853
|
+
private completeRemoteResults;
|
|
1854
|
+
/**
|
|
1855
|
+
* {@link savePendingCheckpoint} for checkpoints at distinct seqs: one
|
|
1856
|
+
* {@link StateStore.saveCheckpointsIfPending} call when the store has it, else one write each.
|
|
1857
|
+
* Never rejects as a whole: a failed write is reported as that entry's error, and the batch call
|
|
1858
|
+
* rejecting means it wrote nothing, so the entries are then written one by one.
|
|
1859
|
+
*/
|
|
1860
|
+
private savePendingCheckpoints;
|
|
1463
1861
|
/**
|
|
1464
1862
|
* The join barrier of a step fan: a result for one of its steps resumes the parent only once no
|
|
1465
1863
|
* step of the fan is still `pending` (a settled wave), or on a failure (failFast surfaces it, and a
|