@cadenza.io/core 3.14.0 → 3.15.1

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.mjs CHANGED
@@ -258,14 +258,13 @@ var debounce_default = debounce;
258
258
 
259
259
  // src/engine/SignalBroker.ts
260
260
  var SignalBroker = class _SignalBroker {
261
- // execId -> emitted signals
262
261
  constructor() {
263
262
  this.debug = false;
264
263
  this.verbose = false;
265
264
  this.debouncedEmitters = /* @__PURE__ */ new Map();
266
265
  // TODO: Signals should be a class with a the observers, registered flag and other data.
267
266
  this.signalObservers = /* @__PURE__ */ new Map();
268
- this.emitStacks = /* @__PURE__ */ new Map();
267
+ this.emittedSignalsRegistry = /* @__PURE__ */ new Set();
269
268
  this.addSignal("meta.signal_broker.added");
270
269
  }
271
270
  static get instance() {
@@ -324,20 +323,6 @@ var SignalBroker = class _SignalBroker {
324
323
  * @return {void} This method does not return a value.
325
324
  */
326
325
  init() {
327
- this.clearSignalsTask = Cadenza.createDebounceMetaTask(
328
- "Execute and clear queued signals",
329
- () => {
330
- for (const [id, signals] of this.emitStacks.entries()) {
331
- signals.forEach((context, signal) => {
332
- this.execute(signal, context);
333
- signals.delete(signal);
334
- });
335
- this.emitStacks.delete(id);
336
- }
337
- return true;
338
- },
339
- "Executes queued signals and clears the stack"
340
- ).doOn("meta.process_signal_queue_requested").emits("meta.signal_broker.queue_empty");
341
326
  this.getSignalsTask = Cadenza.createMetaTask("Get signals", (ctx) => {
342
327
  const uniqueSignals = Array.from(this.signalObservers.keys()).filter(
343
328
  (s) => !s.includes(":")
@@ -371,6 +356,9 @@ var SignalBroker = class _SignalBroker {
371
356
  this.addSignal(signal);
372
357
  this.signalObservers.get(signal).tasks.add(routineOrTask);
373
358
  }
359
+ registerEmittedSignal(signal) {
360
+ this.emittedSignalsRegistry.add(signal);
361
+ }
374
362
  /**
375
363
  * Unsubscribes a routine/task from a signal.
376
364
  * @param signal The signal.
@@ -478,19 +466,9 @@ var SignalBroker = class _SignalBroker {
478
466
  * @return {void} This method does not return a value.
479
467
  */
480
468
  emit(signal, context = {}) {
481
- const execId = context.__routineExecId || "global";
482
469
  delete context.__routineExecId;
483
- if (!this.emitStacks.has(execId)) this.emitStacks.set(execId, /* @__PURE__ */ new Map());
484
- const stack = this.emitStacks.get(execId);
485
- stack.set(signal, context);
486
470
  this.addSignal(signal);
487
- let executed = false;
488
- try {
489
- executed = this.execute(signal, context);
490
- } finally {
491
- if (executed) stack.delete(signal);
492
- if (stack.size === 0) this.emitStacks.delete(execId);
493
- }
471
+ this.execute(signal, context);
494
472
  }
495
473
  /**
496
474
  * Executes a signal by emitting events, updating context, and invoking listeners.
@@ -646,14 +624,17 @@ var SignalBroker = class _SignalBroker {
646
624
  listObservedSignals() {
647
625
  return Array.from(this.signalObservers.keys());
648
626
  }
627
+ listEmittedSignals() {
628
+ return Array.from(this.emittedSignalsRegistry);
629
+ }
649
630
  reset() {
650
- this.emitStacks.clear();
651
631
  this.signalObservers.clear();
632
+ this.emittedSignalsRegistry.clear();
652
633
  }
653
634
  };
654
635
 
655
636
  // src/engine/GraphRunner.ts
656
- import { v4 as uuid6 } from "uuid";
637
+ import { v4 as uuid5 } from "uuid";
657
638
 
658
639
  // src/engine/GraphRun.ts
659
640
  import { v4 as uuid2 } from "uuid";
@@ -2158,8 +2139,178 @@ var GraphRoutine = class extends SignalEmitter {
2158
2139
  }
2159
2140
  };
2160
2141
 
2142
+ // src/engine/GraphRunner.ts
2143
+ var GraphRunner = class extends SignalEmitter {
2144
+ /**
2145
+ * Constructs a runner.
2146
+ * @param isMeta Meta flag (default false).
2147
+ * @edge Creates 'Start run' meta-task chained to registry gets.
2148
+ */
2149
+ constructor(isMeta = false) {
2150
+ super(isMeta);
2151
+ this.debug = false;
2152
+ this.verbose = false;
2153
+ this.isRunning = false;
2154
+ this.isMeta = false;
2155
+ this.isMeta = isMeta;
2156
+ this.strategy = Cadenza.runStrategy.PARALLEL;
2157
+ this.currentRun = new GraphRun(this.strategy);
2158
+ }
2159
+ /**
2160
+ * Adds tasks or routines to the current execution pipeline. Supports both individual tasks,
2161
+ * routines, or arrays of tasks and routines. Handles metadata and execution context management.
2162
+ *
2163
+ * @param {Task|GraphRoutine|(Task|GraphRoutine)[]} tasks - The task(s) or routine(s) to be added.
2164
+ * It can be a single task, a single routine, or an array of tasks and routines.
2165
+ * @param {AnyObject} [context={}] - Optional context object to provide execution trace and metadata.
2166
+ * Used to propagate information across task or routine executions.
2167
+ * @return {void} - This method does not return a value.
2168
+ */
2169
+ addTasks(tasks, context = {}) {
2170
+ let _tasks = Array.isArray(tasks) ? tasks : [tasks];
2171
+ if (_tasks.length === 0) {
2172
+ console.warn("No tasks/routines to add.");
2173
+ return;
2174
+ }
2175
+ let routineName = _tasks.map((t) => t.name).join(" | ");
2176
+ let routineVersion = null;
2177
+ let isMeta = _tasks.every((t) => t.isMeta);
2178
+ const allTasks = _tasks.flatMap((t) => {
2179
+ if (t instanceof GraphRoutine) {
2180
+ routineName = t.name;
2181
+ routineVersion = t.version;
2182
+ isMeta = t.isMeta;
2183
+ const routineTasks = [];
2184
+ t.forEachTask((task) => routineTasks.push(task));
2185
+ return routineTasks;
2186
+ }
2187
+ return t;
2188
+ });
2189
+ const isSubMeta = allTasks.some((t) => t.isSubMeta) || !!context.__isSubMeta;
2190
+ context.__isSubMeta = isSubMeta;
2191
+ const isNewTrace = !context.__routineExecId && !context.__metadata?.__executionTraceId && !context.__executionTraceId;
2192
+ const executionTraceId = context.__metadata?.__executionTraceId ?? context.__executionTraceId ?? uuid5();
2193
+ context.__executionTraceId = executionTraceId;
2194
+ const routineExecId = context.__routineExecId ?? uuid5();
2195
+ context.__routineExecId = routineExecId;
2196
+ const ctx = new GraphContext(context || {});
2197
+ if (!isSubMeta) {
2198
+ const contextData = ctx.export();
2199
+ if (isNewTrace) {
2200
+ this.emitMetrics("meta.runner.new_trace", {
2201
+ data: {
2202
+ uuid: executionTraceId,
2203
+ issuer_type: "service",
2204
+ // TODO: Add issuer type
2205
+ issuer_id: context.__metadata?.__issuerId ?? context.__issuerId ?? null,
2206
+ issued_at: formatTimestamp(Date.now()),
2207
+ intent: context.__metadata?.__intent ?? context.__intent ?? null,
2208
+ context: contextData,
2209
+ is_meta: isMeta
2210
+ },
2211
+ __metadata: {
2212
+ __executionTraceId: executionTraceId
2213
+ }
2214
+ });
2215
+ }
2216
+ this.emitMetrics("meta.runner.added_tasks", {
2217
+ data: {
2218
+ uuid: routineExecId,
2219
+ name: routineName,
2220
+ routineVersion,
2221
+ isMeta,
2222
+ executionTraceId,
2223
+ context: isNewTrace ? contextData.id : contextData,
2224
+ previousRoutineExecution: context.__localRoutineExecId ?? context.__metadata?.__routineExecId ?? null,
2225
+ created: formatTimestamp(Date.now())
2226
+ },
2227
+ __metadata: {
2228
+ __executionTraceId: executionTraceId
2229
+ }
2230
+ });
2231
+ }
2232
+ allTasks.forEach(
2233
+ (task) => this.currentRun.addNode(
2234
+ new GraphNode(task, ctx, routineExecId, [], this.debug, this.verbose)
2235
+ )
2236
+ );
2237
+ }
2238
+ /**
2239
+ * Executes the provided tasks or routines. Maintains the execution state
2240
+ * and handles synchronous or asynchronous processing.
2241
+ *
2242
+ * @param {Task|GraphRoutine|(Task|GraphRoutine)[]} [tasks] - A single task, a single routine, or an array of tasks or routines to execute. Optional.
2243
+ * @param {AnyObject} [context] - An optional context object to be used during task execution.
2244
+ * @return {GraphRun|Promise<GraphRun>} - Returns a `GraphRun` instance if the execution is synchronous, or a `Promise` resolving to a `GraphRun` for asynchronous execution.
2245
+ */
2246
+ run(tasks, context) {
2247
+ if (tasks) {
2248
+ this.addTasks(tasks, context ?? {});
2249
+ }
2250
+ if (this.isRunning) {
2251
+ return this.currentRun;
2252
+ }
2253
+ if (this.currentRun) {
2254
+ this.isRunning = true;
2255
+ const runResult = this.currentRun.run();
2256
+ if (runResult instanceof Promise) {
2257
+ return this.runAsync(runResult);
2258
+ }
2259
+ }
2260
+ return this.reset();
2261
+ }
2262
+ /**
2263
+ * Executes the provided asynchronous operation and resets the state afterwards.
2264
+ *
2265
+ * @param {Promise<void>} run - A promise representing the asynchronous operation to execute.
2266
+ * @return {Promise<GraphRun>} A promise that resolves to the result of the reset operation after the asynchronous operation completes.
2267
+ */
2268
+ async runAsync(run) {
2269
+ await run;
2270
+ return this.reset();
2271
+ }
2272
+ /**
2273
+ * Resets the current state of the graph, creating a new GraphRun instance
2274
+ * and returning the previous run instance.
2275
+ * If the debug mode is not enabled, it will destroy the existing resources.
2276
+ *
2277
+ * @return {GraphRun} The last GraphRun instance before the reset.
2278
+ */
2279
+ reset() {
2280
+ this.isRunning = false;
2281
+ const lastRun = this.currentRun;
2282
+ if (!this.debug) {
2283
+ this.destroy();
2284
+ }
2285
+ this.currentRun = new GraphRun(this.strategy);
2286
+ return lastRun;
2287
+ }
2288
+ setDebug(value) {
2289
+ this.debug = value;
2290
+ }
2291
+ setVerbose(value) {
2292
+ this.verbose = value;
2293
+ }
2294
+ destroy() {
2295
+ this.currentRun.destroy();
2296
+ }
2297
+ /**
2298
+ * Sets the strategy to be used for running the graph and initializes
2299
+ * the current run with the provided strategy if no process is currently running.
2300
+ *
2301
+ * @param {GraphRunStrategy} strategy - The strategy to use for running the graph.
2302
+ * @return {void}
2303
+ */
2304
+ setStrategy(strategy) {
2305
+ this.strategy = strategy;
2306
+ if (!this.isRunning) {
2307
+ this.currentRun = new GraphRun(this.strategy);
2308
+ }
2309
+ }
2310
+ };
2311
+
2161
2312
  // src/graph/definition/Task.ts
2162
- import { v4 as uuid5 } from "uuid";
2313
+ import { v4 as uuid6 } from "uuid";
2163
2314
 
2164
2315
  // src/graph/iterators/TaskIterator.ts
2165
2316
  var TaskIterator = class {
@@ -2308,7 +2459,7 @@ var Task = class _Task extends SignalEmitter {
2308
2459
  }
2309
2460
  clone(traverse = false, includeSignals = false) {
2310
2461
  const clonedTask = new _Task(
2311
- `${this.name} (clone ${uuid5().slice(0, 8)})`,
2462
+ `${this.name} (clone ${uuid6().slice(0, 8)})`,
2312
2463
  this.taskFunction,
2313
2464
  this.description,
2314
2465
  this.concurrency,
@@ -2793,6 +2944,14 @@ var Task = class _Task extends SignalEmitter {
2793
2944
  mapPrevious(callback) {
2794
2945
  return Array.from(this.predecessorTasks).map(callback);
2795
2946
  }
2947
+ makeRoutine(name, description) {
2948
+ if (this.isMeta) {
2949
+ Cadenza.createMetaRoutine(name, [this], description);
2950
+ } else {
2951
+ Cadenza.createRoutine(name, [this], description);
2952
+ }
2953
+ return this;
2954
+ }
2796
2955
  /**
2797
2956
  * Adds the specified signals to the current instance, making it observe them.
2798
2957
  * If the instance is already observing a signal, it will be skipped.
@@ -2849,29 +3008,33 @@ var Task = class _Task extends SignalEmitter {
2849
3008
  emitsOnFail(...signals) {
2850
3009
  signals.forEach((signal) => {
2851
3010
  this.signalsToEmitOnFail.add(signal);
2852
- this.attachSignal(signal, true);
3011
+ this.attachSignal(signal);
2853
3012
  });
2854
3013
  return this;
2855
3014
  }
2856
3015
  /**
2857
3016
  * Attaches a signal to the current context and emits metadata if the register flag is set.
2858
3017
  *
2859
- * @param {string} signal - The name of the signal to attach.
2860
- * @param {boolean} [isOnFail=false] - Indicates if the signal should be marked as "on fail".
3018
+ * @param {...string} signals - The names of the signals to attach.
2861
3019
  * @return {void} This method does not return a value.
2862
3020
  */
2863
- attachSignal(signal, isOnFail = false) {
2864
- this.emitsSignals.add(signal);
2865
- if (this.register) {
2866
- this.emitWithMetadata("meta.task.attached_signal", {
2867
- data: {
2868
- signalName: signal.split(":")[0],
2869
- taskName: this.name,
2870
- taskVersion: this.version,
2871
- isOnFail
2872
- }
2873
- });
2874
- }
3021
+ attachSignal(...signals) {
3022
+ signals.forEach((signal) => {
3023
+ this.emitsSignals.add(signal);
3024
+ Cadenza.broker.registerEmittedSignal(signal);
3025
+ if (this.register) {
3026
+ const isOnFail = this.signalsToEmitOnFail.has(signal);
3027
+ this.emitWithMetadata("meta.task.attached_signal", {
3028
+ data: {
3029
+ signalName: signal.split(":")[0],
3030
+ taskName: this.name,
3031
+ taskVersion: this.version,
3032
+ isOnFail
3033
+ }
3034
+ });
3035
+ }
3036
+ });
3037
+ return this;
2875
3038
  }
2876
3039
  /**
2877
3040
  * Unsubscribes the current instance from the specified signals.
@@ -3251,205 +3414,6 @@ var GraphRegistry = class _GraphRegistry {
3251
3414
  }
3252
3415
  };
3253
3416
 
3254
- // src/engine/GraphRunner.ts
3255
- var GraphRunner = class extends SignalEmitter {
3256
- /**
3257
- * Constructs a runner.
3258
- * @param isMeta Meta flag (default false).
3259
- * @edge Creates 'Start run' meta-task chained to registry gets.
3260
- */
3261
- constructor(isMeta = false) {
3262
- super(isMeta);
3263
- this.debug = false;
3264
- this.verbose = false;
3265
- this.isRunning = false;
3266
- this.isMeta = false;
3267
- this.isMeta = isMeta;
3268
- this.strategy = Cadenza.runStrategy.PARALLEL;
3269
- this.currentRun = new GraphRun(this.strategy);
3270
- }
3271
- init() {
3272
- if (this.isMeta) return;
3273
- Cadenza.createMetaTask(
3274
- "Start run",
3275
- this.startRun.bind(this),
3276
- "Starts a run"
3277
- ).doAfter(
3278
- GraphRegistry.instance.getTaskByName,
3279
- GraphRegistry.instance.getRoutineByName
3280
- );
3281
- }
3282
- /**
3283
- * Adds tasks or routines to the current execution pipeline. Supports both individual tasks,
3284
- * routines, or arrays of tasks and routines. Handles metadata and execution context management.
3285
- *
3286
- * @param {Task|GraphRoutine|(Task|GraphRoutine)[]} tasks - The task(s) or routine(s) to be added.
3287
- * It can be a single task, a single routine, or an array of tasks and routines.
3288
- * @param {AnyObject} [context={}] - Optional context object to provide execution trace and metadata.
3289
- * Used to propagate information across task or routine executions.
3290
- * @return {void} - This method does not return a value.
3291
- */
3292
- addTasks(tasks, context = {}) {
3293
- let _tasks = Array.isArray(tasks) ? tasks : [tasks];
3294
- if (_tasks.length === 0) {
3295
- console.warn("No tasks/routines to add.");
3296
- return;
3297
- }
3298
- let routineName = _tasks.map((t) => t.name).join(" | ");
3299
- let routineVersion = null;
3300
- let isMeta = _tasks.every((t) => t.isMeta);
3301
- const allTasks = _tasks.flatMap((t) => {
3302
- if (t instanceof GraphRoutine) {
3303
- routineName = t.name;
3304
- routineVersion = t.version;
3305
- isMeta = t.isMeta;
3306
- const routineTasks = [];
3307
- t.forEachTask((task) => routineTasks.push(task));
3308
- return routineTasks;
3309
- }
3310
- return t;
3311
- });
3312
- const isSubMeta = allTasks.some((t) => t.isSubMeta) || !!context.__isSubMeta;
3313
- context.__isSubMeta = isSubMeta;
3314
- const isNewTrace = !context.__routineExecId && !context.__metadata?.__executionTraceId && !context.__executionTraceId;
3315
- const executionTraceId = context.__metadata?.__executionTraceId ?? context.__executionTraceId ?? uuid6();
3316
- context.__executionTraceId = executionTraceId;
3317
- const routineExecId = context.__routineExecId ?? uuid6();
3318
- context.__routineExecId = routineExecId;
3319
- const ctx = new GraphContext(context || {});
3320
- if (!isSubMeta) {
3321
- const contextData = ctx.export();
3322
- if (isNewTrace) {
3323
- this.emitMetrics("meta.runner.new_trace", {
3324
- data: {
3325
- uuid: executionTraceId,
3326
- issuer_type: "service",
3327
- // TODO: Add issuer type
3328
- issuer_id: context.__metadata?.__issuerId ?? context.__issuerId ?? null,
3329
- issued_at: formatTimestamp(Date.now()),
3330
- intent: context.__metadata?.__intent ?? context.__intent ?? null,
3331
- context: contextData,
3332
- is_meta: isMeta
3333
- },
3334
- __metadata: {
3335
- __executionTraceId: executionTraceId
3336
- }
3337
- });
3338
- }
3339
- this.emitMetrics("meta.runner.added_tasks", {
3340
- data: {
3341
- uuid: routineExecId,
3342
- name: routineName,
3343
- routineVersion,
3344
- isMeta,
3345
- executionTraceId,
3346
- context: isNewTrace ? contextData.id : contextData,
3347
- previousRoutineExecution: context.__localRoutineExecId ?? context.__metadata?.__routineExecId ?? null,
3348
- // TODO: There is a chance this is not added to the database yet...
3349
- created: formatTimestamp(Date.now())
3350
- },
3351
- __metadata: {
3352
- __executionTraceId: executionTraceId
3353
- }
3354
- });
3355
- }
3356
- allTasks.forEach(
3357
- (task) => this.currentRun.addNode(
3358
- new GraphNode(task, ctx, routineExecId, [], this.debug, this.verbose)
3359
- )
3360
- );
3361
- }
3362
- /**
3363
- * Executes the provided tasks or routines. Maintains the execution state
3364
- * and handles synchronous or asynchronous processing.
3365
- *
3366
- * @param {Task|GraphRoutine|(Task|GraphRoutine)[]} [tasks] - A single task, a single routine, or an array of tasks or routines to execute. Optional.
3367
- * @param {AnyObject} [context] - An optional context object to be used during task execution.
3368
- * @return {GraphRun|Promise<GraphRun>} - Returns a `GraphRun` instance if the execution is synchronous, or a `Promise` resolving to a `GraphRun` for asynchronous execution.
3369
- */
3370
- run(tasks, context) {
3371
- if (tasks) {
3372
- this.addTasks(tasks, context ?? {});
3373
- }
3374
- if (this.isRunning) {
3375
- return this.currentRun;
3376
- }
3377
- if (this.currentRun) {
3378
- this.isRunning = true;
3379
- const runResult = this.currentRun.run();
3380
- if (runResult instanceof Promise) {
3381
- return this.runAsync(runResult);
3382
- }
3383
- }
3384
- return this.reset();
3385
- }
3386
- /**
3387
- * Executes the provided asynchronous operation and resets the state afterwards.
3388
- *
3389
- * @param {Promise<void>} run - A promise representing the asynchronous operation to execute.
3390
- * @return {Promise<GraphRun>} A promise that resolves to the result of the reset operation after the asynchronous operation completes.
3391
- */
3392
- async runAsync(run) {
3393
- await run;
3394
- return this.reset();
3395
- }
3396
- /**
3397
- * Resets the current state of the graph, creating a new GraphRun instance
3398
- * and returning the previous run instance.
3399
- * If the debug mode is not enabled, it will destroy the existing resources.
3400
- *
3401
- * @return {GraphRun} The last GraphRun instance before the reset.
3402
- */
3403
- reset() {
3404
- this.isRunning = false;
3405
- const lastRun = this.currentRun;
3406
- if (!this.debug) {
3407
- this.destroy();
3408
- }
3409
- this.currentRun = new GraphRun(this.strategy);
3410
- return lastRun;
3411
- }
3412
- setDebug(value) {
3413
- this.debug = value;
3414
- }
3415
- setVerbose(value) {
3416
- this.verbose = value;
3417
- }
3418
- destroy() {
3419
- this.currentRun.destroy();
3420
- }
3421
- /**
3422
- * Sets the strategy to be used for running the graph and initializes
3423
- * the current run with the provided strategy if no process is currently running.
3424
- *
3425
- * @param {GraphRunStrategy} strategy - The strategy to use for running the graph.
3426
- * @return {void}
3427
- */
3428
- setStrategy(strategy) {
3429
- this.strategy = strategy;
3430
- if (!this.isRunning) {
3431
- this.currentRun = new GraphRun(this.strategy);
3432
- }
3433
- }
3434
- // TODO This should not live here. This is deputy related.
3435
- startRun(context, emit) {
3436
- if (context.task || context.routine) {
3437
- const routine = context.task ?? context.routine;
3438
- delete context.task;
3439
- delete context.routine;
3440
- context.__routineExecId = context.__metadata?.__deputyExecId ?? null;
3441
- context.__isDeputy = true;
3442
- this.run(routine, context);
3443
- return true;
3444
- } else {
3445
- context.errored = true;
3446
- context.__error = "No routine or task defined.";
3447
- emit("meta.runner.failed", context);
3448
- return false;
3449
- }
3450
- }
3451
- };
3452
-
3453
3417
  // src/graph/definition/DebounceTask.ts
3454
3418
  var DebounceTask = class extends Task {
3455
3419
  constructor(name, task, description = "", debounceTime = 1e3, leading = false, trailing = true, maxWait = 0, concurrency = 0, timeout = 0, register = true, isUnique = false, isMeta = false, isSubMeta = false, isHidden = false, inputSchema = void 0, validateInputSchema = false, outputSchema = void 0, validateOutputSchema = false) {
@@ -4408,8 +4372,6 @@ var Cadenza = class {
4408
4372
  }
4409
4373
  this.registry = GraphRegistry.instance;
4410
4374
  this.broker.init();
4411
- this.runner.init();
4412
- this.metaRunner.init();
4413
4375
  }
4414
4376
  /**
4415
4377
  * Retrieves the available strategies for running graphs.