@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 +524 -283
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +106 -5
- package/dist/index.d.ts +106 -5
- package/dist/index.js +437 -200
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
- package/skills/durable-setup/SKILL.md +6 -0
- package/skills/durable-workflows/SKILL.md +67 -2
package/dist/index.js
CHANGED
|
@@ -125,6 +125,7 @@ function Workflow(options) {
|
|
|
125
125
|
name: options.name,
|
|
126
126
|
version: options.version ?? "1",
|
|
127
127
|
deadLetterWorkflow: options.deadLetterWorkflow,
|
|
128
|
+
onError: options.onError,
|
|
128
129
|
tags: options.tags,
|
|
129
130
|
singleton: options.singleton,
|
|
130
131
|
concurrency: options.concurrency,
|
|
@@ -202,6 +203,26 @@ function isDeadLetterHandler(method) {
|
|
|
202
203
|
return Reflect.getMetadata(DEAD_LETTER_METADATA, method) === true;
|
|
203
204
|
}
|
|
204
205
|
__name(isDeadLetterHandler, "isDeadLetterHandler");
|
|
206
|
+
var ON_ERROR_METADATA = Symbol("nestjs-durable:on-error");
|
|
207
|
+
function OnError(match) {
|
|
208
|
+
const code = match === void 0 || typeof match === "string" ? match : match.code;
|
|
209
|
+
if (match !== void 0 && typeof code !== "string") {
|
|
210
|
+
throw new Error('@OnError(ErrorClass): the class has no static `code`. Declare `static readonly code = "..."` on it, or pass the code string.');
|
|
211
|
+
}
|
|
212
|
+
return (_target, _propertyKey, descriptor) => {
|
|
213
|
+
const method = descriptor.value;
|
|
214
|
+
const codes = Reflect.getMetadata(ON_ERROR_METADATA, method) ?? [];
|
|
215
|
+
Reflect.defineMetadata(ON_ERROR_METADATA, [
|
|
216
|
+
...codes,
|
|
217
|
+
code
|
|
218
|
+
], method);
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
__name(OnError, "OnError");
|
|
222
|
+
function onErrorCodesOf(method) {
|
|
223
|
+
return Reflect.getMetadata(ON_ERROR_METADATA, method);
|
|
224
|
+
}
|
|
225
|
+
__name(onErrorCodesOf, "onErrorCodesOf");
|
|
205
226
|
var ON_EVENT_METADATA = Symbol("nestjs-durable:on-event");
|
|
206
227
|
function OnDurableEvent(...events) {
|
|
207
228
|
return (target) => {
|
|
@@ -404,6 +425,66 @@ function scanSteps(discovery, scanner, register) {
|
|
|
404
425
|
}
|
|
405
426
|
__name(scanSteps, "scanSteps");
|
|
406
427
|
|
|
428
|
+
// src/on-error-handlers.ts
|
|
429
|
+
import { workflowName as workflowName2 } from "@dudousxd/nestjs-durable-core";
|
|
430
|
+
function onErrorHandlersOf(meta, instance, scanner) {
|
|
431
|
+
const handlers = [];
|
|
432
|
+
const routes = [];
|
|
433
|
+
for (const methodName of scanner.getAllMethodNames(Object.getPrototypeOf(instance))) {
|
|
434
|
+
const method = instance[methodName];
|
|
435
|
+
const codes = typeof method === "function" ? onErrorCodesOf(method) : void 0;
|
|
436
|
+
if (!codes) continue;
|
|
437
|
+
const name = `${meta.name}.onError.${methodName}`;
|
|
438
|
+
handlers.push([
|
|
439
|
+
name,
|
|
440
|
+
(ctx, input) => method.call(instance, ctx, input)
|
|
441
|
+
]);
|
|
442
|
+
for (const code of codes) routes.push({
|
|
443
|
+
code,
|
|
444
|
+
workflow: name
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
for (const r of meta.onError ?? []) {
|
|
448
|
+
routes.push({
|
|
449
|
+
code: r.code === void 0 || typeof r.code === "string" ? r.code : r.code.code,
|
|
450
|
+
workflow: workflowName2(r.workflow)
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
return {
|
|
454
|
+
handlers,
|
|
455
|
+
routes
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
__name(onErrorHandlersOf, "onErrorHandlersOf");
|
|
459
|
+
|
|
460
|
+
// src/runtime-registration.ts
|
|
461
|
+
function registerOnRuntime(runtime, scanner, meta, instance, origin) {
|
|
462
|
+
const { handlers, routes } = onErrorHandlersOf(meta, instance, scanner);
|
|
463
|
+
const announced = {
|
|
464
|
+
version: meta.version,
|
|
465
|
+
...origin !== void 0 ? {
|
|
466
|
+
origin
|
|
467
|
+
} : {}
|
|
468
|
+
};
|
|
469
|
+
runtime.registerWorkflow(meta.name, (ctx, input) => instance.run(ctx, input), {
|
|
470
|
+
...announced,
|
|
471
|
+
...meta.requires !== void 0 ? {
|
|
472
|
+
requires: meta.requires
|
|
473
|
+
} : {},
|
|
474
|
+
// A catch-all goes on the wire without a `code` key, not with an undefined one.
|
|
475
|
+
...routes.length > 0 ? {
|
|
476
|
+
onError: routes.map(({ code, workflow }) => code === void 0 ? {
|
|
477
|
+
workflow
|
|
478
|
+
} : {
|
|
479
|
+
code,
|
|
480
|
+
workflow
|
|
481
|
+
})
|
|
482
|
+
} : {}
|
|
483
|
+
});
|
|
484
|
+
for (const [name, fn] of handlers) runtime.registerWorkflow(name, fn, announced);
|
|
485
|
+
}
|
|
486
|
+
__name(registerOnRuntime, "registerOnRuntime");
|
|
487
|
+
|
|
407
488
|
// src/durable-worker.module.ts
|
|
408
489
|
function _ts_decorate2(decorators, target, key, desc) {
|
|
409
490
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -443,34 +524,29 @@ var ThinWorkflowRegistrar = class {
|
|
|
443
524
|
__name(this, "ThinWorkflowRegistrar");
|
|
444
525
|
}
|
|
445
526
|
discovery;
|
|
527
|
+
metadataScanner;
|
|
446
528
|
runtime;
|
|
447
529
|
options;
|
|
448
|
-
constructor(discovery, runtime, options) {
|
|
530
|
+
constructor(discovery, metadataScanner, runtime, options) {
|
|
449
531
|
this.discovery = discovery;
|
|
532
|
+
this.metadataScanner = metadataScanner;
|
|
450
533
|
this.runtime = runtime;
|
|
451
534
|
this.options = options;
|
|
452
535
|
}
|
|
453
536
|
onModuleInit() {
|
|
454
537
|
const runtime = this.runtime;
|
|
455
538
|
if (runtime === null || !isPureThinWorker(this.options)) return;
|
|
456
|
-
scanWorkflows(this.discovery, (meta, instance, origin) => runtime.
|
|
457
|
-
version: meta.version,
|
|
458
|
-
...meta.requires !== void 0 ? {
|
|
459
|
-
requires: meta.requires
|
|
460
|
-
} : {},
|
|
461
|
-
...origin !== void 0 ? {
|
|
462
|
-
origin
|
|
463
|
-
} : {}
|
|
464
|
-
}));
|
|
539
|
+
scanWorkflows(this.discovery, (meta, instance, origin) => registerOnRuntime(runtime, this.metadataScanner, meta, instance, origin));
|
|
465
540
|
}
|
|
466
541
|
};
|
|
467
542
|
ThinWorkflowRegistrar = _ts_decorate2([
|
|
468
543
|
Injectable2(),
|
|
469
|
-
_ts_param(
|
|
470
|
-
_ts_param(
|
|
544
|
+
_ts_param(2, Inject(DURABLE_WORKER_RUNTIME)),
|
|
545
|
+
_ts_param(3, Inject(DURABLE_OPTIONS_CANONICAL)),
|
|
471
546
|
_ts_metadata2("design:type", Function),
|
|
472
547
|
_ts_metadata2("design:paramtypes", [
|
|
473
548
|
typeof DiscoveryService === "undefined" ? Object : DiscoveryService,
|
|
549
|
+
typeof MetadataScanner === "undefined" ? Object : MetadataScanner,
|
|
474
550
|
Object,
|
|
475
551
|
typeof DurableModuleOptions === "undefined" ? Object : DurableModuleOptions
|
|
476
552
|
])
|
|
@@ -897,15 +973,7 @@ var InAppWorkerBootstrap = class {
|
|
|
897
973
|
onModuleInit() {
|
|
898
974
|
const runtime = this.runtime;
|
|
899
975
|
if (runtime === null || !isCoLocatedWorker(this.options)) return;
|
|
900
|
-
scanWorkflows(this.discovery, (meta, instance, origin) => runtime.
|
|
901
|
-
version: meta.version,
|
|
902
|
-
...meta.requires !== void 0 ? {
|
|
903
|
-
requires: meta.requires
|
|
904
|
-
} : {},
|
|
905
|
-
...origin !== void 0 ? {
|
|
906
|
-
origin
|
|
907
|
-
} : {}
|
|
908
|
-
}));
|
|
976
|
+
scanWorkflows(this.discovery, (meta, instance, origin) => registerOnRuntime(runtime, this.metadataScanner, meta, instance, origin));
|
|
909
977
|
scanSteps(this.discovery, this.metadataScanner, (meta, handler) => runtime.registerStep(meta.name, handler));
|
|
910
978
|
}
|
|
911
979
|
async onApplicationBootstrap() {
|
|
@@ -995,7 +1063,212 @@ function inAppWorkerProviders() {
|
|
|
995
1063
|
__name(inAppWorkerProviders, "inAppWorkerProviders");
|
|
996
1064
|
|
|
997
1065
|
// src/proxy-run-gateway.ts
|
|
1066
|
+
import { SUMMARY_CHILD_LIMIT, childIdsOf, pageFan, summarizeTimeline } from "@dudousxd/nestjs-durable-core";
|
|
998
1067
|
import { Injectable as Injectable6 } from "@nestjs/common";
|
|
1068
|
+
|
|
1069
|
+
// src/run-request-responder.ts
|
|
1070
|
+
var UNSUPPORTED_RUN_REQUEST = "unsupported-request";
|
|
1071
|
+
var KNOWN_KINDS = /* @__PURE__ */ new Set([
|
|
1072
|
+
"getRunDetail",
|
|
1073
|
+
"getFanMembers",
|
|
1074
|
+
"listRuns",
|
|
1075
|
+
"runFacets",
|
|
1076
|
+
"runValueFacets",
|
|
1077
|
+
"workerHealth",
|
|
1078
|
+
"cancel",
|
|
1079
|
+
"retry",
|
|
1080
|
+
"continue",
|
|
1081
|
+
"retryWithInput",
|
|
1082
|
+
"redispatch",
|
|
1083
|
+
"waitingFor"
|
|
1084
|
+
]);
|
|
1085
|
+
var RunRequestResponder = class {
|
|
1086
|
+
static {
|
|
1087
|
+
__name(this, "RunRequestResponder");
|
|
1088
|
+
}
|
|
1089
|
+
transport;
|
|
1090
|
+
gateway;
|
|
1091
|
+
constructor(transport, gateway) {
|
|
1092
|
+
this.transport = transport;
|
|
1093
|
+
this.gateway = gateway;
|
|
1094
|
+
}
|
|
1095
|
+
/** Register the consumer on the transport. Each request is answered independently; a handler
|
|
1096
|
+
* failure never throws back into the transport (errors are captured into an error reply). */
|
|
1097
|
+
start() {
|
|
1098
|
+
this.transport.onRunRequest(async (msg) => {
|
|
1099
|
+
let reply;
|
|
1100
|
+
try {
|
|
1101
|
+
reply = await this.handle(msg);
|
|
1102
|
+
} catch (err) {
|
|
1103
|
+
reply = {
|
|
1104
|
+
requestId: msg.requestId,
|
|
1105
|
+
result: {
|
|
1106
|
+
ok: false,
|
|
1107
|
+
error: {
|
|
1108
|
+
message: err instanceof Error ? err.message : String(err)
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
await this.transport.publishRunReply(reply);
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
async handle(msg) {
|
|
1117
|
+
const { body } = msg;
|
|
1118
|
+
if (!KNOWN_KINDS.has(body.kind)) {
|
|
1119
|
+
return {
|
|
1120
|
+
requestId: msg.requestId,
|
|
1121
|
+
result: {
|
|
1122
|
+
ok: false,
|
|
1123
|
+
error: {
|
|
1124
|
+
message: `the control plane does not support the ${String(body.kind)} run request`,
|
|
1125
|
+
code: UNSUPPORTED_RUN_REQUEST
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
if (body.kind === "listRuns") {
|
|
1131
|
+
const data = await this.gateway.listRuns({
|
|
1132
|
+
...body.query,
|
|
1133
|
+
namespace: msg.tenant
|
|
1134
|
+
});
|
|
1135
|
+
return {
|
|
1136
|
+
requestId: msg.requestId,
|
|
1137
|
+
result: {
|
|
1138
|
+
ok: true,
|
|
1139
|
+
data
|
|
1140
|
+
}
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1143
|
+
if (body.kind === "runFacets") {
|
|
1144
|
+
const data = await this.gateway.runFacets({
|
|
1145
|
+
...body.query,
|
|
1146
|
+
namespace: msg.tenant
|
|
1147
|
+
});
|
|
1148
|
+
return {
|
|
1149
|
+
requestId: msg.requestId,
|
|
1150
|
+
result: {
|
|
1151
|
+
ok: true,
|
|
1152
|
+
data
|
|
1153
|
+
}
|
|
1154
|
+
};
|
|
1155
|
+
}
|
|
1156
|
+
if (body.kind === "runValueFacets") {
|
|
1157
|
+
const data = await this.gateway.runValueFacets(body.axis, {
|
|
1158
|
+
...body.query,
|
|
1159
|
+
namespace: msg.tenant
|
|
1160
|
+
}, body.opts);
|
|
1161
|
+
return {
|
|
1162
|
+
requestId: msg.requestId,
|
|
1163
|
+
result: {
|
|
1164
|
+
ok: true,
|
|
1165
|
+
data
|
|
1166
|
+
}
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
if (body.kind === "workerHealth") {
|
|
1170
|
+
const all = await this.gateway.workerHealth();
|
|
1171
|
+
const data = all.filter((h) => h.group.endsWith(`@${msg.tenant}`));
|
|
1172
|
+
return {
|
|
1173
|
+
requestId: msg.requestId,
|
|
1174
|
+
result: {
|
|
1175
|
+
ok: true,
|
|
1176
|
+
data
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
}
|
|
1180
|
+
if (body.kind === "waitingFor") {
|
|
1181
|
+
const all = await this.gateway.waitingFor(body.runIds);
|
|
1182
|
+
const owned = await Promise.all(Object.entries(all).map(async ([runId, waiting]) => {
|
|
1183
|
+
const owner = this.gateway.getRun ? await this.gateway.getRun(runId) : (await this.gateway.getRunDetail(runId))?.run;
|
|
1184
|
+
return owner && owner.namespace === msg.tenant ? [
|
|
1185
|
+
runId,
|
|
1186
|
+
waiting
|
|
1187
|
+
] : void 0;
|
|
1188
|
+
}));
|
|
1189
|
+
const data = {};
|
|
1190
|
+
for (const entry of owned) {
|
|
1191
|
+
if (entry) data[entry[0]] = entry[1];
|
|
1192
|
+
}
|
|
1193
|
+
return {
|
|
1194
|
+
requestId: msg.requestId,
|
|
1195
|
+
result: {
|
|
1196
|
+
ok: true,
|
|
1197
|
+
data
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
const detail = body.kind === "getRunDetail" || !this.gateway.getRun ? await this.gateway.getRunDetail(body.runId, body.kind === "getRunDetail" ? body.options : void 0) : void 0;
|
|
1202
|
+
const run = detail !== void 0 ? detail?.run ?? null : await this.gateway.getRun?.(body.runId);
|
|
1203
|
+
if (run && run.namespace !== msg.tenant) {
|
|
1204
|
+
return {
|
|
1205
|
+
requestId: msg.requestId,
|
|
1206
|
+
result: {
|
|
1207
|
+
ok: false,
|
|
1208
|
+
error: {
|
|
1209
|
+
message: "run belongs to another tenant",
|
|
1210
|
+
code: "cross-tenant"
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
if (body.kind === "getRunDetail") {
|
|
1216
|
+
return {
|
|
1217
|
+
requestId: msg.requestId,
|
|
1218
|
+
result: {
|
|
1219
|
+
ok: true,
|
|
1220
|
+
data: detail
|
|
1221
|
+
}
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
if (body.kind === "getFanMembers") {
|
|
1225
|
+
const data = run ? await this.gateway.getFanMembers?.(body.runId, body.group, body.query) ?? null : null;
|
|
1226
|
+
return {
|
|
1227
|
+
requestId: msg.requestId,
|
|
1228
|
+
result: {
|
|
1229
|
+
ok: true,
|
|
1230
|
+
data
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
1233
|
+
}
|
|
1234
|
+
try {
|
|
1235
|
+
const data = await this.callVerb(body);
|
|
1236
|
+
return {
|
|
1237
|
+
requestId: msg.requestId,
|
|
1238
|
+
result: {
|
|
1239
|
+
ok: true,
|
|
1240
|
+
data
|
|
1241
|
+
}
|
|
1242
|
+
};
|
|
1243
|
+
} catch (err) {
|
|
1244
|
+
return {
|
|
1245
|
+
requestId: msg.requestId,
|
|
1246
|
+
result: {
|
|
1247
|
+
ok: false,
|
|
1248
|
+
error: {
|
|
1249
|
+
message: err instanceof Error ? err.message : String(err)
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
callVerb(body) {
|
|
1256
|
+
switch (body.kind) {
|
|
1257
|
+
case "cancel":
|
|
1258
|
+
return this.gateway.cancel(body.runId, body.opts);
|
|
1259
|
+
case "retry":
|
|
1260
|
+
return this.gateway.retry(body.runId);
|
|
1261
|
+
case "continue":
|
|
1262
|
+
return this.gateway.continue(body.runId);
|
|
1263
|
+
case "retryWithInput":
|
|
1264
|
+
return this.gateway.retryWithInput(body.runId, body.input);
|
|
1265
|
+
case "redispatch":
|
|
1266
|
+
return this.gateway.redispatchPending(body.runId);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
};
|
|
1270
|
+
|
|
1271
|
+
// src/proxy-run-gateway.ts
|
|
999
1272
|
function _ts_decorate6(decorators, target, key, desc) {
|
|
1000
1273
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1001
1274
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") {
|
|
@@ -1016,6 +1289,15 @@ function _ts_metadata6(metadataKey, metadataValue) {
|
|
|
1016
1289
|
}
|
|
1017
1290
|
}
|
|
1018
1291
|
__name(_ts_metadata6, "_ts_metadata");
|
|
1292
|
+
var UnsupportedRunRequestError = class UnsupportedRunRequestError2 extends Error {
|
|
1293
|
+
static {
|
|
1294
|
+
__name(this, "UnsupportedRunRequestError");
|
|
1295
|
+
}
|
|
1296
|
+
};
|
|
1297
|
+
function isUnsupported(err) {
|
|
1298
|
+
return err instanceof UnsupportedRunRequestError;
|
|
1299
|
+
}
|
|
1300
|
+
__name(isUnsupported, "isUnsupported");
|
|
1019
1301
|
var ProxyRunGateway = class {
|
|
1020
1302
|
static {
|
|
1021
1303
|
__name(this, "ProxyRunGateway");
|
|
@@ -1023,11 +1305,18 @@ var ProxyRunGateway = class {
|
|
|
1023
1305
|
transport;
|
|
1024
1306
|
tenant;
|
|
1025
1307
|
timeoutMs;
|
|
1308
|
+
capabilityTtlMs;
|
|
1026
1309
|
pending = /* @__PURE__ */ new Map();
|
|
1027
|
-
|
|
1310
|
+
/** Verb → when to ask the control plane for it again, after it answered that it does not know it.
|
|
1311
|
+
* During a rolling upgrade the control plane is several pods of mixed versions behind one queue,
|
|
1312
|
+
* and a reply does not say which pod sent it, so the whole control plane is assumed old until the
|
|
1313
|
+
* entry expires. */
|
|
1314
|
+
unsupportedUntil = /* @__PURE__ */ new Map();
|
|
1315
|
+
constructor(transport, tenant, timeoutMs = 1e4, capabilityTtlMs = 6e4) {
|
|
1028
1316
|
this.transport = transport;
|
|
1029
1317
|
this.tenant = tenant;
|
|
1030
1318
|
this.timeoutMs = timeoutMs;
|
|
1319
|
+
this.capabilityTtlMs = capabilityTtlMs;
|
|
1031
1320
|
this.transport.onRunReply?.((reply) => this.handleReply(reply));
|
|
1032
1321
|
}
|
|
1033
1322
|
handleReply(reply) {
|
|
@@ -1037,6 +1326,8 @@ var ProxyRunGateway = class {
|
|
|
1037
1326
|
this.pending.delete(reply.requestId);
|
|
1038
1327
|
if (reply.result.ok) {
|
|
1039
1328
|
pending.resolve(reply.result.data);
|
|
1329
|
+
} else if (reply.result.error.code === UNSUPPORTED_RUN_REQUEST) {
|
|
1330
|
+
pending.reject(new UnsupportedRunRequestError(reply.result.error.message));
|
|
1040
1331
|
} else {
|
|
1041
1332
|
pending.reject(new Error(reply.result.error.message));
|
|
1042
1333
|
}
|
|
@@ -1072,20 +1363,59 @@ var ProxyRunGateway = class {
|
|
|
1072
1363
|
tenant: this.tenant
|
|
1073
1364
|
};
|
|
1074
1365
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1366
|
+
/**
|
|
1367
|
+
* A control plane that predates {@link RunDetailOptions} ignores them and sends the full detail;
|
|
1368
|
+
* a summarized detail always carries `fans`, so its absence means the summary is made here.
|
|
1369
|
+
*/
|
|
1370
|
+
async getRunDetail(runId, options) {
|
|
1371
|
+
const detail = await this.request(options === void 0 ? {
|
|
1372
|
+
kind: "getRunDetail",
|
|
1373
|
+
runId
|
|
1374
|
+
} : {
|
|
1077
1375
|
kind: "getRunDetail",
|
|
1078
1376
|
runId,
|
|
1079
1377
|
options
|
|
1080
1378
|
});
|
|
1379
|
+
const over = options?.summarizeFansOver;
|
|
1380
|
+
if (over === void 0 || !detail || detail.fans !== void 0) return detail;
|
|
1381
|
+
const { timeline, fans } = summarizeTimeline(detail.timeline, over);
|
|
1382
|
+
const ids = childIdsOf(detail.timeline);
|
|
1383
|
+
return {
|
|
1384
|
+
...detail,
|
|
1385
|
+
timeline,
|
|
1386
|
+
children: ids.slice(0, SUMMARY_CHILD_LIMIT),
|
|
1387
|
+
fans,
|
|
1388
|
+
childCount: ids.length
|
|
1389
|
+
};
|
|
1081
1390
|
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1391
|
+
/** Paged from the full detail when the control plane is too old to page a fan itself. */
|
|
1392
|
+
async getFanMembers(runId, group, query) {
|
|
1393
|
+
if (!this.knownUnsupported("getFanMembers")) {
|
|
1394
|
+
try {
|
|
1395
|
+
const page = await this.request({
|
|
1396
|
+
kind: "getFanMembers",
|
|
1397
|
+
runId,
|
|
1398
|
+
group,
|
|
1399
|
+
query
|
|
1400
|
+
});
|
|
1401
|
+
if (page !== void 0) return page;
|
|
1402
|
+
} catch (err) {
|
|
1403
|
+
if (!isUnsupported(err)) throw err;
|
|
1404
|
+
}
|
|
1405
|
+
this.unsupportedUntil.set("getFanMembers", Date.now() + this.capabilityTtlMs);
|
|
1406
|
+
}
|
|
1407
|
+
const detail = await this.request({
|
|
1408
|
+
kind: "getRunDetail",
|
|
1409
|
+
runId
|
|
1088
1410
|
});
|
|
1411
|
+
return detail ? pageFan(detail.timeline, group, query) : null;
|
|
1412
|
+
}
|
|
1413
|
+
knownUnsupported(kind) {
|
|
1414
|
+
const until = this.unsupportedUntil.get(kind);
|
|
1415
|
+
if (until === void 0) return false;
|
|
1416
|
+
if (Date.now() < until) return true;
|
|
1417
|
+
this.unsupportedUntil.delete(kind);
|
|
1418
|
+
return false;
|
|
1089
1419
|
}
|
|
1090
1420
|
/** The control plane's `StoreRunGateway` resolves each run's `waiting` descriptor; the reply carries
|
|
1091
1421
|
* it through as plain JSON, so a tenant's list rows name the wait too. */
|
|
@@ -1175,6 +1505,7 @@ ProxyRunGateway = _ts_decorate6([
|
|
|
1175
1505
|
_ts_metadata6("design:paramtypes", [
|
|
1176
1506
|
typeof Transport === "undefined" ? Object : Transport,
|
|
1177
1507
|
String,
|
|
1508
|
+
void 0,
|
|
1178
1509
|
void 0
|
|
1179
1510
|
])
|
|
1180
1511
|
], ProxyRunGateway);
|
|
@@ -1372,170 +1703,8 @@ RetentionPoller = _ts_decorate7([
|
|
|
1372
1703
|
])
|
|
1373
1704
|
], RetentionPoller);
|
|
1374
1705
|
|
|
1375
|
-
// src/run-request-responder.ts
|
|
1376
|
-
var RunRequestResponder = class {
|
|
1377
|
-
static {
|
|
1378
|
-
__name(this, "RunRequestResponder");
|
|
1379
|
-
}
|
|
1380
|
-
transport;
|
|
1381
|
-
gateway;
|
|
1382
|
-
constructor(transport, gateway) {
|
|
1383
|
-
this.transport = transport;
|
|
1384
|
-
this.gateway = gateway;
|
|
1385
|
-
}
|
|
1386
|
-
/** Register the consumer on the transport. Each request is answered independently; a handler
|
|
1387
|
-
* failure never throws back into the transport (errors are captured into an error reply). */
|
|
1388
|
-
start() {
|
|
1389
|
-
this.transport.onRunRequest(async (msg) => {
|
|
1390
|
-
const reply = await this.handle(msg);
|
|
1391
|
-
await this.transport.publishRunReply(reply);
|
|
1392
|
-
});
|
|
1393
|
-
}
|
|
1394
|
-
async handle(msg) {
|
|
1395
|
-
const { body } = msg;
|
|
1396
|
-
if (body.kind === "listRuns") {
|
|
1397
|
-
const data = await this.gateway.listRuns({
|
|
1398
|
-
...body.query,
|
|
1399
|
-
namespace: msg.tenant
|
|
1400
|
-
});
|
|
1401
|
-
return {
|
|
1402
|
-
requestId: msg.requestId,
|
|
1403
|
-
result: {
|
|
1404
|
-
ok: true,
|
|
1405
|
-
data
|
|
1406
|
-
}
|
|
1407
|
-
};
|
|
1408
|
-
}
|
|
1409
|
-
if (body.kind === "runFacets") {
|
|
1410
|
-
const data = await this.gateway.runFacets({
|
|
1411
|
-
...body.query,
|
|
1412
|
-
namespace: msg.tenant
|
|
1413
|
-
});
|
|
1414
|
-
return {
|
|
1415
|
-
requestId: msg.requestId,
|
|
1416
|
-
result: {
|
|
1417
|
-
ok: true,
|
|
1418
|
-
data
|
|
1419
|
-
}
|
|
1420
|
-
};
|
|
1421
|
-
}
|
|
1422
|
-
if (body.kind === "runValueFacets") {
|
|
1423
|
-
const data = await this.gateway.runValueFacets(body.axis, {
|
|
1424
|
-
...body.query,
|
|
1425
|
-
namespace: msg.tenant
|
|
1426
|
-
}, body.opts);
|
|
1427
|
-
return {
|
|
1428
|
-
requestId: msg.requestId,
|
|
1429
|
-
result: {
|
|
1430
|
-
ok: true,
|
|
1431
|
-
data
|
|
1432
|
-
}
|
|
1433
|
-
};
|
|
1434
|
-
}
|
|
1435
|
-
if (body.kind === "workerHealth") {
|
|
1436
|
-
const all = await this.gateway.workerHealth();
|
|
1437
|
-
const data = all.filter((h) => h.group.endsWith(`@${msg.tenant}`));
|
|
1438
|
-
return {
|
|
1439
|
-
requestId: msg.requestId,
|
|
1440
|
-
result: {
|
|
1441
|
-
ok: true,
|
|
1442
|
-
data
|
|
1443
|
-
}
|
|
1444
|
-
};
|
|
1445
|
-
}
|
|
1446
|
-
if (body.kind === "waitingFor") {
|
|
1447
|
-
const all = await this.gateway.waitingFor(body.runIds);
|
|
1448
|
-
const owned = await Promise.all(Object.entries(all).map(async ([runId, waiting]) => {
|
|
1449
|
-
const owner = this.gateway.getRun ? await this.gateway.getRun(runId) : (await this.gateway.getRunDetail(runId))?.run;
|
|
1450
|
-
return owner && owner.namespace === msg.tenant ? [
|
|
1451
|
-
runId,
|
|
1452
|
-
waiting
|
|
1453
|
-
] : void 0;
|
|
1454
|
-
}));
|
|
1455
|
-
const data = {};
|
|
1456
|
-
for (const entry of owned) {
|
|
1457
|
-
if (entry) data[entry[0]] = entry[1];
|
|
1458
|
-
}
|
|
1459
|
-
return {
|
|
1460
|
-
requestId: msg.requestId,
|
|
1461
|
-
result: {
|
|
1462
|
-
ok: true,
|
|
1463
|
-
data
|
|
1464
|
-
}
|
|
1465
|
-
};
|
|
1466
|
-
}
|
|
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) {
|
|
1470
|
-
return {
|
|
1471
|
-
requestId: msg.requestId,
|
|
1472
|
-
result: {
|
|
1473
|
-
ok: false,
|
|
1474
|
-
error: {
|
|
1475
|
-
message: "run belongs to another tenant",
|
|
1476
|
-
code: "cross-tenant"
|
|
1477
|
-
}
|
|
1478
|
-
}
|
|
1479
|
-
};
|
|
1480
|
-
}
|
|
1481
|
-
if (body.kind === "getRunDetail") {
|
|
1482
|
-
return {
|
|
1483
|
-
requestId: msg.requestId,
|
|
1484
|
-
result: {
|
|
1485
|
-
ok: true,
|
|
1486
|
-
data: detail
|
|
1487
|
-
}
|
|
1488
|
-
};
|
|
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
|
-
}
|
|
1500
|
-
try {
|
|
1501
|
-
const data = await this.callVerb(body);
|
|
1502
|
-
return {
|
|
1503
|
-
requestId: msg.requestId,
|
|
1504
|
-
result: {
|
|
1505
|
-
ok: true,
|
|
1506
|
-
data
|
|
1507
|
-
}
|
|
1508
|
-
};
|
|
1509
|
-
} catch (err) {
|
|
1510
|
-
return {
|
|
1511
|
-
requestId: msg.requestId,
|
|
1512
|
-
result: {
|
|
1513
|
-
ok: false,
|
|
1514
|
-
error: {
|
|
1515
|
-
message: err instanceof Error ? err.message : String(err)
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
};
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
callVerb(body) {
|
|
1522
|
-
switch (body.kind) {
|
|
1523
|
-
case "cancel":
|
|
1524
|
-
return this.gateway.cancel(body.runId, body.opts);
|
|
1525
|
-
case "retry":
|
|
1526
|
-
return this.gateway.retry(body.runId);
|
|
1527
|
-
case "continue":
|
|
1528
|
-
return this.gateway.continue(body.runId);
|
|
1529
|
-
case "retryWithInput":
|
|
1530
|
-
return this.gateway.retryWithInput(body.runId, body.input);
|
|
1531
|
-
case "redispatch":
|
|
1532
|
-
return this.gateway.redispatchPending(body.runId);
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
};
|
|
1536
|
-
|
|
1537
1706
|
// src/store-run-gateway.ts
|
|
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";
|
|
1707
|
+
import { STATE_STORE_CANONICAL as STATE_STORE_CANONICAL2, SUMMARY_CHILD_LIMIT as SUMMARY_CHILD_LIMIT2, WorkflowEngine as WorkflowEngine2, aggregatesCheckpoints, childIdsOf as childIdsOf2, etagMatches, fanPageEtag, indexWaitersByRun, listSignalWaitersOfRuns, mergeRunFacetRows, pageFan as pageFan2, pageFanFromStore, resolveRunWaiting, runDetailEtag, summarizeRunFromStore, summarizeTimeline as summarizeTimeline2 } from "@dudousxd/nestjs-durable-core";
|
|
1539
1708
|
import { Inject as Inject5, Injectable as Injectable8 } from "@nestjs/common";
|
|
1540
1709
|
function _ts_decorate8(decorators, target, key, desc) {
|
|
1541
1710
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -1593,13 +1762,31 @@ var StoreRunGateway = class {
|
|
|
1593
1762
|
children
|
|
1594
1763
|
};
|
|
1595
1764
|
}
|
|
1765
|
+
if (aggregatesCheckpoints(this.store)) {
|
|
1766
|
+
const stats = await this.store.checkpointStats(runId);
|
|
1767
|
+
const etag = runDetailEtag(run, stats, over);
|
|
1768
|
+
if (etagMatches(options?.ifNoneMatch, etag)) {
|
|
1769
|
+
return {
|
|
1770
|
+
run,
|
|
1771
|
+
timeline: [],
|
|
1772
|
+
children: [],
|
|
1773
|
+
notModified: true,
|
|
1774
|
+
etag
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
return {
|
|
1778
|
+
run,
|
|
1779
|
+
...await summarizeRunFromStore(this.store, runId, over, stats),
|
|
1780
|
+
etag
|
|
1781
|
+
};
|
|
1782
|
+
}
|
|
1596
1783
|
const full = await this.store.listCheckpoints(runId);
|
|
1597
|
-
const { timeline, fans } =
|
|
1598
|
-
const ids =
|
|
1784
|
+
const { timeline, fans } = summarizeTimeline2(full, over);
|
|
1785
|
+
const ids = childIdsOf2(full);
|
|
1599
1786
|
return {
|
|
1600
1787
|
run,
|
|
1601
1788
|
timeline,
|
|
1602
|
-
children: ids.slice(0,
|
|
1789
|
+
children: ids.slice(0, SUMMARY_CHILD_LIMIT2),
|
|
1603
1790
|
fans,
|
|
1604
1791
|
childCount: ids.length
|
|
1605
1792
|
};
|
|
@@ -1609,7 +1796,25 @@ var StoreRunGateway = class {
|
|
|
1609
1796
|
}
|
|
1610
1797
|
async getFanMembers(runId, group, query) {
|
|
1611
1798
|
if (!await this.store.getRun(runId)) return null;
|
|
1612
|
-
|
|
1799
|
+
if (aggregatesCheckpoints(this.store)) {
|
|
1800
|
+
const stats = await this.store.checkpointStats(runId, {
|
|
1801
|
+
group
|
|
1802
|
+
});
|
|
1803
|
+
const etag = fanPageEtag(group, stats, query);
|
|
1804
|
+
if (etagMatches(query.ifNoneMatch, etag)) {
|
|
1805
|
+
return {
|
|
1806
|
+
items: [],
|
|
1807
|
+
total: 0,
|
|
1808
|
+
notModified: true,
|
|
1809
|
+
etag
|
|
1810
|
+
};
|
|
1811
|
+
}
|
|
1812
|
+
return {
|
|
1813
|
+
...await pageFanFromStore(this.store, runId, group, query, stats),
|
|
1814
|
+
etag
|
|
1815
|
+
};
|
|
1816
|
+
}
|
|
1817
|
+
return pageFan2(await this.store.listCheckpoints(runId), group, query);
|
|
1613
1818
|
}
|
|
1614
1819
|
async listRuns(query) {
|
|
1615
1820
|
const runs = await this.store.listRuns(query);
|
|
@@ -1900,7 +2105,7 @@ var CONTEXT_ACCESSOR = Symbol.for("@dudousxd/nestjs-context:accessor");
|
|
|
1900
2105
|
var RUN_GATEWAY = RunGateway;
|
|
1901
2106
|
|
|
1902
2107
|
// src/workflow.registrar.ts
|
|
1903
|
-
import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL6, RemoteWorkflowExecutor, STATE_STORE_CANONICAL as STATE_STORE_CANONICAL3, WorkflowEngine as WorkflowEngine4, bindWorkflowClass, parseDuration as parseDuration2, sanitizeQueueToken, tenantGroup, workflowName as
|
|
2108
|
+
import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL6, RemoteWorkflowExecutor, STATE_STORE_CANONICAL as STATE_STORE_CANONICAL3, WorkflowEngine as WorkflowEngine4, bindWorkflowClass, parseDuration as parseDuration2, sanitizeQueueToken, tenantGroup, workflowName as workflowName3 } from "@dudousxd/nestjs-durable-core";
|
|
1904
2109
|
import { Inject as Inject7, Injectable as Injectable10 } from "@nestjs/common";
|
|
1905
2110
|
import { DiscoveryService as DiscoveryService4, MetadataScanner as MetadataScanner4 } from "@nestjs/core";
|
|
1906
2111
|
|
|
@@ -1970,6 +2175,7 @@ function _ts_param7(paramIndex, decorator) {
|
|
|
1970
2175
|
};
|
|
1971
2176
|
}
|
|
1972
2177
|
__name(_ts_param7, "_ts_param");
|
|
2178
|
+
var UNSERVED_ROUTES_RECHECK_MS = 3e4;
|
|
1973
2179
|
var WorkflowRegistrar = class {
|
|
1974
2180
|
static {
|
|
1975
2181
|
__name(this, "WorkflowRegistrar");
|
|
@@ -2040,6 +2246,12 @@ var WorkflowRegistrar = class {
|
|
|
2040
2246
|
windowMs: parseDuration2(meta.batch.within)
|
|
2041
2247
|
} : void 0;
|
|
2042
2248
|
const workflowCtor = workflow.constructor;
|
|
2249
|
+
const onError = onErrorHandlersOf(meta, workflow, this.metadataScanner);
|
|
2250
|
+
for (const [name, fn] of onError.handlers) {
|
|
2251
|
+
this.engine.register(name, meta.version, fn, {
|
|
2252
|
+
origin
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
2043
2255
|
this.engine.register(meta.name, meta.version, (ctx, input) => workflow.run(ctx, input), {
|
|
2044
2256
|
// Stamped onto every run this workflow starts (see `WorkflowRun.origin`). Derived from the
|
|
2045
2257
|
// class's declaring file, so a lib gets attributed without opting in; `undefined` when it
|
|
@@ -2054,6 +2266,7 @@ var WorkflowRegistrar = class {
|
|
|
2054
2266
|
searchAttributesSchema: meta.searchAttributes,
|
|
2055
2267
|
onEvent: getOnEvents(meta, workflowCtor),
|
|
2056
2268
|
eventBatch,
|
|
2269
|
+
onError: onError.routes,
|
|
2057
2270
|
// Uniform dispatch (opt-in): when an in-app worker is configured, register the body GROUP-SERVED
|
|
2058
2271
|
// so the engine dispatches its turns over the transport instead of running it inline; the
|
|
2059
2272
|
// co-located worker consumer (Task 5: one queue PER REGISTERED NAME) replays the same body.
|
|
@@ -2083,10 +2296,11 @@ var WorkflowRegistrar = class {
|
|
|
2083
2296
|
});
|
|
2084
2297
|
deadLetterByWorkflow.set(meta.name, dlqName);
|
|
2085
2298
|
} else if (meta.deadLetterWorkflow) {
|
|
2086
|
-
deadLetterByWorkflow.set(meta.name,
|
|
2299
|
+
deadLetterByWorkflow.set(meta.name, workflowName3(meta.deadLetterWorkflow));
|
|
2087
2300
|
}
|
|
2088
2301
|
});
|
|
2089
2302
|
this.reportUnattributed(unattributed);
|
|
2303
|
+
void this.reportUnservedOnErrorRoutes();
|
|
2090
2304
|
this.installDeadLetterRouting(deadLetterByWorkflow);
|
|
2091
2305
|
}
|
|
2092
2306
|
/**
|
|
@@ -2099,6 +2313,20 @@ var WorkflowRegistrar = class {
|
|
|
2099
2313
|
if (names.length === 0) return;
|
|
2100
2314
|
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.`);
|
|
2101
2315
|
}
|
|
2316
|
+
/**
|
|
2317
|
+
* Says, once after boot, which onError routes name a handler workflow nothing can run, so a typo is
|
|
2318
|
+
* caught before the first failure goes nowhere. Routes unserved at boot are checked again after
|
|
2319
|
+
* {@link UNSERVED_ROUTES_RECHECK_MS}, so a handler whose workers start after this process is not
|
|
2320
|
+
* reported.
|
|
2321
|
+
*/
|
|
2322
|
+
async reportUnservedOnErrorRoutes(recheckMs = UNSERVED_ROUTES_RECHECK_MS) {
|
|
2323
|
+
if ((await this.engine.unservedOnErrorRoutes().catch(() => [])).length === 0) return;
|
|
2324
|
+
await new Promise((resolve) => setTimeout(resolve, recheckMs).unref());
|
|
2325
|
+
const unserved = await this.engine.unservedOnErrorRoutes().catch(() => []);
|
|
2326
|
+
if (unserved.length === 0) return;
|
|
2327
|
+
const list = unserved.map(({ workflow, route }) => `${workflow} \u2192 ${route.workflow} (code ${route.code ?? "*"})`).join(", ");
|
|
2328
|
+
console.warn(`[nestjs-durable] ${unserved.length} onError route(s) name a handler workflow that is not registered here and has no live worker: ${list}.`);
|
|
2329
|
+
}
|
|
2102
2330
|
/** Returns the instance's `@DeadLetter()` method bound to the instance, or undefined if none. */
|
|
2103
2331
|
findDeadLetterHandler(instance) {
|
|
2104
2332
|
const prototype = Object.getPrototypeOf(instance);
|
|
@@ -2116,7 +2344,7 @@ var WorkflowRegistrar = class {
|
|
|
2116
2344
|
* a `dlq:<runId>` id, so re-recovery never double-dispatches.
|
|
2117
2345
|
*/
|
|
2118
2346
|
installDeadLetterRouting(byWorkflow) {
|
|
2119
|
-
const fallback = this.options.deadLetterWorkflow ?
|
|
2347
|
+
const fallback = this.options.deadLetterWorkflow ? workflowName3(this.options.deadLetterWorkflow) : void 0;
|
|
2120
2348
|
if (byWorkflow.size === 0 && !fallback) return;
|
|
2121
2349
|
this.engine.onDead((run) => {
|
|
2122
2350
|
const target = byWorkflow.get(run.workflow) ?? fallback;
|
|
@@ -2545,6 +2773,11 @@ var DurableModule = class _DurableModule {
|
|
|
2545
2773
|
remoteAdvanceSilenceMs: options.remoteAdvanceSilenceMs,
|
|
2546
2774
|
remoteRedispatchMs: options.remoteRedispatchMs,
|
|
2547
2775
|
remoteRedispatchMax: options.remoteRedispatchMax,
|
|
2776
|
+
reconcileMs: options.reconcileMs,
|
|
2777
|
+
timerBatchSize: options.timerBatchSize,
|
|
2778
|
+
eventBufferTtlMs: options.eventBufferTtlMs,
|
|
2779
|
+
blockedPollMs: options.blockedPollMs,
|
|
2780
|
+
trackStepStart: options.trackStepStart,
|
|
2548
2781
|
instanceId: options.instanceId,
|
|
2549
2782
|
namespace: options.namespace,
|
|
2550
2783
|
webhookUrl: options.webhookUrl,
|
|
@@ -2646,9 +2879,11 @@ export {
|
|
|
2646
2879
|
IN_APP_WORKER_RUNNERS,
|
|
2647
2880
|
IN_APP_WORKER_RUNTIME,
|
|
2648
2881
|
InAppWorkerBootstrap,
|
|
2882
|
+
ON_ERROR_METADATA,
|
|
2649
2883
|
ON_EVENT_METADATA,
|
|
2650
2884
|
On,
|
|
2651
2885
|
OnDurableEvent,
|
|
2886
|
+
OnError,
|
|
2652
2887
|
OnEvent,
|
|
2653
2888
|
ProxyRunGateway,
|
|
2654
2889
|
RUN_GATEWAY,
|
|
@@ -2663,6 +2898,7 @@ export {
|
|
|
2663
2898
|
ThinStepRegistrar,
|
|
2664
2899
|
ThinWorkerBootstrap,
|
|
2665
2900
|
ThinWorkflowRegistrar,
|
|
2901
|
+
UNSUPPORTED_RUN_REQUEST,
|
|
2666
2902
|
WORKFLOW_METADATA,
|
|
2667
2903
|
Workflow,
|
|
2668
2904
|
WorkflowEngine7 as WorkflowEngine,
|
|
@@ -2678,6 +2914,7 @@ export {
|
|
|
2678
2914
|
isDrivingOperator,
|
|
2679
2915
|
isOperatorRole,
|
|
2680
2916
|
isStepInterceptor,
|
|
2917
|
+
onErrorCodesOf,
|
|
2681
2918
|
readSearchAttributes2 as readSearchAttributes,
|
|
2682
2919
|
thinWorkerProviders,
|
|
2683
2920
|
unavailableRunGateway
|