@izara_project/izara-core-library-asynchronous-flow 1.0.20 → 1.0.22
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 +9 -5
- package/package.json +1 -1
- package/src/asyncFlowSharedLib.js +507 -0
- package/src/awaitingMultipleSteps.js +560 -0
- package/src/awaitingStep.js +244 -0
- package/src/AsyncFlowSharedLib.js +0 -1311
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright (C) 2021 Sven Mason <http://izara.io>
|
|
3
|
+
|
|
4
|
+
This program is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU Affero General Public License as
|
|
6
|
+
published by the Free Software Foundation, either version 3 of the
|
|
7
|
+
License, or (at your option) any later version.
|
|
8
|
+
|
|
9
|
+
This program is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU Affero General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { NoRetryError } from '@izara_project/izara-core-library-core';
|
|
19
|
+
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
20
|
+
|
|
21
|
+
//====================================== AwaitingMultipleSteps
|
|
22
|
+
// AwaitingMultipleSteps is when a flow is awaiting multiple external flows before it can continue
|
|
23
|
+
// One awaitingStepId can have multiple pendingStepIds that are awaiting it
|
|
24
|
+
// One pendingStepId can have multiple awaitingStepIds it is awaiting
|
|
25
|
+
// logic can prepend any prefix to awaitingStepId if want to be share one table and differentiate different external step ids
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Create multiple awaiting records with optional per-record additional attributes.
|
|
29
|
+
* Writes to both "AwaitingMultipleSteps" and "AwaitingMultipleStepByPending".
|
|
30
|
+
* @async
|
|
31
|
+
* @param {IzContext} _izContext
|
|
32
|
+
* @param {AwaitingMultiInputRecord[]} records
|
|
33
|
+
* @param {string} pendingStepId
|
|
34
|
+
* @returns {Promise<void>}
|
|
35
|
+
*/
|
|
36
|
+
export async function createAwaitingMultipleStepsWithAdditionalAttributes(
|
|
37
|
+
_izContext,
|
|
38
|
+
records, // array of object including properties: awaitingStepId / (optional) additionalAttributes
|
|
39
|
+
pendingStepId
|
|
40
|
+
) {
|
|
41
|
+
_izContext.logger.debug(
|
|
42
|
+
'Lib:createAwaitingMultipleStepsWithAdditionalAttributes',
|
|
43
|
+
{
|
|
44
|
+
records: records,
|
|
45
|
+
pendingStepId: pendingStepId
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
let promiseArray = [];
|
|
49
|
+
|
|
50
|
+
for (let record of records) {
|
|
51
|
+
let attributesWhenCreate = {
|
|
52
|
+
awaitingStepId: record.awaitingStepId,
|
|
53
|
+
pendingStepId: pendingStepId,
|
|
54
|
+
timestamp: Date.now(),
|
|
55
|
+
...record.additionalAttributes
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
promiseArray.push(
|
|
59
|
+
dynamodbSharedLib.putItem(
|
|
60
|
+
_izContext,
|
|
61
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
|
|
62
|
+
attributesWhenCreate
|
|
63
|
+
)
|
|
64
|
+
);
|
|
65
|
+
promiseArray.push(
|
|
66
|
+
dynamodbSharedLib.putItem(
|
|
67
|
+
_izContext,
|
|
68
|
+
dynamodbSharedLib.tableName(
|
|
69
|
+
_izContext,
|
|
70
|
+
'AwaitingMultipleStepByPending'
|
|
71
|
+
),
|
|
72
|
+
{
|
|
73
|
+
pendingStepId: pendingStepId,
|
|
74
|
+
awaitingStepId: record.awaitingStepId,
|
|
75
|
+
timestamp: Date.now()
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
await Promise.all(promiseArray);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Batch initializes multiple pending steps in DynamoDB.
|
|
86
|
+
* Records status in both the primary tracking table and the pending-relation table.
|
|
87
|
+
* * @async
|
|
88
|
+
* @param {Object} _izContext - The system context providing logger and shared utilities.
|
|
89
|
+
* @param {Array<Object>} records - Array of step objects to be initialized.
|
|
90
|
+
* @param {string} records[].awaitingStepId - The unique identifier for the specific step.
|
|
91
|
+
* @param {Object} [records[].additionalAttributes] - Optional metadata to store with the step.
|
|
92
|
+
* @param {string} pendingStepId - The parent ID linking all related steps together.
|
|
93
|
+
* @returns {Promise<void>}
|
|
94
|
+
*/
|
|
95
|
+
export async function initAwaitingStepsWithAttrs(
|
|
96
|
+
_izContext,
|
|
97
|
+
records,
|
|
98
|
+
pendingStepId
|
|
99
|
+
) {
|
|
100
|
+
_izContext.logger.debug('Lib:initAwaitingStepsWithAttrs', {
|
|
101
|
+
records,
|
|
102
|
+
pendingStepId
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const timestamp = Date.now();
|
|
106
|
+
const promiseArray = [];
|
|
107
|
+
|
|
108
|
+
for (const record of records) {
|
|
109
|
+
promiseArray.push(
|
|
110
|
+
dynamodbSharedLib.putItem(
|
|
111
|
+
_izContext,
|
|
112
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
|
|
113
|
+
{
|
|
114
|
+
awaitingStepId: record.awaitingStepId,
|
|
115
|
+
pendingStepId,
|
|
116
|
+
timestamp
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
);
|
|
120
|
+
promiseArray.push(
|
|
121
|
+
dynamodbSharedLib.putItem(
|
|
122
|
+
_izContext,
|
|
123
|
+
dynamodbSharedLib.tableName(
|
|
124
|
+
_izContext,
|
|
125
|
+
'AwaitingMultipleStepByPending'
|
|
126
|
+
),
|
|
127
|
+
{
|
|
128
|
+
pendingStepId,
|
|
129
|
+
awaitingStepId: record.awaitingStepId,
|
|
130
|
+
timestamp,
|
|
131
|
+
...record.additionalAttributes
|
|
132
|
+
}
|
|
133
|
+
)
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
await Promise.all(promiseArray);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Create multiple awaiting records given an array of awaitingStepIds.
|
|
142
|
+
* Writes to both "AwaitingMultipleSteps" and "AwaitingMultipleStepByPending".
|
|
143
|
+
* @async
|
|
144
|
+
* @param {IzContext} _izContext
|
|
145
|
+
* @param {string[]} records - array of awaitingStepIds
|
|
146
|
+
* @param {string} pendingStepId
|
|
147
|
+
* @returns {Promise<void>}
|
|
148
|
+
*/
|
|
149
|
+
export async function createAwaitingMultipleSteps(
|
|
150
|
+
_izContext,
|
|
151
|
+
records, // array of awaitingStepIds
|
|
152
|
+
pendingStepId
|
|
153
|
+
) {
|
|
154
|
+
_izContext.logger.debug('Lib:createAwaitingMultipleSteps', {
|
|
155
|
+
records: records,
|
|
156
|
+
pendingStepId: pendingStepId
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
let promiseArray = [];
|
|
160
|
+
|
|
161
|
+
for (let record of records) {
|
|
162
|
+
let attributesWhenCreate = {
|
|
163
|
+
awaitingStepId: record,
|
|
164
|
+
pendingStepId: pendingStepId,
|
|
165
|
+
timestamp: Date.now()
|
|
166
|
+
};
|
|
167
|
+
_izContext.logger.debug('putItem:AwaitingMultipleSteps +++++++', {
|
|
168
|
+
awaitingStepId: attributesWhenCreate.awaitingStepId
|
|
169
|
+
});
|
|
170
|
+
promiseArray.push(
|
|
171
|
+
dynamodbSharedLib.putItem(
|
|
172
|
+
_izContext,
|
|
173
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
|
|
174
|
+
attributesWhenCreate
|
|
175
|
+
)
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
_izContext.logger.debug('putItem:AwaitingMultipleStepByPending', {
|
|
179
|
+
awaitingStepId: attributesWhenCreate.awaitingStepId
|
|
180
|
+
});
|
|
181
|
+
promiseArray.push(
|
|
182
|
+
dynamodbSharedLib.putItem(
|
|
183
|
+
_izContext,
|
|
184
|
+
dynamodbSharedLib.tableName(
|
|
185
|
+
_izContext,
|
|
186
|
+
'AwaitingMultipleStepByPending'
|
|
187
|
+
),
|
|
188
|
+
attributesWhenCreate
|
|
189
|
+
)
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
await Promise.all(promiseArray);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Find all pendingStepIds that are waiting on a given awaitingStepId (multiple).
|
|
197
|
+
* @async
|
|
198
|
+
* @param {IzContext} _izContext
|
|
199
|
+
* @param {string} awaitingStepId
|
|
200
|
+
* @returns {Promise<string[]>}
|
|
201
|
+
*/
|
|
202
|
+
export async function findPendingStepIdsAwaitingMultipleSteps(
|
|
203
|
+
_izContext,
|
|
204
|
+
awaitingStepId
|
|
205
|
+
) {
|
|
206
|
+
let pendingStepIds = [];
|
|
207
|
+
|
|
208
|
+
let listPendingStepIds = await dynamodbSharedLib.query(
|
|
209
|
+
_izContext,
|
|
210
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
|
|
211
|
+
{
|
|
212
|
+
awaitingStepId: awaitingStepId
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
for (let idx = 0; idx < listPendingStepIds.Items.length; idx++) {
|
|
217
|
+
pendingStepIds.push(listPendingStepIds.Items[idx].pendingStepId);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return pendingStepIds;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Return the raw items waiting on a given awaitingStepId (multiple).
|
|
225
|
+
* @async
|
|
226
|
+
* @param {IzContext} _izContext
|
|
227
|
+
* @param {string} awaitingStepId
|
|
228
|
+
* @returns {Promise<AwaitingMultipleStepsItem[]>}
|
|
229
|
+
*/
|
|
230
|
+
export async function findPendingStepsAwaitingMultipleSteps(
|
|
231
|
+
_izContext,
|
|
232
|
+
awaitingStepId
|
|
233
|
+
) {
|
|
234
|
+
let listPendingSteps = await dynamodbSharedLib.query(
|
|
235
|
+
_izContext,
|
|
236
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
|
|
237
|
+
{
|
|
238
|
+
awaitingStepId: awaitingStepId
|
|
239
|
+
}
|
|
240
|
+
);
|
|
241
|
+
_izContext.logger.debug('Record of awaitingStepId', listPendingSteps);
|
|
242
|
+
return listPendingSteps.Items;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Fetch exactly one pending step for a given awaitingStepId (throws if not 1).
|
|
247
|
+
* @async
|
|
248
|
+
* @param {IzContext} _izContext
|
|
249
|
+
* @param {string} awaitingStepId
|
|
250
|
+
* @returns {Promise<AwaitingMultipleStepsItem>}
|
|
251
|
+
* @throws {NoRetryError} if there is not exactly one item
|
|
252
|
+
*/
|
|
253
|
+
export async function findPendingStepAwaitingMultipleSteps(
|
|
254
|
+
_izContext,
|
|
255
|
+
awaitingStepId
|
|
256
|
+
) {
|
|
257
|
+
let listPendingSteps = await dynamodbSharedLib.query(
|
|
258
|
+
_izContext,
|
|
259
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
|
|
260
|
+
{
|
|
261
|
+
awaitingStepId: awaitingStepId
|
|
262
|
+
}
|
|
263
|
+
);
|
|
264
|
+
_izContext.logger.debug('Record of awaitingStepId', listPendingSteps);
|
|
265
|
+
|
|
266
|
+
if (listPendingSteps.Items.length !== 1) {
|
|
267
|
+
throw new NoRetryError('listPendingSteps not equals 1');
|
|
268
|
+
}
|
|
269
|
+
return listPendingSteps.Items[0];
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Use case:
|
|
273
|
+
// Use only after checkAllAwaitingStepsFinished
|
|
274
|
+
// Do NOT delete records in both tables (AwaitingMultipleSteps, AwaitingMultipleStepByPending) if AwaitingMultipleSteps is not yet finished
|
|
275
|
+
// Delete records from both tables only when checkAllAwaitingStepsFinished = true
|
|
276
|
+
// Example usage: flow validateCart lambda ProcessCartOrderFromTraversal
|
|
277
|
+
/**
|
|
278
|
+
* Given a pendingStepId, return all awaiting steps (by the ByPending table).
|
|
279
|
+
* Use only after confirming all awaiting steps are finished, and clean up both tables accordingly.
|
|
280
|
+
* @async
|
|
281
|
+
* @param {IzContext} _izContext
|
|
282
|
+
* @param {string} pendingStepId
|
|
283
|
+
* @returns {Promise<AwaitingMultipleStepByPendingItem[]>}
|
|
284
|
+
*/
|
|
285
|
+
export async function findAwaitingMultipleStepByPending(
|
|
286
|
+
_izContext,
|
|
287
|
+
pendingStepId
|
|
288
|
+
) {
|
|
289
|
+
let listAwaitingSteps = await dynamodbSharedLib.query(
|
|
290
|
+
_izContext,
|
|
291
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
|
|
292
|
+
{
|
|
293
|
+
pendingStepId: pendingStepId
|
|
294
|
+
}
|
|
295
|
+
);
|
|
296
|
+
_izContext.logger.debug(
|
|
297
|
+
'Record of AwaitingMultipleStepByPending',
|
|
298
|
+
listAwaitingSteps
|
|
299
|
+
);
|
|
300
|
+
return listAwaitingSteps.Items;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Same as checkAllAwaitingStepsFinished but writes errors/additionalAttributes to the *_ByPending row.
|
|
305
|
+
* @async
|
|
306
|
+
* @param {IzContext} _izContext
|
|
307
|
+
* @param {string} pendingStepId
|
|
308
|
+
* @param {string|null} [currentAwaitingStepId=null]
|
|
309
|
+
* @param {any[]} [errorsFound=[]]
|
|
310
|
+
* @param {Attrs} [additionalAttributes={}]
|
|
311
|
+
* @returns {Promise<boolean>}
|
|
312
|
+
*/
|
|
313
|
+
export async function checkAllAwaitingStepsFinishedWithError(
|
|
314
|
+
_izContext,
|
|
315
|
+
pendingStepId,
|
|
316
|
+
currentAwaitingStepId = null,
|
|
317
|
+
errorsFound = [],
|
|
318
|
+
additionalAttributes = {}
|
|
319
|
+
) {
|
|
320
|
+
_izContext.logger.debug('Lib:checkAllAwaitingStepsFinishedWithError', {
|
|
321
|
+
pendingStepId: pendingStepId,
|
|
322
|
+
currentAwaitingStepId: currentAwaitingStepId,
|
|
323
|
+
errorsFound: errorsFound
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
if (currentAwaitingStepId) {
|
|
327
|
+
await dynamodbSharedLib.updateItem(
|
|
328
|
+
_izContext,
|
|
329
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
|
|
330
|
+
{
|
|
331
|
+
pendingStepId: pendingStepId,
|
|
332
|
+
awaitingStepId: currentAwaitingStepId
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
complete: true,
|
|
336
|
+
errorsFound: errorsFound,
|
|
337
|
+
...additionalAttributes
|
|
338
|
+
}
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
let listPendingStepIds = await dynamodbSharedLib.query(
|
|
342
|
+
_izContext,
|
|
343
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
|
|
344
|
+
{
|
|
345
|
+
pendingStepId: pendingStepId
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
limit: 50 // arbitrary limit so not pull too many results, need >2 because some others might be marked as "complete" = true
|
|
349
|
+
}
|
|
350
|
+
);
|
|
351
|
+
for (let idx = 0; idx < listPendingStepIds.Items.length; idx++) {
|
|
352
|
+
// if have error found return errorsFound
|
|
353
|
+
// wrap function
|
|
354
|
+
|
|
355
|
+
if (
|
|
356
|
+
currentAwaitingStepId &&
|
|
357
|
+
listPendingStepIds.Items[idx].awaitingStepId == currentAwaitingStepId
|
|
358
|
+
) {
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
// if any record found not set to complete then there are steps not yet finished
|
|
362
|
+
if (!listPendingStepIds.Items[idx].complete) {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return true; // all passed
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Remove all awaiting records for a given pendingStepId from both tables.
|
|
372
|
+
* @async
|
|
373
|
+
* @param {IzContext} _izContext
|
|
374
|
+
* @param {string} pendingStepId
|
|
375
|
+
* @returns {Promise<boolean>} true if delete flow processed
|
|
376
|
+
*/
|
|
377
|
+
export async function clearAllAwaitingSteps(_izContext, pendingStepId) {
|
|
378
|
+
// ----- query items from GSI table
|
|
379
|
+
let listPendingStepIds = await dynamodbSharedLib.query(
|
|
380
|
+
_izContext,
|
|
381
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
|
|
382
|
+
{
|
|
383
|
+
pendingStepId: pendingStepId
|
|
384
|
+
}
|
|
385
|
+
);
|
|
386
|
+
_izContext.logger.debug('listPendingStepIds', listPendingStepIds);
|
|
387
|
+
|
|
388
|
+
let promiseArray = [];
|
|
389
|
+
|
|
390
|
+
for (let idx = 0; idx < listPendingStepIds.Items.length; idx++) {
|
|
391
|
+
_izContext.logger.debug(`delete item in dynamodb AwaitingMultipleSteps`);
|
|
392
|
+
promiseArray.push(
|
|
393
|
+
dynamodbSharedLib.deleteItem(
|
|
394
|
+
_izContext,
|
|
395
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
|
|
396
|
+
{
|
|
397
|
+
awaitingStepId: listPendingStepIds.Items[idx].awaitingStepId,
|
|
398
|
+
pendingStepId: listPendingStepIds.Items[idx].pendingStepId
|
|
399
|
+
}
|
|
400
|
+
)
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
_izContext.logger.debug(
|
|
404
|
+
`delete item in dynamodb AwaitingMultipleStepByPending`
|
|
405
|
+
);
|
|
406
|
+
promiseArray.push(
|
|
407
|
+
dynamodbSharedLib.deleteItem(
|
|
408
|
+
_izContext,
|
|
409
|
+
dynamodbSharedLib.tableName(
|
|
410
|
+
_izContext,
|
|
411
|
+
'AwaitingMultipleStepByPending'
|
|
412
|
+
),
|
|
413
|
+
{
|
|
414
|
+
pendingStepId: listPendingStepIds.Items[idx].pendingStepId,
|
|
415
|
+
awaitingStepId: listPendingStepIds.Items[idx].awaitingStepId
|
|
416
|
+
}
|
|
417
|
+
)
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
await Promise.all(promiseArray);
|
|
422
|
+
|
|
423
|
+
return true;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Remove items for AwaitingMultipleSteps and (conditionally) AwaitingMultipleStepByPending.
|
|
428
|
+
* If errorsFound is empty, delete from ByPending table as well.
|
|
429
|
+
* @async
|
|
430
|
+
* @param {IzContext} _izContext
|
|
431
|
+
* @param {string} awaitingStepId
|
|
432
|
+
* @param {string} pendingStepId
|
|
433
|
+
* @param {any[]} [errorsFound=[]]
|
|
434
|
+
* @returns {Promise<void>}
|
|
435
|
+
*/
|
|
436
|
+
export async function removeAwaitingMultipleStep(
|
|
437
|
+
_izContext,
|
|
438
|
+
awaitingStepId,
|
|
439
|
+
pendingStepId,
|
|
440
|
+
errorsFound = []
|
|
441
|
+
) {
|
|
442
|
+
_izContext.logger.debug('Lib:removeAwaitingMultipleStep', {
|
|
443
|
+
awaitingStepId: awaitingStepId,
|
|
444
|
+
pendingStepId: pendingStepId
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
let promiseArray = [];
|
|
448
|
+
|
|
449
|
+
let keyValues = {
|
|
450
|
+
awaitingStepId: awaitingStepId,
|
|
451
|
+
pendingStepId: pendingStepId
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
let keyValuesForByPending = {
|
|
455
|
+
pendingStepId: pendingStepId,
|
|
456
|
+
awaitingStepId: awaitingStepId
|
|
457
|
+
};
|
|
458
|
+
_izContext.logger.debug('deleting ... ', {
|
|
459
|
+
keyValues,
|
|
460
|
+
keyValuesForByPending
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
_izContext.logger.debug(
|
|
464
|
+
`delete item in dynamodb AwaitingMultipleSteps ==> awaitingStepId:${keyValues.awaitingStepId}`
|
|
465
|
+
);
|
|
466
|
+
promiseArray.push(
|
|
467
|
+
dynamodbSharedLib.deleteItem(
|
|
468
|
+
_izContext,
|
|
469
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
|
|
470
|
+
keyValues
|
|
471
|
+
)
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
if (errorsFound.length == 0) {
|
|
475
|
+
_izContext.logger.debug(
|
|
476
|
+
`delete item in dynamodb AwaitingMultipleStepByPending ==> awaitingStepId:${keyValues.awaitingStepId}`
|
|
477
|
+
);
|
|
478
|
+
promiseArray.push(
|
|
479
|
+
dynamodbSharedLib.deleteItem(
|
|
480
|
+
_izContext,
|
|
481
|
+
dynamodbSharedLib.tableName(
|
|
482
|
+
_izContext,
|
|
483
|
+
'AwaitingMultipleStepByPending'
|
|
484
|
+
),
|
|
485
|
+
keyValuesForByPending
|
|
486
|
+
)
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
await Promise.all(promiseArray);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Checks if all awaiting steps for a pending step are complete after marking the current one as complete.
|
|
494
|
+
* If all steps are finished, it returns `true` and an object containing the `additionalAttributes` from each of the completed steps, keyed by their `awaitingStepId`.
|
|
495
|
+
* If any other step is not yet complete, it returns `[false, null]`.
|
|
496
|
+
* @async
|
|
497
|
+
* @param {IzContext} _izContext
|
|
498
|
+
* @param {string} pendingStepId
|
|
499
|
+
* @param {string|null} [currentAwaitingStepId=null] - The step that has just finished.
|
|
500
|
+
* @param {any[]} [errorsFound=[]]
|
|
501
|
+
* @param {Attrs} [additionalAttributes={}]
|
|
502
|
+
* @returns {Promise<[boolean, Record<string, any>|null]>} A tuple indicating completion status and the collected attributes, or null if not all steps are complete.
|
|
503
|
+
*/
|
|
504
|
+
export async function syncAndCheckStepsCompletion(
|
|
505
|
+
_izContext,
|
|
506
|
+
pendingStepId,
|
|
507
|
+
currentAwaitingStepId = null,
|
|
508
|
+
errorsFound = [],
|
|
509
|
+
additionalAttributes = {}
|
|
510
|
+
) {
|
|
511
|
+
_izContext.logger.debug(
|
|
512
|
+
'Lib:checkAllAwaitingMultipleStepsFinishedWithErrorAndReturnAdditionalAttributes',
|
|
513
|
+
{
|
|
514
|
+
pendingStepId,
|
|
515
|
+
currentAwaitingStepId,
|
|
516
|
+
errorsFound,
|
|
517
|
+
additionalAttributes
|
|
518
|
+
}
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
if (currentAwaitingStepId) {
|
|
522
|
+
await dynamodbSharedLib.updateItem(
|
|
523
|
+
_izContext,
|
|
524
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
|
|
525
|
+
{ pendingStepId, awaitingStepId: currentAwaitingStepId },
|
|
526
|
+
{
|
|
527
|
+
complete: true,
|
|
528
|
+
errorsFound,
|
|
529
|
+
...additionalAttributes
|
|
530
|
+
}
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
const awaitingStepItems = await dynamodbSharedLib.query(
|
|
535
|
+
_izContext,
|
|
536
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
|
|
537
|
+
{ pendingStepId },
|
|
538
|
+
{
|
|
539
|
+
limit: 50 // arbitrary limit so not pull too many results, need >2 because some others might be marked as "complete" = true
|
|
540
|
+
}
|
|
541
|
+
);
|
|
542
|
+
|
|
543
|
+
const collectedAttributes = {};
|
|
544
|
+
for (const item of awaitingStepItems.Items) {
|
|
545
|
+
// For any step OTHER than the one we just completed, if it's not marked as complete,
|
|
546
|
+
// then the overall process is not finished.
|
|
547
|
+
if (item.awaitingStepId !== currentAwaitingStepId && !item.complete) {
|
|
548
|
+
return [false, null];
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
// If the step is complete (which all should be if we reach this point),
|
|
552
|
+
// collect its attributes if they exist.
|
|
553
|
+
if (item.additionalAttributes) {
|
|
554
|
+
collectedAttributes[item.awaitingStepId] = item.additionalAttributes;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// If the loop completes, it means all steps were finished.
|
|
559
|
+
return [true, collectedAttributes];
|
|
560
|
+
}
|