@izara_project/izara-core-library-asynchronous-flow 1.0.28 → 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.28",
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
@@ -374,15 +443,20 @@ export async function checkAllAwaitingStepsFinished(
374
443
 
375
444
  /**
376
445
  * 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]`.
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.
379
448
  * @async
380
449
  * @param {IzContext} _izContext
381
450
  * @param {string} pendingStepId
382
451
  * @param {string|null} [currentAwaitingStepId=null] - The step that has just finished.
383
452
  * @param {any[]} [errorsFound=[]]
384
453
  * @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.
454
+ * @returns {Promise<{
455
+ * isComplete: boolean,
456
+ * collectedAttributes: Record<string, any>|null,
457
+ * collectedErrors: any[],
458
+ * sharedAdditionalAttributes: any|null
459
+ * }>}
386
460
  */
387
461
  export async function checkAllAwaitingStepsFinishedWithReturnParams(
388
462
  _izContext,
@@ -415,24 +489,42 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
415
489
 
416
490
  _izContext.logger.debug('awaitingStepItems:::', awaitingStepItems);
417
491
 
418
- const collectedAttributes = {};
419
- const collectedErrors = [];
420
-
492
+ // Pass 1: check completeness of all other steps before collecting any data
421
493
  for (const item of awaitingStepItems.Items) {
422
494
  if (item.awaitingStepId !== currentAwaitingStepId && !item.complete) {
423
- return [false, null, collectedErrors];
495
+ return {
496
+ isComplete: false,
497
+ collectedAttributes: null,
498
+ collectedErrors: [],
499
+ sharedAdditionalAttributes: null
500
+ };
424
501
  }
502
+ }
503
+
504
+ // Pass 2: all steps are complete — collect errors and attributes
505
+ const collectedAttributes = {};
506
+ const collectedErrors = [];
507
+ let sharedAdditionalAttributes = null;
425
508
 
509
+ for (const item of awaitingStepItems.Items) {
426
510
  if (item.errorsFound?.length > 0) {
427
511
  collectedErrors.push(...item.errorsFound);
428
512
  }
429
513
 
430
514
  if (item.additionalAttributes) {
431
515
  collectedAttributes[item.awaitingStepId] = item.additionalAttributes;
516
+ if (sharedAdditionalAttributes === null) {
517
+ sharedAdditionalAttributes = item.additionalAttributes;
518
+ }
432
519
  }
433
520
  }
434
521
 
435
- return [true, collectedAttributes, collectedErrors];
522
+ return {
523
+ isComplete: true,
524
+ collectedAttributes,
525
+ collectedErrors,
526
+ sharedAdditionalAttributes
527
+ };
436
528
  }
437
529
 
438
530