@izara_project/izara-core-library-asynchronous-flow 1.0.36 → 1.0.37
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 +1 -1
- package/src/asyncFlowSharedLib.js +49 -98
- package/src/awaitingMultipleSteps.js +218 -470
- package/src/awaitingStep.js +51 -191
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.
|
|
6
|
+
"version": "1.0.37",
|
|
7
7
|
"description": "Shared asynchronous flow logic",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "index.js",
|
|
@@ -105,22 +105,15 @@ export function createParentFlowId(prefix = '') {
|
|
|
105
105
|
* @throws {NoRetryError} If the stripped value equals the prefix (invalid)
|
|
106
106
|
*/
|
|
107
107
|
export function explodePendingStepId(pendingStepId, prefix = '') {
|
|
108
|
-
if (!pendingStepId)
|
|
109
|
-
|
|
110
|
-
}
|
|
108
|
+
if (!pendingStepId) throw new NoRetryError('pendingStepId is required');
|
|
109
|
+
if (!prefix) return pendingStepId;
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
let identifierId = pendingStepId.slice(prefix.length);
|
|
116
|
-
// ** validate identifierId == prefix
|
|
117
|
-
if (identifierId == prefix) {
|
|
118
|
-
throw new NoRetryError('IdentifierId should not be like prefix.');
|
|
119
|
-
}
|
|
111
|
+
const identifierId = pendingStepId.slice(prefix.length);
|
|
112
|
+
if (identifierId === prefix)
|
|
113
|
+
throw new NoRetryError('IdentifierId should not be like prefix.');
|
|
120
114
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
115
|
+
Logger.debug('return explode:', identifierId);
|
|
116
|
+
return identifierId;
|
|
124
117
|
}
|
|
125
118
|
|
|
126
119
|
// copy from izara-core-library-trigger-cache
|
|
@@ -204,94 +197,60 @@ export async function checkUniqueRequestProcessing(
|
|
|
204
197
|
_izContext.uniqueRequestId
|
|
205
198
|
);
|
|
206
199
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
uniqueRequestId = overwriteUniqueRequestId;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// add prefix
|
|
200
|
+
const uniqueRequestId =
|
|
201
|
+
overwriteUniqueRequestId || _izContext.uniqueRequestId;
|
|
213
202
|
uniqueRequestIdFieldName = createFieldNameUniqueRequestId(
|
|
214
203
|
prefix,
|
|
215
204
|
uniqueRequestIdFieldName
|
|
216
205
|
);
|
|
217
206
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
if (i == 3) {
|
|
221
|
-
throw new NoRetryError(
|
|
222
|
-
`unable to set uniqueRequestId in table ${tableName}, record`,
|
|
223
|
-
primaryKey
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
//* get record from dynamo
|
|
227
|
-
let existingRecord = await dynamodbSharedLib.getItem(
|
|
207
|
+
for (let i = 0; i < 2; i++) {
|
|
208
|
+
const existingRecord = await dynamodbSharedLib.getItem(
|
|
228
209
|
_izContext,
|
|
229
210
|
dynamodbSharedLib.tableName(_izContext, tableName),
|
|
230
211
|
primaryKey
|
|
231
212
|
);
|
|
232
|
-
_izContext.logger.debug('existingRecord:', existingRecord);
|
|
233
213
|
|
|
234
|
-
|
|
214
|
+
if (!existingRecord) return ['recordNotFound', {}];
|
|
235
215
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
} else if (!existingRecord[uniqueRequestIdFieldName]) {
|
|
240
|
-
// uniqueRequestId not yet exist
|
|
216
|
+
const currentReqId = existingRecord[uniqueRequestIdFieldName];
|
|
217
|
+
if (currentReqId === uniqueRequestId) return ['process', existingRecord];
|
|
218
|
+
if (currentReqId) return ['stop', existingRecord];
|
|
241
219
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
];
|
|
249
|
-
//* conditional check uniqueRequestId still not exist in case another thread added
|
|
250
|
-
const queryElementsWhenUpdate = {
|
|
251
|
-
logicalElements: [
|
|
220
|
+
try {
|
|
221
|
+
const updateRecord = await dynamodbSharedLib.updateItem(
|
|
222
|
+
_izContext,
|
|
223
|
+
dynamodbSharedLib.tableName(_izContext, tableName),
|
|
224
|
+
primaryKey,
|
|
225
|
+
[
|
|
252
226
|
{
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
227
|
+
attributeName: uniqueRequestIdFieldName,
|
|
228
|
+
action: 'set',
|
|
229
|
+
value: _izContext.uniqueRequestId
|
|
256
230
|
}
|
|
257
231
|
],
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
// catch error when put and handle errors.
|
|
275
|
-
_izContext.logger.debug('updateItem storedCache expired err', err);
|
|
276
|
-
if (err.name == 'ConditionalCheckFailedException') {
|
|
277
|
-
continue;
|
|
278
|
-
} else {
|
|
279
|
-
// e.g. ProvisionedThroughputExceededException
|
|
280
|
-
// throw new Error('Unhandled Error when putItem', err) // TT, if throw will stop
|
|
281
|
-
throw err; // TT, if throw will stop
|
|
282
|
-
}
|
|
283
|
-
} //end catch err
|
|
284
|
-
} else if (existingRecord[uniqueRequestIdFieldName] !== uniqueRequestId) {
|
|
285
|
-
// when another request/uniqueRequestId need to stop process
|
|
286
|
-
return ['stop', existingRecord];
|
|
287
|
-
} else if (existingRecord[uniqueRequestIdFieldName] == uniqueRequestId) {
|
|
288
|
-
// if existingRecord[uniqueRequestIdFieldName] == uniqueRequestId then return "process
|
|
289
|
-
return [returnStatus, existingRecord];
|
|
232
|
+
{
|
|
233
|
+
logicalElements: [
|
|
234
|
+
{
|
|
235
|
+
type: 'function',
|
|
236
|
+
function: 'attribute_not_exists',
|
|
237
|
+
attribute: uniqueRequestIdFieldName
|
|
238
|
+
}
|
|
239
|
+
],
|
|
240
|
+
returnValues: 'ALL_NEW'
|
|
241
|
+
},
|
|
242
|
+
{ complexAttributes: true }
|
|
243
|
+
);
|
|
244
|
+
return ['process', updateRecord];
|
|
245
|
+
} catch (err) {
|
|
246
|
+
if (err.name === 'ConditionalCheckFailedException') continue;
|
|
247
|
+
throw err;
|
|
290
248
|
}
|
|
291
|
-
}
|
|
292
|
-
|
|
249
|
+
}
|
|
250
|
+
|
|
293
251
|
throw new NoRetryError(
|
|
294
|
-
|
|
252
|
+
`unable to set uniqueRequestId in table ${tableName}, record`,
|
|
253
|
+
primaryKey
|
|
295
254
|
);
|
|
296
255
|
} catch (err) {
|
|
297
256
|
_izContext.logger.error('ERROR checkUniqueRequestProcessing:', err);
|
|
@@ -437,21 +396,14 @@ export async function checkCacheUniqueRequestId(
|
|
|
437
396
|
checkUniqueRequestId,
|
|
438
397
|
uniqueRequestIdCompleteFieldName
|
|
439
398
|
) {
|
|
440
|
-
|
|
399
|
+
const cacheObject = await dynamodbSharedLib.getItem(
|
|
441
400
|
_izContext,
|
|
442
401
|
fullMainTableName,
|
|
443
402
|
keyValues
|
|
444
403
|
);
|
|
445
404
|
_izContext.logger.debug('cacheObject', cacheObject);
|
|
446
405
|
|
|
447
|
-
|
|
448
|
-
!cacheObject[uniqueRequestIdCompleteFieldName] ||
|
|
449
|
-
cacheObject[uniqueRequestIdCompleteFieldName] !== checkUniqueRequestId
|
|
450
|
-
) {
|
|
451
|
-
return false;
|
|
452
|
-
} else {
|
|
453
|
-
return true;
|
|
454
|
-
}
|
|
406
|
+
return cacheObject[uniqueRequestIdCompleteFieldName] === checkUniqueRequestId;
|
|
455
407
|
}
|
|
456
408
|
|
|
457
409
|
//====================================== end Multiple Lambda Invocations (Logic pagination of handling results)
|
|
@@ -492,17 +444,16 @@ export function validateStartKeyParam(
|
|
|
492
444
|
);
|
|
493
445
|
}
|
|
494
446
|
|
|
495
|
-
if (startKey && Object.keys(startKey).length
|
|
447
|
+
if (startKey && Object.keys(startKey).length !== 0) {
|
|
496
448
|
if (!startKey[partitionKeyFieldName] || !startKey[sortKeyFieldName]) {
|
|
497
449
|
throw new NoRetryError(
|
|
498
450
|
'validateStartKeyParam: Invalid startKey, missing partitionKeyFieldName or sortKeyFieldName'
|
|
499
451
|
);
|
|
500
452
|
}
|
|
501
|
-
|
|
502
|
-
startKey = null; // if empty set to null so lib functions process correctly
|
|
453
|
+
return startKey;
|
|
503
454
|
}
|
|
504
455
|
|
|
505
|
-
return
|
|
456
|
+
return null;
|
|
506
457
|
}
|
|
507
458
|
|
|
508
459
|
/**
|