@izara_project/izara-core-library-asynchronous-flow 1.0.27 → 1.0.29

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.27",
6
+ "version": "1.0.29",
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,73 @@ 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
+ additionalAttributes = {}
212
+ ) {
213
+ _izContext.logger.debug('[Lib:AsyncFlow:createNewAwaitingMultipleSteps] Input: ', {
214
+ pendingStepId,
215
+ countAwaitingMultipleSteps,
216
+ additionalAttributes
217
+ });
218
+
219
+ const awaitingStepIds = Array.from({ length: countAwaitingMultipleSteps }, () => identifierUuid());
220
+
221
+ const promiseArray = [];
222
+
223
+ for (const awaitingStepId of awaitingStepIds) {
224
+ const attributesWhenCreate = {
225
+ awaitingStepId: awaitingStepId,
226
+ pendingStepId: pendingStepId,
227
+ complete: false,
228
+ errorsFound: [],
229
+ };
230
+ promiseArray.push(
231
+ dynamodbSharedLib.putItem(
232
+ _izContext,
233
+ dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
234
+ attributesWhenCreate
235
+ )
236
+ );
237
+
238
+ const attributesForPending = {
239
+ ...attributesWhenCreate,
240
+ additionalAttributes: additionalAttributes
241
+ };
242
+
243
+ promiseArray.push(
244
+ dynamodbSharedLib.putItem(
245
+ _izContext,
246
+ dynamodbSharedLib.tableName(
247
+ _izContext,
248
+ 'AwaitingMultipleStepByPending'
249
+ ),
250
+ attributesForPending
251
+ )
252
+ );
253
+
254
+ _izContext.logger.debug('putItem:AwaitingMultipleStepByPending', {
255
+ awaitingStepId: attributesWhenCreate.awaitingStepId
256
+ });
257
+ }
258
+
259
+ await Promise.all(promiseArray);
260
+
261
+ return awaitingStepIds;
262
+ }
263
+
195
264
  /**
196
265
  * Find all pendingStepIds that are waiting on a given awaitingStepId (multiple).
197
266
  * @async
@@ -348,56 +417,46 @@ export async function checkAllAwaitingStepsFinished(
348
417
  errorsFound = [],
349
418
  additionalAttributes = {}
350
419
  ) {
351
-
352
420
  await checkAllAwaitingStepsFinishedShared(
353
421
  _izContext,
354
422
  pendingStepId,
355
- currentAwaitingStepId = null,
356
- errorsFound = [],
357
- additionalAttributes = {}
423
+ currentAwaitingStepId,
424
+ errorsFound,
425
+ additionalAttributes
358
426
  );
359
427
 
360
- let listPendingStepIds = await dynamodbSharedLib.query(
428
+ const items = await dynamodbSharedLib.query(
361
429
  _izContext,
362
430
  dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
363
- {
364
- pendingStepId: pendingStepId
365
- },
366
- {
367
- limit: 50 // arbitrary limit so not pull too many results, need >2 because some others might be marked as "complete" = true
368
- }
431
+ { pendingStepId },
432
+ { limit: 50 }
369
433
  );
370
- for (let idx = 0; idx < listPendingStepIds.Items.length; idx++) {
371
- // if have error found return errorsFound
372
- // wrap function
373
-
374
- if (
375
- currentAwaitingStepId &&
376
- listPendingStepIds.Items[idx].awaitingStepId == currentAwaitingStepId
377
- ) {
378
- continue;
379
- }
380
- // if any record found not set to complete then there are steps not yet finished
381
- if (!listPendingStepIds.Items[idx].complete) {
382
- return false;
383
- }
434
+
435
+ for (const item of items.Items) {
436
+ if (item.awaitingStepId === currentAwaitingStepId) continue;
437
+ if (!item.complete) return false;
384
438
  }
385
439
 
386
- return true; // all passed
440
+ return true;
387
441
  }
388
442
 
389
443
 
390
444
  /**
391
445
  * Checks if all awaiting steps for a pending step are complete after marking the current one as complete.
392
- * If all steps are finished, it returns `true` and an object containing the `additionalAttributes` from each of the completed steps, indexed by their `awaitingStepId`.
393
- * If any other step is not yet complete, it returns `[false, null]`.
446
+ * If all steps are finished, returns an object with `isComplete: true` and the collected data.
447
+ * If any other step is not yet complete, returns `isComplete: false` with null data.
394
448
  * @async
395
449
  * @param {IzContext} _izContext
396
450
  * @param {string} pendingStepId
397
451
  * @param {string|null} [currentAwaitingStepId=null] - The step that has just finished.
398
452
  * @param {any[]} [errorsFound=[]]
399
453
  * @param {Attrs} [additionalAttributes={}]
400
- * @returns {Promise<[boolean, Record<string, any>|null]>} A tuple indicating completion status and the collected attributes, or null if not all steps are complete.
454
+ * @returns {Promise<{
455
+ * isComplete: boolean,
456
+ * collectedAttributes: Record<string, any>|null,
457
+ * collectedErrors: any[],
458
+ * sharedAdditionalAttributes: any|null
459
+ * }>}
401
460
  */
402
461
  export async function checkAllAwaitingStepsFinishedWithReturnParams(
403
462
  _izContext,
@@ -406,44 +465,66 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
406
465
  errorsFound = [],
407
466
  additionalAttributes = {}
408
467
  ) {
468
+ _izContext.logger.debug('Lib:checkAllAwaitingStepsFinishedWithReturnParams', {
469
+ pendingStepId,
470
+ currentAwaitingStepId,
471
+ errorsFound,
472
+ additionalAttributes
473
+ });
409
474
 
410
475
  await checkAllAwaitingStepsFinishedShared(
411
476
  _izContext,
412
477
  pendingStepId,
413
- currentAwaitingStepId = null,
414
- errorsFound = [],
415
- additionalAttributes = {}
478
+ currentAwaitingStepId,
479
+ errorsFound,
480
+ additionalAttributes
416
481
  );
417
482
 
418
483
  const awaitingStepItems = await dynamodbSharedLib.query(
419
484
  _izContext,
420
485
  dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
421
486
  { pendingStepId },
422
- {
423
- limit: 50
424
- }
487
+ { limit: 50 }
425
488
  );
426
489
 
427
490
  _izContext.logger.debug('awaitingStepItems:::', awaitingStepItems);
428
491
 
429
- const collectedAttributes = {};
430
- const collectedErrors = [];
431
-
492
+ // Pass 1: check completeness of all other steps before collecting any data
432
493
  for (const item of awaitingStepItems.Items) {
433
494
  if (item.awaitingStepId !== currentAwaitingStepId && !item.complete) {
434
- return [false, null, []];
495
+ return {
496
+ isComplete: false,
497
+ collectedAttributes: null,
498
+ collectedErrors: [],
499
+ sharedAdditionalAttributes: null
500
+ };
435
501
  }
502
+ }
436
503
 
504
+ // Pass 2: all steps are complete — collect errors and attributes
505
+ const collectedAttributes = {};
506
+ const collectedErrors = [];
507
+ let sharedAdditionalAttributes = null;
508
+
509
+ for (const item of awaitingStepItems.Items) {
437
510
  if (item.errorsFound?.length > 0) {
438
511
  collectedErrors.push(...item.errorsFound);
439
512
  }
440
513
 
441
514
  if (item.additionalAttributes) {
442
515
  collectedAttributes[item.awaitingStepId] = item.additionalAttributes;
516
+ if (sharedAdditionalAttributes === null) {
517
+ sharedAdditionalAttributes = item.additionalAttributes;
518
+ }
443
519
  }
444
520
  }
445
521
 
446
- return [true, collectedAttributes, collectedErrors];
522
+ return {
523
+ isComplete: true,
524
+ collectedAttributes,
525
+ collectedErrors,
526
+ sharedAdditionalAttributes
527
+ };
447
528
  }
448
529
 
449
530