@dudousxd/nestjs-durable-core 0.76.1 → 0.78.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 +437 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +302 -113
- package/dist/index.d.ts +302 -113
- package/dist/index.js +430 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -39,6 +39,7 @@ __export(index_exports, {
|
|
|
39
39
|
EVENT_TOKEN_PREFIX: () => EVENT_TOKEN_PREFIX,
|
|
40
40
|
Entities: () => Entities,
|
|
41
41
|
EventAccumulators: () => EventAccumulators,
|
|
42
|
+
FAN_SUMMARY_FAILURES: () => FAN_SUMMARY_FAILURES,
|
|
42
43
|
FatalError: () => FatalError,
|
|
43
44
|
GatherError: () => GatherError,
|
|
44
45
|
InMemoryAdmissionBackend: () => InMemoryAdmissionBackend,
|
|
@@ -60,6 +61,7 @@ __export(index_exports, {
|
|
|
60
61
|
SINGLETON_ADMITTED_TAG: () => SINGLETON_ADMITTED_TAG,
|
|
61
62
|
STATE_STORE: () => STATE_STORE,
|
|
62
63
|
STATE_STORE_CANONICAL: () => STATE_STORE_CANONICAL,
|
|
64
|
+
SUMMARY_CHILD_LIMIT: () => SUMMARY_CHILD_LIMIT,
|
|
63
65
|
ScheduleAlreadyExistsError: () => ScheduleAlreadyExistsError,
|
|
64
66
|
ScheduleClient: () => ScheduleClient,
|
|
65
67
|
ScheduleNotFoundError: () => ScheduleNotFoundError,
|
|
@@ -86,6 +88,7 @@ __export(index_exports, {
|
|
|
86
88
|
buildWorkflowDirectory: () => buildWorkflowDirectory,
|
|
87
89
|
canRoute: () => canRoute,
|
|
88
90
|
capableWorkers: () => capableWorkers,
|
|
91
|
+
childIdsOf: () => childIdsOf,
|
|
89
92
|
classifyWaiterToken: () => classifyWaiterToken,
|
|
90
93
|
clearDurableExecutionWrappers: () => clearDurableExecutionWrappers,
|
|
91
94
|
clearTerminalSingletonAdmission: () => clearTerminalSingletonAdmission,
|
|
@@ -114,6 +117,7 @@ __export(index_exports, {
|
|
|
114
117
|
info: () => info,
|
|
115
118
|
isEngineMintedTag: () => isEngineMintedTag,
|
|
116
119
|
isEventToken: () => isEventToken,
|
|
120
|
+
isFailedMember: () => isFailedMember,
|
|
117
121
|
isLegacyDescriptor: () => isLegacyDescriptor,
|
|
118
122
|
isNonEmptyRunScope: () => isNonEmptyRunScope,
|
|
119
123
|
isWorkflowControlFlowSignal: () => isWorkflowControlFlowSignal,
|
|
@@ -128,6 +132,7 @@ __export(index_exports, {
|
|
|
128
132
|
normalizeAttributeRows: () => normalizeAttributeRows,
|
|
129
133
|
normalizeDescriptor: () => normalizeDescriptor,
|
|
130
134
|
observedAnnouncements: () => observedAnnouncements,
|
|
135
|
+
pageFan: () => pageFan,
|
|
131
136
|
parentRunIdOf: () => parentRunIdOf,
|
|
132
137
|
parseDuration: () => parseDuration,
|
|
133
138
|
partitionOfToken: () => partitionOfToken,
|
|
@@ -157,6 +162,8 @@ __export(index_exports, {
|
|
|
157
162
|
sub: () => sub,
|
|
158
163
|
subEvent: () => subEvent,
|
|
159
164
|
subProcess: () => subProcess,
|
|
165
|
+
summarizeFan: () => summarizeFan,
|
|
166
|
+
summarizeTimeline: () => summarizeTimeline,
|
|
160
167
|
tenantGroup: () => tenantGroup,
|
|
161
168
|
useDurableExecution: () => useDurableExecution,
|
|
162
169
|
warn: () => warn,
|
|
@@ -1246,10 +1253,37 @@ function allChildId(runId, firstSeq, index, wave) {
|
|
|
1246
1253
|
return `${allBase(runId, firstSeq, wave)}${index}`;
|
|
1247
1254
|
}
|
|
1248
1255
|
__name(allChildId, "allChildId");
|
|
1249
|
-
function allGroup(firstSeq, mode) {
|
|
1250
|
-
|
|
1256
|
+
function allGroup(firstSeq, size, mode) {
|
|
1257
|
+
const group = `all:${firstSeq}:n${size}`;
|
|
1258
|
+
return mode === "failFast" ? `${group}:failFast` : group;
|
|
1251
1259
|
}
|
|
1252
1260
|
__name(allGroup, "allGroup");
|
|
1261
|
+
function stepFanGroup(firstSeq, size, mode) {
|
|
1262
|
+
const group = `steps:${firstSeq}:${size}`;
|
|
1263
|
+
return mode === "failFast" ? `${group}:failFast` : group;
|
|
1264
|
+
}
|
|
1265
|
+
__name(stepFanGroup, "stepFanGroup");
|
|
1266
|
+
function parseStepFanGroup(group) {
|
|
1267
|
+
const fan = parseFanGroup(group);
|
|
1268
|
+
if (fan?.kind !== "steps" || fan.size === void 0) return void 0;
|
|
1269
|
+
return {
|
|
1270
|
+
firstSeq: fan.firstSeq,
|
|
1271
|
+
size: fan.size
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
__name(parseStepFanGroup, "parseStepFanGroup");
|
|
1275
|
+
function parseFanGroup(group) {
|
|
1276
|
+
const m = group ? /^(all|steps):(\d+)(?::n?(\d+))?(:failFast)?$/.exec(group) : null;
|
|
1277
|
+
if (!m) return void 0;
|
|
1278
|
+
if (m[1] === "steps" && m[3] === void 0) return void 0;
|
|
1279
|
+
return {
|
|
1280
|
+
kind: m[1],
|
|
1281
|
+
firstSeq: Number(m[2]),
|
|
1282
|
+
size: m[3] === void 0 ? void 0 : Number(m[3]),
|
|
1283
|
+
failFast: m[4] !== void 0
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
__name(parseFanGroup, "parseFanGroup");
|
|
1253
1287
|
function allWait(runId, firstSeq, wave) {
|
|
1254
1288
|
const base = allBase(runId, firstSeq, wave);
|
|
1255
1289
|
return {
|
|
@@ -1299,7 +1333,7 @@ function parentRunIdOf(runId) {
|
|
|
1299
1333
|
return ENGINE_CHILD_ID.exec(runId)?.[1];
|
|
1300
1334
|
}
|
|
1301
1335
|
__name(parentRunIdOf, "parentRunIdOf");
|
|
1302
|
-
var GROUP = /^all:(\d+)(:failFast)?$/;
|
|
1336
|
+
var GROUP = /^all:(\d+)(?::n\d+)?(:failFast)?$/;
|
|
1303
1337
|
var REST = /^(?:w(\d+)\.)?\d+$/;
|
|
1304
1338
|
function fanOfWaiter(waiter) {
|
|
1305
1339
|
const group = waiter.parallelGroup ? GROUP.exec(waiter.parallelGroup) : null;
|
|
@@ -3291,12 +3325,15 @@ function createWorkflowCtx(host, runId, compensations, workflow = "", searchAttr
|
|
|
3291
3325
|
}, "child");
|
|
3292
3326
|
const all = /* @__PURE__ */ __name(async (workflow2, inputs, opts) => {
|
|
3293
3327
|
if (inputs.length === 0) return [];
|
|
3328
|
+
if (stepNameOf(workflow2) !== void 0) {
|
|
3329
|
+
return allSteps(workflow2, inputs, opts);
|
|
3330
|
+
}
|
|
3294
3331
|
const mode = opts?.mode ?? "waitAll";
|
|
3295
3332
|
const name = workflowName(workflow2);
|
|
3296
3333
|
const waves = allWaves(inputs.length, opts?.concurrency);
|
|
3297
3334
|
const positions = inputs.map(() => pos.next());
|
|
3298
3335
|
const firstSeq = positions[0];
|
|
3299
|
-
const group = allGroup(firstSeq, mode);
|
|
3336
|
+
const group = allGroup(firstSeq, inputs.length, mode);
|
|
3300
3337
|
const waveOf = /* @__PURE__ */ __name((i) => waves ? Math.floor(i / waves.waveSize) : void 0, "waveOf");
|
|
3301
3338
|
const id = /* @__PURE__ */ __name((i) => allChildId(runId, firstSeq, i, waveOf(i)), "id");
|
|
3302
3339
|
const { checkpoints: existing, folded } = await readFan(positions, [
|
|
@@ -3430,6 +3467,26 @@ function createWorkflowCtx(host, runId, compensations, workflow = "", searchAttr
|
|
|
3430
3467
|
if (failures.length > 0) throw new GatherError(failures, inputs.length);
|
|
3431
3468
|
return outputs;
|
|
3432
3469
|
}, "all");
|
|
3470
|
+
const allSteps = /* @__PURE__ */ __name(async (ref, inputs, opts) => {
|
|
3471
|
+
if (opts?.queue !== void 0) {
|
|
3472
|
+
throw new Error("ctx.all: a flow-control queue is not supported on a step fan");
|
|
3473
|
+
}
|
|
3474
|
+
const name = stepNameOf(ref);
|
|
3475
|
+
const def = {
|
|
3476
|
+
name,
|
|
3477
|
+
...resolveStepPolicy(stepConfigOf(ref), opts)
|
|
3478
|
+
};
|
|
3479
|
+
const positions = inputs.map(() => pos.next());
|
|
3480
|
+
return host.callRemoteAll(runId, positions, def, inputs, {
|
|
3481
|
+
mode: opts?.mode ?? "waitAll",
|
|
3482
|
+
concurrency: opts?.concurrency,
|
|
3483
|
+
transport: opts?.transport,
|
|
3484
|
+
admission: {
|
|
3485
|
+
priority: opts?.priority,
|
|
3486
|
+
fairnessKey: opts?.fairnessKey
|
|
3487
|
+
}
|
|
3488
|
+
});
|
|
3489
|
+
}, "allSteps");
|
|
3433
3490
|
const readFan = /* @__PURE__ */ __name(async (positions, prefixes) => {
|
|
3434
3491
|
const checkpoints = positions.map((seq) => replay?.get(seq) ?? null);
|
|
3435
3492
|
const folded = positions.map(() => false);
|
|
@@ -3766,6 +3823,18 @@ var BREAKPOINT = "breakpoint";
|
|
|
3766
3823
|
var isBreakpoint = /* @__PURE__ */ __name((cp) => cp.status === "pending" && cp.name.startsWith(BREAKPOINT), "isBreakpoint");
|
|
3767
3824
|
var VERSION_UNDECLARED_TAG = "version:undeclared";
|
|
3768
3825
|
var versionKey = /* @__PURE__ */ __name((name, version) => `${name}@${version}`, "versionKey");
|
|
3826
|
+
var STEP_FAN_CHUNK = 200;
|
|
3827
|
+
function shuffle(items) {
|
|
3828
|
+
for (let i = items.length - 1; i > 0; i -= 1) {
|
|
3829
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
3830
|
+
[items[i], items[j]] = [
|
|
3831
|
+
items[j],
|
|
3832
|
+
items[i]
|
|
3833
|
+
];
|
|
3834
|
+
}
|
|
3835
|
+
return items;
|
|
3836
|
+
}
|
|
3837
|
+
__name(shuffle, "shuffle");
|
|
3769
3838
|
function stepGroup(step, runNamespace) {
|
|
3770
3839
|
return tenantGroup(sanitizeQueueToken(step.name), step.partition ?? runNamespace);
|
|
3771
3840
|
}
|
|
@@ -3807,6 +3876,7 @@ var WorkflowEngine = class {
|
|
|
3807
3876
|
maxRecoveryAttempts;
|
|
3808
3877
|
remoteAdvanceSilenceMs;
|
|
3809
3878
|
reconcileMs;
|
|
3879
|
+
timerBatchSize;
|
|
3810
3880
|
eventBufferTtlMs;
|
|
3811
3881
|
remoteRedispatchMs;
|
|
3812
3882
|
remoteRedispatchMax;
|
|
@@ -3873,6 +3943,15 @@ var WorkflowEngine = class {
|
|
|
3873
3943
|
* dropped one {@link redriveSettledSteps} recovers. Pruned by age (see {@link noteSettledHere}).
|
|
3874
3944
|
*/
|
|
3875
3945
|
settledHere = /* @__PURE__ */ new Map();
|
|
3946
|
+
/**
|
|
3947
|
+
* The step fans (`ctx.all` over a `@Step`) a turn suspended on, by run, while that turn executes on
|
|
3948
|
+
* THIS instance — re-checked once its lease is released (see {@link redriveSettledStepFans}).
|
|
3949
|
+
*/
|
|
3950
|
+
awaitedStepFans = /* @__PURE__ */ new Map();
|
|
3951
|
+
/** Step fans whose join barrier this instance opened, by `runId:firstSeq` — see {@link settledHere}. */
|
|
3952
|
+
stepFansFiredHere = /* @__PURE__ */ new Map();
|
|
3953
|
+
/** The tail of each run's queue of results being handled on this instance — see {@link serializedPerRun}. */
|
|
3954
|
+
resultChains = /* @__PURE__ */ new Map();
|
|
3876
3955
|
/** Flow-control admission backend for remote steps (see {@link registerQueue}). */
|
|
3877
3956
|
admission;
|
|
3878
3957
|
/** Runs on THIS instance blocked on admission, by queue — woken early on a freed-slot signal. */
|
|
@@ -3904,6 +3983,8 @@ var WorkflowEngine = class {
|
|
|
3904
3983
|
this.maxRecoveryAttempts = deps.maxRecoveryAttempts;
|
|
3905
3984
|
this.remoteAdvanceSilenceMs = deps.remoteAdvanceSilenceMs;
|
|
3906
3985
|
this.reconcileMs = deps.reconcileMs === void 0 ? 3e5 : deps.reconcileMs || void 0;
|
|
3986
|
+
const batch = deps.timerBatchSize;
|
|
3987
|
+
this.timerBatchSize = batch !== void 0 && Number.isFinite(batch) && batch >= 1 ? Math.floor(batch) : 500;
|
|
3907
3988
|
this.eventBufferTtlMs = deps.eventBufferTtlMs || void 0;
|
|
3908
3989
|
this.remoteRedispatchMs = deps.remoteRedispatchMs || void 0;
|
|
3909
3990
|
this.remoteRedispatchMax = Math.max(1, deps.remoteRedispatchMax ?? 10);
|
|
@@ -3956,7 +4037,11 @@ var WorkflowEngine = class {
|
|
|
3956
4037
|
}
|
|
3957
4038
|
return;
|
|
3958
4039
|
}
|
|
3959
|
-
await this.completeRemoteResult(result);
|
|
4040
|
+
if (!await this.completeRemoteResult(result)) return;
|
|
4041
|
+
await this.serializedPerRun(result.runId, () => this.resumeImplicit(result.runId).then(() => void 0, (err) => {
|
|
4042
|
+
if (err instanceof NamespaceMismatch) return;
|
|
4043
|
+
throw err;
|
|
4044
|
+
}));
|
|
3960
4045
|
},
|
|
3961
4046
|
// A heartbeat resets the liveness window for whatever it targets: an in-flight long STEP (keyed
|
|
3962
4047
|
// by stepId, see callRemote) or — when stepId is absent — the in-flight workflow TURN (keyed by
|
|
@@ -4816,7 +4901,7 @@ var WorkflowEngine = class {
|
|
|
4816
4901
|
* scan, filtered to just this tick's batch, keeps it cheap regardless of store size.
|
|
4817
4902
|
*/
|
|
4818
4903
|
async resumeDueTimers(nowMs = this.clock()) {
|
|
4819
|
-
const due = await this.store.listDueTimers(nowMs, this.namespace);
|
|
4904
|
+
const due = shuffle(await this.store.listDueTimers(nowMs, this.namespace, this.timerBatchSize));
|
|
4820
4905
|
const blocked = await this.dueBlockedRuns(nowMs);
|
|
4821
4906
|
if (due.length === 0 && blocked.length === 0) return [];
|
|
4822
4907
|
const waiterByRun = indexWaitersByRun(await listSignalWaitersOfRuns(this.store, [
|
|
@@ -5315,6 +5400,32 @@ var WorkflowEngine = class {
|
|
|
5315
5400
|
}
|
|
5316
5401
|
}
|
|
5317
5402
|
}
|
|
5403
|
+
/**
|
|
5404
|
+
* {@link redriveSettledSteps} for a step fan: once the turn that suspended on it released its lease,
|
|
5405
|
+
* re-drive the run if no step of the fan is still `pending` — the last result landed on another
|
|
5406
|
+
* instance while this one held the lease, and its wake was dropped there. A fan whose barrier this
|
|
5407
|
+
* instance opened is skipped, for the reason {@link settledHere} gives.
|
|
5408
|
+
*/
|
|
5409
|
+
async redriveSettledStepFans(runId, fans) {
|
|
5410
|
+
for (const fan of fans) {
|
|
5411
|
+
if (this.stepFansFiredHere.has(`${runId}:${fan.from}`)) continue;
|
|
5412
|
+
const pending = this.store.countCheckpoints ? await this.store.countCheckpoints(runId, fan.from, fan.to, [
|
|
5413
|
+
"pending"
|
|
5414
|
+
]) : (await this.store.listCheckpoints(runId)).filter((c) => c.seq >= fan.from && c.seq <= fan.to && c.status === "pending").length;
|
|
5415
|
+
if (pending > 0) continue;
|
|
5416
|
+
const nowMs = this.clock();
|
|
5417
|
+
if (!await this.store.tryLockRun(runId, this.instanceId, nowMs + this.leaseMs, nowMs)) {
|
|
5418
|
+
return;
|
|
5419
|
+
}
|
|
5420
|
+
const run = await this.store.getRun(runId);
|
|
5421
|
+
if (run?.status !== "suspended") {
|
|
5422
|
+
await this.store.releaseRunLock(runId);
|
|
5423
|
+
return;
|
|
5424
|
+
}
|
|
5425
|
+
await this.resumeImplicit(runId);
|
|
5426
|
+
return;
|
|
5427
|
+
}
|
|
5428
|
+
}
|
|
5318
5429
|
async redriveSettledChildren(runId, fan) {
|
|
5319
5430
|
if (!this.store.hasSignalWaiter) return;
|
|
5320
5431
|
for (const wait of fan.waits) {
|
|
@@ -6772,6 +6883,8 @@ var WorkflowEngine = class {
|
|
|
6772
6883
|
let suspendedOnSteps = false;
|
|
6773
6884
|
const awaitedSteps = /* @__PURE__ */ new Set();
|
|
6774
6885
|
this.awaitedRemoteSteps.set(run.id, awaitedSteps);
|
|
6886
|
+
const awaitedFans = [];
|
|
6887
|
+
this.awaitedStepFans.set(run.id, awaitedFans);
|
|
6775
6888
|
const ctx = createWorkflowCtx(this.ctxHostFor(replay, run.namespace), run.id, compensations, run.workflow, registered?.searchAttributesSchema);
|
|
6776
6889
|
try {
|
|
6777
6890
|
const output = await runInWorkflowCtx(ctx, () => fn(ctx, run.input));
|
|
@@ -6851,6 +6964,7 @@ var WorkflowEngine = class {
|
|
|
6851
6964
|
if (this.awaitedRemoteSteps.get(run.id) === awaitedSteps) {
|
|
6852
6965
|
this.awaitedRemoteSteps.delete(run.id);
|
|
6853
6966
|
}
|
|
6967
|
+
if (this.awaitedStepFans.get(run.id) === awaitedFans) this.awaitedStepFans.delete(run.id);
|
|
6854
6968
|
await this.store.releaseRunLock(run.id);
|
|
6855
6969
|
if (suspendedOnFan) {
|
|
6856
6970
|
void this.redriveSettledChildren(run.id, suspendedOnFan).catch(() => void 0);
|
|
@@ -6858,6 +6972,9 @@ var WorkflowEngine = class {
|
|
|
6858
6972
|
if (suspendedOnSteps && awaitedSteps.size > 0) {
|
|
6859
6973
|
void this.redriveSettledSteps(run.id, awaitedSteps).catch(() => void 0);
|
|
6860
6974
|
}
|
|
6975
|
+
if (suspendedOnSteps && awaitedFans.length > 0) {
|
|
6976
|
+
void this.redriveSettledStepFans(run.id, awaitedFans).catch(() => void 0);
|
|
6977
|
+
}
|
|
6861
6978
|
}
|
|
6862
6979
|
}
|
|
6863
6980
|
/**
|
|
@@ -7080,6 +7197,9 @@ var WorkflowEngine = class {
|
|
|
7080
7197
|
callRemote: /* @__PURE__ */ __name((runId, seq, step, input, queue, transport, admission) => this.callRemote(runId, seq, step, input, queue, transport, replay, admission, {
|
|
7081
7198
|
namespace: parentNamespace
|
|
7082
7199
|
}), "callRemote"),
|
|
7200
|
+
callRemoteAll: /* @__PURE__ */ __name((runId, positions, step, inputs, opts) => this.callRemoteAll(runId, positions, step, inputs, opts, {
|
|
7201
|
+
namespace: parentNamespace
|
|
7202
|
+
}), "callRemoteAll"),
|
|
7083
7203
|
// Defer so a fast child can't reentrantly resume a still-running parent. Stamp the child with
|
|
7084
7204
|
// the PARENT run's namespace (not this engine's) so a child belongs to the tenant/partition of
|
|
7085
7205
|
// the run it was spawned from — even when an operator (namespace: undefined, drives every
|
|
@@ -7381,6 +7501,9 @@ var WorkflowEngine = class {
|
|
|
7381
7501
|
input,
|
|
7382
7502
|
attempts: attempt,
|
|
7383
7503
|
workerGroup: group,
|
|
7504
|
+
...routing?.parallelGroup !== void 0 ? {
|
|
7505
|
+
parallelGroup: routing.parallelGroup
|
|
7506
|
+
} : {},
|
|
7384
7507
|
enqueuedAt,
|
|
7385
7508
|
startedAt: enqueuedAt,
|
|
7386
7509
|
finishedAt: enqueuedAt
|
|
@@ -7406,13 +7529,147 @@ var WorkflowEngine = class {
|
|
|
7406
7529
|
this.awaitedRemoteSteps.get(runId)?.add(seq);
|
|
7407
7530
|
throw new WorkflowSuspended();
|
|
7408
7531
|
}
|
|
7532
|
+
/**
|
|
7533
|
+
* `ctx.all` over a `@Step`: one durable step per input, dispatched together, joined once. The ctx
|
|
7534
|
+
* reserves the whole position block up front, so replay re-derives the same seqs.
|
|
7535
|
+
*
|
|
7536
|
+
* Each turn reads the fan's checkpoints fresh, hands every step that already has one to
|
|
7537
|
+
* {@link callRemote} (which owns the completed / pending-lease / failed-retry rules), and sends
|
|
7538
|
+
* the steps nobody has sent yet: all of them, or with `concurrency`, the next wave once the last
|
|
7539
|
+
* one has drained. New steps are written `pending` BEFORE any is dispatched, so a turn that runs
|
|
7540
|
+
* concurrently with this one finds them already sent instead of sending them again. The join
|
|
7541
|
+
* barrier ({@link stepFanStillRunning}) then wakes the parent once per wave, not once per result.
|
|
7542
|
+
*/
|
|
7543
|
+
async callRemoteAll(runId, positions, step, inputs, opts, routing) {
|
|
7544
|
+
if (step.timeoutMs) {
|
|
7545
|
+
throw new Error(`ctx.all: step "${step.name}" has a liveness timeoutMs; a step fan needs durable steps`);
|
|
7546
|
+
}
|
|
7547
|
+
if (opts.concurrency !== void 0 && (!Number.isInteger(opts.concurrency) || opts.concurrency < 1)) {
|
|
7548
|
+
throw new Error(`ctx.all: concurrency must be a positive integer, got ${opts.concurrency}`);
|
|
7549
|
+
}
|
|
7550
|
+
if (this.pool.size === 0) throw new Error("remote steps require a Transport");
|
|
7551
|
+
const first = positions[0];
|
|
7552
|
+
const last = positions[positions.length - 1];
|
|
7553
|
+
const group = stepFanGroup(first, positions.length, opts.mode);
|
|
7554
|
+
const bySeq = /* @__PURE__ */ new Map();
|
|
7555
|
+
for (const cp of await this.store.listCheckpoints(runId)) {
|
|
7556
|
+
if (cp.seq >= first && cp.seq <= last) bySeq.set(cp.seq, cp);
|
|
7557
|
+
}
|
|
7558
|
+
const outputs = new Array(inputs.length);
|
|
7559
|
+
const failures = [];
|
|
7560
|
+
const unsent = [];
|
|
7561
|
+
let inFlight = 0;
|
|
7562
|
+
let wakeAt;
|
|
7563
|
+
for (let i = 0; i < inputs.length; i += 1) {
|
|
7564
|
+
const seq = positions[i];
|
|
7565
|
+
const cp = bySeq.get(seq);
|
|
7566
|
+
if (!cp) {
|
|
7567
|
+
unsent.push(i);
|
|
7568
|
+
continue;
|
|
7569
|
+
}
|
|
7570
|
+
if (cp.name !== step.name) throw new NonDeterminismError(runId, seq, step.name, cp.name);
|
|
7571
|
+
if (cp.status === "completed") {
|
|
7572
|
+
outputs[i] = cp.output;
|
|
7573
|
+
continue;
|
|
7574
|
+
}
|
|
7575
|
+
try {
|
|
7576
|
+
outputs[i] = await this.callRemote(runId, seq, step, inputs[i], void 0, opts.transport, void 0, opts.admission, {
|
|
7577
|
+
...routing,
|
|
7578
|
+
parallelGroup: group
|
|
7579
|
+
});
|
|
7580
|
+
} catch (err) {
|
|
7581
|
+
if (err instanceof WorkflowSuspended) {
|
|
7582
|
+
inFlight += 1;
|
|
7583
|
+
if (err.wakeAt !== void 0) wakeAt = Math.min(wakeAt ?? err.wakeAt, err.wakeAt);
|
|
7584
|
+
} else if (err instanceof RemoteStepError) {
|
|
7585
|
+
const failure = {
|
|
7586
|
+
index: i,
|
|
7587
|
+
id: stepId(runId, seq),
|
|
7588
|
+
error: err.message
|
|
7589
|
+
};
|
|
7590
|
+
if (opts.mode === "failFast") throw new GatherError([
|
|
7591
|
+
failure
|
|
7592
|
+
], inputs.length);
|
|
7593
|
+
failures.push(failure);
|
|
7594
|
+
} else {
|
|
7595
|
+
throw err;
|
|
7596
|
+
}
|
|
7597
|
+
} finally {
|
|
7598
|
+
this.awaitedRemoteSteps.get(runId)?.delete(seq);
|
|
7599
|
+
}
|
|
7600
|
+
}
|
|
7601
|
+
const batch = inFlight > 0 ? [] : opts.concurrency === void 0 ? unsent : unsent.slice(0, opts.concurrency);
|
|
7602
|
+
if (batch.length > 0) await this.sendStepFan(runId, positions, step, inputs, batch, group, opts, routing);
|
|
7603
|
+
if (inFlight + batch.length > 0) {
|
|
7604
|
+
this.awaitedStepFans.get(runId)?.push({
|
|
7605
|
+
from: first,
|
|
7606
|
+
to: last
|
|
7607
|
+
});
|
|
7608
|
+
throw new WorkflowSuspended(wakeAt);
|
|
7609
|
+
}
|
|
7610
|
+
if (failures.length > 0) throw new GatherError(failures, inputs.length);
|
|
7611
|
+
return outputs;
|
|
7612
|
+
}
|
|
7613
|
+
/** Write the `pending` checkpoints of a step fan's new steps, then dispatch them. */
|
|
7614
|
+
async sendStepFan(runId, positions, step, inputs, batch, group, opts, routing) {
|
|
7615
|
+
const workerGroup = stepGroup(step, routing?.namespace);
|
|
7616
|
+
await this.ensureRoutable(workerGroup, step.requires);
|
|
7617
|
+
const enqueuedAt = /* @__PURE__ */ new Date();
|
|
7618
|
+
for (let at = 0; at < batch.length; at += STEP_FAN_CHUNK) {
|
|
7619
|
+
await Promise.all(batch.slice(at, at + STEP_FAN_CHUNK).map((i) => {
|
|
7620
|
+
const seq = positions[i];
|
|
7621
|
+
return this.store.saveCheckpoint({
|
|
7622
|
+
runId,
|
|
7623
|
+
seq,
|
|
7624
|
+
name: step.name,
|
|
7625
|
+
kind: "remote",
|
|
7626
|
+
stepId: stepId(runId, seq),
|
|
7627
|
+
status: "pending",
|
|
7628
|
+
input: inputs[i],
|
|
7629
|
+
attempts: 1,
|
|
7630
|
+
workerGroup,
|
|
7631
|
+
parallelGroup: group,
|
|
7632
|
+
enqueuedAt,
|
|
7633
|
+
startedAt: enqueuedAt,
|
|
7634
|
+
finishedAt: enqueuedAt
|
|
7635
|
+
});
|
|
7636
|
+
}));
|
|
7637
|
+
}
|
|
7638
|
+
for (let at = 0; at < batch.length; at += STEP_FAN_CHUNK) {
|
|
7639
|
+
await Promise.all(batch.slice(at, at + STEP_FAN_CHUNK).map(async (i) => {
|
|
7640
|
+
const seq = positions[i];
|
|
7641
|
+
await this.dispatchRemoteTask({
|
|
7642
|
+
runId,
|
|
7643
|
+
seq,
|
|
7644
|
+
name: step.name,
|
|
7645
|
+
stepId: stepId(runId, seq),
|
|
7646
|
+
group: workerGroup,
|
|
7647
|
+
input: inputs[i],
|
|
7648
|
+
priority: opts.admission?.priority,
|
|
7649
|
+
attempt: 1,
|
|
7650
|
+
transport: opts.transport
|
|
7651
|
+
});
|
|
7652
|
+
this.emit({
|
|
7653
|
+
type: "step.started",
|
|
7654
|
+
runId,
|
|
7655
|
+
seq,
|
|
7656
|
+
name: step.name,
|
|
7657
|
+
kind: "remote"
|
|
7658
|
+
});
|
|
7659
|
+
}));
|
|
7660
|
+
}
|
|
7661
|
+
}
|
|
7409
7662
|
/** Remember a step settled here, forgetting entries older than a lease so the map stays small. */
|
|
7410
7663
|
noteSettledHere(key) {
|
|
7664
|
+
this.noteRecent(this.settledHere, key);
|
|
7665
|
+
}
|
|
7666
|
+
/** Record `key` in a "happened here recently" map, pruning entries older than a lease. */
|
|
7667
|
+
noteRecent(map, key) {
|
|
7411
7668
|
const now = this.clock();
|
|
7412
|
-
|
|
7413
|
-
if (
|
|
7414
|
-
for (const [k, at] of
|
|
7415
|
-
if (now - at > this.leaseMs)
|
|
7669
|
+
map.set(key, now);
|
|
7670
|
+
if (map.size < 1024) return;
|
|
7671
|
+
for (const [k, at] of map) {
|
|
7672
|
+
if (now - at > this.leaseMs) map.delete(k);
|
|
7416
7673
|
}
|
|
7417
7674
|
}
|
|
7418
7675
|
/** {@link StateStore.saveCheckpointIfPending}, or a plain save on a store without it. */
|
|
@@ -7439,16 +7696,33 @@ var WorkflowEngine = class {
|
|
|
7439
7696
|
}, task.transport);
|
|
7440
7697
|
}
|
|
7441
7698
|
/**
|
|
7442
|
-
*
|
|
7443
|
-
*
|
|
7444
|
-
*
|
|
7699
|
+
* Run `work` after every earlier `work` for the same run on this instance has settled. A result
|
|
7700
|
+
* resumes its run inline, and `execute` lets this instance into a lease it already holds — so two
|
|
7701
|
+
* results of one run handled at once here would run two turns of it concurrently. Results of
|
|
7702
|
+
* different runs still go in parallel, which is what a results consumer with concurrency > 1 is for.
|
|
7703
|
+
*/
|
|
7704
|
+
serializedPerRun(runId, work) {
|
|
7705
|
+
const previous = this.resultChains.get(runId) ?? Promise.resolve();
|
|
7706
|
+
const next = previous.then(work, work);
|
|
7707
|
+
const tail = next.catch(() => void 0);
|
|
7708
|
+
this.resultChains.set(runId, tail);
|
|
7709
|
+
void tail.then(() => {
|
|
7710
|
+
if (this.resultChains.get(runId) === tail) this.resultChains.delete(runId);
|
|
7711
|
+
});
|
|
7712
|
+
return next;
|
|
7713
|
+
}
|
|
7714
|
+
/**
|
|
7715
|
+
* Complete a durable remote step from its worker result — runs on whichever instance receives the
|
|
7716
|
+
* result (the dispatching one may be gone), so the run is crash/scale-safe. Resolves whether the
|
|
7717
|
+
* run should now be resumed: not for a duplicate or late delivery (the checkpoint isn't `pending`),
|
|
7718
|
+
* a run already finished, or a step fan whose barrier is still closed.
|
|
7445
7719
|
*/
|
|
7446
7720
|
async completeRemoteResult(result) {
|
|
7447
7721
|
const cp = await this.store.getCheckpoint(result.runId, result.seq);
|
|
7448
|
-
if (!cp || cp.status !== "pending") return;
|
|
7722
|
+
if (!cp || cp.status !== "pending") return false;
|
|
7449
7723
|
void this.releaseQueueSlot(cp.stepId).catch(() => void 0);
|
|
7450
7724
|
const run = await this.store.getRun(result.runId);
|
|
7451
|
-
if (run && (run.status === "cancelled" || run.status === "completed")) return;
|
|
7725
|
+
if (run && (run.status === "cancelled" || run.status === "completed")) return false;
|
|
7452
7726
|
const finishedAt = /* @__PURE__ */ new Date();
|
|
7453
7727
|
const startedAt = result.startedAt ? new Date(result.startedAt) : cp.startedAt;
|
|
7454
7728
|
const claimed = await this.savePendingCheckpoint({
|
|
@@ -7460,7 +7734,7 @@ var WorkflowEngine = class {
|
|
|
7460
7734
|
startedAt,
|
|
7461
7735
|
finishedAt
|
|
7462
7736
|
});
|
|
7463
|
-
if (!claimed) return;
|
|
7737
|
+
if (!claimed) return false;
|
|
7464
7738
|
this.noteSettledHere(`${result.runId}:${result.seq}`);
|
|
7465
7739
|
this.emit({
|
|
7466
7740
|
type: result.status === "completed" ? "step.completed" : "step.failed",
|
|
@@ -7473,10 +7747,25 @@ var WorkflowEngine = class {
|
|
|
7473
7747
|
queueMs: startedAt.getTime() - cp.enqueuedAt.getTime(),
|
|
7474
7748
|
durationMs: finishedAt.getTime() - startedAt.getTime()
|
|
7475
7749
|
});
|
|
7476
|
-
await this.
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7750
|
+
return !await this.stepFanStillRunning(cp, result);
|
|
7751
|
+
}
|
|
7752
|
+
/**
|
|
7753
|
+
* The join barrier of a step fan: a result for one of its steps resumes the parent only once no
|
|
7754
|
+
* step of the fan is still `pending` (a settled wave), or on a failure (failFast surfaces it, and a
|
|
7755
|
+
* retry needs the parent to schedule it). Without it every result would replay the whole parent,
|
|
7756
|
+
* which makes a fan of N steps cost O(N²) checkpoint reads.
|
|
7757
|
+
*/
|
|
7758
|
+
async stepFanStillRunning(cp, result) {
|
|
7759
|
+
const fan = parseStepFanGroup(cp.parallelGroup);
|
|
7760
|
+
if (!fan) return false;
|
|
7761
|
+
if (result.status === "failed") return false;
|
|
7762
|
+
const to = fan.firstSeq + fan.size - 1;
|
|
7763
|
+
const pending = this.store.countCheckpoints ? await this.store.countCheckpoints(result.runId, fan.firstSeq, to, [
|
|
7764
|
+
"pending"
|
|
7765
|
+
]) : (await this.store.listCheckpoints(result.runId)).filter((c) => c.seq >= fan.firstSeq && c.seq <= to && c.status === "pending").length;
|
|
7766
|
+
if (pending > 0) return true;
|
|
7767
|
+
this.noteRecent(this.stepFansFiredHere, `${result.runId}:${fan.firstSeq}`);
|
|
7768
|
+
return false;
|
|
7480
7769
|
}
|
|
7481
7770
|
/**
|
|
7482
7771
|
* Apply a remote workflow-turn {@link WorkflowDecision} durably — runs on WHATEVER instance receives
|
|
@@ -7829,6 +8118,110 @@ var RunGateway = class {
|
|
|
7829
8118
|
}
|
|
7830
8119
|
};
|
|
7831
8120
|
|
|
8121
|
+
// src/run-detail-summary.ts
|
|
8122
|
+
var FAN_SUMMARY_FAILURES = 20;
|
|
8123
|
+
var SUMMARY_CHILD_LIMIT = 200;
|
|
8124
|
+
var FAN_PAGE_MAX = 500;
|
|
8125
|
+
function foldedCount(cp) {
|
|
8126
|
+
if (!cp.name.startsWith(FOLDED_PREFIX)) return void 0;
|
|
8127
|
+
const values = cp.output?.values;
|
|
8128
|
+
return Array.isArray(values) ? values.length : 0;
|
|
8129
|
+
}
|
|
8130
|
+
__name(foldedCount, "foldedCount");
|
|
8131
|
+
function isFailedMember(cp) {
|
|
8132
|
+
if (cp.status === "failed") return true;
|
|
8133
|
+
if (!cp.name.startsWith("signal:child:") || cp.status !== "completed") return false;
|
|
8134
|
+
return cp.output?.ok === false;
|
|
8135
|
+
}
|
|
8136
|
+
__name(isFailedMember, "isFailedMember");
|
|
8137
|
+
function fanLabel(members) {
|
|
8138
|
+
if (members.some((cp) => cp.name.startsWith("signal:child:") || foldedCount(cp) !== void 0)) {
|
|
8139
|
+
return "child runs";
|
|
8140
|
+
}
|
|
8141
|
+
const first = members[0]?.name ?? "";
|
|
8142
|
+
return members.every((cp) => cp.name === first) ? first : "steps";
|
|
8143
|
+
}
|
|
8144
|
+
__name(fanLabel, "fanLabel");
|
|
8145
|
+
function summarizeFan(group, members) {
|
|
8146
|
+
const counts = {};
|
|
8147
|
+
const failures = [];
|
|
8148
|
+
let size = 0;
|
|
8149
|
+
let startedAt;
|
|
8150
|
+
let finishedAt;
|
|
8151
|
+
let firstSeq = Number.POSITIVE_INFINITY;
|
|
8152
|
+
let lastSeq = Number.NEGATIVE_INFINITY;
|
|
8153
|
+
for (const cp of members) {
|
|
8154
|
+
firstSeq = Math.min(firstSeq, cp.seq);
|
|
8155
|
+
lastSeq = Math.max(lastSeq, cp.seq);
|
|
8156
|
+
const folded = foldedCount(cp);
|
|
8157
|
+
const n = folded ?? 1;
|
|
8158
|
+
size += n;
|
|
8159
|
+
const status = isFailedMember(cp) ? "failed" : cp.status;
|
|
8160
|
+
counts[status] = (counts[status] ?? 0) + n;
|
|
8161
|
+
if (status === "failed" && failures.length < FAN_SUMMARY_FAILURES) failures.push(cp);
|
|
8162
|
+
if (cp.status !== "pending" && cp.status !== "running") {
|
|
8163
|
+
if (!startedAt || cp.startedAt < startedAt) startedAt = cp.startedAt;
|
|
8164
|
+
if (!finishedAt || cp.finishedAt > finishedAt) finishedAt = cp.finishedAt;
|
|
8165
|
+
} else if (!startedAt || cp.enqueuedAt < startedAt) {
|
|
8166
|
+
startedAt = cp.enqueuedAt;
|
|
8167
|
+
}
|
|
8168
|
+
}
|
|
8169
|
+
const parsed = parseFanGroup(group);
|
|
8170
|
+
const total = parsed?.size;
|
|
8171
|
+
return {
|
|
8172
|
+
group,
|
|
8173
|
+
label: fanLabel(members),
|
|
8174
|
+
firstSeq,
|
|
8175
|
+
lastSeq,
|
|
8176
|
+
size,
|
|
8177
|
+
total,
|
|
8178
|
+
notStarted: total === void 0 ? void 0 : Math.max(0, total - size),
|
|
8179
|
+
failFast: parsed?.failFast ?? false,
|
|
8180
|
+
counts,
|
|
8181
|
+
startedAt,
|
|
8182
|
+
finishedAt,
|
|
8183
|
+
failures
|
|
8184
|
+
};
|
|
8185
|
+
}
|
|
8186
|
+
__name(summarizeFan, "summarizeFan");
|
|
8187
|
+
function summarizeTimeline(timeline, over) {
|
|
8188
|
+
const byGroup = /* @__PURE__ */ new Map();
|
|
8189
|
+
for (const cp of timeline) {
|
|
8190
|
+
if (cp.parallelGroup === void 0) continue;
|
|
8191
|
+
const members = byGroup.get(cp.parallelGroup);
|
|
8192
|
+
if (members) members.push(cp);
|
|
8193
|
+
else byGroup.set(cp.parallelGroup, [
|
|
8194
|
+
cp
|
|
8195
|
+
]);
|
|
8196
|
+
}
|
|
8197
|
+
const summarized = /* @__PURE__ */ new Set();
|
|
8198
|
+
const fans = [];
|
|
8199
|
+
for (const [group, members] of byGroup) {
|
|
8200
|
+
if (members.length <= over && (parseFanGroup(group)?.size ?? 0) <= over) continue;
|
|
8201
|
+
summarized.add(group);
|
|
8202
|
+
fans.push(summarizeFan(group, members));
|
|
8203
|
+
}
|
|
8204
|
+
if (fans.length === 0) return {
|
|
8205
|
+
timeline,
|
|
8206
|
+
fans
|
|
8207
|
+
};
|
|
8208
|
+
return {
|
|
8209
|
+
timeline: timeline.filter((cp) => cp.parallelGroup === void 0 || !summarized.has(cp.parallelGroup)),
|
|
8210
|
+
fans: fans.sort((a, b) => a.firstSeq - b.firstSeq)
|
|
8211
|
+
};
|
|
8212
|
+
}
|
|
8213
|
+
__name(summarizeTimeline, "summarizeTimeline");
|
|
8214
|
+
function pageFan(timeline, group, query) {
|
|
8215
|
+
const matching = timeline.filter((cp) => cp.parallelGroup === group && (!query.failedOnly || isFailedMember(cp)));
|
|
8216
|
+
const offset = query.offset !== void 0 && Number.isFinite(query.offset) ? Math.max(0, Math.floor(query.offset)) : 0;
|
|
8217
|
+
const limit = query.limit !== void 0 && Number.isFinite(query.limit) ? Math.min(FAN_PAGE_MAX, Math.max(1, Math.floor(query.limit))) : 100;
|
|
8218
|
+
return {
|
|
8219
|
+
items: matching.slice(offset, offset + limit),
|
|
8220
|
+
total: matching.length
|
|
8221
|
+
};
|
|
8222
|
+
}
|
|
8223
|
+
__name(pageFan, "pageFan");
|
|
8224
|
+
|
|
7832
8225
|
// src/codec-state-store.ts
|
|
7833
8226
|
var CodecStateStore = class {
|
|
7834
8227
|
static {
|
|
@@ -7857,6 +8250,8 @@ var CodecStateStore = class {
|
|
|
7857
8250
|
/** Encodes like {@link saveCheckpoint}. Bound only when the inner store has it, so the engine's
|
|
7858
8251
|
* plain-save fallback still kicks in through the wrapper. */
|
|
7859
8252
|
saveCheckpointIfPending;
|
|
8253
|
+
/** Forwarded verbatim — a count reads no payload. Bound only when the inner store has it. */
|
|
8254
|
+
countCheckpoints;
|
|
7860
8255
|
/** Forwarded verbatim — retention selects by status/updatedAt/scope, never by payload. Bound only
|
|
7861
8256
|
* when the inner store prunes, so the retention poller still sees (and warns about) its absence. */
|
|
7862
8257
|
pruneTerminalRuns;
|
|
@@ -7886,6 +8281,8 @@ var CodecStateStore = class {
|
|
|
7886
8281
|
if (deleteRuns) this.deleteRuns = (ids) => deleteRuns.call(inner, ids);
|
|
7887
8282
|
const saveIfPending = inner.saveCheckpointIfPending;
|
|
7888
8283
|
if (saveIfPending) this.saveCheckpointIfPending = (cp) => saveIfPending.call(inner, this.encCp(cp));
|
|
8284
|
+
const countCps = inner.countCheckpoints;
|
|
8285
|
+
if (countCps) this.countCheckpoints = (runId, from, to, statuses) => countCps.call(inner, runId, from, to, statuses);
|
|
7889
8286
|
const prune = inner.pruneTerminalRuns;
|
|
7890
8287
|
if (prune) this.pruneTerminalRuns = (policy, now, limit) => prune.call(inner, policy, now, limit);
|
|
7891
8288
|
const count = inner.countRuns;
|
|
@@ -8016,8 +8413,8 @@ var CodecStateStore = class {
|
|
|
8016
8413
|
async listPendingRuns(limit, namespace) {
|
|
8017
8414
|
return (await this.inner.listPendingRuns(limit, namespace)).map((r) => this.decRun(r));
|
|
8018
8415
|
}
|
|
8019
|
-
async listDueTimers(nowMs, namespace) {
|
|
8020
|
-
return (await this.inner.listDueTimers(nowMs, namespace)).map((r) => this.decRun(r));
|
|
8416
|
+
async listDueTimers(nowMs, namespace, limit) {
|
|
8417
|
+
return (await this.inner.listDueTimers(nowMs, namespace, limit)).map((r) => this.decRun(r));
|
|
8021
8418
|
}
|
|
8022
8419
|
tryLockRun(runId, owner, leaseUntilMs, nowMs) {
|
|
8023
8420
|
return this.inner.tryLockRun(runId, owner, leaseUntilMs, nowMs);
|
|
@@ -8471,10 +8868,11 @@ var InMemoryStateStore = class {
|
|
|
8471
8868
|
...r
|
|
8472
8869
|
}));
|
|
8473
8870
|
}
|
|
8474
|
-
async listDueTimers(nowMs, namespace) {
|
|
8475
|
-
|
|
8871
|
+
async listDueTimers(nowMs, namespace, limit) {
|
|
8872
|
+
const due = [
|
|
8476
8873
|
...this.runs.values()
|
|
8477
|
-
].filter((r) => r.status === "suspended" && r.wakeAt !== void 0 && r.wakeAt <= nowMs && (namespace === void 0 || r.namespace === namespace)).
|
|
8874
|
+
].filter((r) => r.status === "suspended" && r.wakeAt !== void 0 && r.wakeAt <= nowMs && (namespace === void 0 || r.namespace === namespace)).sort((a, b) => (a.wakeAt ?? 0) - (b.wakeAt ?? 0));
|
|
8875
|
+
return (limit === void 0 ? due : due.slice(0, limit)).map((r) => ({
|
|
8478
8876
|
...r
|
|
8479
8877
|
}));
|
|
8480
8878
|
}
|
|
@@ -8748,6 +9146,13 @@ var InMemoryStateStore = class {
|
|
|
8748
9146
|
...latest
|
|
8749
9147
|
} : void 0;
|
|
8750
9148
|
}
|
|
9149
|
+
async countCheckpoints(runId, fromSeq, toSeq, statuses) {
|
|
9150
|
+
let n = 0;
|
|
9151
|
+
for (const cp of this.checkpoints.values()) {
|
|
9152
|
+
if (cp.runId === runId && cp.seq >= fromSeq && cp.seq <= toSeq && statuses.includes(cp.status)) n += 1;
|
|
9153
|
+
}
|
|
9154
|
+
return n;
|
|
9155
|
+
}
|
|
8751
9156
|
async listCheckpointsByNamePrefix(runId, prefixes) {
|
|
8752
9157
|
const rows = [
|
|
8753
9158
|
...this.checkpoints.values()
|
|
@@ -8823,6 +9228,7 @@ var InMemoryTransport = class {
|
|
|
8823
9228
|
EVENT_TOKEN_PREFIX,
|
|
8824
9229
|
Entities,
|
|
8825
9230
|
EventAccumulators,
|
|
9231
|
+
FAN_SUMMARY_FAILURES,
|
|
8826
9232
|
FatalError,
|
|
8827
9233
|
GatherError,
|
|
8828
9234
|
InMemoryAdmissionBackend,
|
|
@@ -8844,6 +9250,7 @@ var InMemoryTransport = class {
|
|
|
8844
9250
|
SINGLETON_ADMITTED_TAG,
|
|
8845
9251
|
STATE_STORE,
|
|
8846
9252
|
STATE_STORE_CANONICAL,
|
|
9253
|
+
SUMMARY_CHILD_LIMIT,
|
|
8847
9254
|
ScheduleAlreadyExistsError,
|
|
8848
9255
|
ScheduleClient,
|
|
8849
9256
|
ScheduleNotFoundError,
|
|
@@ -8870,6 +9277,7 @@ var InMemoryTransport = class {
|
|
|
8870
9277
|
buildWorkflowDirectory,
|
|
8871
9278
|
canRoute,
|
|
8872
9279
|
capableWorkers,
|
|
9280
|
+
childIdsOf,
|
|
8873
9281
|
classifyWaiterToken,
|
|
8874
9282
|
clearDurableExecutionWrappers,
|
|
8875
9283
|
clearTerminalSingletonAdmission,
|
|
@@ -8898,6 +9306,7 @@ var InMemoryTransport = class {
|
|
|
8898
9306
|
info,
|
|
8899
9307
|
isEngineMintedTag,
|
|
8900
9308
|
isEventToken,
|
|
9309
|
+
isFailedMember,
|
|
8901
9310
|
isLegacyDescriptor,
|
|
8902
9311
|
isNonEmptyRunScope,
|
|
8903
9312
|
isWorkflowControlFlowSignal,
|
|
@@ -8912,6 +9321,7 @@ var InMemoryTransport = class {
|
|
|
8912
9321
|
normalizeAttributeRows,
|
|
8913
9322
|
normalizeDescriptor,
|
|
8914
9323
|
observedAnnouncements,
|
|
9324
|
+
pageFan,
|
|
8915
9325
|
parentRunIdOf,
|
|
8916
9326
|
parseDuration,
|
|
8917
9327
|
partitionOfToken,
|
|
@@ -8941,6 +9351,8 @@ var InMemoryTransport = class {
|
|
|
8941
9351
|
sub,
|
|
8942
9352
|
subEvent,
|
|
8943
9353
|
subProcess,
|
|
9354
|
+
summarizeFan,
|
|
9355
|
+
summarizeTimeline,
|
|
8944
9356
|
tenantGroup,
|
|
8945
9357
|
useDurableExecution,
|
|
8946
9358
|
warn,
|