@dudousxd/nestjs-durable-core 0.67.1 → 0.69.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
@@ -32,6 +32,7 @@ __export(index_exports, {
32
32
  DURABLE_STEP_CONFIG: () => DURABLE_STEP_CONFIG,
33
33
  DURABLE_STEP_NAME: () => DURABLE_STEP_NAME,
34
34
  DurableWorkflow: () => DurableWorkflow,
35
+ ENGINE_MINTED_TAG_PREFIXES: () => ENGINE_MINTED_TAG_PREFIXES,
35
36
  EVENT_BUFFER_SCAN_LIMIT: () => EVENT_BUFFER_SCAN_LIMIT,
36
37
  EVENT_TOKEN_PREFIX: () => EVENT_TOKEN_PREFIX,
37
38
  Entities: () => Entities,
@@ -45,6 +46,8 @@ __export(index_exports, {
45
46
  LEGACY_V1_PROTOCOL: () => LEGACY_V1_PROTOCOL,
46
47
  NonDeterminismError: () => NonDeterminismError,
47
48
  QueueController: () => QueueController,
49
+ RUN_VALUE_FACET_LIMIT: () => RUN_VALUE_FACET_LIMIT,
50
+ RUN_VALUE_FACET_SCAN: () => RUN_VALUE_FACET_SCAN,
48
51
  RemoteStepError: () => RemoteStepError,
49
52
  RemoteStepTimeout: () => RemoteStepTimeout,
50
53
  RemoteWorkflowExecutor: () => RemoteWorkflowExecutor,
@@ -67,6 +70,8 @@ __export(index_exports, {
67
70
  applyAttributeQuery: () => applyAttributeQuery,
68
71
  attributeColumnFor: () => attributeColumnFor,
69
72
  attributeOperand: () => attributeOperand,
73
+ attributePredicateOperands: () => attributePredicateOperands,
74
+ axisIsRunColumn: () => axisIsRunColumn,
70
75
  bindWorkflowClass: () => bindWorkflowClass,
71
76
  breakpointToken: () => breakpointToken,
72
77
  buildWorkflowDirectory: () => buildWorkflowDirectory,
@@ -94,12 +99,14 @@ __export(index_exports, {
94
99
  heartbeatStatus: () => heartbeatStatus,
95
100
  indexWaitersByRun: () => indexWaitersByRun,
96
101
  info: () => info,
102
+ isEngineMintedTag: () => isEngineMintedTag,
97
103
  isEventToken: () => isEventToken,
98
104
  isLegacyDescriptor: () => isLegacyDescriptor,
99
105
  isWorkflowControlFlowSignal: () => isWorkflowControlFlowSignal,
100
106
  log: () => log,
101
107
  matchesAttributes: () => matchesAttributes,
102
108
  mergeRunFacetRows: () => mergeRunFacetRows,
109
+ mergeRunValueFacetRows: () => mergeRunValueFacetRows,
103
110
  missingCapabilities: () => missingCapabilities,
104
111
  negotiate: () => negotiate,
105
112
  normalizeAttributeRows: () => normalizeAttributeRows,
@@ -118,6 +125,7 @@ __export(index_exports, {
118
125
  runInWorkflowCtx: () => runInWorkflowCtx,
119
126
  runSchedules: () => runSchedules,
120
127
  runStepHandler: () => runStepHandler,
128
+ runValueFacetsFromRuns: () => runValueFacetsFromRuns,
121
129
  sanitizeQueueToken: () => sanitizeQueueToken,
122
130
  scheduledRunId: () => scheduledRunId,
123
131
  sqlComparator: () => sqlComparator,
@@ -6133,6 +6141,86 @@ function mergeRunFacetRows(rows) {
6133
6141
  }
6134
6142
  __name(mergeRunFacetRows, "mergeRunFacetRows");
6135
6143
 
6144
+ // src/run-value-facets.ts
6145
+ var RUN_VALUE_FACET_LIMIT = 100;
6146
+ var RUN_VALUE_FACET_SCAN = 5e3;
6147
+ var ENGINE_MINTED_TAG_PREFIXES = [
6148
+ "singleton:"
6149
+ ];
6150
+ function isEngineMintedTag(value) {
6151
+ return value !== null && ENGINE_MINTED_TAG_PREFIXES.some((prefix) => value.startsWith(prefix));
6152
+ }
6153
+ __name(isEngineMintedTag, "isEngineMintedTag");
6154
+ function axisIsRunColumn(axis) {
6155
+ return axis.field === "workflow" || axis.field === "status" || axis.field === "origin" || axis.field === "namespace";
6156
+ }
6157
+ __name(axisIsRunColumn, "axisIsRunColumn");
6158
+ function valuesOf(run, axis) {
6159
+ switch (axis.field) {
6160
+ case "workflow":
6161
+ return [
6162
+ run.workflow
6163
+ ];
6164
+ case "status":
6165
+ return [
6166
+ run.status
6167
+ ];
6168
+ case "origin":
6169
+ return [
6170
+ facetOrigin(run.origin)
6171
+ ];
6172
+ case "namespace":
6173
+ return run.namespace === void 0 ? [] : [
6174
+ run.namespace
6175
+ ];
6176
+ case "tag":
6177
+ return run.tags ?? [];
6178
+ case "attributeKey":
6179
+ return Object.keys(run.searchAttributes ?? {});
6180
+ case "attributeValue": {
6181
+ const value = run.searchAttributes?.[axis.key];
6182
+ return value === void 0 ? [] : [
6183
+ String(value)
6184
+ ];
6185
+ }
6186
+ }
6187
+ }
6188
+ __name(valuesOf, "valuesOf");
6189
+ function mergeRunValueFacetRows(rows, opts) {
6190
+ const counts = /* @__PURE__ */ new Map();
6191
+ for (const row of rows) {
6192
+ const value = row.value ?? null;
6193
+ counts.set(value, (counts.get(value) ?? 0) + Number(row.count));
6194
+ }
6195
+ const merged = [
6196
+ ...counts
6197
+ ].map(([value, count]) => ({
6198
+ value,
6199
+ count
6200
+ })).filter((row) => row.count > 0).sort((a, b) => {
6201
+ const engineA = isEngineMintedTag(a.value);
6202
+ const engineB = isEngineMintedTag(b.value);
6203
+ if (engineA !== engineB) return engineA ? 1 : -1;
6204
+ if (b.count !== a.count) return b.count - a.count;
6205
+ if (a.value === null) return 1;
6206
+ if (b.value === null) return -1;
6207
+ return a.value.localeCompare(b.value);
6208
+ });
6209
+ return merged.slice(0, opts?.limit ?? RUN_VALUE_FACET_LIMIT);
6210
+ }
6211
+ __name(mergeRunValueFacetRows, "mergeRunValueFacetRows");
6212
+ function runValueFacetsFromRuns(runs, axis, opts) {
6213
+ const rows = [];
6214
+ for (const run of runs) {
6215
+ for (const value of valuesOf(run, axis)) rows.push({
6216
+ value,
6217
+ count: 1
6218
+ });
6219
+ }
6220
+ return mergeRunValueFacetRows(rows, opts);
6221
+ }
6222
+ __name(runValueFacetsFromRuns, "runValueFacetsFromRuns");
6223
+
6136
6224
  // src/run-gateway.ts
6137
6225
  var RunGateway = class {
6138
6226
  static {
@@ -6154,11 +6242,21 @@ var CodecStateStore = class {
6154
6242
  * of resolving to a silently wrong empty result.
6155
6243
  */
6156
6244
  runFacets;
6245
+ /**
6246
+ * Forwarded verbatim, and safe to: the axes a value facet enumerates are searchable metadata
6247
+ * (workflow, status, origin, namespace, tags, search attributes), none of which the codec encodes.
6248
+ * Bound the same conditional way as {@link runFacets} so absence is reported, not faked.
6249
+ */
6250
+ runValueFacets;
6157
6251
  constructor(inner, codec) {
6158
6252
  this.inner = inner;
6159
6253
  this.codec = codec;
6160
6254
  const facets = inner.runFacets;
6161
6255
  if (facets) this.runFacets = (query) => facets.call(inner, query);
6256
+ const valueFacets = inner.runValueFacets;
6257
+ if (valueFacets) {
6258
+ this.runValueFacets = (axis, query, opts) => valueFacets.call(inner, axis, query, opts);
6259
+ }
6162
6260
  }
6163
6261
  enc(v) {
6164
6262
  return v === void 0 ? void 0 : this.codec.encode(v);
@@ -6513,8 +6611,10 @@ async function runSchedules(engine, schedules, nowMs, opts) {
6513
6611
  __name(runSchedules, "runSchedules");
6514
6612
 
6515
6613
  // src/search-attributes.ts
6516
- function compare(actual, op, expected) {
6517
- switch (op) {
6614
+ function compare(actual, filter) {
6615
+ if (filter.op === "in") return filter.values.some((v) => actual === v);
6616
+ const expected = filter.value;
6617
+ switch (filter.op) {
6518
6618
  case "eq":
6519
6619
  return actual === expected;
6520
6620
  case "ne":
@@ -6533,7 +6633,7 @@ __name(compare, "compare");
6533
6633
  function matchesAttributes(attributes, filters) {
6534
6634
  if (!filters?.length) return true;
6535
6635
  if (!attributes) return false;
6536
- return filters.every((f) => f.key in attributes && compare(attributes[f.key], f.op, f.value));
6636
+ return filters.every((f) => f.key in attributes && compare(attributes[f.key], f));
6537
6637
  }
6538
6638
  __name(matchesAttributes, "matchesAttributes");
6539
6639
  function applyAttributeQuery(rows, query) {
@@ -6599,6 +6699,30 @@ function attributeOperand(filter) {
6599
6699
  return filter.value;
6600
6700
  }
6601
6701
  __name(attributeOperand, "attributeOperand");
6702
+ function attributePredicateOperands(filter) {
6703
+ if (filter.op === "in") {
6704
+ return filter.values.map((value) => {
6705
+ const scalar = {
6706
+ key: filter.key,
6707
+ op: "eq",
6708
+ value
6709
+ };
6710
+ return {
6711
+ column: attributeColumnFor(scalar),
6712
+ comparator: "=",
6713
+ operand: attributeOperand(scalar)
6714
+ };
6715
+ });
6716
+ }
6717
+ return [
6718
+ {
6719
+ column: attributeColumnFor(filter),
6720
+ comparator: sqlComparator(filter.op),
6721
+ operand: attributeOperand(filter)
6722
+ }
6723
+ ];
6724
+ }
6725
+ __name(attributePredicateOperands, "attributePredicateOperands");
6602
6726
 
6603
6727
  // src/search-attributes-schema.ts
6604
6728
  function readSearchAttributes(schema, run) {
@@ -6826,33 +6950,27 @@ var InMemoryStateStore = class {
6826
6950
  const byRun = this.attributeIndex.get(f.key);
6827
6951
  const out = /* @__PURE__ */ new Set();
6828
6952
  if (!byRun) return out;
6829
- const numeric = typeof f.value === "number";
6830
- const operand = typeof f.value === "boolean" ? f.value ? "true" : "false" : f.value;
6953
+ const comparisons = attributePredicateOperands(f);
6831
6954
  for (const row of byRun.values()) {
6832
- const actual = numeric ? row.numValue : row.strValue;
6833
- if (actual == null) continue;
6834
- let ok = false;
6835
- switch (f.op) {
6836
- case "eq":
6837
- ok = actual === operand;
6838
- break;
6839
- case "ne":
6840
- ok = actual !== operand;
6841
- break;
6842
- case "gt":
6843
- ok = actual > operand;
6844
- break;
6845
- case "gte":
6846
- ok = actual >= operand;
6847
- break;
6848
- case "lt":
6849
- ok = actual < operand;
6850
- break;
6851
- case "lte":
6852
- ok = actual <= operand;
6853
- break;
6854
- }
6855
- if (ok) out.add(row.runId);
6955
+ const matched = comparisons.some(({ column, comparator, operand }) => {
6956
+ const actual = column === "numValue" ? row.numValue : row.strValue;
6957
+ if (actual == null) return false;
6958
+ switch (comparator) {
6959
+ case "=":
6960
+ return actual === operand;
6961
+ case "<>":
6962
+ return actual !== operand;
6963
+ case ">":
6964
+ return actual > operand;
6965
+ case ">=":
6966
+ return actual >= operand;
6967
+ case "<":
6968
+ return actual < operand;
6969
+ default:
6970
+ return actual <= operand;
6971
+ }
6972
+ });
6973
+ if (matched) out.add(row.runId);
6856
6974
  }
6857
6975
  return out;
6858
6976
  }
@@ -6863,12 +6981,20 @@ var InMemoryStateStore = class {
6863
6981
  ...this.runs.values()
6864
6982
  ];
6865
6983
  if (query.workflow) runs = runs.filter((r) => r.workflow === query.workflow);
6984
+ if (query.workflows) runs = runs.filter((r) => query.workflows?.includes(r.workflow));
6866
6985
  if (query.status) runs = runs.filter((r) => r.status === query.status);
6867
6986
  if (query.statuses) runs = runs.filter((r) => query.statuses?.includes(r.status));
6868
6987
  if (query.tag) runs = runs.filter((r) => r.tags?.includes(query.tag));
6988
+ if (query.tags) runs = runs.filter((r) => r.tags?.some((t) => query.tags?.includes(t)));
6869
6989
  if (query.namespace !== void 0) runs = runs.filter((r) => r.namespace === query.namespace);
6990
+ if (query.namespaces) {
6991
+ runs = runs.filter((r) => r.namespace !== void 0 && query.namespaces?.includes(r.namespace));
6992
+ }
6870
6993
  if (query.origin === null) runs = runs.filter((r) => r.origin == null);
6871
6994
  else if (query.origin !== void 0) runs = runs.filter((r) => r.origin === query.origin);
6995
+ if (query.origins) {
6996
+ runs = runs.filter((r) => query.origins?.includes(r.origin ?? null));
6997
+ }
6872
6998
  if (query.attributes?.length) {
6873
6999
  let candidates = null;
6874
7000
  for (const f of query.attributes) {
@@ -6905,6 +7031,16 @@ var InMemoryStateStore = class {
6905
7031
  count: 1
6906
7032
  })));
6907
7033
  }
7034
+ /** Counted over the newest `scan` matching runs for EVERY axis, not just `tag`: this store holds
7035
+ * its runs in a Map with no index to group by, so the bound that the SQL stores need only for tags
7036
+ * is the honest one to apply here throughout. */
7037
+ async runValueFacets(axis, query, opts) {
7038
+ const runs = await this.listRuns({
7039
+ ...query,
7040
+ limit: opts?.scan ?? RUN_VALUE_FACET_SCAN
7041
+ });
7042
+ return runValueFacetsFromRuns(runs, axis, opts);
7043
+ }
6908
7044
  async listCheckpoints(runId) {
6909
7045
  const rows = [
6910
7046
  ...this.checkpoints.values()
@@ -6993,6 +7129,7 @@ var InMemoryTransport = class {
6993
7129
  DURABLE_STEP_CONFIG,
6994
7130
  DURABLE_STEP_NAME,
6995
7131
  DurableWorkflow,
7132
+ ENGINE_MINTED_TAG_PREFIXES,
6996
7133
  EVENT_BUFFER_SCAN_LIMIT,
6997
7134
  EVENT_TOKEN_PREFIX,
6998
7135
  Entities,
@@ -7006,6 +7143,8 @@ var InMemoryTransport = class {
7006
7143
  LEGACY_V1_PROTOCOL,
7007
7144
  NonDeterminismError,
7008
7145
  QueueController,
7146
+ RUN_VALUE_FACET_LIMIT,
7147
+ RUN_VALUE_FACET_SCAN,
7009
7148
  RemoteStepError,
7010
7149
  RemoteStepTimeout,
7011
7150
  RemoteWorkflowExecutor,
@@ -7028,6 +7167,8 @@ var InMemoryTransport = class {
7028
7167
  applyAttributeQuery,
7029
7168
  attributeColumnFor,
7030
7169
  attributeOperand,
7170
+ attributePredicateOperands,
7171
+ axisIsRunColumn,
7031
7172
  bindWorkflowClass,
7032
7173
  breakpointToken,
7033
7174
  buildWorkflowDirectory,
@@ -7055,12 +7196,14 @@ var InMemoryTransport = class {
7055
7196
  heartbeatStatus,
7056
7197
  indexWaitersByRun,
7057
7198
  info,
7199
+ isEngineMintedTag,
7058
7200
  isEventToken,
7059
7201
  isLegacyDescriptor,
7060
7202
  isWorkflowControlFlowSignal,
7061
7203
  log,
7062
7204
  matchesAttributes,
7063
7205
  mergeRunFacetRows,
7206
+ mergeRunValueFacetRows,
7064
7207
  missingCapabilities,
7065
7208
  negotiate,
7066
7209
  normalizeAttributeRows,
@@ -7079,6 +7222,7 @@ var InMemoryTransport = class {
7079
7222
  runInWorkflowCtx,
7080
7223
  runSchedules,
7081
7224
  runStepHandler,
7225
+ runValueFacetsFromRuns,
7082
7226
  sanitizeQueueToken,
7083
7227
  scheduledRunId,
7084
7228
  sqlComparator,