@dudousxd/nestjs-durable 0.47.0 → 0.48.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 CHANGED
@@ -49,14 +49,16 @@ __export(index_exports, {
49
49
  IN_APP_WORKER_RUNNERS: () => IN_APP_WORKER_RUNNERS,
50
50
  IN_APP_WORKER_RUNTIME: () => IN_APP_WORKER_RUNTIME,
51
51
  InAppWorkerBootstrap: () => InAppWorkerBootstrap,
52
+ ON_ERROR_METADATA: () => ON_ERROR_METADATA,
52
53
  ON_EVENT_METADATA: () => ON_EVENT_METADATA,
53
54
  On: () => On,
54
55
  OnDurableEvent: () => OnDurableEvent,
56
+ OnError: () => OnError,
55
57
  OnEvent: () => OnEvent,
56
58
  ProxyRunGateway: () => ProxyRunGateway,
57
59
  RUN_GATEWAY: () => RUN_GATEWAY,
58
60
  RUN_REDIS_WORKER: () => RUN_REDIS_WORKER,
59
- RunGateway: () => import_nestjs_durable_core15.RunGateway,
61
+ RunGateway: () => import_nestjs_durable_core17.RunGateway,
60
62
  RunRequestResponder: () => RunRequestResponder,
61
63
  STEP_INTERCEPTOR_METADATA: () => STEP_INTERCEPTOR_METADATA,
62
64
  Step: () => Step,
@@ -66,9 +68,10 @@ __export(index_exports, {
66
68
  ThinStepRegistrar: () => ThinStepRegistrar,
67
69
  ThinWorkerBootstrap: () => ThinWorkerBootstrap,
68
70
  ThinWorkflowRegistrar: () => ThinWorkflowRegistrar,
71
+ UNSUPPORTED_RUN_REQUEST: () => UNSUPPORTED_RUN_REQUEST,
69
72
  WORKFLOW_METADATA: () => WORKFLOW_METADATA,
70
73
  Workflow: () => Workflow,
71
- WorkflowEngine: () => import_nestjs_durable_core15.WorkflowEngine,
74
+ WorkflowEngine: () => import_nestjs_durable_core17.WorkflowEngine,
72
75
  WorkflowService: () => WorkflowService,
73
76
  attributesOf: () => attributesOf,
74
77
  entityConfigFor: () => entityConfigFor,
@@ -81,7 +84,8 @@ __export(index_exports, {
81
84
  isDrivingOperator: () => isDrivingOperator,
82
85
  isOperatorRole: () => isOperatorRole,
83
86
  isStepInterceptor: () => isStepInterceptor,
84
- readSearchAttributes: () => import_nestjs_durable_core15.readSearchAttributes,
87
+ onErrorCodesOf: () => onErrorCodesOf,
88
+ readSearchAttributes: () => import_nestjs_durable_core17.readSearchAttributes,
85
89
  thinWorkerProviders: () => thinWorkerProviders,
86
90
  unavailableRunGateway: () => unavailableRunGateway
87
91
  });
@@ -211,6 +215,7 @@ function Workflow(options) {
211
215
  name: options.name,
212
216
  version: options.version ?? "1",
213
217
  deadLetterWorkflow: options.deadLetterWorkflow,
218
+ onError: options.onError,
214
219
  tags: options.tags,
215
220
  singleton: options.singleton,
216
221
  concurrency: options.concurrency,
@@ -288,6 +293,26 @@ function isDeadLetterHandler(method) {
288
293
  return Reflect.getMetadata(DEAD_LETTER_METADATA, method) === true;
289
294
  }
290
295
  __name(isDeadLetterHandler, "isDeadLetterHandler");
296
+ var ON_ERROR_METADATA = Symbol("nestjs-durable:on-error");
297
+ function OnError(match) {
298
+ const code = match === void 0 || typeof match === "string" ? match : match.code;
299
+ if (match !== void 0 && typeof code !== "string") {
300
+ throw new Error('@OnError(ErrorClass): the class has no static `code`. Declare `static readonly code = "..."` on it, or pass the code string.');
301
+ }
302
+ return (_target, _propertyKey, descriptor) => {
303
+ const method = descriptor.value;
304
+ const codes = Reflect.getMetadata(ON_ERROR_METADATA, method) ?? [];
305
+ Reflect.defineMetadata(ON_ERROR_METADATA, [
306
+ ...codes,
307
+ code
308
+ ], method);
309
+ };
310
+ }
311
+ __name(OnError, "OnError");
312
+ function onErrorCodesOf(method) {
313
+ return Reflect.getMetadata(ON_ERROR_METADATA, method);
314
+ }
315
+ __name(onErrorCodesOf, "onErrorCodesOf");
291
316
  var ON_EVENT_METADATA = Symbol("nestjs-durable:on-event");
292
317
  function OnDurableEvent(...events) {
293
318
  return (target) => {
@@ -449,7 +474,7 @@ function tenantUnsupported(method) {
449
474
  __name(tenantUnsupported, "tenantUnsupported");
450
475
 
451
476
  // src/durable-worker.module.ts
452
- var import_nestjs_durable_core4 = require("@dudousxd/nestjs-durable-core");
477
+ var import_nestjs_durable_core5 = require("@dudousxd/nestjs-durable-core");
453
478
  var import_common2 = require("@nestjs/common");
454
479
  var import_core = require("@nestjs/core");
455
480
 
@@ -490,6 +515,66 @@ function scanSteps(discovery, scanner, register) {
490
515
  }
491
516
  __name(scanSteps, "scanSteps");
492
517
 
518
+ // src/on-error-handlers.ts
519
+ var import_nestjs_durable_core4 = require("@dudousxd/nestjs-durable-core");
520
+ function onErrorHandlersOf(meta, instance, scanner) {
521
+ const handlers = [];
522
+ const routes = [];
523
+ for (const methodName of scanner.getAllMethodNames(Object.getPrototypeOf(instance))) {
524
+ const method = instance[methodName];
525
+ const codes = typeof method === "function" ? onErrorCodesOf(method) : void 0;
526
+ if (!codes) continue;
527
+ const name = `${meta.name}.onError.${methodName}`;
528
+ handlers.push([
529
+ name,
530
+ (ctx, input) => method.call(instance, ctx, input)
531
+ ]);
532
+ for (const code of codes) routes.push({
533
+ code,
534
+ workflow: name
535
+ });
536
+ }
537
+ for (const r of meta.onError ?? []) {
538
+ routes.push({
539
+ code: r.code === void 0 || typeof r.code === "string" ? r.code : r.code.code,
540
+ workflow: (0, import_nestjs_durable_core4.workflowName)(r.workflow)
541
+ });
542
+ }
543
+ return {
544
+ handlers,
545
+ routes
546
+ };
547
+ }
548
+ __name(onErrorHandlersOf, "onErrorHandlersOf");
549
+
550
+ // src/runtime-registration.ts
551
+ function registerOnRuntime(runtime, scanner, meta, instance, origin) {
552
+ const { handlers, routes } = onErrorHandlersOf(meta, instance, scanner);
553
+ const announced = {
554
+ version: meta.version,
555
+ ...origin !== void 0 ? {
556
+ origin
557
+ } : {}
558
+ };
559
+ runtime.registerWorkflow(meta.name, (ctx, input) => instance.run(ctx, input), {
560
+ ...announced,
561
+ ...meta.requires !== void 0 ? {
562
+ requires: meta.requires
563
+ } : {},
564
+ // A catch-all goes on the wire without a `code` key, not with an undefined one.
565
+ ...routes.length > 0 ? {
566
+ onError: routes.map(({ code, workflow }) => code === void 0 ? {
567
+ workflow
568
+ } : {
569
+ code,
570
+ workflow
571
+ })
572
+ } : {}
573
+ });
574
+ for (const [name, fn] of handlers) runtime.registerWorkflow(name, fn, announced);
575
+ }
576
+ __name(registerOnRuntime, "registerOnRuntime");
577
+
493
578
  // src/durable-worker.module.ts
494
579
  function _ts_decorate2(decorators, target, key, desc) {
495
580
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -529,34 +614,29 @@ var ThinWorkflowRegistrar = class {
529
614
  __name(this, "ThinWorkflowRegistrar");
530
615
  }
531
616
  discovery;
617
+ metadataScanner;
532
618
  runtime;
533
619
  options;
534
- constructor(discovery, runtime, options) {
620
+ constructor(discovery, metadataScanner, runtime, options) {
535
621
  this.discovery = discovery;
622
+ this.metadataScanner = metadataScanner;
536
623
  this.runtime = runtime;
537
624
  this.options = options;
538
625
  }
539
626
  onModuleInit() {
540
627
  const runtime = this.runtime;
541
628
  if (runtime === null || !isPureThinWorker(this.options)) return;
542
- scanWorkflows(this.discovery, (meta, instance, origin) => runtime.registerWorkflow(meta.name, (ctx, input) => instance.run(ctx, input), {
543
- version: meta.version,
544
- ...meta.requires !== void 0 ? {
545
- requires: meta.requires
546
- } : {},
547
- ...origin !== void 0 ? {
548
- origin
549
- } : {}
550
- }));
629
+ scanWorkflows(this.discovery, (meta, instance, origin) => registerOnRuntime(runtime, this.metadataScanner, meta, instance, origin));
551
630
  }
552
631
  };
553
632
  ThinWorkflowRegistrar = _ts_decorate2([
554
633
  (0, import_common2.Injectable)(),
555
- _ts_param(1, (0, import_common2.Inject)(DURABLE_WORKER_RUNTIME)),
556
- _ts_param(2, (0, import_common2.Inject)(import_nestjs_durable_core4.DURABLE_OPTIONS_CANONICAL)),
634
+ _ts_param(2, (0, import_common2.Inject)(DURABLE_WORKER_RUNTIME)),
635
+ _ts_param(3, (0, import_common2.Inject)(import_nestjs_durable_core5.DURABLE_OPTIONS_CANONICAL)),
557
636
  _ts_metadata2("design:type", Function),
558
637
  _ts_metadata2("design:paramtypes", [
559
638
  typeof import_core.DiscoveryService === "undefined" ? Object : import_core.DiscoveryService,
639
+ typeof import_core.MetadataScanner === "undefined" ? Object : import_core.MetadataScanner,
560
640
  Object,
561
641
  typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
562
642
  ])
@@ -584,7 +664,7 @@ var ThinStepRegistrar = class {
584
664
  ThinStepRegistrar = _ts_decorate2([
585
665
  (0, import_common2.Injectable)(),
586
666
  _ts_param(2, (0, import_common2.Inject)(DURABLE_WORKER_RUNTIME)),
587
- _ts_param(3, (0, import_common2.Inject)(import_nestjs_durable_core4.DURABLE_OPTIONS_CANONICAL)),
667
+ _ts_param(3, (0, import_common2.Inject)(import_nestjs_durable_core5.DURABLE_OPTIONS_CANONICAL)),
588
668
  _ts_metadata2("design:type", Function),
589
669
  _ts_metadata2("design:paramtypes", [
590
670
  typeof import_core.DiscoveryService === "undefined" ? Object : import_core.DiscoveryService,
@@ -638,7 +718,7 @@ var ThinWorkerBootstrap = class {
638
718
  ThinWorkerBootstrap = _ts_decorate2([
639
719
  (0, import_common2.Injectable)(),
640
720
  _ts_param(0, (0, import_common2.Inject)(DURABLE_WORKER_RUNTIME)),
641
- _ts_param(1, (0, import_common2.Inject)(import_nestjs_durable_core4.DURABLE_OPTIONS_CANONICAL)),
721
+ _ts_param(1, (0, import_common2.Inject)(import_nestjs_durable_core5.DURABLE_OPTIONS_CANONICAL)),
642
722
  _ts_param(2, (0, import_common2.Inject)(RUN_REDIS_WORKER)),
643
723
  _ts_param(3, (0, import_common2.Inject)(DURABLE_WORKER_RUNNERS)),
644
724
  _ts_metadata2("design:type", Function),
@@ -668,7 +748,7 @@ function thinWorkerProviders() {
668
748
  workflowGroup: options.partition ?? ""
669
749
  }) : null, "useFactory"),
670
750
  inject: [
671
- import_nestjs_durable_core4.DURABLE_OPTIONS_CANONICAL
751
+ import_nestjs_durable_core5.DURABLE_OPTIONS_CANONICAL
672
752
  ]
673
753
  },
674
754
  {
@@ -738,12 +818,12 @@ function unavailableRunGateway() {
738
818
  __name(unavailableRunGateway, "unavailableRunGateway");
739
819
 
740
820
  // src/durable.module.ts
741
- var import_nestjs_durable_core14 = require("@dudousxd/nestjs-durable-core");
821
+ var import_nestjs_durable_core16 = require("@dudousxd/nestjs-durable-core");
742
822
  var import_common12 = require("@nestjs/common");
743
823
  var import_core5 = require("@nestjs/core");
744
824
 
745
825
  // src/durable-step.registrar.ts
746
- var import_nestjs_durable_core5 = require("@dudousxd/nestjs-durable-core");
826
+ var import_nestjs_durable_core6 = require("@dudousxd/nestjs-durable-core");
747
827
  var import_common3 = require("@nestjs/common");
748
828
  var import_core2 = require("@nestjs/core");
749
829
 
@@ -811,8 +891,8 @@ var DurableStepRegistrar = class {
811
891
  };
812
892
  DurableStepRegistrar = _ts_decorate3([
813
893
  (0, import_common3.Injectable)(),
814
- _ts_param2(2, (0, import_common3.Inject)(import_nestjs_durable_core5.TRANSPORT_CANONICAL)),
815
- _ts_param2(3, (0, import_common3.Inject)(import_nestjs_durable_core5.DURABLE_OPTIONS_CANONICAL)),
894
+ _ts_param2(2, (0, import_common3.Inject)(import_nestjs_durable_core6.TRANSPORT_CANONICAL)),
895
+ _ts_param2(3, (0, import_common3.Inject)(import_nestjs_durable_core6.DURABLE_OPTIONS_CANONICAL)),
816
896
  _ts_metadata3("design:type", Function),
817
897
  _ts_metadata3("design:paramtypes", [
818
898
  typeof import_core2.DiscoveryService === "undefined" ? Object : import_core2.DiscoveryService,
@@ -823,7 +903,7 @@ DurableStepRegistrar = _ts_decorate3([
823
903
  ], DurableStepRegistrar);
824
904
 
825
905
  // src/entity.ts
826
- var import_nestjs_durable_core6 = require("@dudousxd/nestjs-durable-core");
906
+ var import_nestjs_durable_core7 = require("@dudousxd/nestjs-durable-core");
827
907
  var import_common4 = require("@nestjs/common");
828
908
  var import_reflect_metadata2 = require("reflect-metadata");
829
909
  function _ts_decorate4(decorators, target, key, desc) {
@@ -906,12 +986,12 @@ EntityService = _ts_decorate4([
906
986
  (0, import_common4.Injectable)(),
907
987
  _ts_metadata4("design:type", Function),
908
988
  _ts_metadata4("design:paramtypes", [
909
- typeof import_nestjs_durable_core6.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core6.WorkflowEngine
989
+ typeof import_nestjs_durable_core7.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core7.WorkflowEngine
910
990
  ])
911
991
  ], EntityService);
912
992
 
913
993
  // src/in-app-worker.ts
914
- var import_nestjs_durable_core7 = require("@dudousxd/nestjs-durable-core");
994
+ var import_nestjs_durable_core8 = require("@dudousxd/nestjs-durable-core");
915
995
  var import_common5 = require("@nestjs/common");
916
996
  var import_core3 = require("@nestjs/core");
917
997
  function _ts_decorate5(decorators, target, key, desc) {
@@ -983,15 +1063,7 @@ var InAppWorkerBootstrap = class {
983
1063
  onModuleInit() {
984
1064
  const runtime = this.runtime;
985
1065
  if (runtime === null || !isCoLocatedWorker(this.options)) return;
986
- scanWorkflows(this.discovery, (meta, instance, origin) => runtime.registerWorkflow(meta.name, (ctx, input) => instance.run(ctx, input), {
987
- version: meta.version,
988
- ...meta.requires !== void 0 ? {
989
- requires: meta.requires
990
- } : {},
991
- ...origin !== void 0 ? {
992
- origin
993
- } : {}
994
- }));
1066
+ scanWorkflows(this.discovery, (meta, instance, origin) => registerOnRuntime(runtime, this.metadataScanner, meta, instance, origin));
995
1067
  scanSteps(this.discovery, this.metadataScanner, (meta, handler) => runtime.registerStep(meta.name, handler));
996
1068
  }
997
1069
  async onApplicationBootstrap() {
@@ -1023,7 +1095,7 @@ var InAppWorkerBootstrap = class {
1023
1095
  };
1024
1096
  InAppWorkerBootstrap = _ts_decorate5([
1025
1097
  (0, import_common5.Injectable)(),
1026
- _ts_param3(2, (0, import_common5.Inject)(import_nestjs_durable_core7.DURABLE_OPTIONS_CANONICAL)),
1098
+ _ts_param3(2, (0, import_common5.Inject)(import_nestjs_durable_core8.DURABLE_OPTIONS_CANONICAL)),
1027
1099
  _ts_param3(3, (0, import_common5.Inject)(IN_APP_WORKER_RUNTIME)),
1028
1100
  _ts_param3(4, (0, import_common5.Inject)(IN_APP_RUN_REDIS_WORKER)),
1029
1101
  _ts_param3(5, (0, import_common5.Inject)(IN_APP_WORKER_RUNNERS)),
@@ -1043,8 +1115,8 @@ function inAppWorkerProviders() {
1043
1115
  provide: IN_APP_WORKER_BINDING,
1044
1116
  useFactory: /* @__PURE__ */ __name((transport, options) => inAppWorkerBinding(transport, options), "useFactory"),
1045
1117
  inject: [
1046
- import_nestjs_durable_core7.TRANSPORT_CANONICAL,
1047
- import_nestjs_durable_core7.DURABLE_OPTIONS_CANONICAL
1118
+ import_nestjs_durable_core8.TRANSPORT_CANONICAL,
1119
+ import_nestjs_durable_core8.DURABLE_OPTIONS_CANONICAL
1048
1120
  ]
1049
1121
  },
1050
1122
  {
@@ -1064,7 +1136,7 @@ function inAppWorkerProviders() {
1064
1136
  workflowGroup: options.partition ?? ""
1065
1137
  }) : null, "useFactory"),
1066
1138
  inject: [
1067
- import_nestjs_durable_core7.DURABLE_OPTIONS_CANONICAL
1139
+ import_nestjs_durable_core8.DURABLE_OPTIONS_CANONICAL
1068
1140
  ]
1069
1141
  },
1070
1142
  {
@@ -1081,7 +1153,212 @@ function inAppWorkerProviders() {
1081
1153
  __name(inAppWorkerProviders, "inAppWorkerProviders");
1082
1154
 
1083
1155
  // src/proxy-run-gateway.ts
1156
+ var import_nestjs_durable_core9 = require("@dudousxd/nestjs-durable-core");
1084
1157
  var import_common6 = require("@nestjs/common");
1158
+
1159
+ // src/run-request-responder.ts
1160
+ var UNSUPPORTED_RUN_REQUEST = "unsupported-request";
1161
+ var KNOWN_KINDS = /* @__PURE__ */ new Set([
1162
+ "getRunDetail",
1163
+ "getFanMembers",
1164
+ "listRuns",
1165
+ "runFacets",
1166
+ "runValueFacets",
1167
+ "workerHealth",
1168
+ "cancel",
1169
+ "retry",
1170
+ "continue",
1171
+ "retryWithInput",
1172
+ "redispatch",
1173
+ "waitingFor"
1174
+ ]);
1175
+ var RunRequestResponder = class {
1176
+ static {
1177
+ __name(this, "RunRequestResponder");
1178
+ }
1179
+ transport;
1180
+ gateway;
1181
+ constructor(transport, gateway) {
1182
+ this.transport = transport;
1183
+ this.gateway = gateway;
1184
+ }
1185
+ /** Register the consumer on the transport. Each request is answered independently; a handler
1186
+ * failure never throws back into the transport (errors are captured into an error reply). */
1187
+ start() {
1188
+ this.transport.onRunRequest(async (msg) => {
1189
+ let reply;
1190
+ try {
1191
+ reply = await this.handle(msg);
1192
+ } catch (err) {
1193
+ reply = {
1194
+ requestId: msg.requestId,
1195
+ result: {
1196
+ ok: false,
1197
+ error: {
1198
+ message: err instanceof Error ? err.message : String(err)
1199
+ }
1200
+ }
1201
+ };
1202
+ }
1203
+ await this.transport.publishRunReply(reply);
1204
+ });
1205
+ }
1206
+ async handle(msg) {
1207
+ const { body } = msg;
1208
+ if (!KNOWN_KINDS.has(body.kind)) {
1209
+ return {
1210
+ requestId: msg.requestId,
1211
+ result: {
1212
+ ok: false,
1213
+ error: {
1214
+ message: `the control plane does not support the ${String(body.kind)} run request`,
1215
+ code: UNSUPPORTED_RUN_REQUEST
1216
+ }
1217
+ }
1218
+ };
1219
+ }
1220
+ if (body.kind === "listRuns") {
1221
+ const data = await this.gateway.listRuns({
1222
+ ...body.query,
1223
+ namespace: msg.tenant
1224
+ });
1225
+ return {
1226
+ requestId: msg.requestId,
1227
+ result: {
1228
+ ok: true,
1229
+ data
1230
+ }
1231
+ };
1232
+ }
1233
+ if (body.kind === "runFacets") {
1234
+ const data = await this.gateway.runFacets({
1235
+ ...body.query,
1236
+ namespace: msg.tenant
1237
+ });
1238
+ return {
1239
+ requestId: msg.requestId,
1240
+ result: {
1241
+ ok: true,
1242
+ data
1243
+ }
1244
+ };
1245
+ }
1246
+ if (body.kind === "runValueFacets") {
1247
+ const data = await this.gateway.runValueFacets(body.axis, {
1248
+ ...body.query,
1249
+ namespace: msg.tenant
1250
+ }, body.opts);
1251
+ return {
1252
+ requestId: msg.requestId,
1253
+ result: {
1254
+ ok: true,
1255
+ data
1256
+ }
1257
+ };
1258
+ }
1259
+ if (body.kind === "workerHealth") {
1260
+ const all = await this.gateway.workerHealth();
1261
+ const data = all.filter((h) => h.group.endsWith(`@${msg.tenant}`));
1262
+ return {
1263
+ requestId: msg.requestId,
1264
+ result: {
1265
+ ok: true,
1266
+ data
1267
+ }
1268
+ };
1269
+ }
1270
+ if (body.kind === "waitingFor") {
1271
+ const all = await this.gateway.waitingFor(body.runIds);
1272
+ const owned = await Promise.all(Object.entries(all).map(async ([runId, waiting]) => {
1273
+ const owner = this.gateway.getRun ? await this.gateway.getRun(runId) : (await this.gateway.getRunDetail(runId))?.run;
1274
+ return owner && owner.namespace === msg.tenant ? [
1275
+ runId,
1276
+ waiting
1277
+ ] : void 0;
1278
+ }));
1279
+ const data = {};
1280
+ for (const entry of owned) {
1281
+ if (entry) data[entry[0]] = entry[1];
1282
+ }
1283
+ return {
1284
+ requestId: msg.requestId,
1285
+ result: {
1286
+ ok: true,
1287
+ data
1288
+ }
1289
+ };
1290
+ }
1291
+ const detail = body.kind === "getRunDetail" || !this.gateway.getRun ? await this.gateway.getRunDetail(body.runId, body.kind === "getRunDetail" ? body.options : void 0) : void 0;
1292
+ const run = detail !== void 0 ? detail?.run ?? null : await this.gateway.getRun?.(body.runId);
1293
+ if (run && run.namespace !== msg.tenant) {
1294
+ return {
1295
+ requestId: msg.requestId,
1296
+ result: {
1297
+ ok: false,
1298
+ error: {
1299
+ message: "run belongs to another tenant",
1300
+ code: "cross-tenant"
1301
+ }
1302
+ }
1303
+ };
1304
+ }
1305
+ if (body.kind === "getRunDetail") {
1306
+ return {
1307
+ requestId: msg.requestId,
1308
+ result: {
1309
+ ok: true,
1310
+ data: detail
1311
+ }
1312
+ };
1313
+ }
1314
+ if (body.kind === "getFanMembers") {
1315
+ const data = run ? await this.gateway.getFanMembers?.(body.runId, body.group, body.query) ?? null : null;
1316
+ return {
1317
+ requestId: msg.requestId,
1318
+ result: {
1319
+ ok: true,
1320
+ data
1321
+ }
1322
+ };
1323
+ }
1324
+ try {
1325
+ const data = await this.callVerb(body);
1326
+ return {
1327
+ requestId: msg.requestId,
1328
+ result: {
1329
+ ok: true,
1330
+ data
1331
+ }
1332
+ };
1333
+ } catch (err) {
1334
+ return {
1335
+ requestId: msg.requestId,
1336
+ result: {
1337
+ ok: false,
1338
+ error: {
1339
+ message: err instanceof Error ? err.message : String(err)
1340
+ }
1341
+ }
1342
+ };
1343
+ }
1344
+ }
1345
+ callVerb(body) {
1346
+ switch (body.kind) {
1347
+ case "cancel":
1348
+ return this.gateway.cancel(body.runId, body.opts);
1349
+ case "retry":
1350
+ return this.gateway.retry(body.runId);
1351
+ case "continue":
1352
+ return this.gateway.continue(body.runId);
1353
+ case "retryWithInput":
1354
+ return this.gateway.retryWithInput(body.runId, body.input);
1355
+ case "redispatch":
1356
+ return this.gateway.redispatchPending(body.runId);
1357
+ }
1358
+ }
1359
+ };
1360
+
1361
+ // src/proxy-run-gateway.ts
1085
1362
  function _ts_decorate6(decorators, target, key, desc) {
1086
1363
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1087
1364
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
@@ -1102,6 +1379,15 @@ function _ts_metadata6(metadataKey, metadataValue) {
1102
1379
  }
1103
1380
  }
1104
1381
  __name(_ts_metadata6, "_ts_metadata");
1382
+ var UnsupportedRunRequestError = class UnsupportedRunRequestError2 extends Error {
1383
+ static {
1384
+ __name(this, "UnsupportedRunRequestError");
1385
+ }
1386
+ };
1387
+ function isUnsupported(err) {
1388
+ return err instanceof UnsupportedRunRequestError;
1389
+ }
1390
+ __name(isUnsupported, "isUnsupported");
1105
1391
  var ProxyRunGateway = class {
1106
1392
  static {
1107
1393
  __name(this, "ProxyRunGateway");
@@ -1109,11 +1395,18 @@ var ProxyRunGateway = class {
1109
1395
  transport;
1110
1396
  tenant;
1111
1397
  timeoutMs;
1398
+ capabilityTtlMs;
1112
1399
  pending = /* @__PURE__ */ new Map();
1113
- constructor(transport, tenant, timeoutMs = 1e4) {
1400
+ /** Verb → when to ask the control plane for it again, after it answered that it does not know it.
1401
+ * During a rolling upgrade the control plane is several pods of mixed versions behind one queue,
1402
+ * and a reply does not say which pod sent it, so the whole control plane is assumed old until the
1403
+ * entry expires. */
1404
+ unsupportedUntil = /* @__PURE__ */ new Map();
1405
+ constructor(transport, tenant, timeoutMs = 1e4, capabilityTtlMs = 6e4) {
1114
1406
  this.transport = transport;
1115
1407
  this.tenant = tenant;
1116
1408
  this.timeoutMs = timeoutMs;
1409
+ this.capabilityTtlMs = capabilityTtlMs;
1117
1410
  this.transport.onRunReply?.((reply) => this.handleReply(reply));
1118
1411
  }
1119
1412
  handleReply(reply) {
@@ -1123,6 +1416,8 @@ var ProxyRunGateway = class {
1123
1416
  this.pending.delete(reply.requestId);
1124
1417
  if (reply.result.ok) {
1125
1418
  pending.resolve(reply.result.data);
1419
+ } else if (reply.result.error.code === UNSUPPORTED_RUN_REQUEST) {
1420
+ pending.reject(new UnsupportedRunRequestError(reply.result.error.message));
1126
1421
  } else {
1127
1422
  pending.reject(new Error(reply.result.error.message));
1128
1423
  }
@@ -1158,20 +1453,59 @@ var ProxyRunGateway = class {
1158
1453
  tenant: this.tenant
1159
1454
  };
1160
1455
  }
1161
- getRunDetail(runId, options) {
1162
- return this.request({
1456
+ /**
1457
+ * A control plane that predates {@link RunDetailOptions} ignores them and sends the full detail;
1458
+ * a summarized detail always carries `fans`, so its absence means the summary is made here.
1459
+ */
1460
+ async getRunDetail(runId, options) {
1461
+ const detail = await this.request(options === void 0 ? {
1462
+ kind: "getRunDetail",
1463
+ runId
1464
+ } : {
1163
1465
  kind: "getRunDetail",
1164
1466
  runId,
1165
1467
  options
1166
1468
  });
1469
+ const over = options?.summarizeFansOver;
1470
+ if (over === void 0 || !detail || detail.fans !== void 0) return detail;
1471
+ const { timeline, fans } = (0, import_nestjs_durable_core9.summarizeTimeline)(detail.timeline, over);
1472
+ const ids = (0, import_nestjs_durable_core9.childIdsOf)(detail.timeline);
1473
+ return {
1474
+ ...detail,
1475
+ timeline,
1476
+ children: ids.slice(0, import_nestjs_durable_core9.SUMMARY_CHILD_LIMIT),
1477
+ fans,
1478
+ childCount: ids.length
1479
+ };
1167
1480
  }
1168
- getFanMembers(runId, group, query) {
1169
- return this.request({
1170
- kind: "getFanMembers",
1171
- runId,
1172
- group,
1173
- query
1481
+ /** Paged from the full detail when the control plane is too old to page a fan itself. */
1482
+ async getFanMembers(runId, group, query) {
1483
+ if (!this.knownUnsupported("getFanMembers")) {
1484
+ try {
1485
+ const page = await this.request({
1486
+ kind: "getFanMembers",
1487
+ runId,
1488
+ group,
1489
+ query
1490
+ });
1491
+ if (page !== void 0) return page;
1492
+ } catch (err) {
1493
+ if (!isUnsupported(err)) throw err;
1494
+ }
1495
+ this.unsupportedUntil.set("getFanMembers", Date.now() + this.capabilityTtlMs);
1496
+ }
1497
+ const detail = await this.request({
1498
+ kind: "getRunDetail",
1499
+ runId
1174
1500
  });
1501
+ return detail ? (0, import_nestjs_durable_core9.pageFan)(detail.timeline, group, query) : null;
1502
+ }
1503
+ knownUnsupported(kind) {
1504
+ const until = this.unsupportedUntil.get(kind);
1505
+ if (until === void 0) return false;
1506
+ if (Date.now() < until) return true;
1507
+ this.unsupportedUntil.delete(kind);
1508
+ return false;
1175
1509
  }
1176
1510
  /** The control plane's `StoreRunGateway` resolves each run's `waiting` descriptor; the reply carries
1177
1511
  * it through as plain JSON, so a tenant's list rows name the wait too. */
@@ -1261,12 +1595,13 @@ ProxyRunGateway = _ts_decorate6([
1261
1595
  _ts_metadata6("design:paramtypes", [
1262
1596
  typeof Transport === "undefined" ? Object : Transport,
1263
1597
  String,
1598
+ void 0,
1264
1599
  void 0
1265
1600
  ])
1266
1601
  ], ProxyRunGateway);
1267
1602
 
1268
1603
  // src/retention-poller.ts
1269
- var import_nestjs_durable_core8 = require("@dudousxd/nestjs-durable-core");
1604
+ var import_nestjs_durable_core10 = require("@dudousxd/nestjs-durable-core");
1270
1605
  var import_common7 = require("@nestjs/common");
1271
1606
 
1272
1607
  // src/settle-within.ts
@@ -1332,10 +1667,10 @@ function validateRetention(retention) {
1332
1667
  if (policy.maxAge == null && policy.maxCount == null) {
1333
1668
  throw new Error("durable retention: each policy must set maxAge and/or maxCount");
1334
1669
  }
1335
- if (policy.maxAge != null) (0, import_nestjs_durable_core8.parseDuration)(policy.maxAge);
1670
+ if (policy.maxAge != null) (0, import_nestjs_durable_core10.parseDuration)(policy.maxAge);
1336
1671
  for (const status of policy.statuses) {
1337
- if (!import_nestjs_durable_core8.TERMINAL_RUN_STATUSES.includes(status)) {
1338
- throw new Error(`durable retention: status "${status}" is not terminal; only ${import_nestjs_durable_core8.TERMINAL_RUN_STATUSES.join(", ")} can be pruned`);
1672
+ if (!import_nestjs_durable_core10.TERMINAL_RUN_STATUSES.includes(status)) {
1673
+ throw new Error(`durable retention: status "${status}" is not terminal; only ${import_nestjs_durable_core10.TERMINAL_RUN_STATUSES.join(", ")} can be pruned`);
1339
1674
  }
1340
1675
  const key = `${scopeKey}|${status}`;
1341
1676
  if (seen.has(key)) {
@@ -1387,7 +1722,7 @@ var RetentionPoller = class {
1387
1722
  return;
1388
1723
  }
1389
1724
  await this.sweep();
1390
- const intervalMs = retention.sweepInterval != null ? (0, import_nestjs_durable_core8.parseDuration)(retention.sweepInterval) : DEFAULT_SWEEP_INTERVAL_MS;
1725
+ const intervalMs = retention.sweepInterval != null ? (0, import_nestjs_durable_core10.parseDuration)(retention.sweepInterval) : DEFAULT_SWEEP_INTERVAL_MS;
1391
1726
  if (intervalMs > 0) {
1392
1727
  this.timer = setInterval(() => void this.sweep(), intervalMs);
1393
1728
  this.timer.unref?.();
@@ -1449,8 +1784,8 @@ var RetentionPoller = class {
1449
1784
  };
1450
1785
  RetentionPoller = _ts_decorate7([
1451
1786
  (0, import_common7.Injectable)(),
1452
- _ts_param4(0, (0, import_common7.Inject)(import_nestjs_durable_core8.STATE_STORE_CANONICAL)),
1453
- _ts_param4(1, (0, import_common7.Inject)(import_nestjs_durable_core8.DURABLE_OPTIONS_CANONICAL)),
1787
+ _ts_param4(0, (0, import_common7.Inject)(import_nestjs_durable_core10.STATE_STORE_CANONICAL)),
1788
+ _ts_param4(1, (0, import_common7.Inject)(import_nestjs_durable_core10.DURABLE_OPTIONS_CANONICAL)),
1454
1789
  _ts_metadata7("design:type", Function),
1455
1790
  _ts_metadata7("design:paramtypes", [
1456
1791
  Object,
@@ -1458,170 +1793,8 @@ RetentionPoller = _ts_decorate7([
1458
1793
  ])
1459
1794
  ], RetentionPoller);
1460
1795
 
1461
- // src/run-request-responder.ts
1462
- var RunRequestResponder = class {
1463
- static {
1464
- __name(this, "RunRequestResponder");
1465
- }
1466
- transport;
1467
- gateway;
1468
- constructor(transport, gateway) {
1469
- this.transport = transport;
1470
- this.gateway = gateway;
1471
- }
1472
- /** Register the consumer on the transport. Each request is answered independently; a handler
1473
- * failure never throws back into the transport (errors are captured into an error reply). */
1474
- start() {
1475
- this.transport.onRunRequest(async (msg) => {
1476
- const reply = await this.handle(msg);
1477
- await this.transport.publishRunReply(reply);
1478
- });
1479
- }
1480
- async handle(msg) {
1481
- const { body } = msg;
1482
- if (body.kind === "listRuns") {
1483
- const data = await this.gateway.listRuns({
1484
- ...body.query,
1485
- namespace: msg.tenant
1486
- });
1487
- return {
1488
- requestId: msg.requestId,
1489
- result: {
1490
- ok: true,
1491
- data
1492
- }
1493
- };
1494
- }
1495
- if (body.kind === "runFacets") {
1496
- const data = await this.gateway.runFacets({
1497
- ...body.query,
1498
- namespace: msg.tenant
1499
- });
1500
- return {
1501
- requestId: msg.requestId,
1502
- result: {
1503
- ok: true,
1504
- data
1505
- }
1506
- };
1507
- }
1508
- if (body.kind === "runValueFacets") {
1509
- const data = await this.gateway.runValueFacets(body.axis, {
1510
- ...body.query,
1511
- namespace: msg.tenant
1512
- }, body.opts);
1513
- return {
1514
- requestId: msg.requestId,
1515
- result: {
1516
- ok: true,
1517
- data
1518
- }
1519
- };
1520
- }
1521
- if (body.kind === "workerHealth") {
1522
- const all = await this.gateway.workerHealth();
1523
- const data = all.filter((h) => h.group.endsWith(`@${msg.tenant}`));
1524
- return {
1525
- requestId: msg.requestId,
1526
- result: {
1527
- ok: true,
1528
- data
1529
- }
1530
- };
1531
- }
1532
- if (body.kind === "waitingFor") {
1533
- const all = await this.gateway.waitingFor(body.runIds);
1534
- const owned = await Promise.all(Object.entries(all).map(async ([runId, waiting]) => {
1535
- const owner = this.gateway.getRun ? await this.gateway.getRun(runId) : (await this.gateway.getRunDetail(runId))?.run;
1536
- return owner && owner.namespace === msg.tenant ? [
1537
- runId,
1538
- waiting
1539
- ] : void 0;
1540
- }));
1541
- const data = {};
1542
- for (const entry of owned) {
1543
- if (entry) data[entry[0]] = entry[1];
1544
- }
1545
- return {
1546
- requestId: msg.requestId,
1547
- result: {
1548
- ok: true,
1549
- data
1550
- }
1551
- };
1552
- }
1553
- const detail = body.kind === "getRunDetail" || !this.gateway.getRun ? await this.gateway.getRunDetail(body.runId, body.kind === "getRunDetail" ? body.options : void 0) : void 0;
1554
- const run = detail !== void 0 ? detail?.run ?? null : await this.gateway.getRun?.(body.runId);
1555
- if (run && run.namespace !== msg.tenant) {
1556
- return {
1557
- requestId: msg.requestId,
1558
- result: {
1559
- ok: false,
1560
- error: {
1561
- message: "run belongs to another tenant",
1562
- code: "cross-tenant"
1563
- }
1564
- }
1565
- };
1566
- }
1567
- if (body.kind === "getRunDetail") {
1568
- return {
1569
- requestId: msg.requestId,
1570
- result: {
1571
- ok: true,
1572
- data: detail
1573
- }
1574
- };
1575
- }
1576
- if (body.kind === "getFanMembers") {
1577
- const data = run ? await this.gateway.getFanMembers?.(body.runId, body.group, body.query) ?? null : null;
1578
- return {
1579
- requestId: msg.requestId,
1580
- result: {
1581
- ok: true,
1582
- data
1583
- }
1584
- };
1585
- }
1586
- try {
1587
- const data = await this.callVerb(body);
1588
- return {
1589
- requestId: msg.requestId,
1590
- result: {
1591
- ok: true,
1592
- data
1593
- }
1594
- };
1595
- } catch (err) {
1596
- return {
1597
- requestId: msg.requestId,
1598
- result: {
1599
- ok: false,
1600
- error: {
1601
- message: err instanceof Error ? err.message : String(err)
1602
- }
1603
- }
1604
- };
1605
- }
1606
- }
1607
- callVerb(body) {
1608
- switch (body.kind) {
1609
- case "cancel":
1610
- return this.gateway.cancel(body.runId, body.opts);
1611
- case "retry":
1612
- return this.gateway.retry(body.runId);
1613
- case "continue":
1614
- return this.gateway.continue(body.runId);
1615
- case "retryWithInput":
1616
- return this.gateway.retryWithInput(body.runId, body.input);
1617
- case "redispatch":
1618
- return this.gateway.redispatchPending(body.runId);
1619
- }
1620
- }
1621
- };
1622
-
1623
1796
  // src/store-run-gateway.ts
1624
- var import_nestjs_durable_core9 = require("@dudousxd/nestjs-durable-core");
1797
+ var import_nestjs_durable_core11 = require("@dudousxd/nestjs-durable-core");
1625
1798
  var import_common8 = require("@nestjs/common");
1626
1799
  function _ts_decorate8(decorators, target, key, desc) {
1627
1800
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -1679,13 +1852,31 @@ var StoreRunGateway = class {
1679
1852
  children
1680
1853
  };
1681
1854
  }
1855
+ if ((0, import_nestjs_durable_core11.aggregatesCheckpoints)(this.store)) {
1856
+ const stats = await this.store.checkpointStats(runId);
1857
+ const etag = (0, import_nestjs_durable_core11.runDetailEtag)(run, stats, over);
1858
+ if ((0, import_nestjs_durable_core11.etagMatches)(options?.ifNoneMatch, etag)) {
1859
+ return {
1860
+ run,
1861
+ timeline: [],
1862
+ children: [],
1863
+ notModified: true,
1864
+ etag
1865
+ };
1866
+ }
1867
+ return {
1868
+ run,
1869
+ ...await (0, import_nestjs_durable_core11.summarizeRunFromStore)(this.store, runId, over, stats),
1870
+ etag
1871
+ };
1872
+ }
1682
1873
  const full = await this.store.listCheckpoints(runId);
1683
- const { timeline, fans } = (0, import_nestjs_durable_core9.summarizeTimeline)(full, over);
1684
- const ids = (0, import_nestjs_durable_core9.childIdsOf)(full);
1874
+ const { timeline, fans } = (0, import_nestjs_durable_core11.summarizeTimeline)(full, over);
1875
+ const ids = (0, import_nestjs_durable_core11.childIdsOf)(full);
1685
1876
  return {
1686
1877
  run,
1687
1878
  timeline,
1688
- children: ids.slice(0, import_nestjs_durable_core9.SUMMARY_CHILD_LIMIT),
1879
+ children: ids.slice(0, import_nestjs_durable_core11.SUMMARY_CHILD_LIMIT),
1689
1880
  fans,
1690
1881
  childCount: ids.length
1691
1882
  };
@@ -1695,13 +1886,31 @@ var StoreRunGateway = class {
1695
1886
  }
1696
1887
  async getFanMembers(runId, group, query) {
1697
1888
  if (!await this.store.getRun(runId)) return null;
1698
- return (0, import_nestjs_durable_core9.pageFan)(await this.store.listCheckpoints(runId), group, query);
1889
+ if ((0, import_nestjs_durable_core11.aggregatesCheckpoints)(this.store)) {
1890
+ const stats = await this.store.checkpointStats(runId, {
1891
+ group
1892
+ });
1893
+ const etag = (0, import_nestjs_durable_core11.fanPageEtag)(group, stats, query);
1894
+ if ((0, import_nestjs_durable_core11.etagMatches)(query.ifNoneMatch, etag)) {
1895
+ return {
1896
+ items: [],
1897
+ total: 0,
1898
+ notModified: true,
1899
+ etag
1900
+ };
1901
+ }
1902
+ return {
1903
+ ...await (0, import_nestjs_durable_core11.pageFanFromStore)(this.store, runId, group, query, stats),
1904
+ etag
1905
+ };
1906
+ }
1907
+ return (0, import_nestjs_durable_core11.pageFan)(await this.store.listCheckpoints(runId), group, query);
1699
1908
  }
1700
1909
  async listRuns(query) {
1701
1910
  const runs = await this.store.listRuns(query);
1702
- const waiterByRun = (0, import_nestjs_durable_core9.indexWaitersByRun)(await (0, import_nestjs_durable_core9.listSignalWaitersOfRuns)(this.store, runs.filter((run) => run.status === "suspended").map((run) => run.id)));
1911
+ const waiterByRun = (0, import_nestjs_durable_core11.indexWaitersByRun)(await (0, import_nestjs_durable_core11.listSignalWaitersOfRuns)(this.store, runs.filter((run) => run.status === "suspended").map((run) => run.id)));
1703
1912
  return runs.map((run) => {
1704
- const waiting = (0, import_nestjs_durable_core9.resolveRunWaiting)(run, waiterByRun);
1913
+ const waiting = (0, import_nestjs_durable_core11.resolveRunWaiting)(run, waiterByRun);
1705
1914
  return waiting ? {
1706
1915
  ...run,
1707
1916
  waiting
@@ -1717,7 +1926,7 @@ var StoreRunGateway = class {
1717
1926
  async runFacets(query) {
1718
1927
  if (this.store.runFacets) return this.store.runFacets(query);
1719
1928
  const runs = await this.store.listRuns(query);
1720
- return (0, import_nestjs_durable_core9.mergeRunFacetRows)(runs.map((r) => ({
1929
+ return (0, import_nestjs_durable_core11.mergeRunFacetRows)(runs.map((r) => ({
1721
1930
  status: r.status,
1722
1931
  origin: r.origin,
1723
1932
  count: 1
@@ -1752,13 +1961,13 @@ var StoreRunGateway = class {
1752
1961
  "suspended"
1753
1962
  ]
1754
1963
  }),
1755
- (0, import_nestjs_durable_core9.listSignalWaitersOfRuns)(this.store, runIds)
1964
+ (0, import_nestjs_durable_core11.listSignalWaitersOfRuns)(this.store, runIds)
1756
1965
  ]);
1757
- const waiterByRun = (0, import_nestjs_durable_core9.indexWaitersByRun)(waiters);
1966
+ const waiterByRun = (0, import_nestjs_durable_core11.indexWaitersByRun)(waiters);
1758
1967
  const result = {};
1759
1968
  for (const run of suspended) {
1760
1969
  if (!idSet.has(run.id)) continue;
1761
- const waiting = (0, import_nestjs_durable_core9.resolveRunWaiting)(run, waiterByRun);
1970
+ const waiting = (0, import_nestjs_durable_core11.resolveRunWaiting)(run, waiterByRun);
1762
1971
  if (waiting) result[run.id] = waiting;
1763
1972
  }
1764
1973
  return result;
@@ -1792,11 +2001,11 @@ var StoreRunGateway = class {
1792
2001
  };
1793
2002
  StoreRunGateway = _ts_decorate8([
1794
2003
  (0, import_common8.Injectable)(),
1795
- _ts_param5(0, (0, import_common8.Inject)(import_nestjs_durable_core9.STATE_STORE_CANONICAL)),
2004
+ _ts_param5(0, (0, import_common8.Inject)(import_nestjs_durable_core11.STATE_STORE_CANONICAL)),
1796
2005
  _ts_metadata8("design:type", Function),
1797
2006
  _ts_metadata8("design:paramtypes", [
1798
2007
  typeof StateStore === "undefined" ? Object : StateStore,
1799
- typeof import_nestjs_durable_core9.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core9.WorkflowEngine
2008
+ typeof import_nestjs_durable_core11.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core11.WorkflowEngine
1800
2009
  ])
1801
2010
  ], StoreRunGateway);
1802
2011
 
@@ -1842,7 +2051,7 @@ var TenantEventRepublisher = class {
1842
2051
  };
1843
2052
 
1844
2053
  // src/timer-poller.ts
1845
- var import_nestjs_durable_core10 = require("@dudousxd/nestjs-durable-core");
2054
+ var import_nestjs_durable_core12 = require("@dudousxd/nestjs-durable-core");
1846
2055
  var import_common9 = require("@nestjs/common");
1847
2056
  function _ts_decorate9(decorators, target, key, desc) {
1848
2057
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -1954,7 +2163,7 @@ var TimerPoller = class {
1954
2163
  await this.sweep("sweepTimeouts", () => this.engine.sweepTimeouts());
1955
2164
  const schedules = this.options.schedules;
1956
2165
  if (schedules && schedules.length > 0) {
1957
- await this.sweep("schedules", () => (0, import_nestjs_durable_core10.runSchedules)(this.engine, schedules, Date.now()));
2166
+ await this.sweep("schedules", () => (0, import_nestjs_durable_core12.runSchedules)(this.engine, schedules, Date.now()));
1958
2167
  }
1959
2168
  if (this.options.persistedSchedules) {
1960
2169
  await this.sweep("persistedSchedules", () => this.engine.schedules.tick());
@@ -1972,21 +2181,21 @@ var TimerPoller = class {
1972
2181
  };
1973
2182
  TimerPoller = _ts_decorate9([
1974
2183
  (0, import_common9.Injectable)(),
1975
- _ts_param6(1, (0, import_common9.Inject)(import_nestjs_durable_core10.DURABLE_OPTIONS_CANONICAL)),
2184
+ _ts_param6(1, (0, import_common9.Inject)(import_nestjs_durable_core12.DURABLE_OPTIONS_CANONICAL)),
1976
2185
  _ts_metadata9("design:type", Function),
1977
2186
  _ts_metadata9("design:paramtypes", [
1978
- typeof import_nestjs_durable_core10.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core10.WorkflowEngine,
2187
+ typeof import_nestjs_durable_core12.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core12.WorkflowEngine,
1979
2188
  typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
1980
2189
  ])
1981
2190
  ], TimerPoller);
1982
2191
 
1983
2192
  // src/tokens.ts
1984
- var import_nestjs_durable_core11 = require("@dudousxd/nestjs-durable-core");
2193
+ var import_nestjs_durable_core13 = require("@dudousxd/nestjs-durable-core");
1985
2194
  var CONTEXT_ACCESSOR = Symbol.for("@dudousxd/nestjs-context:accessor");
1986
- var RUN_GATEWAY = import_nestjs_durable_core11.RunGateway;
2195
+ var RUN_GATEWAY = import_nestjs_durable_core13.RunGateway;
1987
2196
 
1988
2197
  // src/workflow.registrar.ts
1989
- var import_nestjs_durable_core12 = require("@dudousxd/nestjs-durable-core");
2198
+ var import_nestjs_durable_core14 = require("@dudousxd/nestjs-durable-core");
1990
2199
  var import_common10 = require("@nestjs/common");
1991
2200
  var import_core4 = require("@nestjs/core");
1992
2201
 
@@ -2056,6 +2265,7 @@ function _ts_param7(paramIndex, decorator) {
2056
2265
  };
2057
2266
  }
2058
2267
  __name(_ts_param7, "_ts_param");
2268
+ var UNSERVED_ROUTES_RECHECK_MS = 3e4;
2059
2269
  var WorkflowRegistrar = class {
2060
2270
  static {
2061
2271
  __name(this, "WorkflowRegistrar");
@@ -2119,13 +2329,19 @@ var WorkflowRegistrar = class {
2119
2329
  const validateInput = meta.validateInput ?? (meta.inputSchema ? classValidatorInput(meta.inputSchema) : void 0);
2120
2330
  const eventBatch = meta.debounce ? {
2121
2331
  mode: "debounce",
2122
- windowMs: (0, import_nestjs_durable_core12.parseDuration)(meta.debounce)
2332
+ windowMs: (0, import_nestjs_durable_core14.parseDuration)(meta.debounce)
2123
2333
  } : meta.batch ? {
2124
2334
  mode: "batch",
2125
2335
  maxSize: meta.batch.maxSize,
2126
- windowMs: (0, import_nestjs_durable_core12.parseDuration)(meta.batch.within)
2336
+ windowMs: (0, import_nestjs_durable_core14.parseDuration)(meta.batch.within)
2127
2337
  } : void 0;
2128
2338
  const workflowCtor = workflow.constructor;
2339
+ const onError = onErrorHandlersOf(meta, workflow, this.metadataScanner);
2340
+ for (const [name, fn] of onError.handlers) {
2341
+ this.engine.register(name, meta.version, fn, {
2342
+ origin
2343
+ });
2344
+ }
2129
2345
  this.engine.register(meta.name, meta.version, (ctx, input) => workflow.run(ctx, input), {
2130
2346
  // Stamped onto every run this workflow starts (see `WorkflowRun.origin`). Derived from the
2131
2347
  // class's declaring file, so a lib gets attributed without opting in; `undefined` when it
@@ -2140,6 +2356,7 @@ var WorkflowRegistrar = class {
2140
2356
  searchAttributesSchema: meta.searchAttributes,
2141
2357
  onEvent: getOnEvents(meta, workflowCtor),
2142
2358
  eventBatch,
2359
+ onError: onError.routes,
2143
2360
  // Uniform dispatch (opt-in): when an in-app worker is configured, register the body GROUP-SERVED
2144
2361
  // so the engine dispatches its turns over the transport instead of running it inline; the
2145
2362
  // co-located worker consumer (Task 5: one queue PER REGISTERED NAME) replays the same body.
@@ -2150,11 +2367,11 @@ var WorkflowRegistrar = class {
2150
2367
  // so a turn dispatched under the wrong token would never be consumed. Absent → the inline fast
2151
2368
  // path (unchanged).
2152
2369
  ...this.inAppWorker ? {
2153
- group: (0, import_nestjs_durable_core12.tenantGroup)((0, import_nestjs_durable_core12.sanitizeQueueToken)(meta.name), this.inAppWorker.partition),
2154
- executor: new import_nestjs_durable_core12.RemoteWorkflowExecutor(this.inAppWorker.transport, meta.name, this.inAppWorker.partition)
2370
+ group: (0, import_nestjs_durable_core14.tenantGroup)((0, import_nestjs_durable_core14.sanitizeQueueToken)(meta.name), this.inAppWorker.partition),
2371
+ executor: new import_nestjs_durable_core14.RemoteWorkflowExecutor(this.inAppWorker.transport, meta.name, this.inAppWorker.partition)
2155
2372
  } : {}
2156
2373
  });
2157
- (0, import_nestjs_durable_core12.bindWorkflowClass)(workflowCtor, {
2374
+ (0, import_nestjs_durable_core14.bindWorkflowClass)(workflowCtor, {
2158
2375
  start: /* @__PURE__ */ __name((name, input, runId, opts) => this.engine.start(name, input, runId, opts), "start"),
2159
2376
  waitForRun: /* @__PURE__ */ __name((runId, opts) => this.engine.waitForRun(runId, opts), "waitForRun")
2160
2377
  });
@@ -2169,10 +2386,11 @@ var WorkflowRegistrar = class {
2169
2386
  });
2170
2387
  deadLetterByWorkflow.set(meta.name, dlqName);
2171
2388
  } else if (meta.deadLetterWorkflow) {
2172
- deadLetterByWorkflow.set(meta.name, (0, import_nestjs_durable_core12.workflowName)(meta.deadLetterWorkflow));
2389
+ deadLetterByWorkflow.set(meta.name, (0, import_nestjs_durable_core14.workflowName)(meta.deadLetterWorkflow));
2173
2390
  }
2174
2391
  });
2175
2392
  this.reportUnattributed(unattributed);
2393
+ void this.reportUnservedOnErrorRoutes();
2176
2394
  this.installDeadLetterRouting(deadLetterByWorkflow);
2177
2395
  }
2178
2396
  /**
@@ -2185,6 +2403,20 @@ var WorkflowRegistrar = class {
2185
2403
  if (names.length === 0) return;
2186
2404
  console.warn(`[nestjs-durable] could not derive an origin (declaring package) for ${names.length} workflow(s): ${names.join(", ")}. Their runs carry no origin and will not match an origin filter.`);
2187
2405
  }
2406
+ /**
2407
+ * Says, once after boot, which onError routes name a handler workflow nothing can run, so a typo is
2408
+ * caught before the first failure goes nowhere. Routes unserved at boot are checked again after
2409
+ * {@link UNSERVED_ROUTES_RECHECK_MS}, so a handler whose workers start after this process is not
2410
+ * reported.
2411
+ */
2412
+ async reportUnservedOnErrorRoutes(recheckMs = UNSERVED_ROUTES_RECHECK_MS) {
2413
+ if ((await this.engine.unservedOnErrorRoutes().catch(() => [])).length === 0) return;
2414
+ await new Promise((resolve) => setTimeout(resolve, recheckMs).unref());
2415
+ const unserved = await this.engine.unservedOnErrorRoutes().catch(() => []);
2416
+ if (unserved.length === 0) return;
2417
+ const list = unserved.map(({ workflow, route }) => `${workflow} \u2192 ${route.workflow} (code ${route.code ?? "*"})`).join(", ");
2418
+ console.warn(`[nestjs-durable] ${unserved.length} onError route(s) name a handler workflow that is not registered here and has no live worker: ${list}.`);
2419
+ }
2188
2420
  /** Returns the instance's `@DeadLetter()` method bound to the instance, or undefined if none. */
2189
2421
  findDeadLetterHandler(instance) {
2190
2422
  const prototype = Object.getPrototypeOf(instance);
@@ -2202,7 +2434,7 @@ var WorkflowRegistrar = class {
2202
2434
  * a `dlq:<runId>` id, so re-recovery never double-dispatches.
2203
2435
  */
2204
2436
  installDeadLetterRouting(byWorkflow) {
2205
- const fallback = this.options.deadLetterWorkflow ? (0, import_nestjs_durable_core12.workflowName)(this.options.deadLetterWorkflow) : void 0;
2437
+ const fallback = this.options.deadLetterWorkflow ? (0, import_nestjs_durable_core14.workflowName)(this.options.deadLetterWorkflow) : void 0;
2206
2438
  if (byWorkflow.size === 0 && !fallback) return;
2207
2439
  this.engine.onDead((run) => {
2208
2440
  const target = byWorkflow.get(run.workflow) ?? fallback;
@@ -2227,14 +2459,14 @@ var WorkflowRegistrar = class {
2227
2459
  };
2228
2460
  WorkflowRegistrar = _ts_decorate10([
2229
2461
  (0, import_common10.Injectable)(),
2230
- _ts_param7(3, (0, import_common10.Inject)(import_nestjs_durable_core12.STATE_STORE_CANONICAL)),
2231
- _ts_param7(4, (0, import_common10.Inject)(import_nestjs_durable_core12.DURABLE_OPTIONS_CANONICAL)),
2462
+ _ts_param7(3, (0, import_common10.Inject)(import_nestjs_durable_core14.STATE_STORE_CANONICAL)),
2463
+ _ts_param7(4, (0, import_common10.Inject)(import_nestjs_durable_core14.DURABLE_OPTIONS_CANONICAL)),
2232
2464
  _ts_param7(5, (0, import_common10.Inject)(IN_APP_WORKER_BINDING)),
2233
2465
  _ts_metadata10("design:type", Function),
2234
2466
  _ts_metadata10("design:paramtypes", [
2235
2467
  typeof import_core4.DiscoveryService === "undefined" ? Object : import_core4.DiscoveryService,
2236
2468
  typeof import_core4.MetadataScanner === "undefined" ? Object : import_core4.MetadataScanner,
2237
- typeof import_nestjs_durable_core12.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core12.WorkflowEngine,
2469
+ typeof import_nestjs_durable_core14.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core14.WorkflowEngine,
2238
2470
  Object,
2239
2471
  typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions,
2240
2472
  Object
@@ -2243,7 +2475,7 @@ WorkflowRegistrar = _ts_decorate10([
2243
2475
 
2244
2476
  // src/workflow.service.ts
2245
2477
  var import_node_crypto = require("crypto");
2246
- var import_nestjs_durable_core13 = require("@dudousxd/nestjs-durable-core");
2478
+ var import_nestjs_durable_core15 = require("@dudousxd/nestjs-durable-core");
2247
2479
  var import_common11 = require("@nestjs/common");
2248
2480
  function _ts_decorate11(decorators, target, key, desc) {
2249
2481
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -2312,7 +2544,7 @@ WorkflowService = _ts_decorate11([
2312
2544
  (0, import_common11.Injectable)(),
2313
2545
  _ts_metadata11("design:type", Function),
2314
2546
  _ts_metadata11("design:paramtypes", [
2315
- typeof import_nestjs_durable_core13.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core13.WorkflowEngine
2547
+ typeof import_nestjs_durable_core15.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core15.WorkflowEngine
2316
2548
  ])
2317
2549
  ], WorkflowService);
2318
2550
 
@@ -2515,14 +2747,14 @@ var RunGatewayBootstrap = class RunGatewayBootstrap2 {
2515
2747
  };
2516
2748
  RunGatewayBootstrap = _ts_decorate12([
2517
2749
  (0, import_common12.Injectable)(),
2518
- _ts_param8(1, (0, import_common12.Inject)(import_nestjs_durable_core14.TRANSPORT_CANONICAL)),
2519
- _ts_param8(3, (0, import_common12.Inject)(import_nestjs_durable_core14.STATE_STORE_CANONICAL)),
2520
- _ts_param8(4, (0, import_common12.Inject)(import_nestjs_durable_core14.DURABLE_OPTIONS_CANONICAL)),
2750
+ _ts_param8(1, (0, import_common12.Inject)(import_nestjs_durable_core16.TRANSPORT_CANONICAL)),
2751
+ _ts_param8(3, (0, import_common12.Inject)(import_nestjs_durable_core16.STATE_STORE_CANONICAL)),
2752
+ _ts_param8(4, (0, import_common12.Inject)(import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL)),
2521
2753
  _ts_metadata12("design:type", Function),
2522
2754
  _ts_metadata12("design:paramtypes", [
2523
- typeof import_nestjs_durable_core14.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core14.WorkflowEngine,
2755
+ typeof import_nestjs_durable_core16.WorkflowEngine === "undefined" ? Object : import_nestjs_durable_core16.WorkflowEngine,
2524
2756
  Object,
2525
- typeof import_nestjs_durable_core14.RunGateway === "undefined" ? Object : import_nestjs_durable_core14.RunGateway,
2757
+ typeof import_nestjs_durable_core16.RunGateway === "undefined" ? Object : import_nestjs_durable_core16.RunGateway,
2526
2758
  Object,
2527
2759
  typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
2528
2760
  ])
@@ -2534,13 +2766,13 @@ var DurableModule = class _DurableModule {
2534
2766
  static forRoot(options) {
2535
2767
  _DurableModule.assertValid(options);
2536
2768
  return _DurableModule.build({
2537
- provide: import_nestjs_durable_core14.DURABLE_OPTIONS_CANONICAL,
2769
+ provide: import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL,
2538
2770
  useValue: resolveTopology(options)
2539
2771
  });
2540
2772
  }
2541
2773
  static forRootAsync(options) {
2542
2774
  return _DurableModule.build({
2543
- provide: import_nestjs_durable_core14.DURABLE_OPTIONS_CANONICAL,
2775
+ provide: import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL,
2544
2776
  useFactory: /* @__PURE__ */ __name(async (...args) => {
2545
2777
  const resolved = await options.useFactory(...args);
2546
2778
  _DurableModule.assertValid(resolved);
@@ -2573,41 +2805,41 @@ var DurableModule = class _DurableModule {
2573
2805
  providers: [
2574
2806
  optionsProvider,
2575
2807
  {
2576
- provide: import_nestjs_durable_core14.STATE_STORE_CANONICAL,
2808
+ provide: import_nestjs_durable_core16.STATE_STORE_CANONICAL,
2577
2809
  useFactory: /* @__PURE__ */ __name((options) => options.store !== void 0 ? scopedStore(options.store, options) : null, "useFactory"),
2578
2810
  inject: [
2579
- import_nestjs_durable_core14.DURABLE_OPTIONS_CANONICAL
2811
+ import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL
2580
2812
  ]
2581
2813
  },
2582
2814
  {
2583
- provide: import_nestjs_durable_core14.TRANSPORT_CANONICAL,
2815
+ provide: import_nestjs_durable_core16.TRANSPORT_CANONICAL,
2584
2816
  // With a POOL (`transports`) and no singular `transport`, the canonical transport is the
2585
2817
  // pool's PRIMARY — the same one the engine dispatches on first. Leaving it null starved
2586
2818
  // the step registrar / in-app worker of a transport, so a pool-configured operator
2587
2819
  // registered NO step handlers and its own steps parked in `wait` with no consumer.
2588
2820
  useFactory: /* @__PURE__ */ __name((options) => options.transport ?? options.transports?.[0]?.transport ?? null, "useFactory"),
2589
2821
  inject: [
2590
- import_nestjs_durable_core14.DURABLE_OPTIONS_CANONICAL
2822
+ import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL
2591
2823
  ]
2592
2824
  },
2593
2825
  // Legacy back-compat aliases (deprecated tokens still resolve to the same instances):
2594
2826
  {
2595
- provide: import_nestjs_durable_core14.STATE_STORE,
2596
- useExisting: import_nestjs_durable_core14.STATE_STORE_CANONICAL
2827
+ provide: import_nestjs_durable_core16.STATE_STORE,
2828
+ useExisting: import_nestjs_durable_core16.STATE_STORE_CANONICAL
2597
2829
  },
2598
2830
  {
2599
- provide: import_nestjs_durable_core14.TRANSPORT,
2600
- useExisting: import_nestjs_durable_core14.TRANSPORT_CANONICAL
2831
+ provide: import_nestjs_durable_core16.TRANSPORT,
2832
+ useExisting: import_nestjs_durable_core16.TRANSPORT_CANONICAL
2601
2833
  },
2602
2834
  {
2603
- provide: import_nestjs_durable_core14.DURABLE_OPTIONS,
2604
- useExisting: import_nestjs_durable_core14.DURABLE_OPTIONS_CANONICAL
2835
+ provide: import_nestjs_durable_core16.DURABLE_OPTIONS,
2836
+ useExisting: import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL
2605
2837
  },
2606
2838
  {
2607
2839
  // Shared token, bound EXACTLY once: a real engine for the operator role, or a store-less
2608
2840
  // `DurableStartClient` facade for a thin worker (no `store`) — either way, `WorkflowService`
2609
2841
  // and app code call `engine.start(...)` unchanged.
2610
- provide: import_nestjs_durable_core14.WorkflowEngine,
2842
+ provide: import_nestjs_durable_core16.WorkflowEngine,
2611
2843
  useFactory: /* @__PURE__ */ __name(async (options, store, transport, moduleRef) => {
2612
2844
  if (options.store === void 0) {
2613
2845
  return new DurableStartClient(options);
@@ -2620,7 +2852,7 @@ var DurableModule = class _DurableModule {
2620
2852
  const context = options.context ?? (accessor ? () => carrierFromAccessor(accessor) : void 0);
2621
2853
  const runtime = accessor ? await resolveContextRuntime() : void 0;
2622
2854
  const rehydrate = runtime && ((carrier, fn) => carrier && Object.keys(carrier).length > 0 ? runtime.deserialize(carrier, fn) : fn());
2623
- const engine = new import_nestjs_durable_core14.WorkflowEngine({
2855
+ const engine = new import_nestjs_durable_core16.WorkflowEngine({
2624
2856
  store,
2625
2857
  transport: transport ?? void 0,
2626
2858
  transports: options.transports,
@@ -2631,6 +2863,11 @@ var DurableModule = class _DurableModule {
2631
2863
  remoteAdvanceSilenceMs: options.remoteAdvanceSilenceMs,
2632
2864
  remoteRedispatchMs: options.remoteRedispatchMs,
2633
2865
  remoteRedispatchMax: options.remoteRedispatchMax,
2866
+ reconcileMs: options.reconcileMs,
2867
+ timerBatchSize: options.timerBatchSize,
2868
+ eventBufferTtlMs: options.eventBufferTtlMs,
2869
+ blockedPollMs: options.blockedPollMs,
2870
+ trackStepStart: options.trackStepStart,
2634
2871
  instanceId: options.instanceId,
2635
2872
  namespace: options.namespace,
2636
2873
  webhookUrl: options.webhookUrl,
@@ -2653,9 +2890,9 @@ var DurableModule = class _DurableModule {
2653
2890
  return engine;
2654
2891
  }, "useFactory"),
2655
2892
  inject: [
2656
- import_nestjs_durable_core14.DURABLE_OPTIONS_CANONICAL,
2657
- import_nestjs_durable_core14.STATE_STORE_CANONICAL,
2658
- import_nestjs_durable_core14.TRANSPORT_CANONICAL,
2893
+ import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL,
2894
+ import_nestjs_durable_core16.STATE_STORE_CANONICAL,
2895
+ import_nestjs_durable_core16.TRANSPORT_CANONICAL,
2659
2896
  import_core5.ModuleRef
2660
2897
  ]
2661
2898
  },
@@ -2669,7 +2906,7 @@ var DurableModule = class _DurableModule {
2669
2906
  // or (for a thin worker, no `store`) a `ProxyRunGateway` over `transport` when given, else a
2670
2907
  // gateway whose every method rejects with a clear tenant error.
2671
2908
  {
2672
- provide: import_nestjs_durable_core14.RunGateway,
2909
+ provide: import_nestjs_durable_core16.RunGateway,
2673
2910
  useFactory: /* @__PURE__ */ __name((options, store, engine) => {
2674
2911
  if (options.store !== void 0) {
2675
2912
  if (!store) {
@@ -2680,9 +2917,9 @@ var DurableModule = class _DurableModule {
2680
2917
  return options.transport ? new ProxyRunGateway(options.transport, options.partition ?? "default", options.runGatewayTimeoutMs) : unavailableRunGateway();
2681
2918
  }, "useFactory"),
2682
2919
  inject: [
2683
- import_nestjs_durable_core14.DURABLE_OPTIONS_CANONICAL,
2684
- import_nestjs_durable_core14.STATE_STORE_CANONICAL,
2685
- import_nestjs_durable_core14.WorkflowEngine
2920
+ import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL,
2921
+ import_nestjs_durable_core16.STATE_STORE_CANONICAL,
2922
+ import_nestjs_durable_core16.WorkflowEngine
2686
2923
  ]
2687
2924
  },
2688
2925
  RunGatewayBootstrap,
@@ -2696,13 +2933,13 @@ var DurableModule = class _DurableModule {
2696
2933
  exports: [
2697
2934
  WorkflowService,
2698
2935
  EntityService,
2699
- import_nestjs_durable_core14.WorkflowEngine,
2700
- import_nestjs_durable_core14.STATE_STORE,
2701
- import_nestjs_durable_core14.STATE_STORE_CANONICAL,
2702
- import_nestjs_durable_core14.TRANSPORT,
2703
- import_nestjs_durable_core14.TRANSPORT_CANONICAL,
2704
- import_nestjs_durable_core14.DURABLE_OPTIONS_CANONICAL,
2705
- import_nestjs_durable_core14.RunGateway
2936
+ import_nestjs_durable_core16.WorkflowEngine,
2937
+ import_nestjs_durable_core16.STATE_STORE,
2938
+ import_nestjs_durable_core16.STATE_STORE_CANONICAL,
2939
+ import_nestjs_durable_core16.TRANSPORT,
2940
+ import_nestjs_durable_core16.TRANSPORT_CANONICAL,
2941
+ import_nestjs_durable_core16.DURABLE_OPTIONS_CANONICAL,
2942
+ import_nestjs_durable_core16.RunGateway
2706
2943
  ]
2707
2944
  };
2708
2945
  }
@@ -2712,7 +2949,7 @@ DurableModule = _ts_decorate12([
2712
2949
  ], DurableModule);
2713
2950
 
2714
2951
  // src/index.ts
2715
- var import_nestjs_durable_core15 = require("@dudousxd/nestjs-durable-core");
2952
+ var import_nestjs_durable_core17 = require("@dudousxd/nestjs-durable-core");
2716
2953
  // Annotate the CommonJS export names for ESM import in node:
2717
2954
  0 && (module.exports = {
2718
2955
  CONTEXT_ACCESSOR,
@@ -2733,9 +2970,11 @@ var import_nestjs_durable_core15 = require("@dudousxd/nestjs-durable-core");
2733
2970
  IN_APP_WORKER_RUNNERS,
2734
2971
  IN_APP_WORKER_RUNTIME,
2735
2972
  InAppWorkerBootstrap,
2973
+ ON_ERROR_METADATA,
2736
2974
  ON_EVENT_METADATA,
2737
2975
  On,
2738
2976
  OnDurableEvent,
2977
+ OnError,
2739
2978
  OnEvent,
2740
2979
  ProxyRunGateway,
2741
2980
  RUN_GATEWAY,
@@ -2750,6 +2989,7 @@ var import_nestjs_durable_core15 = require("@dudousxd/nestjs-durable-core");
2750
2989
  ThinStepRegistrar,
2751
2990
  ThinWorkerBootstrap,
2752
2991
  ThinWorkflowRegistrar,
2992
+ UNSUPPORTED_RUN_REQUEST,
2753
2993
  WORKFLOW_METADATA,
2754
2994
  Workflow,
2755
2995
  WorkflowEngine,
@@ -2765,6 +3005,7 @@ var import_nestjs_durable_core15 = require("@dudousxd/nestjs-durable-core");
2765
3005
  isDrivingOperator,
2766
3006
  isOperatorRole,
2767
3007
  isStepInterceptor,
3008
+ onErrorCodesOf,
2768
3009
  readSearchAttributes,
2769
3010
  thinWorkerProviders,
2770
3011
  unavailableRunGateway