@dudousxd/nestjs-durable 0.44.0 → 0.45.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/dist/index.cjs +19 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -5
- package/dist/index.d.ts +30 -5
- package/dist/index.js +19 -3
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { WorkflowCtx, SearchAttributes, WorkflowClass, StepError, WorkflowRef, SingletonConfig, SearchAttributesSchema, StateStore, Transport, NamedTransport, ControlPlane, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, WorkflowInputOf, StartOptions, RunResult, RunGateway, WorkflowEngine, EntityHandler, DurableTopology, RunDetail, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, TenantEvent } from '@dudousxd/nestjs-durable-core';
|
|
2
|
-
export { AttributeFilter, EngineEvent, InferSearchAttributes, RunDetail, RunGateway, RunListItem, RunQuery, RunStatus, RunWaiting, SearchAttributes, SearchAttributesSchema, StepCheckpoint, StepEvent, StepLogger, WorkflowCtx, WorkflowEngine, WorkflowHandler, WorkflowRun, readSearchAttributes } from '@dudousxd/nestjs-durable-core';
|
|
1
|
+
import { WorkflowCtx, SearchAttributes, WorkflowClass, StepError, WorkflowRef, SingletonConfig, ConcurrencyConfig, SearchAttributesSchema, StateStore, Transport, NamedTransport, ControlPlane, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, WorkflowInputOf, StartOptions, RunResult, RunGateway, WorkflowEngine, EntityHandler, DurableTopology, RunDetail, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, TenantEvent } from '@dudousxd/nestjs-durable-core';
|
|
2
|
+
export { AttributeFilter, DynamicWorkflowCtx, EngineEvent, InferSearchAttributes, RunDetail, RunGateway, RunListItem, RunQuery, RunStatus, RunWaiting, SearchAttributes, SearchAttributesSchema, StepCheckpoint, StepEvent, StepLogger, WorkflowCtx, WorkflowEngine, WorkflowHandler, WorkflowRun, readSearchAttributes } from '@dudousxd/nestjs-durable-core';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { ConcurrencyOption, StartRunDeps, RunRedisWorkerOptions, RunningWorker, DurableWorkerRuntime } from '@dudousxd/durable-worker';
|
|
5
5
|
import { DynamicModule, InjectionToken, OnModuleInit, OnApplicationBootstrap, OnApplicationShutdown, Provider } from '@nestjs/common';
|
|
@@ -112,6 +112,8 @@ interface WorkflowMeta {
|
|
|
112
112
|
tags?: string[] | undefined;
|
|
113
113
|
/** Per-key serialization (a durable mutex). See `WorkflowOptions`. */
|
|
114
114
|
singleton?: SingletonConfig | undefined;
|
|
115
|
+
/** Start-time concurrency quota (rejecting). See `WorkflowOptions`. */
|
|
116
|
+
concurrency?: ConcurrencyConfig | undefined;
|
|
115
117
|
/** Max wall-clock lifetime before a run is cancelled (e.g. `'2h'`). See `WorkflowOptions`. */
|
|
116
118
|
executionTimeout?: string | number | undefined;
|
|
117
119
|
/** class-validator DTO validated at start. See `WorkflowOptions`. */
|
|
@@ -156,6 +158,15 @@ interface WorkflowOptions {
|
|
|
156
158
|
* 1) raises the concurrency.
|
|
157
159
|
*/
|
|
158
160
|
singleton?: SingletonConfig;
|
|
161
|
+
/**
|
|
162
|
+
* A start-time concurrency QUOTA: at most `limit` runs sharing a key in flight, and a start over it
|
|
163
|
+
* is REJECTED (`ConcurrencyLimitError`, nothing created) rather than queued. e.g.
|
|
164
|
+
* `concurrency: { key: (input) => `tenant:${input.tenantId}`, limit: 8 }` caps what one tenant can
|
|
165
|
+
* have executing at once. The key is shared across workflows; `limit` may be a (async) function of
|
|
166
|
+
* the key for per-plan limits; `countStatuses` narrows what occupies a slot (default: every
|
|
167
|
+
* non-terminal status). Use `singleton` instead when excess runs should wait their turn.
|
|
168
|
+
*/
|
|
169
|
+
concurrency?: ConcurrencyConfig;
|
|
159
170
|
/**
|
|
160
171
|
* Max wall-clock lifetime for a run of this workflow (e.g. `'2h'`, `'7 days'`, or ms). A run that
|
|
161
172
|
* outlives it is moved to `cancelled` (`execution_timeout`) by the timer poller — a backstop for
|
|
@@ -363,7 +374,7 @@ declare function getOnEvents(meta: WorkflowMeta, target: object): string[];
|
|
|
363
374
|
|
|
364
375
|
/**
|
|
365
376
|
* Retention config for the {@link RetentionPoller}. One or more {@link RetentionPolicy policies}
|
|
366
|
-
* (status sets must be disjoint — validated at boot), swept together on a shared interval.
|
|
377
|
+
* (status sets must be disjoint per scope — validated at boot), swept together on a shared interval.
|
|
367
378
|
*
|
|
368
379
|
* ```ts
|
|
369
380
|
* retention: {
|
|
@@ -372,9 +383,14 @@ declare function getOnEvents(meta: WorkflowMeta, target: object): string[];
|
|
|
372
383
|
* policies: [
|
|
373
384
|
* { statuses: ['completed', 'cancelled'], maxAge: '14d', maxCount: 200 },
|
|
374
385
|
* { statuses: ['failed'], maxAge: '90d' }, // keep failures longer for debugging
|
|
386
|
+
* // Scoped: chat turns age out after a day, whatever the defaults above say.
|
|
387
|
+
* { statuses: ['completed', 'failed', 'cancelled'], maxAge: '1d', scope: { tags: ['chat'] } },
|
|
375
388
|
* ],
|
|
376
389
|
* }
|
|
377
390
|
* ```
|
|
391
|
+
*
|
|
392
|
+
* Policies are applied one after another, so a run matched by several scopes is pruned by the
|
|
393
|
+
* strictest of them.
|
|
378
394
|
*/
|
|
379
395
|
interface DurableRetentionOptions {
|
|
380
396
|
/** The retention rules, one per (disjoint) status group. */
|
|
@@ -513,12 +529,21 @@ interface DurableModuleOptions {
|
|
|
513
529
|
* optional `cron-parser` peer dependency. Operator only.
|
|
514
530
|
*/
|
|
515
531
|
schedules?: ScheduledWorkflow[];
|
|
532
|
+
/**
|
|
533
|
+
* Fire the PERSISTED schedules managed at runtime through `engine.schedules` (create/upsert/pause/
|
|
534
|
+
* resume/delete/list) on every timer-poll tick of a driving instance — one indexed "due by now"
|
|
535
|
+
* query per tick. Off by default, so a deployment that never uses them doesn't need the
|
|
536
|
+
* `durable_schedules` table. Safe with any number of driving instances: each window's run id is
|
|
537
|
+
* deterministic and advancing a schedule is a compare-and-set. Operator only.
|
|
538
|
+
*/
|
|
539
|
+
persistedSchedules?: boolean;
|
|
516
540
|
/**
|
|
517
541
|
* Hard-prune terminal run history on an interval so `durable_workflow_runs` (and its child tables)
|
|
518
542
|
* stays bounded — without it, completed/failed/cancelled runs accumulate forever and the timer
|
|
519
543
|
* poller's per-tick status scans get linearly slower. Driving instances only. Omit to keep all
|
|
520
|
-
* history (the default). Requires a store adapter that implements `pruneTerminalRuns` (
|
|
521
|
-
*
|
|
544
|
+
* history (the default). Requires a store adapter that implements `pruneTerminalRuns` (every
|
|
545
|
+
* first-party adapter does); a custom store without it no-ops with a warning. See
|
|
546
|
+
* {@link DurableRetentionOptions}.
|
|
522
547
|
* Operator only.
|
|
523
548
|
*/
|
|
524
549
|
retention?: DurableRetentionOptions;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { WorkflowCtx, SearchAttributes, WorkflowClass, StepError, WorkflowRef, SingletonConfig, SearchAttributesSchema, StateStore, Transport, NamedTransport, ControlPlane, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, WorkflowInputOf, StartOptions, RunResult, RunGateway, WorkflowEngine, EntityHandler, DurableTopology, RunDetail, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, TenantEvent } from '@dudousxd/nestjs-durable-core';
|
|
2
|
-
export { AttributeFilter, EngineEvent, InferSearchAttributes, RunDetail, RunGateway, RunListItem, RunQuery, RunStatus, RunWaiting, SearchAttributes, SearchAttributesSchema, StepCheckpoint, StepEvent, StepLogger, WorkflowCtx, WorkflowEngine, WorkflowHandler, WorkflowRun, readSearchAttributes } from '@dudousxd/nestjs-durable-core';
|
|
1
|
+
import { WorkflowCtx, SearchAttributes, WorkflowClass, StepError, WorkflowRef, SingletonConfig, ConcurrencyConfig, SearchAttributesSchema, StateStore, Transport, NamedTransport, ControlPlane, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, WorkflowInputOf, StartOptions, RunResult, RunGateway, WorkflowEngine, EntityHandler, DurableTopology, RunDetail, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, TenantEvent } from '@dudousxd/nestjs-durable-core';
|
|
2
|
+
export { AttributeFilter, DynamicWorkflowCtx, EngineEvent, InferSearchAttributes, RunDetail, RunGateway, RunListItem, RunQuery, RunStatus, RunWaiting, SearchAttributes, SearchAttributesSchema, StepCheckpoint, StepEvent, StepLogger, WorkflowCtx, WorkflowEngine, WorkflowHandler, WorkflowRun, readSearchAttributes } from '@dudousxd/nestjs-durable-core';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { ConcurrencyOption, StartRunDeps, RunRedisWorkerOptions, RunningWorker, DurableWorkerRuntime } from '@dudousxd/durable-worker';
|
|
5
5
|
import { DynamicModule, InjectionToken, OnModuleInit, OnApplicationBootstrap, OnApplicationShutdown, Provider } from '@nestjs/common';
|
|
@@ -112,6 +112,8 @@ interface WorkflowMeta {
|
|
|
112
112
|
tags?: string[] | undefined;
|
|
113
113
|
/** Per-key serialization (a durable mutex). See `WorkflowOptions`. */
|
|
114
114
|
singleton?: SingletonConfig | undefined;
|
|
115
|
+
/** Start-time concurrency quota (rejecting). See `WorkflowOptions`. */
|
|
116
|
+
concurrency?: ConcurrencyConfig | undefined;
|
|
115
117
|
/** Max wall-clock lifetime before a run is cancelled (e.g. `'2h'`). See `WorkflowOptions`. */
|
|
116
118
|
executionTimeout?: string | number | undefined;
|
|
117
119
|
/** class-validator DTO validated at start. See `WorkflowOptions`. */
|
|
@@ -156,6 +158,15 @@ interface WorkflowOptions {
|
|
|
156
158
|
* 1) raises the concurrency.
|
|
157
159
|
*/
|
|
158
160
|
singleton?: SingletonConfig;
|
|
161
|
+
/**
|
|
162
|
+
* A start-time concurrency QUOTA: at most `limit` runs sharing a key in flight, and a start over it
|
|
163
|
+
* is REJECTED (`ConcurrencyLimitError`, nothing created) rather than queued. e.g.
|
|
164
|
+
* `concurrency: { key: (input) => `tenant:${input.tenantId}`, limit: 8 }` caps what one tenant can
|
|
165
|
+
* have executing at once. The key is shared across workflows; `limit` may be a (async) function of
|
|
166
|
+
* the key for per-plan limits; `countStatuses` narrows what occupies a slot (default: every
|
|
167
|
+
* non-terminal status). Use `singleton` instead when excess runs should wait their turn.
|
|
168
|
+
*/
|
|
169
|
+
concurrency?: ConcurrencyConfig;
|
|
159
170
|
/**
|
|
160
171
|
* Max wall-clock lifetime for a run of this workflow (e.g. `'2h'`, `'7 days'`, or ms). A run that
|
|
161
172
|
* outlives it is moved to `cancelled` (`execution_timeout`) by the timer poller — a backstop for
|
|
@@ -363,7 +374,7 @@ declare function getOnEvents(meta: WorkflowMeta, target: object): string[];
|
|
|
363
374
|
|
|
364
375
|
/**
|
|
365
376
|
* Retention config for the {@link RetentionPoller}. One or more {@link RetentionPolicy policies}
|
|
366
|
-
* (status sets must be disjoint — validated at boot), swept together on a shared interval.
|
|
377
|
+
* (status sets must be disjoint per scope — validated at boot), swept together on a shared interval.
|
|
367
378
|
*
|
|
368
379
|
* ```ts
|
|
369
380
|
* retention: {
|
|
@@ -372,9 +383,14 @@ declare function getOnEvents(meta: WorkflowMeta, target: object): string[];
|
|
|
372
383
|
* policies: [
|
|
373
384
|
* { statuses: ['completed', 'cancelled'], maxAge: '14d', maxCount: 200 },
|
|
374
385
|
* { statuses: ['failed'], maxAge: '90d' }, // keep failures longer for debugging
|
|
386
|
+
* // Scoped: chat turns age out after a day, whatever the defaults above say.
|
|
387
|
+
* { statuses: ['completed', 'failed', 'cancelled'], maxAge: '1d', scope: { tags: ['chat'] } },
|
|
375
388
|
* ],
|
|
376
389
|
* }
|
|
377
390
|
* ```
|
|
391
|
+
*
|
|
392
|
+
* Policies are applied one after another, so a run matched by several scopes is pruned by the
|
|
393
|
+
* strictest of them.
|
|
378
394
|
*/
|
|
379
395
|
interface DurableRetentionOptions {
|
|
380
396
|
/** The retention rules, one per (disjoint) status group. */
|
|
@@ -513,12 +529,21 @@ interface DurableModuleOptions {
|
|
|
513
529
|
* optional `cron-parser` peer dependency. Operator only.
|
|
514
530
|
*/
|
|
515
531
|
schedules?: ScheduledWorkflow[];
|
|
532
|
+
/**
|
|
533
|
+
* Fire the PERSISTED schedules managed at runtime through `engine.schedules` (create/upsert/pause/
|
|
534
|
+
* resume/delete/list) on every timer-poll tick of a driving instance — one indexed "due by now"
|
|
535
|
+
* query per tick. Off by default, so a deployment that never uses them doesn't need the
|
|
536
|
+
* `durable_schedules` table. Safe with any number of driving instances: each window's run id is
|
|
537
|
+
* deterministic and advancing a schedule is a compare-and-set. Operator only.
|
|
538
|
+
*/
|
|
539
|
+
persistedSchedules?: boolean;
|
|
516
540
|
/**
|
|
517
541
|
* Hard-prune terminal run history on an interval so `durable_workflow_runs` (and its child tables)
|
|
518
542
|
* stays bounded — without it, completed/failed/cancelled runs accumulate forever and the timer
|
|
519
543
|
* poller's per-tick status scans get linearly slower. Driving instances only. Omit to keep all
|
|
520
|
-
* history (the default). Requires a store adapter that implements `pruneTerminalRuns` (
|
|
521
|
-
*
|
|
544
|
+
* history (the default). Requires a store adapter that implements `pruneTerminalRuns` (every
|
|
545
|
+
* first-party adapter does); a custom store without it no-ops with a warning. See
|
|
546
|
+
* {@link DurableRetentionOptions}.
|
|
522
547
|
* Operator only.
|
|
523
548
|
*/
|
|
524
549
|
retention?: DurableRetentionOptions;
|
package/dist/index.js
CHANGED
|
@@ -127,6 +127,7 @@ function Workflow(options) {
|
|
|
127
127
|
deadLetterWorkflow: options.deadLetterWorkflow,
|
|
128
128
|
tags: options.tags,
|
|
129
129
|
singleton: options.singleton,
|
|
130
|
+
concurrency: options.concurrency,
|
|
130
131
|
executionTimeout: options.executionTimeout,
|
|
131
132
|
inputSchema: options.inputSchema,
|
|
132
133
|
validateInput: options.validateInput,
|
|
@@ -1204,6 +1205,7 @@ var MAX_BATCHES_PER_POLICY = 100;
|
|
|
1204
1205
|
function validateRetention(retention) {
|
|
1205
1206
|
const seen = /* @__PURE__ */ new Set();
|
|
1206
1207
|
for (const policy of retention.policies) {
|
|
1208
|
+
const scopeKey = policy.scope ? stableKey(policy.scope) : "";
|
|
1207
1209
|
if (policy.statuses.length === 0) {
|
|
1208
1210
|
throw new Error("durable retention: each policy must list at least one status");
|
|
1209
1211
|
}
|
|
@@ -1215,14 +1217,24 @@ function validateRetention(retention) {
|
|
|
1215
1217
|
if (!TERMINAL_RUN_STATUSES.includes(status)) {
|
|
1216
1218
|
throw new Error(`durable retention: status "${status}" is not terminal; only ${TERMINAL_RUN_STATUSES.join(", ")} can be pruned`);
|
|
1217
1219
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
+
const key = `${scopeKey}|${status}`;
|
|
1221
|
+
if (seen.has(key)) {
|
|
1222
|
+
throw new Error(`durable retention: status "${status}" appears in more than one policy with the same scope; status sets must be disjoint per scope`);
|
|
1220
1223
|
}
|
|
1221
|
-
seen.add(
|
|
1224
|
+
seen.add(key);
|
|
1222
1225
|
}
|
|
1223
1226
|
}
|
|
1224
1227
|
}
|
|
1225
1228
|
__name(validateRetention, "validateRetention");
|
|
1229
|
+
function stableKey(value) {
|
|
1230
|
+
if (Array.isArray(value)) return `[${value.map(stableKey).join(",")}]`;
|
|
1231
|
+
if (value && typeof value === "object") {
|
|
1232
|
+
const entries = Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a.localeCompare(b));
|
|
1233
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableKey(v)}`).join(",")}}`;
|
|
1234
|
+
}
|
|
1235
|
+
return JSON.stringify(value);
|
|
1236
|
+
}
|
|
1237
|
+
__name(stableKey, "stableKey");
|
|
1226
1238
|
var RetentionPoller = class {
|
|
1227
1239
|
static {
|
|
1228
1240
|
__name(this, "RetentionPoller");
|
|
@@ -1743,6 +1755,9 @@ var TimerPoller = class {
|
|
|
1743
1755
|
if (schedules && schedules.length > 0) {
|
|
1744
1756
|
await this.sweep("schedules", () => runSchedules(this.engine, schedules, Date.now()));
|
|
1745
1757
|
}
|
|
1758
|
+
if (this.options.persistedSchedules) {
|
|
1759
|
+
await this.sweep("persistedSchedules", () => this.engine.schedules.tick());
|
|
1760
|
+
}
|
|
1746
1761
|
} finally {
|
|
1747
1762
|
this.polling = false;
|
|
1748
1763
|
}
|
|
@@ -1919,6 +1934,7 @@ var WorkflowRegistrar = class {
|
|
|
1919
1934
|
origin,
|
|
1920
1935
|
tags: meta.tags,
|
|
1921
1936
|
singleton: meta.singleton,
|
|
1937
|
+
concurrency: meta.concurrency,
|
|
1922
1938
|
executionTimeout: meta.executionTimeout,
|
|
1923
1939
|
requires: meta.requires,
|
|
1924
1940
|
validateInput,
|