@dudousxd/nestjs-durable-core 0.77.0 → 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 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,8 +1253,9 @@ 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
- return mode === "failFast" ? `all:${firstSeq}:failFast` : `all:${firstSeq}`;
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");
1253
1261
  function stepFanGroup(firstSeq, size, mode) {
@@ -1256,14 +1264,26 @@ function stepFanGroup(firstSeq, size, mode) {
1256
1264
  }
1257
1265
  __name(stepFanGroup, "stepFanGroup");
1258
1266
  function parseStepFanGroup(group) {
1259
- const m = group ? /^steps:(\d+):(\d+)(?::failFast)?$/.exec(group) : null;
1260
- if (!m) return void 0;
1267
+ const fan = parseFanGroup(group);
1268
+ if (fan?.kind !== "steps" || fan.size === void 0) return void 0;
1261
1269
  return {
1262
- firstSeq: Number(m[1]),
1263
- size: Number(m[2])
1270
+ firstSeq: fan.firstSeq,
1271
+ size: fan.size
1264
1272
  };
1265
1273
  }
1266
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");
1267
1287
  function allWait(runId, firstSeq, wave) {
1268
1288
  const base = allBase(runId, firstSeq, wave);
1269
1289
  return {
@@ -1313,7 +1333,7 @@ function parentRunIdOf(runId) {
1313
1333
  return ENGINE_CHILD_ID.exec(runId)?.[1];
1314
1334
  }
1315
1335
  __name(parentRunIdOf, "parentRunIdOf");
1316
- var GROUP = /^all:(\d+)(:failFast)?$/;
1336
+ var GROUP = /^all:(\d+)(?::n\d+)?(:failFast)?$/;
1317
1337
  var REST = /^(?:w(\d+)\.)?\d+$/;
1318
1338
  function fanOfWaiter(waiter) {
1319
1339
  const group = waiter.parallelGroup ? GROUP.exec(waiter.parallelGroup) : null;
@@ -3313,7 +3333,7 @@ function createWorkflowCtx(host, runId, compensations, workflow = "", searchAttr
3313
3333
  const waves = allWaves(inputs.length, opts?.concurrency);
3314
3334
  const positions = inputs.map(() => pos.next());
3315
3335
  const firstSeq = positions[0];
3316
- const group = allGroup(firstSeq, mode);
3336
+ const group = allGroup(firstSeq, inputs.length, mode);
3317
3337
  const waveOf = /* @__PURE__ */ __name((i) => waves ? Math.floor(i / waves.waveSize) : void 0, "waveOf");
3318
3338
  const id = /* @__PURE__ */ __name((i) => allChildId(runId, firstSeq, i, waveOf(i)), "id");
3319
3339
  const { checkpoints: existing, folded } = await readFan(positions, [
@@ -8098,6 +8118,110 @@ var RunGateway = class {
8098
8118
  }
8099
8119
  };
8100
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
+
8101
8225
  // src/codec-state-store.ts
8102
8226
  var CodecStateStore = class {
8103
8227
  static {
@@ -9104,6 +9228,7 @@ var InMemoryTransport = class {
9104
9228
  EVENT_TOKEN_PREFIX,
9105
9229
  Entities,
9106
9230
  EventAccumulators,
9231
+ FAN_SUMMARY_FAILURES,
9107
9232
  FatalError,
9108
9233
  GatherError,
9109
9234
  InMemoryAdmissionBackend,
@@ -9125,6 +9250,7 @@ var InMemoryTransport = class {
9125
9250
  SINGLETON_ADMITTED_TAG,
9126
9251
  STATE_STORE,
9127
9252
  STATE_STORE_CANONICAL,
9253
+ SUMMARY_CHILD_LIMIT,
9128
9254
  ScheduleAlreadyExistsError,
9129
9255
  ScheduleClient,
9130
9256
  ScheduleNotFoundError,
@@ -9151,6 +9277,7 @@ var InMemoryTransport = class {
9151
9277
  buildWorkflowDirectory,
9152
9278
  canRoute,
9153
9279
  capableWorkers,
9280
+ childIdsOf,
9154
9281
  classifyWaiterToken,
9155
9282
  clearDurableExecutionWrappers,
9156
9283
  clearTerminalSingletonAdmission,
@@ -9179,6 +9306,7 @@ var InMemoryTransport = class {
9179
9306
  info,
9180
9307
  isEngineMintedTag,
9181
9308
  isEventToken,
9309
+ isFailedMember,
9182
9310
  isLegacyDescriptor,
9183
9311
  isNonEmptyRunScope,
9184
9312
  isWorkflowControlFlowSignal,
@@ -9193,6 +9321,7 @@ var InMemoryTransport = class {
9193
9321
  normalizeAttributeRows,
9194
9322
  normalizeDescriptor,
9195
9323
  observedAnnouncements,
9324
+ pageFan,
9196
9325
  parentRunIdOf,
9197
9326
  parseDuration,
9198
9327
  partitionOfToken,
@@ -9222,6 +9351,8 @@ var InMemoryTransport = class {
9222
9351
  sub,
9223
9352
  subEvent,
9224
9353
  subProcess,
9354
+ summarizeFan,
9355
+ summarizeTimeline,
9225
9356
  tenantGroup,
9226
9357
  useDurableExecution,
9227
9358
  warn,