@izara_project/izara-core-library-asynchronous-flow 1.0.46 → 1.0.48

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.46",
6
+ "version": "1.0.48",
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",
@@ -168,7 +168,7 @@ export async function createAwaitingMultipleSteps(
168
168
 
169
169
  return {
170
170
  awaitingStepId,
171
- additionalAttributes,
171
+ additionalAttributes: record.additionalAttributes,
172
172
  message: {
173
173
  ...record.message,
174
174
  parentFlowId: awaitingStepId
@@ -194,7 +194,7 @@ export async function createAwaitingMultipleSteps(
194
194
  }
195
195
 
196
196
  return {
197
- awaitingStepId,
197
+ awaitingStepId: createAwaitingStepId(awaitingStepId, prefix),
198
198
  additionalAttributes: mergedAttributes
199
199
  };
200
200
  }
@@ -370,6 +370,17 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
370
370
  _assertPendingStepId(pendingStepId);
371
371
 
372
372
  if (currentAwaitingStepId) {
373
+ _izContext.logger.debug(
374
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Updating awaitingStepItem in DB',
375
+ {
376
+ pendingStepId,
377
+ awaitingStepId: currentAwaitingStepId,
378
+ complete: true,
379
+ errorsFound,
380
+ returnValues
381
+ }
382
+ );
383
+
373
384
  await dynamodbSharedLib.updateItem(
374
385
  _izContext,
375
386
  dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
@@ -383,6 +394,16 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
383
394
  returnValues
384
395
  }
385
396
  );
397
+
398
+ _izContext.logger.debug(
399
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] After updating awaitingStepItems',
400
+ {
401
+ pendingStepId,
402
+ awaitingStepId: currentAwaitingStepId,
403
+ errorsFound,
404
+ returnValues
405
+ }
406
+ );
386
407
  }
387
408
 
388
409
  const awaitingStepItems = await _queryAwaitingStepsByPendingStepId(
@@ -391,10 +412,30 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
391
412
  );
392
413
 
393
414
  _izContext.logger.debug(
394
- '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] awaitingStepItems',
395
- { awaitingStepItems }
415
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Queried awaitingStepItems',
416
+ {
417
+ pendingStepId,
418
+ itemsCount: awaitingStepItems ? awaitingStepItems.length : 0,
419
+ awaitingStepItems
420
+ }
396
421
  );
397
422
 
423
+ if (!awaitingStepItems || awaitingStepItems.length === 0) {
424
+ _izContext.logger.warn(
425
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] No awaiting steps found for pendingStepId',
426
+ { pendingStepId, currentAwaitingStepId }
427
+ );
428
+ return {
429
+ isComplete: false,
430
+ collectedReturnValueByAwaitingStepId: null,
431
+ collectedErrors: [
432
+ `No awaiting steps found for pendingStepId: ${pendingStepId}`
433
+ ],
434
+ returnValues: null,
435
+ additionalAttributes: null
436
+ };
437
+ }
438
+
398
439
  const hasIncomplete = awaitingStepItems.some(
399
440
  item => item.awaitingStepId !== currentAwaitingStepId && !item.complete
400
441
  );
@@ -404,7 +445,64 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
404
445
  defaultAttrs = awaitingStepItems[0].additionalAttributes;
405
446
  }
406
447
 
448
+ _izContext.logger.debug(
449
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Completion check status',
450
+ {
451
+ pendingStepId,
452
+ currentAwaitingStepId,
453
+ hasIncomplete,
454
+ defaultAttrs
455
+ }
456
+ );
457
+
407
458
  if (hasIncomplete) {
459
+ _izContext.logger.debug(
460
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Incomplete steps remaining',
461
+ {
462
+ pendingStepId,
463
+ incompleteSteps: awaitingStepItems
464
+ .filter(
465
+ item =>
466
+ item.awaitingStepId !== currentAwaitingStepId && !item.complete
467
+ )
468
+ .map(item => item.awaitingStepId)
469
+ }
470
+ );
471
+ return {
472
+ isComplete: false,
473
+ collectedReturnValueByAwaitingStepId: null,
474
+ collectedErrors: [],
475
+ returnValues: null,
476
+ additionalAttributes: defaultAttrs
477
+ };
478
+ }
479
+
480
+ // ── Atomic completion claim to prevent concurrent duplicate execution ─────
481
+ const primaryStep = awaitingStepItems[0];
482
+ try {
483
+ await dynamodbSharedLib.updateItem(
484
+ _izContext,
485
+ dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
486
+ {
487
+ pendingStepId,
488
+ awaitingStepId: primaryStep.awaitingStepId
489
+ },
490
+ { isFinalized: true },
491
+ {
492
+ conditionExpression: 'attribute_not_exists(isFinalized)'
493
+ },
494
+ {
495
+ errorOnConditionalExpNotPass: true
496
+ }
497
+ );
498
+ } catch (err) {
499
+ _izContext.logger.debug(
500
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Completion already claimed by another process',
501
+ {
502
+ pendingStepId,
503
+ error: err.message
504
+ }
505
+ );
408
506
  return {
409
507
  isComplete: false,
410
508
  collectedReturnValueByAwaitingStepId: null,
@@ -453,6 +551,14 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
453
551
  );
454
552
  }
455
553
 
554
+ _izContext.logger.debug(
555
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Completed. Returning result:',
556
+ {
557
+ pendingStepId,
558
+ result
559
+ }
560
+ );
561
+
456
562
  return result;
457
563
  }
458
564
 
@@ -523,7 +629,7 @@ export async function removeAwaitingMultipleStep(
523
629
  if (!awaitingStepId || !pendingStepId) {
524
630
  throw new NoRetryError(
525
631
  '[Lib:removeAwaitingMultipleStep]' +
526
- ' awaitingStepId or pendingStepId required'
632
+ ' awaitingStepId or pendingStepId required'
527
633
  );
528
634
  }
529
635
 
@@ -565,23 +671,19 @@ export async function completeAction(
565
671
  prefix = '',
566
672
  returnValue = {},
567
673
  errorsFound = []
568
- ){
569
- _izContext.logger.debug('[Lib:CompleteAction] Input parameters', {
570
- parentFlowId,
571
- prefix
674
+ ) {
675
+ _izContext.logger.debug('[Lib:CompleteAction] Input parameters', {
676
+ parentFlowId,
677
+ prefix
572
678
  });
573
679
 
574
680
  try {
575
-
576
681
  const { pendingStepId } = await findPendingStepAwaitingMultipleSteps(
577
682
  _izContext,
578
- createAwaitingStepId(
579
- parentFlowId,
580
- prefix
581
- )
683
+ createAwaitingStepId(parentFlowId, prefix)
582
684
  );
583
685
 
584
- if (!pendingStepId) {
686
+ if (!pendingStepId) {
585
687
  _izContext.logger.warn(
586
688
  `No pending step found for awaitingStepId: ${awaitingStepId}`
587
689
  );
@@ -597,29 +699,26 @@ export async function completeAction(
597
699
  } = await checkAllAwaitingStepsFinishedWithReturnParams(
598
700
  _izContext,
599
701
  pendingStepId,
600
- createAwaitingStepId(
601
- parentFlowId,
602
- prefix
603
- )
702
+ createAwaitingStepId(parentFlowId, prefix)
604
703
  );
605
704
 
606
705
  let status = true;
607
706
 
608
707
  if (!isComplete) {
609
- status = false
610
- };
708
+ status = false;
709
+ }
611
710
 
612
711
  if (collectedErrors.length > 0 || errorsFound.length > 0) {
613
- status =false
614
- };
712
+ status = false;
713
+ }
615
714
 
616
715
  if (status) {
617
- await Promise.all(
618
- (pendingStepId.listOfRecords ?? []).flatMap((records) =>
619
- Object.values(records).map(async (record) =>
620
- dynamodbSharedLib.putItem(
621
- _izContext,
622
- await dynamodbSharedLib.tableName(
716
+ await Promise.all(
717
+ (pendingStepId.listOfRecords ?? []).flatMap(records =>
718
+ Object.values(records).map(async record =>
719
+ dynamodbSharedLib.putItem(
720
+ _izContext,
721
+ await dynamodbSharedLib.tableName(
623
722
  _izContext,
624
723
  record.tableName,
625
724
  record.serviceTag
@@ -641,9 +740,8 @@ export async function completeAction(
641
740
  collectedErrors,
642
741
  returnValues,
643
742
  additionalAttributes
644
- }
645
-
743
+ };
646
744
  } catch (err) {
647
- _izContext.logger.error(err)
745
+ _izContext.logger.error(err);
648
746
  }
649
- }
747
+ }