@izara_project/izara-core-library-asynchronous-flow 1.0.47 → 1.0.49

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.47",
6
+ "version": "1.0.49",
7
7
  "description": "Shared asynchronous flow logic",
8
8
  "type": "module",
9
9
  "main": "index.js",
@@ -16,8 +16,8 @@
16
16
  },
17
17
  "devDependencies": {
18
18
  "@izara_project/izara-core-library-core": "^1.0.32",
19
- "@izara_project/izara-core-library-dynamodb": "^1.0.21",
20
- "@izara_project/izara-core-library-external-request": "^1.0.30",
19
+ "@izara_project/izara-core-library-dynamodb": "^1.0.22",
20
+ "@izara_project/izara-core-library-external-request": "^1.0.32",
21
21
  "@izara_project/izara-core-library-logger": "^1.0.11",
22
22
  "@izara_project/izara-core-library-sns": "^1.0.8",
23
23
  "@izara_project/izara-core-library-sqs": "^1.0.7",
@@ -55,7 +55,14 @@ async function _putAwaitingMultipleStepRecords(
55
55
  ...sharedAttributes
56
56
  };
57
57
  if (additionalAttributes) {
58
- itemPending.additionalAttributes = additionalAttributes;
58
+ if (sharedAttributes.additionalAttributes) {
59
+ itemPending.additionalAttributes = {
60
+ ...sharedAttributes.additionalAttributes,
61
+ ...additionalAttributes
62
+ };
63
+ } else {
64
+ itemPending.additionalAttributes = additionalAttributes;
65
+ }
59
66
  }
60
67
 
61
68
  return [
@@ -168,7 +175,7 @@ export async function createAwaitingMultipleSteps(
168
175
 
169
176
  return {
170
177
  awaitingStepId,
171
- additionalAttributes,
178
+ additionalAttributes: record.additionalAttributes,
172
179
  message: {
173
180
  ...record.message,
174
181
  parentFlowId: awaitingStepId
@@ -194,10 +201,7 @@ export async function createAwaitingMultipleSteps(
194
201
  }
195
202
 
196
203
  return {
197
- awaitingStepId: createAwaitingStepId(
198
- awaitingStepId,
199
- prefix
200
- ),
204
+ awaitingStepId: createAwaitingStepId(awaitingStepId, prefix),
201
205
  additionalAttributes: mergedAttributes
202
206
  };
203
207
  }
@@ -373,6 +377,17 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
373
377
  _assertPendingStepId(pendingStepId);
374
378
 
375
379
  if (currentAwaitingStepId) {
380
+ _izContext.logger.debug(
381
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Updating awaitingStepItem in DB',
382
+ {
383
+ pendingStepId,
384
+ awaitingStepId: currentAwaitingStepId,
385
+ complete: true,
386
+ errorsFound,
387
+ returnValues
388
+ }
389
+ );
390
+
376
391
  await dynamodbSharedLib.updateItem(
377
392
  _izContext,
378
393
  dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
@@ -386,6 +401,16 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
386
401
  returnValues
387
402
  }
388
403
  );
404
+
405
+ _izContext.logger.debug(
406
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] After updating awaitingStepItems',
407
+ {
408
+ pendingStepId,
409
+ awaitingStepId: currentAwaitingStepId,
410
+ errorsFound,
411
+ returnValues
412
+ }
413
+ );
389
414
  }
390
415
 
391
416
  const awaitingStepItems = await _queryAwaitingStepsByPendingStepId(
@@ -394,10 +419,30 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
394
419
  );
395
420
 
396
421
  _izContext.logger.debug(
397
- '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] awaitingStepItems',
398
- { awaitingStepItems }
422
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Queried awaitingStepItems',
423
+ {
424
+ pendingStepId,
425
+ itemsCount: awaitingStepItems ? awaitingStepItems.length : 0,
426
+ awaitingStepItems
427
+ }
399
428
  );
400
429
 
430
+ if (!awaitingStepItems || awaitingStepItems.length === 0) {
431
+ _izContext.logger.warn(
432
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] No awaiting steps found for pendingStepId',
433
+ { pendingStepId, currentAwaitingStepId }
434
+ );
435
+ return {
436
+ isComplete: false,
437
+ collectedReturnValueByAwaitingStepId: null,
438
+ collectedErrors: [
439
+ `No awaiting steps found for pendingStepId: ${pendingStepId}`
440
+ ],
441
+ returnValues: null,
442
+ additionalAttributes: null
443
+ };
444
+ }
445
+
401
446
  const hasIncomplete = awaitingStepItems.some(
402
447
  item => item.awaitingStepId !== currentAwaitingStepId && !item.complete
403
448
  );
@@ -407,7 +452,64 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
407
452
  defaultAttrs = awaitingStepItems[0].additionalAttributes;
408
453
  }
409
454
 
455
+ _izContext.logger.debug(
456
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Completion check status',
457
+ {
458
+ pendingStepId,
459
+ currentAwaitingStepId,
460
+ hasIncomplete,
461
+ defaultAttrs
462
+ }
463
+ );
464
+
410
465
  if (hasIncomplete) {
466
+ _izContext.logger.debug(
467
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Incomplete steps remaining',
468
+ {
469
+ pendingStepId,
470
+ incompleteSteps: awaitingStepItems
471
+ .filter(
472
+ item =>
473
+ item.awaitingStepId !== currentAwaitingStepId && !item.complete
474
+ )
475
+ .map(item => item.awaitingStepId)
476
+ }
477
+ );
478
+ return {
479
+ isComplete: false,
480
+ collectedReturnValueByAwaitingStepId: null,
481
+ collectedErrors: [],
482
+ returnValues: null,
483
+ additionalAttributes: defaultAttrs
484
+ };
485
+ }
486
+
487
+ // ── Atomic completion claim to prevent concurrent duplicate execution ─────
488
+ const primaryStep = awaitingStepItems[0];
489
+ try {
490
+ await dynamodbSharedLib.updateItem(
491
+ _izContext,
492
+ dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
493
+ {
494
+ pendingStepId,
495
+ awaitingStepId: primaryStep.awaitingStepId
496
+ },
497
+ { isFinalized: true },
498
+ {
499
+ conditionExpression: 'attribute_not_exists(isFinalized)'
500
+ },
501
+ {
502
+ errorOnConditionalExpNotPass: true
503
+ }
504
+ );
505
+ } catch (err) {
506
+ _izContext.logger.debug(
507
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Completion already claimed by another process',
508
+ {
509
+ pendingStepId,
510
+ error: err.message
511
+ }
512
+ );
411
513
  return {
412
514
  isComplete: false,
413
515
  collectedReturnValueByAwaitingStepId: null,
@@ -456,6 +558,14 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
456
558
  );
457
559
  }
458
560
 
561
+ _izContext.logger.debug(
562
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Completed. Returning result:',
563
+ {
564
+ pendingStepId,
565
+ result
566
+ }
567
+ );
568
+
459
569
  return result;
460
570
  }
461
571
 
@@ -526,7 +636,7 @@ export async function removeAwaitingMultipleStep(
526
636
  if (!awaitingStepId || !pendingStepId) {
527
637
  throw new NoRetryError(
528
638
  '[Lib:removeAwaitingMultipleStep]' +
529
- ' awaitingStepId or pendingStepId required'
639
+ ' awaitingStepId or pendingStepId required'
530
640
  );
531
641
  }
532
642
 
@@ -568,23 +678,19 @@ export async function completeAction(
568
678
  prefix = '',
569
679
  returnValue = {},
570
680
  errorsFound = []
571
- ){
572
- _izContext.logger.debug('[Lib:CompleteAction] Input parameters', {
573
- parentFlowId,
574
- prefix
681
+ ) {
682
+ _izContext.logger.debug('[Lib:CompleteAction] Input parameters', {
683
+ parentFlowId,
684
+ prefix
575
685
  });
576
686
 
577
687
  try {
578
-
579
688
  const { pendingStepId } = await findPendingStepAwaitingMultipleSteps(
580
689
  _izContext,
581
- createAwaitingStepId(
582
- parentFlowId,
583
- prefix
584
- )
690
+ createAwaitingStepId(parentFlowId, prefix)
585
691
  );
586
692
 
587
- if (!pendingStepId) {
693
+ if (!pendingStepId) {
588
694
  _izContext.logger.warn(
589
695
  `No pending step found for awaitingStepId: ${awaitingStepId}`
590
696
  );
@@ -600,29 +706,26 @@ export async function completeAction(
600
706
  } = await checkAllAwaitingStepsFinishedWithReturnParams(
601
707
  _izContext,
602
708
  pendingStepId,
603
- createAwaitingStepId(
604
- parentFlowId,
605
- prefix
606
- )
709
+ createAwaitingStepId(parentFlowId, prefix)
607
710
  );
608
711
 
609
712
  let status = true;
610
713
 
611
714
  if (!isComplete) {
612
- status = false
613
- };
715
+ status = false;
716
+ }
614
717
 
615
718
  if (collectedErrors.length > 0 || errorsFound.length > 0) {
616
- status =false
617
- };
719
+ status = false;
720
+ }
618
721
 
619
722
  if (status) {
620
- await Promise.all(
621
- (pendingStepId.listOfRecords ?? []).flatMap((records) =>
622
- Object.values(records).map(async (record) =>
623
- dynamodbSharedLib.putItem(
624
- _izContext,
625
- await dynamodbSharedLib.tableName(
723
+ await Promise.all(
724
+ (pendingStepId.listOfRecords ?? []).flatMap(records =>
725
+ Object.values(records).map(async record =>
726
+ dynamodbSharedLib.putItem(
727
+ _izContext,
728
+ await dynamodbSharedLib.tableName(
626
729
  _izContext,
627
730
  record.tableName,
628
731
  record.serviceTag
@@ -644,9 +747,8 @@ export async function completeAction(
644
747
  collectedErrors,
645
748
  returnValues,
646
749
  additionalAttributes
647
- }
648
-
750
+ };
649
751
  } catch (err) {
650
- _izContext.logger.error(err)
752
+ _izContext.logger.error(err);
651
753
  }
652
- }
754
+ }