@izara_project/izara-core-library-asynchronous-flow 1.0.15 → 1.0.17

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/index.js CHANGED
@@ -34,8 +34,8 @@ module.exports = {
34
34
  createAwaitingMultipleStepsWithAdditionalAttributes: asyncFlowSharedLib.createAwaitingMultipleStepsWithAdditionalAttributes,
35
35
  createAwaitingMultipleSteps: asyncFlowSharedLib.createAwaitingMultipleSteps,
36
36
  findPendingStepIdsAwaitingMultipleSteps: asyncFlowSharedLib.findPendingStepIdsAwaitingMultipleSteps,
37
- findPendingStepsAwaitingMultipleSteps: asyncFlowSharedLib.findPendingStepIdsAwaitingMultipleSteps,
38
- findPendingStepAwaitingMultipleSteps: asyncFlowSharedLib.findPendingStepIdsAwaitingMultipleSteps,
37
+ findPendingStepsAwaitingMultipleSteps: asyncFlowSharedLib.findPendingStepsAwaitingMultipleSteps,
38
+ findPendingStepAwaitingMultipleSteps: asyncFlowSharedLib.findPendingStepAwaitingMultipleSteps,
39
39
  findAwaitingMultipleStepByPending: asyncFlowSharedLib.findAwaitingMultipleStepByPending,
40
40
  // Awaiting Step
41
41
  createAwaitingStep: asyncFlowSharedLib.createAwaitingStep,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@izara_project/izara-core-library-asynchronous-flow",
3
- "version": "1.0.15",
3
+ "version": "1.0.17",
4
4
  "description": "Shared asynchronous flow logic",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -28,6 +28,13 @@ const sqsSharedLib = require('@izara_project/izara-core-library-sqs');
28
28
  // External service interactions
29
29
  const { sqs } = require('@izara_project/izara-core-library-external-request');
30
30
 
31
+
32
+ /**
33
+ * Create a field name for storing the unique-request id, with optional prefix.
34
+ * @param {string} prefix
35
+ * @param {string} [uniqueRequestIdFieldName='UniqueRequestId']
36
+ * @returns {string}
37
+ */
31
38
  function createFieldNameUniqueRequestId(
32
39
  prefix,
33
40
  uniqueRequestIdFieldName = 'UniqueRequestId'
@@ -35,6 +42,13 @@ function createFieldNameUniqueRequestId(
35
42
  return prefix + uniqueRequestIdFieldName;
36
43
  }
37
44
 
45
+ /**
46
+ * Create a concatenated awaitingStepId from composite parts.
47
+ * @param {string} partitionKey
48
+ * @param {string|number} sortId
49
+ * @param {string} [prefix=""]
50
+ * @returns {string}
51
+ */
38
52
  function createConcatenatedAwaitingStepId(
39
53
  partitionKey,
40
54
  sortId,
@@ -43,6 +57,12 @@ function createConcatenatedAwaitingStepId(
43
57
  return prefix + partitionKey + "_" + sortId
44
58
  }
45
59
 
60
+ /**
61
+ * Create a concatenated pendingStepId from parent/child ids.
62
+ * @param {string} parentId
63
+ * @param {string} childId
64
+ * @returns {string}
65
+ */
46
66
  function createConcatenatedPendingStepId(
47
67
  parentId,
48
68
  childId
@@ -50,6 +70,12 @@ function createConcatenatedPendingStepId(
50
70
  return parentId + "_" + childId
51
71
  }
52
72
 
73
+ /**
74
+ * Create a simple awaitingStepId (prefix + partitionKey).
75
+ * @param {string} partitionKey
76
+ * @param {string} [prefix=""]
77
+ * @returns {string}
78
+ */
53
79
  function createAwaitingStepId(
54
80
  partitionKey,
55
81
  prefix = ""
@@ -57,6 +83,12 @@ function createAwaitingStepId(
57
83
  return prefix + partitionKey
58
84
  }
59
85
 
86
+ /**
87
+ * Create a simple pendingStepId (prefix + identifierId).
88
+ * @param {string} identifierId
89
+ * @param {string} [prefix=""]
90
+ * @returns {string}
91
+ */
60
92
  function createPendingStepId(
61
93
  identifierId,
62
94
  prefix = ""
@@ -64,6 +96,14 @@ function createPendingStepId(
64
96
  return prefix + identifierId
65
97
  }
66
98
 
99
+ /**
100
+ * Remove the known prefix from a pendingStepId and validate it is not equal to the prefix.
101
+ * If prefix is empty, the original ID is returned.
102
+ * @param {string} pendingStepId
103
+ * @param {string} [prefix=""]
104
+ * @returns {string}
105
+ * @throws {NoRetryError} If the stripped value equals the prefix (invalid)
106
+ */
67
107
  function explodePendingStepId(
68
108
  pendingStepId,
69
109
  prefix = ""
@@ -84,20 +124,40 @@ function explodePendingStepId(
84
124
  }
85
125
 
86
126
  // copy from izara-core-library-trigger-cache
127
+ /**
128
+ * Build the field name that stores "cache complete" marker.
129
+ * @param {string} [prefix='cache']
130
+ * @returns {string}
131
+ */
87
132
  function createFieldNameCacheComplete(prefix = 'cache') {
88
133
  return prefix + 'CacheComplete';
89
134
  }
135
+
136
+ /**
137
+ * Build the field name that stores a cache "status".
138
+ * @param {string} [prefix='cache']
139
+ * @returns {string}
140
+ */
90
141
  function createFieldNameStatus(prefix = 'cache') {
91
142
  return prefix + 'Status';
92
143
  }
93
144
 
145
+
94
146
  //====================================== AwaitingMultipleSteps
95
147
  // AwaitingMultipleSteps is when a flow is awaiting multiple external flows before it can continue
96
148
  // One awaitingStepId can have multiple pendingStepIds that are awaiting it
97
149
  // One pendingStepId can have multiple awaitingStepIds it is awaiting
98
150
  // logic can prepend any prefix to awaitingStepId if want to be share one table and differentiate different external step ids
99
151
 
100
- //not yet used ?
152
+ /**
153
+ * Create multiple awaiting records with optional per-record additional attributes.
154
+ * Writes to both "AwaitingMultipleSteps" and "AwaitingMultipleStepByPending".
155
+ * @async
156
+ * @param {IzContext} _izContext
157
+ * @param {AwaitingMultiInputRecord[]} records
158
+ * @param {string} pendingStepId
159
+ * @returns {Promise<void>}
160
+ */
101
161
  async function createAwaitingMultipleStepsWithAdditionalAttributes(
102
162
  _izContext,
103
163
  records, // array of object including properties: awaitingStepId / (optional) additionalAttributes
@@ -142,6 +202,15 @@ async function createAwaitingMultipleStepsWithAdditionalAttributes(
142
202
 
143
203
  }
144
204
 
205
+ /**
206
+ * Create multiple awaiting records given an array of awaitingStepIds.
207
+ * Writes to both "AwaitingMultipleSteps" and "AwaitingMultipleStepByPending".
208
+ * @async
209
+ * @param {IzContext} _izContext
210
+ * @param {string[]} records - array of awaitingStepIds
211
+ * @param {string} pendingStepId
212
+ * @returns {Promise<void>}
213
+ */
145
214
  async function createAwaitingMultipleSteps(
146
215
  _izContext,
147
216
  records, // array of awaitingStepIds
@@ -188,6 +257,13 @@ async function createAwaitingMultipleSteps(
188
257
 
189
258
  }
190
259
 
260
+ /**
261
+ * Find all pendingStepIds that are waiting on a given awaitingStepId (multiple).
262
+ * @async
263
+ * @param {IzContext} _izContext
264
+ * @param {string} awaitingStepId
265
+ * @returns {Promise<string[]>}
266
+ */
191
267
  async function findPendingStepIdsAwaitingMultipleSteps(
192
268
  _izContext,
193
269
  awaitingStepId
@@ -210,6 +286,13 @@ async function findPendingStepIdsAwaitingMultipleSteps(
210
286
  return pendingStepIds
211
287
  }
212
288
 
289
+ /**
290
+ * Return the raw items waiting on a given awaitingStepId (multiple).
291
+ * @async
292
+ * @param {IzContext} _izContext
293
+ * @param {string} awaitingStepId
294
+ * @returns {Promise<AwaitingMultipleStepsItem[]>}
295
+ */
213
296
  async function findPendingStepsAwaitingMultipleSteps(
214
297
  _izContext,
215
298
  awaitingStepId
@@ -226,6 +309,14 @@ async function findPendingStepsAwaitingMultipleSteps(
226
309
  return listPendingSteps.Items;
227
310
  }
228
311
 
312
+ /**
313
+ * Fetch exactly one pending step for a given awaitingStepId (throws if not 1).
314
+ * @async
315
+ * @param {IzContext} _izContext
316
+ * @param {string} awaitingStepId
317
+ * @returns {Promise<AwaitingMultipleStepsItem>}
318
+ * @throws {NoRetryError} if there is not exactly one item
319
+ */
229
320
  async function findPendingStepAwaitingMultipleSteps(
230
321
  _izContext,
231
322
  awaitingStepId
@@ -251,6 +342,14 @@ async function findPendingStepAwaitingMultipleSteps(
251
342
  // Do NOT delete records in both tables (AwaitingMultipleSteps, AwaitingMultipleStepByPending) if AwaitingMultipleSteps is not yet finished
252
343
  // Delete records from both tables only when checkAllAwaitingStepsFinished = true
253
344
  // Example usage: flow validateCart lambda ProcessCartOrderFromTraversal
345
+ /**
346
+ * Given a pendingStepId, return all awaiting steps (by the ByPending table).
347
+ * Use only after confirming all awaiting steps are finished, and clean up both tables accordingly.
348
+ * @async
349
+ * @param {IzContext} _izContext
350
+ * @param {string} pendingStepId
351
+ * @returns {Promise<AwaitingMultipleStepByPendingItem[]>}
352
+ */
254
353
  async function findAwaitingMultipleStepByPending(
255
354
  _izContext,
256
355
  pendingStepId
@@ -272,6 +371,16 @@ async function findAwaitingMultipleStepByPending(
272
371
  // One awaitingStepId can have multiple pendingStepIds that are awaiting it
273
372
  // logic can prepend any prefix to awaitingStepId if want to be share one table and differentiate different external step ids
274
373
 
374
+ /**
375
+ * Create a single AwaitingStep record, optionally attaching additional attributes and callingFlowConfig.
376
+ * @async
377
+ * @param {IzContext} _izContext
378
+ * @param {string} awaitingStepId
379
+ * @param {string} pendingStepId
380
+ * @param {Attrs} [additionalAttributes={}]
381
+ * @param {Attrs} [callingFlowConfig={}]
382
+ * @returns {Promise<void>}
383
+ */
275
384
  async function createAwaitingStep(
276
385
  _izContext,
277
386
  awaitingStepId,
@@ -307,7 +416,13 @@ async function createAwaitingStep(
307
416
  );
308
417
  }
309
418
 
310
-
419
+ /**
420
+ * Find all pendingStepIds that are waiting on a given awaitingStepId (single).
421
+ * @async
422
+ * @param {IzContext} _izContext
423
+ * @param {string} awaitingStepId
424
+ * @returns {Promise<string[]>}
425
+ */
311
426
  async function findPendingStepIdsAwaitingStep(
312
427
  _izContext,
313
428
  awaitingStepId
@@ -330,6 +445,13 @@ async function findPendingStepIdsAwaitingStep(
330
445
  return pendingStepIds
331
446
  }
332
447
 
448
+ /**
449
+ * Return the raw items waiting on a given awaitingStepId (single).
450
+ * @async
451
+ * @param {IzContext} _izContext
452
+ * @param {string} awaitingStepId
453
+ * @returns {Promise<AwaitingStepItem[]>}
454
+ */
333
455
  async function findPendingStepsAwaitingStep(
334
456
  _izContext,
335
457
  awaitingStepId
@@ -346,6 +468,14 @@ async function findPendingStepsAwaitingStep(
346
468
  return listPendingSteps.Items;
347
469
  }
348
470
 
471
+ /**
472
+ * Fetch exactly one pending step for a given awaitingStepId (throws if not 1).
473
+ * @async
474
+ * @param {IzContext} _izContext
475
+ * @param {string} awaitingStepId
476
+ * @returns {Promise<AwaitingStepItem>}
477
+ * @throws {NoRetryError} if there is not exactly one item
478
+ */
349
479
  async function findPendingStepAwaitingStep(
350
480
  _izContext,
351
481
  awaitingStepId
@@ -366,7 +496,15 @@ async function findPendingStepAwaitingStep(
366
496
  return listPendingSteps.Items[0];
367
497
  }
368
498
 
369
- // for get callingFlow save in awaitingStpe and remove property callingFlow in awaitingStpe
499
+ // for get callingFlow save in awaitingStep and remove property callingFlow in awaitingStep
500
+ /**
501
+ * Get one awaiting step by id and also extract (and remove) its callingFlowConfig (if present).
502
+ * Returns a tuple: [AwaitingStepItemWithoutCallingFlow, callingFlowConfig|null].
503
+ * @async
504
+ * @param {IzContext} _izContext
505
+ * @param {string} awaitingStepId
506
+ * @returns {Promise<[AwaitingStepItem, Attrs|null]>}
507
+ */
370
508
  async function findPendingStepAwaitingStepWithCallingFlow(
371
509
  _izContext,
372
510
  awaitingStepId,
@@ -379,7 +517,7 @@ async function findPendingStepAwaitingStepWithCallingFlow(
379
517
  );
380
518
 
381
519
  // callingFlowConfig.
382
- // cleaning object awaitingStep not have callingFlowComfig after return.
520
+ // cleaning object awaitingStep not have callingFlowConfig after return.
383
521
  if (awaitingStep.hasOwnProperty("callingFlowConfig")) {
384
522
  callingFlowConfig = awaitingStep.callingFlowConfig
385
523
  delete awaitingStep.callingFlowConfig
@@ -389,6 +527,17 @@ async function findPendingStepAwaitingStepWithCallingFlow(
389
527
  return [awaitingStep, callingFlowConfig]
390
528
  }
391
529
 
530
+ /**
531
+ * Mark current awaiting step as complete (in *_ByPending), then check if all awaiting steps are done.
532
+ * Returns true if all are finished; false otherwise.
533
+ * @async
534
+ * @param {IzContext} _izContext
535
+ * @param {string} pendingStepId
536
+ * @param {string|null} [currentAwaitingStepId=null]
537
+ * @param {any[]} [errorsFound=[]]
538
+ * @param {Attrs} [additionalAttributes={}]
539
+ * @returns {Promise<boolean>}
540
+ */
392
541
  async function checkAllAwaitingStepsFinished(
393
542
  _izContext,
394
543
  pendingStepId,
@@ -407,8 +556,16 @@ async function checkAllAwaitingStepsFinished(
407
556
  return remaining;
408
557
  }
409
558
 
410
-
411
-
559
+ /**
560
+ * Same as checkAllAwaitingStepsFinished but writes errors/additionalAttributes to the *_ByPending row.
561
+ * @async
562
+ * @param {IzContext} _izContext
563
+ * @param {string} pendingStepId
564
+ * @param {string|null} [currentAwaitingStepId=null]
565
+ * @param {any[]} [errorsFound=[]]
566
+ * @param {Attrs} [additionalAttributes={}]
567
+ * @returns {Promise<boolean>}
568
+ */
412
569
  async function checkAllAwaitingStepsFinishedWithError(
413
570
  _izContext,
414
571
  pendingStepId,
@@ -445,12 +602,12 @@ async function checkAllAwaitingStepsFinishedWithError(
445
602
  pendingStepId: pendingStepId
446
603
  },
447
604
  {
448
- limit: 50 // arbritrary limit so not pull too many results, need >2 because some others might be marked as "complete" = true
605
+ limit: 50 // arbitrary limit so not pull too many results, need >2 because some others might be marked as "complete" = true
449
606
  }
450
607
  );
451
608
  for (let idx = 0; idx < listPendingStepIds.Items.length; idx++) {
452
609
 
453
- // if have error found return errorfound
610
+ // if have error found return errorsFound
454
611
  // wrap function
455
612
 
456
613
  if (currentAwaitingStepId && listPendingStepIds.Items[idx].awaitingStepId == currentAwaitingStepId) {
@@ -492,7 +649,7 @@ async function checkAllAwaitingStepsFinishedWithError(
492
649
  // },
493
650
  // {
494
651
  // indexName: dynamodbSharedLib.tableName(tableName + 'Index'),
495
- // limit: 50 // arbritrary limit so not pull too many results, need >2 because some others might be marked as "complete" = true
652
+ // limit: 50 // arbitrary limit so not pull too many results, need >2 because some others might be marked as "complete" = true
496
653
  // }
497
654
  // );
498
655
  // for (let idx = 0; idx < listPendingStepIds.Items.length; idx++) {
@@ -509,8 +666,13 @@ async function checkAllAwaitingStepsFinishedWithError(
509
666
  // return true;
510
667
  }
511
668
 
512
-
513
-
669
+ /**
670
+ * Remove all awaiting records for a given pendingStepId from both tables.
671
+ * @async
672
+ * @param {IzContext} _izContext
673
+ * @param {string} pendingStepId
674
+ * @returns {Promise<boolean>} true if delete flow processed
675
+ */
514
676
  async function clearAllAwaitingSteps(
515
677
  _izContext,
516
678
  pendingStepId
@@ -559,7 +721,14 @@ async function clearAllAwaitingSteps(
559
721
  return true;
560
722
  }
561
723
 
562
-
724
+ /**
725
+ * Remove a single AwaitingStep record (single dependency table).
726
+ * @async
727
+ * @param {IzContext} _izContext
728
+ * @param {string} awaitingStepId
729
+ * @param {string} pendingStepId
730
+ * @returns {Promise<void>}
731
+ */
563
732
  async function removeAwaitingStep(
564
733
  _izContext,
565
734
  awaitingStepId,
@@ -576,6 +745,16 @@ async function removeAwaitingStep(
576
745
  );
577
746
  }
578
747
 
748
+ /**
749
+ * Remove items for AwaitingMultipleSteps and (conditionally) AwaitingMultipleStepByPending.
750
+ * If errorsFound is empty, delete from ByPending table as well.
751
+ * @async
752
+ * @param {IzContext} _izContext
753
+ * @param {string} awaitingStepId
754
+ * @param {string} pendingStepId
755
+ * @param {any[]} [errorsFound=[]]
756
+ * @returns {Promise<void>}
757
+ */
579
758
  async function removeAwaitingMultipleStep(
580
759
  _izContext,
581
760
  awaitingStepId,
@@ -626,6 +805,17 @@ async function removeAwaitingMultipleStep(
626
805
  }
627
806
 
628
807
  // only works with AwaitingStep, does not work with AwaitingMultipleSteps, need to make new function that checks conditional pass? If pass delete from byPending table too
808
+ /**
809
+ * Remove an AwaitingStep item only if its stored UniqueRequestId matches `checkUniqueRequestId`.
810
+ * Uses a conditional expression; will not error if the condition fails.
811
+ * @async
812
+ * @param {IzContext} _izContext
813
+ * @param {string} awaitingStepId
814
+ * @param {string} pendingStepId
815
+ * @param {string} checkUniqueRequestId
816
+ * @param {string} [prefix=""] - Optional prefix for UniqueRequestId field name
817
+ * @returns {Promise<void>}
818
+ */
629
819
  async function removeAwaitingStepWithCheckUniqueRequestId(
630
820
  _izContext,
631
821
  awaitingStepId,
@@ -664,14 +854,8 @@ async function removeAwaitingStepWithCheckUniqueRequestId(
664
854
  );
665
855
  }
666
856
 
667
-
668
-
669
857
  //====================================== end AwaitingStep
670
858
 
671
-
672
-
673
-
674
-
675
859
  /**
676
860
  * Checks if record has uniqueRequestId set, if not set to this requests uniqueRequestId and continue to process
677
861
  * if already set check if matches this request uniqueRequestId, if yes continue to process, if not then stop processing
@@ -684,6 +868,27 @@ async function removeAwaitingStepWithCheckUniqueRequestId(
684
868
 
685
869
  * @returns [string] [returnStatus, existingRecord]
686
870
  */
871
+
872
+
873
+ /**
874
+ * Coordinate unique-request processing over a record:
875
+ * - If no record: returns ["recordNotFound", {}]
876
+ * - If record exists but no uniqueRequestId: tries to set it via conditional update
877
+ * - If record has a different uniqueRequestId: returns ["stop", existingRecord]
878
+ * - If record has the same uniqueRequestId: returns ["process", existingRecord]
879
+ *
880
+ * Will loop up to 2 attempts to avoid races; throws on 3rd iteration.
881
+ *
882
+ * @async
883
+ * @param {IzContext} _izContext
884
+ * @param {string} tableName - Logical table name known by dynamodbSharedLib.tableName
885
+ * @param {DynamoKey} primaryKey - Primary key for the target record
886
+ * @param {string} [prefix=''] - Optional field-name prefix
887
+ * @param {string|null} [overwriteUniqueRequestId=null] - If provided, use this as the "current" unique request id
888
+ * @param {string} [uniqueRequestIdFieldName="UniqueRequestId"] - Base field name before prefix
889
+ * @returns {Promise<[UniqueRequestStatus, Attrs]>}
890
+ * @throws {NoRetryError} If unable to set uniqueRequestId after 2 tries
891
+ */
687
892
  async function checkUniqueRequestProcessing(
688
893
  _izContext,
689
894
  tableName,
@@ -789,6 +994,17 @@ async function checkUniqueRequestProcessing(
789
994
  };
790
995
 
791
996
  // ----- Helper funtion, common use case in triggerFlow ---------
997
+ /**
998
+ * Convenience wrapper around checkAndGetTimeCacheComplete.
999
+ * Returns [isSameOrUnset, uniqueRequestIdWhenComplete].
1000
+ * @async
1001
+ * @param {IzContext} _izContext
1002
+ * @param {string} fullMainTableName - Fully resolved table name (not logical)
1003
+ * @param {DynamoKey} keyValues
1004
+ * @param {number|string} timeCacheComplete - Caller’s expected cache mark
1005
+ * @param {string} prefix - Field prefix used in cache fields
1006
+ * @returns {Promise<[boolean, string|undefined]>}
1007
+ */
792
1008
  async function checkTimeCacheComplete(
793
1009
  _izContext,
794
1010
  fullMainTableName,
@@ -805,6 +1021,20 @@ async function checkTimeCacheComplete(
805
1021
  );
806
1022
  return [returnValue, uniqueRequestId];
807
1023
  }
1024
+
1025
+ /**
1026
+ * Read cache fields from a record and compare cacheComplete value to caller’s `timeCacheComplete`.
1027
+ * If stored differs (and is present), returns [false, storedValue].
1028
+ * Otherwise returns [true, storedValue, uniqueRequestId].
1029
+ * @async
1030
+ * @param {IzContext} _izContext
1031
+ * @param {string} fullMainTableName - Fully resolved table name (not logical)
1032
+ * @param {DynamoKey} keyValues
1033
+ * @param {number|string} timeCacheComplete
1034
+ * @param {string} prefix
1035
+ * @returns {Promise<[boolean, any, string|undefined]>}
1036
+ * @throws {NoRetryError} If record cannot be fetched
1037
+ */
808
1038
  async function checkAndGetTimeCacheComplete(
809
1039
  _izContext,
810
1040
  fullMainTableName,
@@ -857,6 +1087,16 @@ async function checkAndGetTimeCacheComplete(
857
1087
 
858
1088
 
859
1089
  // ----- shared both stored cache and triggered cache, check uniqueRequestId changed ---------
1090
+ /**
1091
+ * Ensure the cache object’s "uniqueRequestIdCompleteFieldName" equals the given checkUniqueRequestId.
1092
+ * @async
1093
+ * @param {IzContext} _izContext
1094
+ * @param {string} fullMainTableName
1095
+ * @param {DynamoKey} keyValues
1096
+ * @param {string} checkUniqueRequestId
1097
+ * @param {string} uniqueRequestIdCompleteFieldName
1098
+ * @returns {Promise<boolean>}
1099
+ */
860
1100
  async function checkCacheUniqueRequestId(
861
1101
  _izContext,
862
1102
  fullMainTableName,
@@ -880,10 +1120,6 @@ async function checkCacheUniqueRequestId(
880
1120
  }
881
1121
 
882
1122
 
883
-
884
-
885
-
886
-
887
1123
  // use shared findPendingStepIdsAwaitingStep
888
1124
  // module.exports.findPendingStepIdsAwaitingStepM = async (
889
1125
  // _izContext,
@@ -909,8 +1145,6 @@ async function checkCacheUniqueRequestId(
909
1145
  // }
910
1146
 
911
1147
 
912
-
913
-
914
1148
  // use shared removeAwaitingStep
915
1149
  // module.exports.removeAwaitingStep = async (
916
1150
  // _izContext,
@@ -936,6 +1170,17 @@ async function checkCacheUniqueRequestId(
936
1170
 
937
1171
  //====================================== end Multiple Lambda Invocations (Logic pagination of handling results)
938
1172
 
1173
+ /**
1174
+ * Validate and normalize a DynamoDB pagination startKey object.
1175
+ * Ensures partitionKeyFieldName/sortKeyFieldName are alphanumeric/underscore/hyphen.
1176
+ * If startKey is empty object, returns `null` for easier processing downstream.
1177
+ * @param {IzContext} _izContext
1178
+ * @param {Attrs|null|undefined} startKey
1179
+ * @param {string} partitionKeyFieldName
1180
+ * @param {string} sortKeyFieldName
1181
+ * @returns {Attrs|null}
1182
+ * @throws {NoRetryError} On invalid field names or malformed startKey
1183
+ */
939
1184
  function validateStartKeyParam(
940
1185
  _izContext,
941
1186
  startKey,
@@ -963,7 +1208,19 @@ function validateStartKeyParam(
963
1208
  return startKey;
964
1209
  }
965
1210
 
966
-
1211
+ /**
1212
+ * For paginated multi-invocation flows: validates the current invocation count,
1213
+ * attaches the (optional) next startKey to the message, increments the count,
1214
+ * and re-enqueues the message to the specified SQS queue.
1215
+ * @async
1216
+ * @param {IzContext} _izContext
1217
+ * @param {Attrs} messageProperty - The message body object to re-dispatch
1218
+ * @param {Attrs} [passOnStartKey={}] - Optional startKey to pass along
1219
+ * @param {number} numberInvocation - Current invocation count
1220
+ * @param {string} queueName - Logical queue name resolvable via sqsSharedLib.sqsQueueUrl
1221
+ * @returns {Promise<void>}
1222
+ * @throws {NoRetryError} If `numberInvocation` exceeds internal safety limit
1223
+ */
967
1224
  async function validateMultipleInvocations(
968
1225
  _izContext,
969
1226
  messageProperty,