@dudousxd/nestjs-durable 0.46.3 → 0.47.1

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.d.cts CHANGED
@@ -1,4 +1,4 @@
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';
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, RunDetailOptions, RunDetail, FanPageQuery, FanPage, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, WorkflowRun, TenantEvent } from '@dudousxd/nestjs-durable-core';
2
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';
@@ -500,6 +500,37 @@ interface DurableModuleOptions {
500
500
  * Ignored when `remoteRedispatchMs` is unset. Operator only.
501
501
  */
502
502
  remoteRedispatchMax?: number;
503
+ /**
504
+ * Fallback wake-up (ms) for a run suspended on an event (child, signal, `waitForEvent`, remote
505
+ * result) whose wake-up was lost: the reconcile pass re-drives it after this window, an idempotent
506
+ * replay that re-suspends a still-pending wait. Defaults to 300000 (5min); `0` disables it.
507
+ * See `WorkflowEngineDeps.reconcileMs`. Operator only.
508
+ */
509
+ reconcileMs?: number;
510
+ /**
511
+ * The most due timers one timer-poll pass loads and drives, most overdue first, so a wave of
512
+ * thousands of due runs is worked through in batches. Defaults to 500; a non-finite or sub-1 value
513
+ * falls back to the default. See `WorkflowEngineDeps.timerBatchSize`. Operator only.
514
+ */
515
+ timerBatchSize?: number;
516
+ /**
517
+ * Retention (ms) for a buffered event that no `waitForEvent` ever claims; the reconcile pass prunes
518
+ * rows past `publishedAt + eventBufferTtlMs`. Omit (or `0`) to keep them until consumed, the
519
+ * default. See `WorkflowEngineDeps.eventBufferTtlMs`. Operator only.
520
+ */
521
+ eventBufferTtlMs?: number;
522
+ /**
523
+ * How long (ms) a run parked `blocked` (no capable, protocol-compatible live worker) waits before
524
+ * the blocked-recovery poll re-checks the fleet. Defaults to 5000. See
525
+ * `WorkflowEngineDeps.blockedPollMs`. Operator only.
526
+ */
527
+ blockedPollMs?: number;
528
+ /**
529
+ * Persist a `running` checkpoint when a local step's body begins, so an in-flight step survives a
530
+ * dashboard reload. Defaults to `true`; set `false` on hot paths with many short local steps to
531
+ * halve their checkpoint writes. See `WorkflowEngineDeps.trackStepStart`. Operator only.
532
+ */
533
+ trackStepStart?: boolean;
503
534
  /**
504
535
  * The **default** workflow to route dead-lettered runs to, for workflows that don't declare their
505
536
  * own. When a run is moved to `dead` (exceeded `maxRecoveryAttempts`), the started handler gets a
@@ -945,7 +976,8 @@ declare class ProxyRunGateway implements RunGateway {
945
976
  private handleReply;
946
977
  private request;
947
978
  topology(): DurableTopology;
948
- getRunDetail(runId: string): Promise<RunDetail | null>;
979
+ getRunDetail(runId: string, options?: RunDetailOptions): Promise<RunDetail | null>;
980
+ getFanMembers(runId: string, group: string, query: FanPageQuery): Promise<FanPage | null>;
949
981
  /** The control plane's `StoreRunGateway` resolves each run's `waiting` descriptor; the reply carries
950
982
  * it through as plain JSON, so a tenant's list rows name the wait too. */
951
983
  listRuns(query: RunQuery): Promise<RunListItem[]>;
@@ -1045,7 +1077,9 @@ declare class StoreRunGateway implements RunGateway {
1045
1077
  private readonly engine;
1046
1078
  constructor(store: StateStore, engine: WorkflowEngine);
1047
1079
  topology(): DurableTopology;
1048
- getRunDetail(runId: string): Promise<RunDetail | null>;
1080
+ getRunDetail(runId: string, options?: RunDetailOptions): Promise<RunDetail | null>;
1081
+ getRun(runId: string): Promise<WorkflowRun | null>;
1082
+ getFanMembers(runId: string, group: string, query: FanPageQuery): Promise<FanPage | null>;
1049
1083
  listRuns(query: RunQuery): Promise<RunListItem[]>;
1050
1084
  /**
1051
1085
  * The `(status, origin)` counts behind a console's chips, straight off the store's aggregate. The
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
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';
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, RunDetailOptions, RunDetail, FanPageQuery, FanPage, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, WorkflowRun, TenantEvent } from '@dudousxd/nestjs-durable-core';
2
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';
@@ -500,6 +500,37 @@ interface DurableModuleOptions {
500
500
  * Ignored when `remoteRedispatchMs` is unset. Operator only.
501
501
  */
502
502
  remoteRedispatchMax?: number;
503
+ /**
504
+ * Fallback wake-up (ms) for a run suspended on an event (child, signal, `waitForEvent`, remote
505
+ * result) whose wake-up was lost: the reconcile pass re-drives it after this window, an idempotent
506
+ * replay that re-suspends a still-pending wait. Defaults to 300000 (5min); `0` disables it.
507
+ * See `WorkflowEngineDeps.reconcileMs`. Operator only.
508
+ */
509
+ reconcileMs?: number;
510
+ /**
511
+ * The most due timers one timer-poll pass loads and drives, most overdue first, so a wave of
512
+ * thousands of due runs is worked through in batches. Defaults to 500; a non-finite or sub-1 value
513
+ * falls back to the default. See `WorkflowEngineDeps.timerBatchSize`. Operator only.
514
+ */
515
+ timerBatchSize?: number;
516
+ /**
517
+ * Retention (ms) for a buffered event that no `waitForEvent` ever claims; the reconcile pass prunes
518
+ * rows past `publishedAt + eventBufferTtlMs`. Omit (or `0`) to keep them until consumed, the
519
+ * default. See `WorkflowEngineDeps.eventBufferTtlMs`. Operator only.
520
+ */
521
+ eventBufferTtlMs?: number;
522
+ /**
523
+ * How long (ms) a run parked `blocked` (no capable, protocol-compatible live worker) waits before
524
+ * the blocked-recovery poll re-checks the fleet. Defaults to 5000. See
525
+ * `WorkflowEngineDeps.blockedPollMs`. Operator only.
526
+ */
527
+ blockedPollMs?: number;
528
+ /**
529
+ * Persist a `running` checkpoint when a local step's body begins, so an in-flight step survives a
530
+ * dashboard reload. Defaults to `true`; set `false` on hot paths with many short local steps to
531
+ * halve their checkpoint writes. See `WorkflowEngineDeps.trackStepStart`. Operator only.
532
+ */
533
+ trackStepStart?: boolean;
503
534
  /**
504
535
  * The **default** workflow to route dead-lettered runs to, for workflows that don't declare their
505
536
  * own. When a run is moved to `dead` (exceeded `maxRecoveryAttempts`), the started handler gets a
@@ -945,7 +976,8 @@ declare class ProxyRunGateway implements RunGateway {
945
976
  private handleReply;
946
977
  private request;
947
978
  topology(): DurableTopology;
948
- getRunDetail(runId: string): Promise<RunDetail | null>;
979
+ getRunDetail(runId: string, options?: RunDetailOptions): Promise<RunDetail | null>;
980
+ getFanMembers(runId: string, group: string, query: FanPageQuery): Promise<FanPage | null>;
949
981
  /** The control plane's `StoreRunGateway` resolves each run's `waiting` descriptor; the reply carries
950
982
  * it through as plain JSON, so a tenant's list rows name the wait too. */
951
983
  listRuns(query: RunQuery): Promise<RunListItem[]>;
@@ -1045,7 +1077,9 @@ declare class StoreRunGateway implements RunGateway {
1045
1077
  private readonly engine;
1046
1078
  constructor(store: StateStore, engine: WorkflowEngine);
1047
1079
  topology(): DurableTopology;
1048
- getRunDetail(runId: string): Promise<RunDetail | null>;
1080
+ getRunDetail(runId: string, options?: RunDetailOptions): Promise<RunDetail | null>;
1081
+ getRun(runId: string): Promise<WorkflowRun | null>;
1082
+ getFanMembers(runId: string, group: string, query: FanPageQuery): Promise<FanPage | null>;
1049
1083
  listRuns(query: RunQuery): Promise<RunListItem[]>;
1050
1084
  /**
1051
1085
  * The `(status, origin)` counts behind a console's chips, straight off the store's aggregate. The
package/dist/index.js CHANGED
@@ -1072,10 +1072,19 @@ var ProxyRunGateway = class {
1072
1072
  tenant: this.tenant
1073
1073
  };
1074
1074
  }
1075
- getRunDetail(runId) {
1075
+ getRunDetail(runId, options) {
1076
1076
  return this.request({
1077
1077
  kind: "getRunDetail",
1078
- runId
1078
+ runId,
1079
+ options
1080
+ });
1081
+ }
1082
+ getFanMembers(runId, group, query) {
1083
+ return this.request({
1084
+ kind: "getFanMembers",
1085
+ runId,
1086
+ group,
1087
+ query
1079
1088
  });
1080
1089
  }
1081
1090
  /** The control plane's `StoreRunGateway` resolves each run's `waiting` descriptor; the reply carries
@@ -1437,8 +1446,8 @@ var RunRequestResponder = class {
1437
1446
  if (body.kind === "waitingFor") {
1438
1447
  const all = await this.gateway.waitingFor(body.runIds);
1439
1448
  const owned = await Promise.all(Object.entries(all).map(async ([runId, waiting]) => {
1440
- const runDetail = await this.gateway.getRunDetail(runId);
1441
- return runDetail && runDetail.run.namespace === msg.tenant ? [
1449
+ const owner = this.gateway.getRun ? await this.gateway.getRun(runId) : (await this.gateway.getRunDetail(runId))?.run;
1450
+ return owner && owner.namespace === msg.tenant ? [
1442
1451
  runId,
1443
1452
  waiting
1444
1453
  ] : void 0;
@@ -1455,8 +1464,9 @@ var RunRequestResponder = class {
1455
1464
  }
1456
1465
  };
1457
1466
  }
1458
- const detail = await this.gateway.getRunDetail(body.runId);
1459
- if (detail && detail.run.namespace !== msg.tenant) {
1467
+ const detail = body.kind === "getRunDetail" || !this.gateway.getRun ? await this.gateway.getRunDetail(body.runId, body.kind === "getRunDetail" ? body.options : void 0) : void 0;
1468
+ const run = detail !== void 0 ? detail?.run ?? null : await this.gateway.getRun?.(body.runId);
1469
+ if (run && run.namespace !== msg.tenant) {
1460
1470
  return {
1461
1471
  requestId: msg.requestId,
1462
1472
  result: {
@@ -1477,6 +1487,16 @@ var RunRequestResponder = class {
1477
1487
  }
1478
1488
  };
1479
1489
  }
1490
+ if (body.kind === "getFanMembers") {
1491
+ const data = run ? await this.gateway.getFanMembers?.(body.runId, body.group, body.query) ?? null : null;
1492
+ return {
1493
+ requestId: msg.requestId,
1494
+ result: {
1495
+ ok: true,
1496
+ data
1497
+ }
1498
+ };
1499
+ }
1480
1500
  try {
1481
1501
  const data = await this.callVerb(body);
1482
1502
  return {
@@ -1515,7 +1535,7 @@ var RunRequestResponder = class {
1515
1535
  };
1516
1536
 
1517
1537
  // src/store-run-gateway.ts
1518
- import { STATE_STORE_CANONICAL as STATE_STORE_CANONICAL2, WorkflowEngine as WorkflowEngine2, indexWaitersByRun, listSignalWaitersOfRuns, mergeRunFacetRows, resolveRunWaiting } from "@dudousxd/nestjs-durable-core";
1538
+ import { STATE_STORE_CANONICAL as STATE_STORE_CANONICAL2, SUMMARY_CHILD_LIMIT, WorkflowEngine as WorkflowEngine2, childIdsOf, indexWaitersByRun, listSignalWaitersOfRuns, mergeRunFacetRows, pageFan, resolveRunWaiting, summarizeTimeline } from "@dudousxd/nestjs-durable-core";
1519
1539
  import { Inject as Inject5, Injectable as Injectable8 } from "@nestjs/common";
1520
1540
  function _ts_decorate8(decorators, target, key, desc) {
1521
1541
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -1558,19 +1578,39 @@ var StoreRunGateway = class {
1558
1578
  role: "control-plane"
1559
1579
  };
1560
1580
  }
1561
- async getRunDetail(runId) {
1581
+ async getRunDetail(runId, options) {
1562
1582
  const run = await this.store.getRun(runId);
1563
1583
  if (!run) return null;
1564
- const [timeline, children] = await Promise.all([
1565
- this.store.listCheckpoints(runId),
1566
- this.engine.getRunChildren(runId)
1567
- ]);
1584
+ const over = options?.summarizeFansOver;
1585
+ if (over === void 0) {
1586
+ const [timeline2, children] = await Promise.all([
1587
+ this.store.listCheckpoints(runId),
1588
+ this.engine.getRunChildren(runId)
1589
+ ]);
1590
+ return {
1591
+ run,
1592
+ timeline: timeline2,
1593
+ children
1594
+ };
1595
+ }
1596
+ const full = await this.store.listCheckpoints(runId);
1597
+ const { timeline, fans } = summarizeTimeline(full, over);
1598
+ const ids = childIdsOf(full);
1568
1599
  return {
1569
1600
  run,
1570
1601
  timeline,
1571
- children
1602
+ children: ids.slice(0, SUMMARY_CHILD_LIMIT),
1603
+ fans,
1604
+ childCount: ids.length
1572
1605
  };
1573
1606
  }
1607
+ getRun(runId) {
1608
+ return this.store.getRun(runId);
1609
+ }
1610
+ async getFanMembers(runId, group, query) {
1611
+ if (!await this.store.getRun(runId)) return null;
1612
+ return pageFan(await this.store.listCheckpoints(runId), group, query);
1613
+ }
1574
1614
  async listRuns(query) {
1575
1615
  const runs = await this.store.listRuns(query);
1576
1616
  const waiterByRun = indexWaitersByRun(await listSignalWaitersOfRuns(this.store, runs.filter((run) => run.status === "suspended").map((run) => run.id)));
@@ -2505,6 +2545,11 @@ var DurableModule = class _DurableModule {
2505
2545
  remoteAdvanceSilenceMs: options.remoteAdvanceSilenceMs,
2506
2546
  remoteRedispatchMs: options.remoteRedispatchMs,
2507
2547
  remoteRedispatchMax: options.remoteRedispatchMax,
2548
+ reconcileMs: options.reconcileMs,
2549
+ timerBatchSize: options.timerBatchSize,
2550
+ eventBufferTtlMs: options.eventBufferTtlMs,
2551
+ blockedPollMs: options.blockedPollMs,
2552
+ trackStepStart: options.trackStepStart,
2508
2553
  instanceId: options.instanceId,
2509
2554
  namespace: options.namespace,
2510
2555
  webhookUrl: options.webhookUrl,