@izara_project/izara-core-library-asynchronous-flow 1.0.28 → 1.0.30

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/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "author": "Sven Mason <thebarbariansven@gmail.com>",
4
4
  "license": "AGPL-3.0-or-later",
5
5
  "homepage": "https://bitbucket.org/izara-core-libraries/izara-core-library-asynchronous-flow#readme",
6
- "version": "1.0.28",
6
+ "version": "1.0.30",
7
7
  "description": "Shared asynchronous flow logic",
8
8
  "type": "module",
9
9
  "main": "index.js",
@@ -31,5 +31,7 @@
31
31
  "@izara_project/izara-core-library-sqs": "^1.0.7"
32
32
  },
33
33
  "peerDependenciesMeta": {},
34
- "dependencies": {}
34
+ "dependencies": {
35
+ "@izara_project/izara-shared-core": "^1.0.12"
36
+ }
35
37
  }
@@ -18,6 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
18
18
  import { NoRetryError } from '@izara_project/izara-core-library-core';
19
19
  import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
20
20
 
21
+ import { identifierUuid } from '@izara_project/izara-shared-core';
22
+
21
23
  //====================================== AwaitingMultipleSteps
22
24
  // AwaitingMultipleSteps is when a flow is awaiting multiple external flows before it can continue
23
25
  // One awaitingStepId can have multiple pendingStepIds that are awaiting it
@@ -192,6 +194,80 @@ export async function createAwaitingMultipleSteps(
192
194
  await Promise.all(promiseArray);
193
195
  }
194
196
 
197
+ /**
198
+ * Create new awaiting multiple steps for a pending step.
199
+ * @async
200
+ * @param {IzContext} _izContext
201
+ * @param {string} pendingStepId
202
+ * @param {number} countAwaitingMultipleSteps
203
+ * @param {Object.<string, any>} [additionalAttributes={}] - Shared attributes stored for every step in AwaitingMultipleStepByPending.
204
+ * The same object is applied to all steps (caller cannot know the generated UUIDs beforehand).
205
+ * @returns {Promise<string[]>} The list of awaiting step IDs created.
206
+ */
207
+ export async function createNewAwaitingMultipleSteps(
208
+ _izContext,
209
+ pendingStepId,
210
+ countAwaitingMultipleSteps,
211
+ prefix = '',
212
+ additionalAttributes = {}
213
+ ) {
214
+ _izContext.logger.debug(
215
+ '[Lib:AsyncFlow:createNewAwaitingMultipleSteps] Input: ',
216
+ {
217
+ pendingStepId,
218
+ countAwaitingMultipleSteps,
219
+ additionalAttributes
220
+ }
221
+ );
222
+
223
+ const parendIds = Array.from(
224
+ { length: countAwaitingMultipleSteps },
225
+ () => (prefix ? `${prefix}_` : '') + identifierUuid.generate()
226
+ );
227
+
228
+ const promiseArray = [];
229
+
230
+ for (const parendId of parendIds) {
231
+ const attributesWhenCreate = {
232
+ awaitingStepId: parendId,
233
+ pendingStepId: pendingStepId,
234
+ complete: false,
235
+ errorsFound: []
236
+ };
237
+ promiseArray.push(
238
+ dynamodbSharedLib.putItem(
239
+ _izContext,
240
+ dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
241
+ attributesWhenCreate
242
+ )
243
+ );
244
+
245
+ const attributesForPending = {
246
+ ...attributesWhenCreate,
247
+ additionalAttributes: additionalAttributes
248
+ };
249
+
250
+ promiseArray.push(
251
+ dynamodbSharedLib.putItem(
252
+ _izContext,
253
+ dynamodbSharedLib.tableName(
254
+ _izContext,
255
+ 'AwaitingMultipleStepByPending'
256
+ ),
257
+ attributesForPending
258
+ )
259
+ );
260
+
261
+ _izContext.logger.debug('putItem:AwaitingMultipleStepByPending', {
262
+ awaitingStepId: attributesWhenCreate.awaitingStepId
263
+ });
264
+ }
265
+
266
+ await Promise.all(promiseArray);
267
+
268
+ return parendIds;
269
+ }
270
+
195
271
  /**
196
272
  * Find all pendingStepIds that are waiting on a given awaitingStepId (multiple).
197
273
  * @async
@@ -330,7 +406,6 @@ export async function checkAllAwaitingStepsFinishedShared(
330
406
  }
331
407
  }
332
408
 
333
-
334
409
  /**
335
410
  * Same as checkAllAwaitingStepsFinished but writes errors/additionalAttributes to the *_ByPending row.
336
411
  * @async
@@ -371,18 +446,22 @@ export async function checkAllAwaitingStepsFinished(
371
446
  return true;
372
447
  }
373
448
 
374
-
375
449
  /**
376
450
  * Checks if all awaiting steps for a pending step are complete after marking the current one as complete.
377
- * If all steps are finished, it returns `true` and an object containing the `additionalAttributes` from each of the completed steps, indexed by their `awaitingStepId`.
378
- * If any other step is not yet complete, it returns `[false, null]`.
451
+ * If all steps are finished, returns an object with `isComplete: true` and the collected data.
452
+ * If any other step is not yet complete, returns `isComplete: false` with null data.
379
453
  * @async
380
454
  * @param {IzContext} _izContext
381
455
  * @param {string} pendingStepId
382
456
  * @param {string|null} [currentAwaitingStepId=null] - The step that has just finished.
383
457
  * @param {any[]} [errorsFound=[]]
384
458
  * @param {Attrs} [additionalAttributes={}]
385
- * @returns {Promise<[boolean, Record<string, any>|null]>} A tuple indicating completion status and the collected attributes, or null if not all steps are complete.
459
+ * @returns {Promise<{
460
+ * isComplete: boolean,
461
+ * collectedAttributes: Record<string, any>|null,
462
+ * collectedErrors: any[],
463
+ * sharedAdditionalAttributes: any|null
464
+ * }>}
386
465
  */
387
466
  export async function checkAllAwaitingStepsFinishedWithReturnParams(
388
467
  _izContext,
@@ -415,27 +494,44 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
415
494
 
416
495
  _izContext.logger.debug('awaitingStepItems:::', awaitingStepItems);
417
496
 
418
- const collectedAttributes = {};
419
- const collectedErrors = [];
420
-
497
+ // Pass 1: check completeness of all other steps before collecting any data
421
498
  for (const item of awaitingStepItems.Items) {
422
499
  if (item.awaitingStepId !== currentAwaitingStepId && !item.complete) {
423
- return [false, null, collectedErrors];
500
+ return {
501
+ isComplete: false,
502
+ collectedAttributes: null,
503
+ collectedErrors: [],
504
+ sharedAdditionalAttributes: null
505
+ };
424
506
  }
507
+ }
425
508
 
509
+ // Pass 2: all steps are complete — collect errors and attributes
510
+ const collectedAttributes = {};
511
+ const collectedErrors = [];
512
+ let sharedAdditionalAttributes = null;
513
+
514
+ for (const item of awaitingStepItems.Items) {
426
515
  if (item.errorsFound?.length > 0) {
427
516
  collectedErrors.push(...item.errorsFound);
428
517
  }
429
518
 
430
519
  if (item.additionalAttributes) {
431
520
  collectedAttributes[item.awaitingStepId] = item.additionalAttributes;
521
+ if (sharedAdditionalAttributes === null) {
522
+ sharedAdditionalAttributes = item.additionalAttributes;
523
+ }
432
524
  }
433
525
  }
434
526
 
435
- return [true, collectedAttributes, collectedErrors];
527
+ return {
528
+ isComplete: true,
529
+ collectedAttributes,
530
+ collectedErrors,
531
+ sharedAdditionalAttributes
532
+ };
436
533
  }
437
534
 
438
-
439
535
  /**
440
536
  * Remove all awaiting records for a given pendingStepId from both tables.
441
537
  * @async
@@ -556,4 +652,4 @@ export async function removeAwaitingMultipleStep(
556
652
  );
557
653
  }
558
654
  await Promise.all(promiseArray);
559
- }
655
+ }