aws-local-stepfunctions 0.6.0 → 1.0.0
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/README.md +249 -4
- package/build/CLI.cjs +279 -0
- package/build/main.browser.esm.js +349 -98
- package/build/main.d.ts +97 -21
- package/build/main.node.cjs +349 -98
- package/build/main.node.esm.js +349 -98
- package/package.json +9 -2
package/build/main.node.cjs
CHANGED
|
@@ -50,7 +50,7 @@ var main_exports = {};
|
|
|
50
50
|
__export(main_exports, {
|
|
51
51
|
ExecutionAbortedError: () => ExecutionAbortedError,
|
|
52
52
|
ExecutionError: () => ExecutionError,
|
|
53
|
-
ExecutionTimeoutError: () =>
|
|
53
|
+
ExecutionTimeoutError: () => ExecutionTimeoutError,
|
|
54
54
|
StateMachine: () => StateMachine
|
|
55
55
|
});
|
|
56
56
|
module.exports = __toCommonJS(main_exports);
|
|
@@ -63,27 +63,11 @@ var ExecutionAbortedError = class extends Error {
|
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
-
// src/error/
|
|
67
|
-
var
|
|
68
|
-
constructor(message) {
|
|
69
|
-
super(message);
|
|
70
|
-
this.name = "RuntimeError";
|
|
71
|
-
this.retryable = true;
|
|
72
|
-
this.catchable = true;
|
|
73
|
-
}
|
|
74
|
-
get isRetryable() {
|
|
75
|
-
return this.retryable;
|
|
76
|
-
}
|
|
77
|
-
get isCatchable() {
|
|
78
|
-
return this.catchable;
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
// src/error/predefined/StatesTimeoutError.ts
|
|
83
|
-
var StatesTimeoutError = class extends RuntimeError {
|
|
66
|
+
// src/error/ExecutionTimeoutError.ts
|
|
67
|
+
var ExecutionTimeoutError = class extends Error {
|
|
84
68
|
constructor() {
|
|
85
|
-
super("
|
|
86
|
-
this.name = "
|
|
69
|
+
super("Execution timed out");
|
|
70
|
+
this.name = "ExecutionTimeoutError";
|
|
87
71
|
}
|
|
88
72
|
};
|
|
89
73
|
|
|
@@ -134,20 +118,32 @@ function sfc32(a, b, c, d) {
|
|
|
134
118
|
return (t >>> 0) / 4294967296;
|
|
135
119
|
};
|
|
136
120
|
}
|
|
137
|
-
function getRandomNumber(min, max,
|
|
138
|
-
return Math.floor(
|
|
121
|
+
function getRandomNumber(min, max, rng = Math.random) {
|
|
122
|
+
return Math.floor(rng() * (max - min + 1)) + min;
|
|
139
123
|
}
|
|
140
124
|
|
|
141
125
|
// src/util/index.ts
|
|
142
126
|
function isPlainObj(value) {
|
|
143
127
|
return !!value && Object.getPrototypeOf(value) === Object.prototype;
|
|
144
128
|
}
|
|
145
|
-
function sleep(ms, abortSignal) {
|
|
129
|
+
function sleep(ms, abortSignal, rootAbortSignal) {
|
|
146
130
|
return new Promise((resolve) => {
|
|
147
|
-
|
|
148
|
-
|
|
131
|
+
if (abortSignal?.aborted || rootAbortSignal?.aborted) {
|
|
132
|
+
return resolve();
|
|
133
|
+
}
|
|
134
|
+
const onAbort = () => {
|
|
135
|
+
abortSignal?.removeEventListener("abort", onAbort);
|
|
136
|
+
rootAbortSignal?.removeEventListener("abort", onAbort);
|
|
149
137
|
clearTimeout(timeout);
|
|
150
|
-
|
|
138
|
+
resolve();
|
|
139
|
+
};
|
|
140
|
+
const timeout = setTimeout(() => {
|
|
141
|
+
abortSignal?.removeEventListener("abort", onAbort);
|
|
142
|
+
rootAbortSignal?.removeEventListener("abort", onAbort);
|
|
143
|
+
resolve();
|
|
144
|
+
}, ms);
|
|
145
|
+
abortSignal?.addEventListener("abort", onAbort);
|
|
146
|
+
rootAbortSignal?.addEventListener("abort", onAbort);
|
|
151
147
|
});
|
|
152
148
|
}
|
|
153
149
|
function byteToHex(byte) {
|
|
@@ -163,6 +159,22 @@ function jsonPathQuery(pathExpression, json, context) {
|
|
|
163
159
|
return (0, import_jsonpath_plus.JSONPath)({ path: pathExpression, json, wrap: false });
|
|
164
160
|
}
|
|
165
161
|
|
|
162
|
+
// src/error/RuntimeError.ts
|
|
163
|
+
var RuntimeError = class extends Error {
|
|
164
|
+
constructor(message) {
|
|
165
|
+
super(message);
|
|
166
|
+
this.name = "RuntimeError";
|
|
167
|
+
this.retryable = true;
|
|
168
|
+
this.catchable = true;
|
|
169
|
+
}
|
|
170
|
+
get isRetryable() {
|
|
171
|
+
return this.retryable;
|
|
172
|
+
}
|
|
173
|
+
get isCatchable() {
|
|
174
|
+
return this.catchable;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
166
178
|
// src/error/predefined/StatesResultPathMatchFailureError.ts
|
|
167
179
|
var StatesResultPathMatchFailureError = class extends RuntimeError {
|
|
168
180
|
constructor() {
|
|
@@ -207,7 +219,7 @@ function validateArgumentType(allowedTypes, argPosition, funcArg, funcName) {
|
|
|
207
219
|
if (matchesAllowedType)
|
|
208
220
|
break;
|
|
209
221
|
}
|
|
210
|
-
const expectedType = allowedTypes.map((type) => `
|
|
222
|
+
const expectedType = allowedTypes.map((type) => `'${type}'`).join(" | ");
|
|
211
223
|
if (!matchesAllowedType) {
|
|
212
224
|
throw new StatesRuntimeError(
|
|
213
225
|
`Intrinsic function ${funcName} expected argument ${argPosition} to be of type ${expectedType}, but received ${typeof funcArg}`
|
|
@@ -235,7 +247,7 @@ function validateArgumentConstraints(argConstraints, argPosition, funcArg, funcN
|
|
|
235
247
|
if (matchesAllConstraints)
|
|
236
248
|
break;
|
|
237
249
|
}
|
|
238
|
-
const expectedConstraints = argConstraints.map((constraint) => `
|
|
250
|
+
const expectedConstraints = argConstraints.map((constraint) => `'${constraint}'`).join(" | ");
|
|
239
251
|
if (!matchesAllConstraints) {
|
|
240
252
|
throw new StatesRuntimeError(
|
|
241
253
|
`Intrinsic function ${funcName} expected argument ${argPosition} to satisfy the following constraints: ${expectedConstraints}`
|
|
@@ -857,7 +869,7 @@ function processPayloadTemplate(payloadTemplate, json, context) {
|
|
|
857
869
|
let sanitizedKey = key;
|
|
858
870
|
let resolvedValue = value;
|
|
859
871
|
if (isPlainObj(value)) {
|
|
860
|
-
resolvedValue = processPayloadTemplate(value, json);
|
|
872
|
+
resolvedValue = processPayloadTemplate(value, json, context);
|
|
861
873
|
}
|
|
862
874
|
if (key.endsWith(".$") && typeof value === "string") {
|
|
863
875
|
sanitizedKey = key.replace(".$", "");
|
|
@@ -897,8 +909,9 @@ function processOutputPath(path, result, context) {
|
|
|
897
909
|
|
|
898
910
|
// src/stateMachine/stateActions/BaseStateAction.ts
|
|
899
911
|
var BaseStateAction = class {
|
|
900
|
-
constructor(stateDefinition) {
|
|
912
|
+
constructor(stateDefinition, stateName) {
|
|
901
913
|
this.stateDefinition = stateDefinition;
|
|
914
|
+
this.stateName = stateName;
|
|
902
915
|
}
|
|
903
916
|
buildExecutionResult(stateResult) {
|
|
904
917
|
const executionResult = { stateResult, nextState: "", isEndState: false };
|
|
@@ -923,8 +936,8 @@ var StatesNoChoiceMatchedError = class extends RuntimeError {
|
|
|
923
936
|
// src/stateMachine/stateActions/ChoiceStateAction.ts
|
|
924
937
|
var import_wildcard_match = __toESM(require("wildcard-match"), 1);
|
|
925
938
|
var ChoiceStateAction = class extends BaseStateAction {
|
|
926
|
-
constructor(stateDefinition) {
|
|
927
|
-
super(stateDefinition);
|
|
939
|
+
constructor(stateDefinition, stateName) {
|
|
940
|
+
super(stateDefinition, stateName);
|
|
928
941
|
}
|
|
929
942
|
testChoiceRule(choiceRule, input) {
|
|
930
943
|
if ("And" in choiceRule) {
|
|
@@ -1147,8 +1160,8 @@ var FailStateError = class extends RuntimeError {
|
|
|
1147
1160
|
|
|
1148
1161
|
// src/stateMachine/stateActions/FailStateAction.ts
|
|
1149
1162
|
var FailStateAction = class extends BaseStateAction {
|
|
1150
|
-
constructor(stateDefinition) {
|
|
1151
|
-
super(stateDefinition);
|
|
1163
|
+
constructor(stateDefinition, stateName) {
|
|
1164
|
+
super(stateDefinition, stateName);
|
|
1152
1165
|
}
|
|
1153
1166
|
async execute(input, context, options) {
|
|
1154
1167
|
throw new FailStateError(this.stateDefinition.Error, this.stateDefinition.Cause);
|
|
@@ -1159,10 +1172,17 @@ var FailStateAction = class extends BaseStateAction {
|
|
|
1159
1172
|
var import_p_limit = __toESM(require("p-limit"), 1);
|
|
1160
1173
|
var DEFAULT_MAX_CONCURRENCY = 40;
|
|
1161
1174
|
var MapStateAction = class extends BaseStateAction {
|
|
1162
|
-
constructor(stateDefinition) {
|
|
1163
|
-
super(stateDefinition);
|
|
1175
|
+
constructor(stateDefinition, stateName) {
|
|
1176
|
+
super(stateDefinition, stateName);
|
|
1164
1177
|
this.executionAbortFuncs = [];
|
|
1165
1178
|
}
|
|
1179
|
+
async forwardEventsToRootEventLogger(eventLogger, executionEventLogs, index, parentStateRawInput) {
|
|
1180
|
+
if (!eventLogger)
|
|
1181
|
+
return;
|
|
1182
|
+
for await (const event of executionEventLogs) {
|
|
1183
|
+
eventLogger.forwardNestedMapEvent(event, index, this.stateName, parentStateRawInput);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1166
1186
|
processItem(stateMachine, item, input, context, index, options) {
|
|
1167
1187
|
const state = this.stateDefinition;
|
|
1168
1188
|
let paramValue;
|
|
@@ -1177,6 +1197,7 @@ var MapStateAction = class extends BaseStateAction {
|
|
|
1177
1197
|
}
|
|
1178
1198
|
const execution = stateMachine.run(paramValue ?? item, options?.runOptions);
|
|
1179
1199
|
this.executionAbortFuncs.push(execution.abort);
|
|
1200
|
+
this.forwardEventsToRootEventLogger(options?.eventLogger, execution.eventLogs, index, options?.rawInput);
|
|
1180
1201
|
return execution.result;
|
|
1181
1202
|
}
|
|
1182
1203
|
async execute(input, context, options) {
|
|
@@ -1188,7 +1209,10 @@ var MapStateAction = class extends BaseStateAction {
|
|
|
1188
1209
|
if (!Array.isArray(items)) {
|
|
1189
1210
|
throw new StatesRuntimeError("Input of Map state must be an array or ItemsPath property must point to an array");
|
|
1190
1211
|
}
|
|
1191
|
-
const iteratorStateMachine = new StateMachine(state.Iterator,
|
|
1212
|
+
const iteratorStateMachine = new StateMachine(state.Iterator, {
|
|
1213
|
+
...options?.stateMachineOptions,
|
|
1214
|
+
validationOptions: { _noValidate: true }
|
|
1215
|
+
});
|
|
1192
1216
|
const limit = (0, import_p_limit.default)(state.MaxConcurrency || DEFAULT_MAX_CONCURRENCY);
|
|
1193
1217
|
const processedItemsPromise = items.map(
|
|
1194
1218
|
(item, i) => limit(() => this.processItem(iteratorStateMachine, item, input, context, i, options))
|
|
@@ -1212,14 +1236,25 @@ var MapStateAction = class extends BaseStateAction {
|
|
|
1212
1236
|
var import_p_limit2 = __toESM(require("p-limit"), 1);
|
|
1213
1237
|
var DEFAULT_CONCURRENCY = 40;
|
|
1214
1238
|
var ParallelStateAction = class extends BaseStateAction {
|
|
1215
|
-
constructor(stateDefinition) {
|
|
1216
|
-
super(stateDefinition);
|
|
1239
|
+
constructor(stateDefinition, stateName) {
|
|
1240
|
+
super(stateDefinition, stateName);
|
|
1217
1241
|
this.executionAbortFuncs = [];
|
|
1218
1242
|
}
|
|
1243
|
+
async forwardEventsToRootEventLogger(eventLogger, executionEventLogs, parentStateRawInput) {
|
|
1244
|
+
if (!eventLogger)
|
|
1245
|
+
return;
|
|
1246
|
+
for await (const event of executionEventLogs) {
|
|
1247
|
+
eventLogger.forwardNestedParallelEvent(event, this.stateName, parentStateRawInput);
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1219
1250
|
processBranch(branch, input, context, options) {
|
|
1220
|
-
const stateMachine = new StateMachine(branch,
|
|
1251
|
+
const stateMachine = new StateMachine(branch, {
|
|
1252
|
+
...options?.stateMachineOptions,
|
|
1253
|
+
validationOptions: { _noValidate: true }
|
|
1254
|
+
});
|
|
1221
1255
|
const execution = stateMachine.run(input, options?.runOptions);
|
|
1222
1256
|
this.executionAbortFuncs.push(execution.abort);
|
|
1257
|
+
this.forwardEventsToRootEventLogger(options?.eventLogger, execution.eventLogs, options?.rawInput);
|
|
1223
1258
|
return execution.result;
|
|
1224
1259
|
}
|
|
1225
1260
|
async execute(input, context, options) {
|
|
@@ -1243,8 +1278,8 @@ var ParallelStateAction = class extends BaseStateAction {
|
|
|
1243
1278
|
|
|
1244
1279
|
// src/stateMachine/stateActions/PassStateAction.ts
|
|
1245
1280
|
var PassStateAction = class extends BaseStateAction {
|
|
1246
|
-
constructor(stateDefinition) {
|
|
1247
|
-
super(stateDefinition);
|
|
1281
|
+
constructor(stateDefinition, stateName) {
|
|
1282
|
+
super(stateDefinition, stateName);
|
|
1248
1283
|
}
|
|
1249
1284
|
async execute(input, context, options) {
|
|
1250
1285
|
if (this.stateDefinition.Result) {
|
|
@@ -1256,8 +1291,8 @@ var PassStateAction = class extends BaseStateAction {
|
|
|
1256
1291
|
|
|
1257
1292
|
// src/stateMachine/stateActions/SucceedStateAction.ts
|
|
1258
1293
|
var SucceedStateAction = class extends BaseStateAction {
|
|
1259
|
-
constructor(stateDefinition) {
|
|
1260
|
-
super(stateDefinition);
|
|
1294
|
+
constructor(stateDefinition, stateName) {
|
|
1295
|
+
super(stateDefinition, stateName);
|
|
1261
1296
|
}
|
|
1262
1297
|
async execute(input, context, options) {
|
|
1263
1298
|
return { stateResult: input, nextState: "", isEndState: true };
|
|
@@ -1273,12 +1308,12 @@ var LambdaClient = class {
|
|
|
1273
1308
|
if (config) {
|
|
1274
1309
|
if (!config.region) {
|
|
1275
1310
|
throw new StatesRuntimeError(
|
|
1276
|
-
"
|
|
1311
|
+
"'awsConfig' option was specified for state machine, but 'region' property is not set"
|
|
1277
1312
|
);
|
|
1278
1313
|
}
|
|
1279
1314
|
if (config.credentials) {
|
|
1280
1315
|
const credentialsTypes = Object.keys(config.credentials);
|
|
1281
|
-
const credentialsNames = credentialsTypes.map((name) =>
|
|
1316
|
+
const credentialsNames = credentialsTypes.map((name) => `'${name}'`).join(", ");
|
|
1282
1317
|
if (credentialsTypes.length > 1) {
|
|
1283
1318
|
throw new StatesRuntimeError(
|
|
1284
1319
|
`More than one type of AWS credentials were specified: ${credentialsNames}. Only one type may be specified`
|
|
@@ -1312,7 +1347,7 @@ var LambdaClient = class {
|
|
|
1312
1347
|
}
|
|
1313
1348
|
if (invocationResult.FunctionError) {
|
|
1314
1349
|
const errorResult = resultValue;
|
|
1315
|
-
throw new FailStateError(errorResult.errorType, `Execution of Lambda function
|
|
1350
|
+
throw new FailStateError(errorResult.errorType, `Execution of Lambda function '${funcNameOrArn}' failed`);
|
|
1316
1351
|
}
|
|
1317
1352
|
return resultValue;
|
|
1318
1353
|
}
|
|
@@ -1320,8 +1355,8 @@ var LambdaClient = class {
|
|
|
1320
1355
|
|
|
1321
1356
|
// src/stateMachine/stateActions/TaskStateAction.ts
|
|
1322
1357
|
var TaskStateAction = class extends BaseStateAction {
|
|
1323
|
-
constructor(stateDefinition) {
|
|
1324
|
-
super(stateDefinition);
|
|
1358
|
+
constructor(stateDefinition, stateName) {
|
|
1359
|
+
super(stateDefinition, stateName);
|
|
1325
1360
|
}
|
|
1326
1361
|
async execute(input, context, options) {
|
|
1327
1362
|
const state = this.stateDefinition;
|
|
@@ -1337,36 +1372,44 @@ var TaskStateAction = class extends BaseStateAction {
|
|
|
1337
1372
|
|
|
1338
1373
|
// src/stateMachine/stateActions/WaitStateAction.ts
|
|
1339
1374
|
var WaitStateAction = class extends BaseStateAction {
|
|
1340
|
-
constructor(stateDefinition) {
|
|
1341
|
-
super(stateDefinition);
|
|
1375
|
+
constructor(stateDefinition, stateName) {
|
|
1376
|
+
super(stateDefinition, stateName);
|
|
1342
1377
|
}
|
|
1343
1378
|
async execute(input, context, options) {
|
|
1344
1379
|
const state = this.stateDefinition;
|
|
1345
1380
|
if (options?.waitTimeOverrideOption !== void 0) {
|
|
1346
|
-
await sleep(options.waitTimeOverrideOption, options.abortSignal);
|
|
1381
|
+
await sleep(options.waitTimeOverrideOption, options.abortSignal, options.rootAbortSignal);
|
|
1347
1382
|
return this.buildExecutionResult(input);
|
|
1348
1383
|
}
|
|
1349
1384
|
if (state.Seconds) {
|
|
1350
|
-
await sleep(state.Seconds * 1e3, options?.abortSignal);
|
|
1385
|
+
await sleep(state.Seconds * 1e3, options?.abortSignal, options?.rootAbortSignal);
|
|
1351
1386
|
} else if (state.Timestamp) {
|
|
1352
1387
|
const dateTimestamp = new Date(state.Timestamp);
|
|
1353
1388
|
const currentTime = Date.now();
|
|
1354
1389
|
const timeDiff = dateTimestamp.getTime() - currentTime;
|
|
1355
|
-
await sleep(timeDiff, options?.abortSignal);
|
|
1390
|
+
await sleep(timeDiff, options?.abortSignal, options?.rootAbortSignal);
|
|
1356
1391
|
} else if (state.SecondsPath) {
|
|
1357
1392
|
const seconds = jsonPathQuery(state.SecondsPath, input, context);
|
|
1358
|
-
await sleep(seconds * 1e3, options?.abortSignal);
|
|
1393
|
+
await sleep(seconds * 1e3, options?.abortSignal, options?.rootAbortSignal);
|
|
1359
1394
|
} else if (state.TimestampPath) {
|
|
1360
1395
|
const timestamp = jsonPathQuery(state.TimestampPath, input, context);
|
|
1361
1396
|
const dateTimestamp = new Date(timestamp);
|
|
1362
1397
|
const currentTime = Date.now();
|
|
1363
1398
|
const timeDiff = dateTimestamp.getTime() - currentTime;
|
|
1364
|
-
await sleep(timeDiff, options?.abortSignal);
|
|
1399
|
+
await sleep(timeDiff, options?.abortSignal, options?.rootAbortSignal);
|
|
1365
1400
|
}
|
|
1366
1401
|
return this.buildExecutionResult(input);
|
|
1367
1402
|
}
|
|
1368
1403
|
};
|
|
1369
1404
|
|
|
1405
|
+
// src/error/predefined/StatesTimeoutError.ts
|
|
1406
|
+
var StatesTimeoutError = class extends RuntimeError {
|
|
1407
|
+
constructor() {
|
|
1408
|
+
super("States.Timeout");
|
|
1409
|
+
this.name = "States.Timeout";
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
|
|
1370
1413
|
// src/stateMachine/StateExecutor.ts
|
|
1371
1414
|
var import_cloneDeep2 = __toESM(require("lodash/cloneDeep.js"), 1);
|
|
1372
1415
|
var DEFAULT_MAX_ATTEMPTS = 3;
|
|
@@ -1404,6 +1447,7 @@ var StateExecutor = class {
|
|
|
1404
1447
|
} = await this.stateHandlers[this.stateDefinition.Type](
|
|
1405
1448
|
// @ts-expect-error Indexing `this.stateActions` by non-literal value produces a `never` type for the `this.stateDefinition` parameter of the handler being called
|
|
1406
1449
|
this.stateDefinition,
|
|
1450
|
+
rawInput,
|
|
1407
1451
|
processedInput,
|
|
1408
1452
|
context,
|
|
1409
1453
|
this.stateName,
|
|
@@ -1414,7 +1458,7 @@ var StateExecutor = class {
|
|
|
1414
1458
|
} catch (error) {
|
|
1415
1459
|
const { shouldRetry, waitTimeBeforeRetry } = this.shouldRetry(error);
|
|
1416
1460
|
if (shouldRetry && waitTimeBeforeRetry) {
|
|
1417
|
-
await sleep(waitTimeBeforeRetry, options.abortSignal);
|
|
1461
|
+
await sleep(waitTimeBeforeRetry, options.abortSignal, options.runOptions?._rootAbortSignal);
|
|
1418
1462
|
return this.execute(input, context, options);
|
|
1419
1463
|
}
|
|
1420
1464
|
const { nextState, errorOutput, resultPath } = this.catchError(error);
|
|
@@ -1516,10 +1560,10 @@ var StateExecutor = class {
|
|
|
1516
1560
|
* Invokes the Lambda function specified in the `Resource` field
|
|
1517
1561
|
* and sets the current result of the state machine to the value returned by the Lambda.
|
|
1518
1562
|
*/
|
|
1519
|
-
async executeTaskState(stateDefinition, input, context, stateName, options) {
|
|
1563
|
+
async executeTaskState(stateDefinition, rawInput, input, context, stateName, options) {
|
|
1520
1564
|
const overrideFn = options.runOptions?.overrides?.taskResourceLocalHandlers?.[stateName];
|
|
1521
1565
|
const awsConfig = options.stateMachineOptions?.awsConfig;
|
|
1522
|
-
const taskStateAction = new TaskStateAction(stateDefinition);
|
|
1566
|
+
const taskStateAction = new TaskStateAction(stateDefinition, stateName);
|
|
1523
1567
|
const executionResult = await taskStateAction.execute(input, context, { overrideFn, awsConfig });
|
|
1524
1568
|
return executionResult;
|
|
1525
1569
|
}
|
|
@@ -1529,11 +1573,13 @@ var StateExecutor = class {
|
|
|
1529
1573
|
* Creates a new state machine for each of the branches specified in the `Branches` field,
|
|
1530
1574
|
* and then executes each branch state machine by passing them the Parallel state input.
|
|
1531
1575
|
*/
|
|
1532
|
-
async executeParallelState(stateDefinition, input, context, stateName, options) {
|
|
1533
|
-
const parallelStateAction = new ParallelStateAction(stateDefinition);
|
|
1576
|
+
async executeParallelState(stateDefinition, rawInput, input, context, stateName, options) {
|
|
1577
|
+
const parallelStateAction = new ParallelStateAction(stateDefinition, stateName);
|
|
1534
1578
|
const executionResult = await parallelStateAction.execute(input, context, {
|
|
1535
1579
|
stateMachineOptions: options.stateMachineOptions,
|
|
1536
|
-
runOptions: options.runOptions
|
|
1580
|
+
runOptions: options.runOptions,
|
|
1581
|
+
eventLogger: options.eventLogger,
|
|
1582
|
+
rawInput
|
|
1537
1583
|
});
|
|
1538
1584
|
return executionResult;
|
|
1539
1585
|
}
|
|
@@ -1544,11 +1590,13 @@ var StateExecutor = class {
|
|
|
1544
1590
|
* by the `ItemsPath` field, and then processes each item by passing it
|
|
1545
1591
|
* as the input to the state machine specified in the `Iterator` field.
|
|
1546
1592
|
*/
|
|
1547
|
-
async executeMapState(stateDefinition, input, context, stateName, options) {
|
|
1548
|
-
const mapStateAction = new MapStateAction(stateDefinition);
|
|
1593
|
+
async executeMapState(stateDefinition, rawInput, input, context, stateName, options) {
|
|
1594
|
+
const mapStateAction = new MapStateAction(stateDefinition, stateName);
|
|
1549
1595
|
const executionResult = await mapStateAction.execute(input, context, {
|
|
1550
1596
|
stateMachineOptions: options.stateMachineOptions,
|
|
1551
|
-
runOptions: options.runOptions
|
|
1597
|
+
runOptions: options.runOptions,
|
|
1598
|
+
eventLogger: options.eventLogger,
|
|
1599
|
+
rawInput
|
|
1552
1600
|
});
|
|
1553
1601
|
return executionResult;
|
|
1554
1602
|
}
|
|
@@ -1558,8 +1606,8 @@ var StateExecutor = class {
|
|
|
1558
1606
|
* If the `Result` field is specified, copies `Result` into the current result.
|
|
1559
1607
|
* Else, copies the current input into the current result.
|
|
1560
1608
|
*/
|
|
1561
|
-
async executePassState(stateDefinition, input, context, stateName, options) {
|
|
1562
|
-
const passStateAction = new PassStateAction(stateDefinition);
|
|
1609
|
+
async executePassState(stateDefinition, rawInput, input, context, stateName, options) {
|
|
1610
|
+
const passStateAction = new PassStateAction(stateDefinition, stateName);
|
|
1563
1611
|
const executionResult = await passStateAction.execute(input, context);
|
|
1564
1612
|
return executionResult;
|
|
1565
1613
|
}
|
|
@@ -1569,13 +1617,13 @@ var StateExecutor = class {
|
|
|
1569
1617
|
* Pauses the state machine execution for a certain amount of time
|
|
1570
1618
|
* based on one of the `Seconds`, `Timestamp`, `SecondsPath` or `TimestampPath` fields.
|
|
1571
1619
|
*/
|
|
1572
|
-
async executeWaitState(stateDefinition, input, context, stateName, options) {
|
|
1620
|
+
async executeWaitState(stateDefinition, rawInput, input, context, stateName, options) {
|
|
1573
1621
|
const waitTimeOverrideOption = options.runOptions?.overrides?.waitTimeOverrides?.[stateName];
|
|
1574
|
-
const
|
|
1575
|
-
const waitStateAction = new WaitStateAction(stateDefinition);
|
|
1622
|
+
const waitStateAction = new WaitStateAction(stateDefinition, stateName);
|
|
1576
1623
|
const executionResult = await waitStateAction.execute(input, context, {
|
|
1577
1624
|
waitTimeOverrideOption,
|
|
1578
|
-
abortSignal
|
|
1625
|
+
abortSignal: options.abortSignal,
|
|
1626
|
+
rootAbortSignal: options.runOptions?._rootAbortSignal
|
|
1579
1627
|
});
|
|
1580
1628
|
return executionResult;
|
|
1581
1629
|
}
|
|
@@ -1593,8 +1641,8 @@ var StateExecutor = class {
|
|
|
1593
1641
|
* If no rule matches and the `Default` field is not specified, throws a
|
|
1594
1642
|
* States.NoChoiceMatched error.
|
|
1595
1643
|
*/
|
|
1596
|
-
async executeChoiceState(stateDefinition, input, context, stateName, options) {
|
|
1597
|
-
const choiceStateAction = new ChoiceStateAction(stateDefinition);
|
|
1644
|
+
async executeChoiceState(stateDefinition, rawInput, input, context, stateName, options) {
|
|
1645
|
+
const choiceStateAction = new ChoiceStateAction(stateDefinition, stateName);
|
|
1598
1646
|
const executionResult = await choiceStateAction.execute(input, context);
|
|
1599
1647
|
return executionResult;
|
|
1600
1648
|
}
|
|
@@ -1603,8 +1651,8 @@ var StateExecutor = class {
|
|
|
1603
1651
|
*
|
|
1604
1652
|
* Ends the state machine execution successfully.
|
|
1605
1653
|
*/
|
|
1606
|
-
async executeSucceedState(stateDefinition, input, context, stateName, options) {
|
|
1607
|
-
const succeedStateAction = new SucceedStateAction(stateDefinition);
|
|
1654
|
+
async executeSucceedState(stateDefinition, rawInput, input, context, stateName, options) {
|
|
1655
|
+
const succeedStateAction = new SucceedStateAction(stateDefinition, stateName);
|
|
1608
1656
|
const executionResult = await succeedStateAction.execute(input, context);
|
|
1609
1657
|
return executionResult;
|
|
1610
1658
|
}
|
|
@@ -1613,13 +1661,186 @@ var StateExecutor = class {
|
|
|
1613
1661
|
*
|
|
1614
1662
|
* Ends the state machine execution and marks it as a failure.
|
|
1615
1663
|
*/
|
|
1616
|
-
async executeFailState(stateDefinition, input, context, stateName, options) {
|
|
1617
|
-
const failStateAction = new FailStateAction(stateDefinition);
|
|
1664
|
+
async executeFailState(stateDefinition, rawInput, input, context, stateName, options) {
|
|
1665
|
+
const failStateAction = new FailStateAction(stateDefinition, stateName);
|
|
1618
1666
|
const executionResult = await failStateAction.execute(input, context);
|
|
1619
1667
|
return executionResult;
|
|
1620
1668
|
}
|
|
1621
1669
|
};
|
|
1622
1670
|
|
|
1671
|
+
// src/stateMachine/EventLogger.ts
|
|
1672
|
+
var EventLogger = class {
|
|
1673
|
+
constructor() {
|
|
1674
|
+
this.eventTarget = new EventTarget();
|
|
1675
|
+
this.eventQueue = [];
|
|
1676
|
+
this.isLoggerClosed = false;
|
|
1677
|
+
}
|
|
1678
|
+
async *getEvents() {
|
|
1679
|
+
while (true) {
|
|
1680
|
+
if (this.eventQueue.length === 0) {
|
|
1681
|
+
await this.waitForNewEvent();
|
|
1682
|
+
}
|
|
1683
|
+
let event = null;
|
|
1684
|
+
while (event = this.eventQueue.shift()) {
|
|
1685
|
+
yield event;
|
|
1686
|
+
}
|
|
1687
|
+
if (this.isLoggerClosed)
|
|
1688
|
+
return;
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
/**
|
|
1692
|
+
* Forward nested events created by `Map` states, to the root state machine event logger.
|
|
1693
|
+
* @param event An event dispatched by the nested state machine spawned by a `Map` state.
|
|
1694
|
+
* @param index Index of the current iteration being processed.
|
|
1695
|
+
* @param mapStateName Name of the `Map` state being executed.
|
|
1696
|
+
* @param mapStateRawInput Raw input passed to the `Map` state being executed.
|
|
1697
|
+
*/
|
|
1698
|
+
forwardNestedMapEvent(event, index, mapStateName, mapStateRawInput) {
|
|
1699
|
+
switch (event.type) {
|
|
1700
|
+
case "ExecutionStarted":
|
|
1701
|
+
this.dispatchMapIterationStartedEvent(event, index, mapStateName, mapStateRawInput);
|
|
1702
|
+
break;
|
|
1703
|
+
case "ExecutionSucceeded":
|
|
1704
|
+
this.dispatchMapIterationSucceededEvent(event, index, mapStateName, mapStateRawInput);
|
|
1705
|
+
break;
|
|
1706
|
+
case "ExecutionFailed":
|
|
1707
|
+
this.dispatchMapIterationFailedEvent(event, index, mapStateName, mapStateRawInput);
|
|
1708
|
+
break;
|
|
1709
|
+
case "StateEntered":
|
|
1710
|
+
case "StateExited":
|
|
1711
|
+
event.index = index;
|
|
1712
|
+
this.dispatch(event);
|
|
1713
|
+
break;
|
|
1714
|
+
case "ExecutionAborted":
|
|
1715
|
+
case "ExecutionTimeout":
|
|
1716
|
+
return;
|
|
1717
|
+
default:
|
|
1718
|
+
this.dispatch(event);
|
|
1719
|
+
break;
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
/**
|
|
1723
|
+
* Forward nested events created by `Parallel` states, to the root state machine event logger.
|
|
1724
|
+
* @param event An event dispatched by the nested state machines spawned by a `Parallel` state.
|
|
1725
|
+
* @param parallelStateName Name of the `Parallel` state being executed.
|
|
1726
|
+
* @param parallelStateRawInput Raw input passed to the `Parallel` state being executed.
|
|
1727
|
+
*/
|
|
1728
|
+
forwardNestedParallelEvent(event, parallelStateName, parallelStateRawInput) {
|
|
1729
|
+
switch (event.type) {
|
|
1730
|
+
case "ExecutionStarted":
|
|
1731
|
+
this.dispatchParallelBranchStartedEvent(event, parallelStateName, parallelStateRawInput);
|
|
1732
|
+
break;
|
|
1733
|
+
case "ExecutionSucceeded":
|
|
1734
|
+
this.dispatchParallelBranchSucceededEvent(event, parallelStateName, parallelStateRawInput);
|
|
1735
|
+
break;
|
|
1736
|
+
case "ExecutionFailed":
|
|
1737
|
+
this.dispatchParallelBranchFailedEvent(event, parallelStateName, parallelStateRawInput);
|
|
1738
|
+
break;
|
|
1739
|
+
case "ExecutionAborted":
|
|
1740
|
+
case "ExecutionTimeout":
|
|
1741
|
+
return;
|
|
1742
|
+
default:
|
|
1743
|
+
this.dispatch(event);
|
|
1744
|
+
break;
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
dispatchExecutionStartedEvent(input) {
|
|
1748
|
+
this.dispatch({ type: "ExecutionStarted", timestamp: Date.now(), input });
|
|
1749
|
+
}
|
|
1750
|
+
dispatchExecutionSucceededEvent(output) {
|
|
1751
|
+
this.dispatch({ type: "ExecutionSucceeded", timestamp: Date.now(), output });
|
|
1752
|
+
this.close();
|
|
1753
|
+
}
|
|
1754
|
+
dispatchExecutionFailedEvent(error) {
|
|
1755
|
+
this.dispatch({ type: "ExecutionFailed", timestamp: Date.now(), Error: error.name, Cause: error.message });
|
|
1756
|
+
this.close();
|
|
1757
|
+
}
|
|
1758
|
+
dispatchExecutionAbortedEvent() {
|
|
1759
|
+
this.dispatch({ type: "ExecutionAborted", timestamp: Date.now() });
|
|
1760
|
+
this.close();
|
|
1761
|
+
}
|
|
1762
|
+
dispatchExecutionTimeoutEvent() {
|
|
1763
|
+
this.dispatch({ type: "ExecutionTimeout", timestamp: Date.now() });
|
|
1764
|
+
this.close();
|
|
1765
|
+
}
|
|
1766
|
+
dispatchStateEnteredEvent(stateName, stateType, input) {
|
|
1767
|
+
this.dispatch({
|
|
1768
|
+
type: "StateEntered",
|
|
1769
|
+
timestamp: Date.now(),
|
|
1770
|
+
state: { name: stateName, type: stateType, input }
|
|
1771
|
+
});
|
|
1772
|
+
}
|
|
1773
|
+
dispatchStateExitedEvent(stateName, stateType, input, output) {
|
|
1774
|
+
this.dispatch({
|
|
1775
|
+
type: "StateExited",
|
|
1776
|
+
timestamp: Date.now(),
|
|
1777
|
+
state: { name: stateName, type: stateType, input, output }
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
dispatchMapIterationStartedEvent(event, index, mapStateName, mapStateRawInput) {
|
|
1781
|
+
this.dispatch({
|
|
1782
|
+
...event,
|
|
1783
|
+
type: "MapIterationStarted",
|
|
1784
|
+
index,
|
|
1785
|
+
parentState: { type: "Map", name: mapStateName, input: mapStateRawInput }
|
|
1786
|
+
});
|
|
1787
|
+
}
|
|
1788
|
+
dispatchMapIterationSucceededEvent(event, index, mapStateName, mapStateRawInput) {
|
|
1789
|
+
this.dispatch({
|
|
1790
|
+
...event,
|
|
1791
|
+
type: "MapIterationSucceeded",
|
|
1792
|
+
index,
|
|
1793
|
+
parentState: { type: "Map", name: mapStateName, input: mapStateRawInput }
|
|
1794
|
+
});
|
|
1795
|
+
}
|
|
1796
|
+
dispatchMapIterationFailedEvent(event, index, mapStateName, mapStateRawInput) {
|
|
1797
|
+
this.dispatch({
|
|
1798
|
+
...event,
|
|
1799
|
+
type: "MapIterationFailed",
|
|
1800
|
+
index,
|
|
1801
|
+
parentState: { type: "Map", name: mapStateName, input: mapStateRawInput }
|
|
1802
|
+
});
|
|
1803
|
+
}
|
|
1804
|
+
dispatchParallelBranchStartedEvent(event, parallelStateName, parallelStateRawInput) {
|
|
1805
|
+
this.dispatch({
|
|
1806
|
+
...event,
|
|
1807
|
+
type: "ParallelBranchStarted",
|
|
1808
|
+
parentState: { type: "Parallel", name: parallelStateName, input: parallelStateRawInput }
|
|
1809
|
+
});
|
|
1810
|
+
}
|
|
1811
|
+
dispatchParallelBranchSucceededEvent(event, parallelStateName, parallelStateRawInput) {
|
|
1812
|
+
this.dispatch({
|
|
1813
|
+
...event,
|
|
1814
|
+
type: "ParallelBranchSucceeded",
|
|
1815
|
+
parentState: { type: "Parallel", name: parallelStateName, input: parallelStateRawInput }
|
|
1816
|
+
});
|
|
1817
|
+
}
|
|
1818
|
+
dispatchParallelBranchFailedEvent(event, parallelStateName, parallelStateRawInput) {
|
|
1819
|
+
this.dispatch({
|
|
1820
|
+
...event,
|
|
1821
|
+
type: "ParallelBranchFailed",
|
|
1822
|
+
parentState: { type: "Parallel", name: parallelStateName, input: parallelStateRawInput }
|
|
1823
|
+
});
|
|
1824
|
+
}
|
|
1825
|
+
close() {
|
|
1826
|
+
this.isLoggerClosed = true;
|
|
1827
|
+
this.eventTarget.dispatchEvent(new Event("newEvent"));
|
|
1828
|
+
}
|
|
1829
|
+
dispatch(event) {
|
|
1830
|
+
if (this.isLoggerClosed)
|
|
1831
|
+
return;
|
|
1832
|
+
this.eventQueue.push(event);
|
|
1833
|
+
this.eventTarget.dispatchEvent(new Event("newEvent"));
|
|
1834
|
+
}
|
|
1835
|
+
waitForNewEvent() {
|
|
1836
|
+
if (this.isLoggerClosed)
|
|
1837
|
+
return;
|
|
1838
|
+
return new Promise((resolve) => {
|
|
1839
|
+
this.eventTarget.addEventListener("newEvent", resolve, { once: true });
|
|
1840
|
+
});
|
|
1841
|
+
}
|
|
1842
|
+
};
|
|
1843
|
+
|
|
1623
1844
|
// src/stateMachine/StateMachine.ts
|
|
1624
1845
|
var import_asl_validator = __toESM(require("asl-validator"), 1);
|
|
1625
1846
|
var import_cloneDeep3 = __toESM(require("lodash/cloneDeep.js"), 1);
|
|
@@ -1631,14 +1852,16 @@ var StateMachine = class {
|
|
|
1631
1852
|
* These options also apply to state machines defined in the `Iterator` field of `Map` states and in the `Branches` field of `Parallel` states.
|
|
1632
1853
|
*/
|
|
1633
1854
|
constructor(definition, stateMachineOptions) {
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1855
|
+
if (!stateMachineOptions?.validationOptions?._noValidate) {
|
|
1856
|
+
const { isValid, errorsText } = (0, import_asl_validator.default)(definition, {
|
|
1857
|
+
checkArn: true,
|
|
1858
|
+
checkPaths: true,
|
|
1859
|
+
...stateMachineOptions?.validationOptions
|
|
1860
|
+
});
|
|
1861
|
+
if (!isValid) {
|
|
1862
|
+
throw new Error(`State machine definition is invalid, see error(s) below:
|
|
1641
1863
|
${errorsText("\n")}`);
|
|
1864
|
+
}
|
|
1642
1865
|
}
|
|
1643
1866
|
this.definition = definition;
|
|
1644
1867
|
this.stateMachineOptions = stateMachineOptions;
|
|
@@ -1648,6 +1871,9 @@ var StateMachine = class {
|
|
|
1648
1871
|
* If the execution fails, the result will throw an `ExecutionError` explaining why the
|
|
1649
1872
|
* execution failed.
|
|
1650
1873
|
*
|
|
1874
|
+
* If the execution times out because the number of seconds specified in
|
|
1875
|
+
* the `TimeoutSeconds` top-level field has elapsed, the result will throw an `ExecutionTimeoutError`.
|
|
1876
|
+
*
|
|
1651
1877
|
* By default, if the execution is aborted, the result will throw an `ExecutionAbortedError`. This behavior can be changed by setting
|
|
1652
1878
|
* the `noThrowOnAbort` option to `true`, in which case the result will be `null`.
|
|
1653
1879
|
*
|
|
@@ -1656,30 +1882,47 @@ var StateMachine = class {
|
|
|
1656
1882
|
*/
|
|
1657
1883
|
run(input, options) {
|
|
1658
1884
|
const abortController = new AbortController();
|
|
1885
|
+
const eventLogger = new EventLogger();
|
|
1659
1886
|
let onAbortHandler;
|
|
1660
1887
|
const settleOnAbort = new Promise((resolve, reject) => {
|
|
1661
1888
|
if (options?.noThrowOnAbort) {
|
|
1662
|
-
onAbortHandler = () =>
|
|
1889
|
+
onAbortHandler = () => {
|
|
1890
|
+
eventLogger.dispatchExecutionAbortedEvent();
|
|
1891
|
+
resolve(null);
|
|
1892
|
+
};
|
|
1663
1893
|
} else {
|
|
1664
|
-
onAbortHandler = () =>
|
|
1894
|
+
onAbortHandler = () => {
|
|
1895
|
+
eventLogger.dispatchExecutionAbortedEvent();
|
|
1896
|
+
reject(new ExecutionAbortedError());
|
|
1897
|
+
};
|
|
1665
1898
|
}
|
|
1666
1899
|
abortController.signal.addEventListener("abort", onAbortHandler);
|
|
1667
1900
|
});
|
|
1668
|
-
let rejectOnTimeout
|
|
1669
|
-
|
|
1901
|
+
let rejectOnTimeout;
|
|
1902
|
+
let timeoutId;
|
|
1903
|
+
if (this.definition.TimeoutSeconds !== void 0) {
|
|
1670
1904
|
rejectOnTimeout = new Promise((_, reject) => {
|
|
1671
|
-
setTimeout(() => {
|
|
1905
|
+
timeoutId = setTimeout(() => {
|
|
1672
1906
|
abortController.signal.removeEventListener("abort", onAbortHandler);
|
|
1673
1907
|
abortController.abort();
|
|
1674
|
-
|
|
1908
|
+
eventLogger.dispatchExecutionTimeoutEvent();
|
|
1909
|
+
reject(new ExecutionTimeoutError());
|
|
1675
1910
|
}, this.definition.TimeoutSeconds * 1e3);
|
|
1676
1911
|
});
|
|
1677
1912
|
}
|
|
1678
|
-
const executionResult = this.execute(
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1913
|
+
const executionResult = this.execute(
|
|
1914
|
+
input,
|
|
1915
|
+
{
|
|
1916
|
+
stateMachineOptions: this.stateMachineOptions,
|
|
1917
|
+
runOptions: { ...options, _rootAbortSignal: options?._rootAbortSignal ?? abortController.signal },
|
|
1918
|
+
abortSignal: abortController.signal,
|
|
1919
|
+
eventLogger
|
|
1920
|
+
},
|
|
1921
|
+
() => {
|
|
1922
|
+
abortController.signal.removeEventListener("abort", onAbortHandler);
|
|
1923
|
+
clearTimeout(timeoutId);
|
|
1924
|
+
}
|
|
1925
|
+
);
|
|
1683
1926
|
const racingPromises = [executionResult, settleOnAbort];
|
|
1684
1927
|
if (rejectOnTimeout) {
|
|
1685
1928
|
racingPromises.push(rejectOnTimeout);
|
|
@@ -1687,31 +1930,39 @@ var StateMachine = class {
|
|
|
1687
1930
|
const result = Promise.race(racingPromises);
|
|
1688
1931
|
return {
|
|
1689
1932
|
abort: () => abortController.abort(),
|
|
1933
|
+
eventLogs: eventLogger.getEvents(),
|
|
1690
1934
|
result
|
|
1691
1935
|
};
|
|
1692
1936
|
}
|
|
1693
1937
|
/**
|
|
1694
1938
|
* Helper method that handles the execution of the machine states and the transitions between them.
|
|
1695
1939
|
*/
|
|
1696
|
-
async execute(input, options) {
|
|
1940
|
+
async execute(input, options, cleanupFn) {
|
|
1941
|
+
options.eventLogger.dispatchExecutionStartedEvent(input);
|
|
1942
|
+
const context = options.runOptions?.context ?? {};
|
|
1697
1943
|
let currState = this.definition.States[this.definition.StartAt];
|
|
1698
1944
|
let currStateName = this.definition.StartAt;
|
|
1699
1945
|
let currInput = (0, import_cloneDeep3.default)(input);
|
|
1700
1946
|
let currResult = null;
|
|
1701
1947
|
let nextState = "";
|
|
1702
1948
|
let isEndState = false;
|
|
1703
|
-
let context = {};
|
|
1704
1949
|
try {
|
|
1705
1950
|
do {
|
|
1951
|
+
options.eventLogger.dispatchStateEnteredEvent(currStateName, currState.Type, currInput);
|
|
1706
1952
|
const stateExecutor = new StateExecutor(currStateName, currState);
|
|
1707
1953
|
({ stateResult: currResult, nextState, isEndState } = await stateExecutor.execute(currInput, context, options));
|
|
1954
|
+
options.eventLogger.dispatchStateExitedEvent(currStateName, currState.Type, currInput, currResult);
|
|
1708
1955
|
currInput = currResult;
|
|
1709
1956
|
currState = this.definition.States[nextState];
|
|
1710
1957
|
currStateName = nextState;
|
|
1711
1958
|
} while (!isEndState && !options.abortSignal.aborted);
|
|
1712
1959
|
} catch (error) {
|
|
1960
|
+
options.eventLogger.dispatchExecutionFailedEvent(error);
|
|
1713
1961
|
throw new ExecutionError(error);
|
|
1962
|
+
} finally {
|
|
1963
|
+
cleanupFn();
|
|
1714
1964
|
}
|
|
1965
|
+
options.eventLogger.dispatchExecutionSucceededEvent(currResult);
|
|
1715
1966
|
return currResult;
|
|
1716
1967
|
}
|
|
1717
1968
|
};
|