@dudousxd/nestjs-durable-core 0.65.0 → 0.67.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 +307 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +330 -7
- package/dist/index.d.ts +330 -7
- package/dist/index.js +299 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1185,6 +1185,7 @@ function aggregateAnnouncements(descriptors) {
|
|
|
1185
1185
|
const first = announcements[0];
|
|
1186
1186
|
if (!first) continue;
|
|
1187
1187
|
out.push({
|
|
1188
|
+
evidence: "declared",
|
|
1188
1189
|
key,
|
|
1189
1190
|
name: first.name,
|
|
1190
1191
|
...first.version !== void 0 ? {
|
|
@@ -1205,6 +1206,137 @@ function aggregateAnnouncements(descriptors) {
|
|
|
1205
1206
|
return out.sort((a, b) => a.key.localeCompare(b.key));
|
|
1206
1207
|
}
|
|
1207
1208
|
__name(aggregateAnnouncements, "aggregateAnnouncements");
|
|
1209
|
+
function observedAnnouncements(heartbeats, covered) {
|
|
1210
|
+
const byToken = /* @__PURE__ */ new Map();
|
|
1211
|
+
for (const beat of heartbeats) {
|
|
1212
|
+
if (!beat.group || covered.has(beat.group)) continue;
|
|
1213
|
+
const instances = byToken.get(beat.group);
|
|
1214
|
+
if (instances) instances.add(beat.instanceId);
|
|
1215
|
+
else byToken.set(beat.group, /* @__PURE__ */ new Set([
|
|
1216
|
+
beat.instanceId
|
|
1217
|
+
]));
|
|
1218
|
+
}
|
|
1219
|
+
return [
|
|
1220
|
+
...byToken.entries()
|
|
1221
|
+
].map(([group, instances]) => ({
|
|
1222
|
+
evidence: "observed",
|
|
1223
|
+
key: group,
|
|
1224
|
+
name: group,
|
|
1225
|
+
groups: [
|
|
1226
|
+
group
|
|
1227
|
+
],
|
|
1228
|
+
origins: [],
|
|
1229
|
+
requires: [],
|
|
1230
|
+
runtimes: [],
|
|
1231
|
+
instances: [
|
|
1232
|
+
...instances
|
|
1233
|
+
].sort(),
|
|
1234
|
+
disagreements: []
|
|
1235
|
+
})).sort((a, b) => a.key.localeCompare(b.key));
|
|
1236
|
+
}
|
|
1237
|
+
__name(observedAnnouncements, "observedAnnouncements");
|
|
1238
|
+
function coveredTokens(announced, descriptors, sanitize) {
|
|
1239
|
+
const tokens = /* @__PURE__ */ new Set();
|
|
1240
|
+
for (const entry of announced) {
|
|
1241
|
+
tokens.add(sanitize(entry.name));
|
|
1242
|
+
for (const group of entry.groups) tokens.add(group);
|
|
1243
|
+
}
|
|
1244
|
+
for (const raw of descriptors) {
|
|
1245
|
+
const d = normalizeDescriptor(raw);
|
|
1246
|
+
for (const step of d.steps) {
|
|
1247
|
+
const token = sanitize(step);
|
|
1248
|
+
tokens.add(token);
|
|
1249
|
+
if (d.partition) tokens.add(`${token}@${d.partition}`);
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
return tokens;
|
|
1253
|
+
}
|
|
1254
|
+
__name(coveredTokens, "coveredTokens");
|
|
1255
|
+
|
|
1256
|
+
// src/handshake/directory.ts
|
|
1257
|
+
var DEFAULT_PARTITION = "default";
|
|
1258
|
+
function partitionOfToken(token) {
|
|
1259
|
+
const at = token.lastIndexOf("@");
|
|
1260
|
+
return at === -1 ? DEFAULT_PARTITION : token.slice(at + 1);
|
|
1261
|
+
}
|
|
1262
|
+
__name(partitionOfToken, "partitionOfToken");
|
|
1263
|
+
function buildWorkflowDirectory(input) {
|
|
1264
|
+
const { descriptors, heartbeats, namespace, supported, sanitize } = input;
|
|
1265
|
+
if (!supported) {
|
|
1266
|
+
return {
|
|
1267
|
+
supported: false,
|
|
1268
|
+
workflows: [],
|
|
1269
|
+
otherPartitions: [],
|
|
1270
|
+
detail: "No transport in this process can read what the fleet advertises, so nothing here was asked and this list is empty for that reason alone. Workers may well be running. A workflow can still be called by name."
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
const mine = namespace === void 0 ? void 0 : namespace;
|
|
1274
|
+
const ownDescriptors = mine === void 0 ? descriptors : descriptors.filter((d) => (d.namespace ?? DEFAULT_PARTITION) === mine);
|
|
1275
|
+
const ownBeats = [];
|
|
1276
|
+
const foreign = /* @__PURE__ */ new Map();
|
|
1277
|
+
for (const beat of heartbeats) {
|
|
1278
|
+
if (!beat.group) continue;
|
|
1279
|
+
const partition = partitionOfToken(beat.group);
|
|
1280
|
+
if (mine === void 0 || partition === mine) {
|
|
1281
|
+
ownBeats.push(beat);
|
|
1282
|
+
continue;
|
|
1283
|
+
}
|
|
1284
|
+
const seen = foreign.get(partition);
|
|
1285
|
+
if (seen) {
|
|
1286
|
+
seen.groups.add(beat.group);
|
|
1287
|
+
seen.instances.add(beat.instanceId);
|
|
1288
|
+
} else {
|
|
1289
|
+
foreign.set(partition, {
|
|
1290
|
+
groups: /* @__PURE__ */ new Set([
|
|
1291
|
+
beat.group
|
|
1292
|
+
]),
|
|
1293
|
+
instances: /* @__PURE__ */ new Set([
|
|
1294
|
+
beat.instanceId
|
|
1295
|
+
])
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
const declared = aggregateAnnouncements(ownDescriptors);
|
|
1300
|
+
const observed = observedAnnouncements(ownBeats, coveredTokens(declared, ownDescriptors, sanitize));
|
|
1301
|
+
const workflows = [
|
|
1302
|
+
...declared,
|
|
1303
|
+
...observed
|
|
1304
|
+
].sort((a, b) => a.key.localeCompare(b.key));
|
|
1305
|
+
const otherPartitions = [
|
|
1306
|
+
...foreign.entries()
|
|
1307
|
+
].map(([partition, seen]) => ({
|
|
1308
|
+
partition,
|
|
1309
|
+
groups: [
|
|
1310
|
+
...seen.groups
|
|
1311
|
+
].sort(),
|
|
1312
|
+
instances: [
|
|
1313
|
+
...seen.instances
|
|
1314
|
+
].sort()
|
|
1315
|
+
})).sort((a, b) => a.partition.localeCompare(b.partition));
|
|
1316
|
+
return {
|
|
1317
|
+
supported: true,
|
|
1318
|
+
workflows,
|
|
1319
|
+
otherPartitions,
|
|
1320
|
+
detail: describeDirectory(workflows, otherPartitions, mine)
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1323
|
+
__name(buildWorkflowDirectory, "buildWorkflowDirectory");
|
|
1324
|
+
function summarize(names, limit = 3) {
|
|
1325
|
+
if (names.length <= limit) return names.join(", ");
|
|
1326
|
+
return `${names.slice(0, limit).join(", ")} and ${names.length - limit} more`;
|
|
1327
|
+
}
|
|
1328
|
+
__name(summarize, "summarize");
|
|
1329
|
+
function describeDirectory(workflows, otherPartitions, namespace) {
|
|
1330
|
+
const here = namespace === void 0 ? "this deployment" : `partition "${namespace}"`;
|
|
1331
|
+
const elsewhere = otherPartitions.length === 0 ? "" : ` Live workers were seen on ${otherPartitions.map((p) => `"${p.partition}" (${summarize(p.groups)})`).join(", ")}, which ${here} does not route to \u2014 a worker on the wrong partition looks exactly like no worker at all, so it is named here rather than left out.`;
|
|
1332
|
+
if (workflows.length === 0) {
|
|
1333
|
+
return `The fleet was asked just now and nothing is live in ${here}, so this list is empty because the deployment is empty \u2014 not because the question could not be put.${elsewhere}`;
|
|
1334
|
+
}
|
|
1335
|
+
const observed = workflows.filter((w) => w.evidence === "observed").length;
|
|
1336
|
+
const declaredNote = observed === 0 ? "" : ` ${observed} of them ${observed === 1 ? "is" : "are"} known only from a live queue: the worker serving ${observed === 1 ? "it" : "them"} publishes no description, so ${observed === 1 ? "its" : "their"} version, origin and runtime are genuinely unknown and a version pinned against ${observed === 1 ? "it" : "them"} cannot be checked.`;
|
|
1337
|
+
return `Every workflow a live worker in ${here} can execute, read just now. A worker that stops beating drops off this list within about half a minute.${declaredNote}${elsewhere}`;
|
|
1338
|
+
}
|
|
1339
|
+
__name(describeDirectory, "describeDirectory");
|
|
1208
1340
|
|
|
1209
1341
|
// src/handshake/negotiate.ts
|
|
1210
1342
|
var rangesOverlap = /* @__PURE__ */ __name((a, b) => Math.max(a[0], b[0]) <= Math.min(a[1], b[1]), "rangesOverlap");
|
|
@@ -1756,6 +1888,36 @@ var TransportPool = class {
|
|
|
1756
1888
|
...byInstance.values()
|
|
1757
1889
|
];
|
|
1758
1890
|
}
|
|
1891
|
+
/**
|
|
1892
|
+
* Every live worker heartbeat in the deployment, merged across every transport that can report
|
|
1893
|
+
* them and de-duplicated by `(group, instanceId)` — the same worker is one beat per token, and two
|
|
1894
|
+
* transports scanning the same keyspace must not double-count it.
|
|
1895
|
+
*
|
|
1896
|
+
* Returns `[]` when no transport implements {@link Transport.readAllWorkerHeartbeats}, which is
|
|
1897
|
+
* indistinguishable from "nothing is beating" on its own — {@link introspectsFleet} is what tells
|
|
1898
|
+
* those apart, and the directory reads it rather than guessing from an empty array.
|
|
1899
|
+
*/
|
|
1900
|
+
async readAllWorkerHeartbeats() {
|
|
1901
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1902
|
+
for (const { transport } of this.transports) {
|
|
1903
|
+
if (!transport.readAllWorkerHeartbeats) continue;
|
|
1904
|
+
for (const beat of await transport.readAllWorkerHeartbeats()) {
|
|
1905
|
+
const key = `${beat.group}\0${beat.instanceId}`;
|
|
1906
|
+
if (!seen.has(key)) seen.set(key, beat);
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
return [
|
|
1910
|
+
...seen.values()
|
|
1911
|
+
];
|
|
1912
|
+
}
|
|
1913
|
+
/**
|
|
1914
|
+
* Can ANY transport here introspect the fleet — descriptors or heartbeats? This is the difference
|
|
1915
|
+
* between "the fleet is empty" and "nobody asked", and it is a property of the POOL rather than of
|
|
1916
|
+
* a read's result, so it stays answerable when both reads legitimately come back empty.
|
|
1917
|
+
*/
|
|
1918
|
+
get introspectsFleet() {
|
|
1919
|
+
return this.transports.some(({ transport }) => transport.readAllWorkerDescriptors || transport.readAllWorkerHeartbeats);
|
|
1920
|
+
}
|
|
1759
1921
|
/** Distinct worker groups with a live heartbeat, merged across every transport that can report it. */
|
|
1760
1922
|
async listWorkerGroups() {
|
|
1761
1923
|
const groups = /* @__PURE__ */ new Set();
|
|
@@ -2520,6 +2682,7 @@ function mergeTags(staticTags, runTags) {
|
|
|
2520
2682
|
__name(mergeTags, "mergeTags");
|
|
2521
2683
|
var BREAKPOINT = "breakpoint";
|
|
2522
2684
|
var isBreakpoint = /* @__PURE__ */ __name((cp) => cp.status === "pending" && cp.name.startsWith(BREAKPOINT), "isBreakpoint");
|
|
2685
|
+
var VERSION_UNDECLARED_TAG = "version:undeclared";
|
|
2523
2686
|
var versionKey = /* @__PURE__ */ __name((name, version) => `${name}@${version}`, "versionKey");
|
|
2524
2687
|
function stepGroup(step, runNamespace) {
|
|
2525
2688
|
return tenantGroup(sanitizeQueueToken(step.name), step.partition ?? runNamespace);
|
|
@@ -3011,7 +3174,9 @@ var WorkflowEngine = class {
|
|
|
3011
3174
|
createdAt: /* @__PURE__ */ new Date(),
|
|
3012
3175
|
updatedAt: /* @__PURE__ */ new Date()
|
|
3013
3176
|
};
|
|
3014
|
-
registered = await this.resolveRemoteByConvention(conventionRun
|
|
3177
|
+
registered = await this.resolveRemoteByConvention(conventionRun, {
|
|
3178
|
+
askFleetForVersion: true
|
|
3179
|
+
});
|
|
3015
3180
|
}
|
|
3016
3181
|
if (!registered) {
|
|
3017
3182
|
throw new Error(pinned === void 0 ? `workflow ${name} is not registered` : `workflow ${versionKey(name, pinned)} is not registered \u2014 a pinned start never falls back to the newest version (registered: ${this.registeredVersions(name)})`);
|
|
@@ -3027,10 +3192,16 @@ var WorkflowEngine = class {
|
|
|
3027
3192
|
};
|
|
3028
3193
|
}
|
|
3029
3194
|
const now = /* @__PURE__ */ new Date();
|
|
3030
|
-
const
|
|
3195
|
+
const stampedTags = [
|
|
3031
3196
|
...opts?.tags ?? [],
|
|
3032
|
-
|
|
3033
|
-
|
|
3197
|
+
...registered.singleton ? [
|
|
3198
|
+
this.singletons.tag(registered.singleton, input)
|
|
3199
|
+
] : [],
|
|
3200
|
+
...registered.versionDeclared === false ? [
|
|
3201
|
+
VERSION_UNDECLARED_TAG
|
|
3202
|
+
] : []
|
|
3203
|
+
];
|
|
3204
|
+
const tags = mergeTags(registered.tags, stampedTags);
|
|
3034
3205
|
if (registered.singleton) {
|
|
3035
3206
|
await this.singletons.assertCapacity(name, registered.singleton, input);
|
|
3036
3207
|
}
|
|
@@ -3140,14 +3311,15 @@ var WorkflowEngine = class {
|
|
|
3140
3311
|
* Recomputed per call (never memoized into `this.workflows`) so it stays correct if group
|
|
3141
3312
|
* liveness changes between calls, exactly as {@link synthesizeRemoteChild} does.
|
|
3142
3313
|
*/
|
|
3143
|
-
async resolveRemoteByConvention(run) {
|
|
3314
|
+
async resolveRemoteByConvention(run, opts = {}) {
|
|
3144
3315
|
const group = tenantGroup(sanitizeQueueToken(run.workflow), run.namespace);
|
|
3145
3316
|
const liveTransport = await this.pool.transportWithLiveGroup(group);
|
|
3146
3317
|
if (!liveTransport) return void 0;
|
|
3147
3318
|
const executor = new RemoteWorkflowExecutor(liveTransport, run.workflow, run.namespace);
|
|
3319
|
+
const declared = opts.askFleetForVersion ? await this.declaredVersion(liveTransport, group, run.workflow) : void 0;
|
|
3148
3320
|
return {
|
|
3149
3321
|
name: run.workflow,
|
|
3150
|
-
version: run.workflowVersion,
|
|
3322
|
+
version: declared ?? run.workflowVersion,
|
|
3151
3323
|
fn: /* @__PURE__ */ __name(() => {
|
|
3152
3324
|
throw new Error(`remote workflow ${run.workflow} has no local body`);
|
|
3153
3325
|
}, "fn"),
|
|
@@ -3155,10 +3327,46 @@ var WorkflowEngine = class {
|
|
|
3155
3327
|
remote: {
|
|
3156
3328
|
group,
|
|
3157
3329
|
executor
|
|
3158
|
-
}
|
|
3330
|
+
},
|
|
3331
|
+
...opts.askFleetForVersion ? {
|
|
3332
|
+
versionDeclared: declared !== void 0
|
|
3333
|
+
} : {}
|
|
3159
3334
|
};
|
|
3160
3335
|
}
|
|
3161
3336
|
/**
|
|
3337
|
+
* The version the LIVE fleet declares for `workflow` on `group`, or `undefined` when it declares
|
|
3338
|
+
* none — which is a fact about the fleet, not a failure to read it.
|
|
3339
|
+
*
|
|
3340
|
+
* The read is the descriptor advertisement, scoped to the one group being resolved: the workers on
|
|
3341
|
+
* that queue, their `registrations`, the entry whose `name` matches. That is where a version can
|
|
3342
|
+
* come from at all — a heartbeat has no room for one, so a worker on an SDK too old to publish a
|
|
3343
|
+
* descriptor declares nothing and the caller is told so rather than handed a default.
|
|
3344
|
+
*
|
|
3345
|
+
* `undefined` when the announcers DISAGREE, and deliberately: two live workers claiming different
|
|
3346
|
+
* versions of one name is a deployment in the middle of something, and picking either would stamp
|
|
3347
|
+
* a run with a version half the fleet does not serve. Undeclared is the honest reading of a
|
|
3348
|
+
* contradiction, and it is the reading that refuses to let a pin pass on a coin flip.
|
|
3349
|
+
*/
|
|
3350
|
+
async declaredVersion(transport, group, workflow) {
|
|
3351
|
+
if (!transport.readWorkerDescriptors) return void 0;
|
|
3352
|
+
let descriptors;
|
|
3353
|
+
try {
|
|
3354
|
+
descriptors = await transport.readWorkerDescriptors(group);
|
|
3355
|
+
} catch {
|
|
3356
|
+
return void 0;
|
|
3357
|
+
}
|
|
3358
|
+
const versions = /* @__PURE__ */ new Set();
|
|
3359
|
+
for (const announced of aggregateAnnouncements(descriptors)) {
|
|
3360
|
+
if (announced.name === workflow && announced.version !== void 0) {
|
|
3361
|
+
versions.add(announced.version);
|
|
3362
|
+
}
|
|
3363
|
+
}
|
|
3364
|
+
const only = [
|
|
3365
|
+
...versions
|
|
3366
|
+
];
|
|
3367
|
+
return only.length === 1 ? only[0] : void 0;
|
|
3368
|
+
}
|
|
3369
|
+
/**
|
|
3162
3370
|
* Walk the parent chain of `childRunId` to the nearest ancestor registered as REMOTE, returning its
|
|
3163
3371
|
* registration (or `undefined` if there is none). The parent of an awaited child is found via its
|
|
3164
3372
|
* live `child:<childId>` signal waiter — present for as long as the parent is suspended awaiting the
|
|
@@ -4113,9 +4321,30 @@ var WorkflowEngine = class {
|
|
|
4113
4321
|
* Workflows only, and deliberately: see the "steps are out of scope" note in `handshake/announced`.
|
|
4114
4322
|
*/
|
|
4115
4323
|
async announcedWorkflows() {
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4324
|
+
return (await this.workflowDirectory()).workflows;
|
|
4325
|
+
}
|
|
4326
|
+
/**
|
|
4327
|
+
* {@link announcedWorkflows}, plus the thing a list of workflows can never say: why it is the
|
|
4328
|
+
* length it is. See {@link WorkflowDirectory} for the three states an empty array used to collapse
|
|
4329
|
+
* into one — "nobody asked", "nothing is live", and the partition mismatch that reads exactly like
|
|
4330
|
+
* the second from the caller's side.
|
|
4331
|
+
*
|
|
4332
|
+
* Two live reads, both on demand and neither retained: the descriptor advertisement (what workers
|
|
4333
|
+
* SAY they serve) and the heartbeat keyspace (what is demonstrably consuming a queue right now).
|
|
4334
|
+
* The second is why a worker on an SDK too old to publish a descriptor appears here at all — it
|
|
4335
|
+
* beats and never describes itself, and reading only descriptors reported such a fleet as empty
|
|
4336
|
+
* while `resolveRemoteByConvention`, a few lines away in this same class, was routing calls to it
|
|
4337
|
+
* off those very keys. Two answers out of one Redis, disagreeing. Now they agree, and the entry
|
|
4338
|
+
* says which of the two kinds of evidence it rests on rather than flattening them together.
|
|
4339
|
+
*/
|
|
4340
|
+
async workflowDirectory() {
|
|
4341
|
+
return buildWorkflowDirectory({
|
|
4342
|
+
descriptors: await this.pool.readAllWorkerDescriptors(),
|
|
4343
|
+
heartbeats: await this.pool.readAllWorkerHeartbeats(),
|
|
4344
|
+
namespace: this.namespace,
|
|
4345
|
+
supported: this.pool.introspectsFleet,
|
|
4346
|
+
sanitize: sanitizeQueueToken
|
|
4347
|
+
});
|
|
4119
4348
|
}
|
|
4120
4349
|
/**
|
|
4121
4350
|
* The routing groups of every in-flight run's still-`pending` remote step — the queues where work is
|
|
@@ -5746,6 +5975,33 @@ var TERMINAL_RUN_STATUSES = [
|
|
|
5746
5975
|
"dead"
|
|
5747
5976
|
];
|
|
5748
5977
|
|
|
5978
|
+
// src/run-facets.ts
|
|
5979
|
+
function facetOrigin(origin) {
|
|
5980
|
+
return origin?.trim() ? origin : null;
|
|
5981
|
+
}
|
|
5982
|
+
__name(facetOrigin, "facetOrigin");
|
|
5983
|
+
function mergeRunFacetRows(rows) {
|
|
5984
|
+
const cells = /* @__PURE__ */ new Map();
|
|
5985
|
+
for (const row of rows) {
|
|
5986
|
+
const origin = facetOrigin(row.origin);
|
|
5987
|
+
const key = JSON.stringify([
|
|
5988
|
+
row.status,
|
|
5989
|
+
origin
|
|
5990
|
+
]);
|
|
5991
|
+
const cell = cells.get(key);
|
|
5992
|
+
if (cell) cell.count += row.count;
|
|
5993
|
+
else cells.set(key, {
|
|
5994
|
+
status: row.status,
|
|
5995
|
+
origin,
|
|
5996
|
+
count: row.count
|
|
5997
|
+
});
|
|
5998
|
+
}
|
|
5999
|
+
return [
|
|
6000
|
+
...cells.values()
|
|
6001
|
+
];
|
|
6002
|
+
}
|
|
6003
|
+
__name(mergeRunFacetRows, "mergeRunFacetRows");
|
|
6004
|
+
|
|
5749
6005
|
// src/run-gateway.ts
|
|
5750
6006
|
var RunGateway = class {
|
|
5751
6007
|
static {
|
|
@@ -5760,9 +6016,18 @@ var CodecStateStore = class {
|
|
|
5760
6016
|
}
|
|
5761
6017
|
inner;
|
|
5762
6018
|
codec;
|
|
6019
|
+
/**
|
|
6020
|
+
* Forwarded verbatim — a facet cell counts `status`/`origin`, neither of which the codec touches
|
|
6021
|
+
* (it encodes payloads: input/output/error). Bound as a PROPERTY, and only when the inner store
|
|
6022
|
+
* actually aggregates, so `store.runFacets?.()` still reports absence through the wrapper instead
|
|
6023
|
+
* of resolving to a silently wrong empty result.
|
|
6024
|
+
*/
|
|
6025
|
+
runFacets;
|
|
5763
6026
|
constructor(inner, codec) {
|
|
5764
6027
|
this.inner = inner;
|
|
5765
6028
|
this.codec = codec;
|
|
6029
|
+
const facets = inner.runFacets;
|
|
6030
|
+
if (facets) this.runFacets = (query) => facets.call(inner, query);
|
|
5766
6031
|
}
|
|
5767
6032
|
enc(v) {
|
|
5768
6033
|
return v === void 0 ? void 0 : this.codec.encode(v);
|
|
@@ -6460,7 +6725,9 @@ var InMemoryStateStore = class {
|
|
|
6460
6725
|
}
|
|
6461
6726
|
return out;
|
|
6462
6727
|
}
|
|
6463
|
-
|
|
6728
|
+
/** Every run satisfying `query`'s predicates, unsorted and unpaged — the shared body of
|
|
6729
|
+
* {@link listRuns} (which then sorts + pages it) and {@link runFacets} (which groups it). */
|
|
6730
|
+
matching(query) {
|
|
6464
6731
|
let runs = [
|
|
6465
6732
|
...this.runs.values()
|
|
6466
6733
|
];
|
|
@@ -6469,7 +6736,8 @@ var InMemoryStateStore = class {
|
|
|
6469
6736
|
if (query.statuses) runs = runs.filter((r) => query.statuses?.includes(r.status));
|
|
6470
6737
|
if (query.tag) runs = runs.filter((r) => r.tags?.includes(query.tag));
|
|
6471
6738
|
if (query.namespace !== void 0) runs = runs.filter((r) => r.namespace === query.namespace);
|
|
6472
|
-
if (query.origin
|
|
6739
|
+
if (query.origin === null) runs = runs.filter((r) => r.origin == null);
|
|
6740
|
+
else if (query.origin !== void 0) runs = runs.filter((r) => r.origin === query.origin);
|
|
6473
6741
|
if (query.attributes?.length) {
|
|
6474
6742
|
let candidates = null;
|
|
6475
6743
|
for (const f of query.attributes) {
|
|
@@ -6488,6 +6756,10 @@ var InMemoryStateStore = class {
|
|
|
6488
6756
|
this.lastAttributeCandidates = ids.size;
|
|
6489
6757
|
runs = runs.filter((r) => ids.has(r.id));
|
|
6490
6758
|
}
|
|
6759
|
+
return runs;
|
|
6760
|
+
}
|
|
6761
|
+
async listRuns(query) {
|
|
6762
|
+
const runs = this.matching(query);
|
|
6491
6763
|
runs.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
6492
6764
|
const offset = query.offset ?? 0;
|
|
6493
6765
|
const limit = query.limit ?? runs.length;
|
|
@@ -6495,6 +6767,13 @@ var InMemoryStateStore = class {
|
|
|
6495
6767
|
...r
|
|
6496
6768
|
}));
|
|
6497
6769
|
}
|
|
6770
|
+
async runFacets(query) {
|
|
6771
|
+
return mergeRunFacetRows(this.matching(query).map((run) => ({
|
|
6772
|
+
status: run.status,
|
|
6773
|
+
origin: run.origin,
|
|
6774
|
+
count: 1
|
|
6775
|
+
})));
|
|
6776
|
+
}
|
|
6498
6777
|
async listCheckpoints(runId) {
|
|
6499
6778
|
const rows = [
|
|
6500
6779
|
...this.checkpoints.values()
|
|
@@ -6576,6 +6855,7 @@ export {
|
|
|
6576
6855
|
CURRENT_PROTOCOL_VERSION,
|
|
6577
6856
|
CodecStateStore,
|
|
6578
6857
|
ContinueAsNew,
|
|
6858
|
+
DEFAULT_PARTITION,
|
|
6579
6859
|
DURABLE_OPTIONS,
|
|
6580
6860
|
DURABLE_OPTIONS_CANONICAL,
|
|
6581
6861
|
DURABLE_STEP_CONFIG,
|
|
@@ -6606,6 +6886,7 @@ export {
|
|
|
6606
6886
|
TERMINAL_RUN_STATUSES,
|
|
6607
6887
|
TRANSPORT,
|
|
6608
6888
|
TRANSPORT_CANONICAL,
|
|
6889
|
+
VERSION_UNDECLARED_TAG,
|
|
6609
6890
|
WORKFLOW_NAME_KEY,
|
|
6610
6891
|
WorkflowBlocked,
|
|
6611
6892
|
WorkflowEngine,
|
|
@@ -6617,12 +6898,14 @@ export {
|
|
|
6617
6898
|
attributeOperand,
|
|
6618
6899
|
bindWorkflowClass,
|
|
6619
6900
|
breakpointToken,
|
|
6901
|
+
buildWorkflowDirectory,
|
|
6620
6902
|
canRoute,
|
|
6621
6903
|
capableWorkers,
|
|
6622
6904
|
classifyWaiterToken,
|
|
6623
6905
|
clearDurableExecutionWrappers,
|
|
6624
6906
|
collectMetrics,
|
|
6625
6907
|
controlPlaneDescriptor,
|
|
6908
|
+
coveredTokens,
|
|
6626
6909
|
createStepLogger,
|
|
6627
6910
|
currentStep,
|
|
6628
6911
|
currentWorkflowCtx,
|
|
@@ -6635,6 +6918,7 @@ export {
|
|
|
6635
6918
|
eventNameOf,
|
|
6636
6919
|
eventPrefix,
|
|
6637
6920
|
eventToken,
|
|
6921
|
+
facetOrigin,
|
|
6638
6922
|
hasDurableExecutionWrappers,
|
|
6639
6923
|
heartbeatStatus,
|
|
6640
6924
|
indexWaitersByRun,
|
|
@@ -6644,11 +6928,14 @@ export {
|
|
|
6644
6928
|
isWorkflowControlFlowSignal,
|
|
6645
6929
|
log,
|
|
6646
6930
|
matchesAttributes,
|
|
6931
|
+
mergeRunFacetRows,
|
|
6647
6932
|
missingCapabilities,
|
|
6648
6933
|
negotiate,
|
|
6649
6934
|
normalizeAttributeRows,
|
|
6650
6935
|
normalizeDescriptor,
|
|
6936
|
+
observedAnnouncements,
|
|
6651
6937
|
parseDuration,
|
|
6938
|
+
partitionOfToken,
|
|
6652
6939
|
planDispatch,
|
|
6653
6940
|
prevCronFireMs,
|
|
6654
6941
|
readSearchAttributes,
|