UNPKG

@deliverr/serverless-offline-step-functions

Version:

Serverless Offline Plugin to Support Step Functions for Local Development

118 lines (117 loc) 6.32 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MapExecutor = void 0; const lodash_chunk_1 = __importDefault(require("lodash.chunk")); const StateTypeExecutor_1 = require("../StateTypeExecutor"); const StateMachineExecutor_1 = require("../../StateMachineExecutor"); const StateContext_1 = require("../../Context/StateContext"); const StateProcessor_1 = require("../../StateProcessor"); const StateMachine_1 = require("../../StateMachine/StateMachine"); const Logger_1 = require("../../utils/Logger"); class MapExecutor extends StateTypeExecutor_1.StateTypeExecutor { constructor() { super(...arguments); this.pendingStateMachineExecutions = {}; } async execute(context, stateDefinition, inputJson) { const stateMachineDescription = { name: stateDefinition.Comment, definition: stateDefinition.Iterator, }; const stateMachine = StateMachine_1.StateMachine.create(stateMachineDescription.name || '', stateMachineDescription); if (!inputJson) { throw new Error(`Undefined inputJson for state `); } const iterable = this.processInput(inputJson, stateDefinition, context); const iterableOutputPromises = iterable.map(async (value, index) => { const tempContext = context.clone(); const iterationInputValue = typeof value === 'string' ? value : JSON.stringify(value); tempContext.startMapItration(index, iterationInputValue); const iterationInput = StateProcessor_1.StateProcessor.processParameters(iterationInputValue, stateDefinition.Parameters, tempContext); const stateName = stateDefinition.Iterator.StartAt; const stateContext = StateContext_1.StateContext.create(stateName); tempContext.transitionTo(stateContext); const sme = new StateMachineExecutor_1.StateMachineExecutor(stateMachine, tempContext); const startAtState = stateDefinition.Iterator.States[stateDefinition.Iterator.StartAt]; const execution = await sme.execute(startAtState, iterationInput); if (execution instanceof StateMachineExecutor_1.StateMachineExecutorError) { throw execution.error; } return typeof execution === 'string' ? JSON.parse(execution) : execution; }); const maxConcurrency = stateDefinition.MaxConcurrency || 0; let iterableOutput = []; if (maxConcurrency <= 0) { this.logger.log('Running Map iterables in Parallel'); iterableOutput = await Promise.all(iterableOutputPromises); } else { this.logger.log(`Running Map iterables in chunks of ${maxConcurrency}`); const promiseChunks = lodash_chunk_1.default(iterableOutputPromises, maxConcurrency); for (let index = 0; index < promiseChunks.length; index++) { const promisechunk = promiseChunks[index]; this.logger.log(`Running Map iterable chunk (${index + 1}/${promiseChunks.length})`); const result = await Promise.all(promisechunk); iterableOutput.push(...result); } } this.logger.debug('Finished processing iterable'); this.logger.debug(JSON.stringify(iterableOutput)); const output = this.processOutput(JSON.parse(inputJson), iterableOutput, stateDefinition); return { Next: stateDefinition.Next, End: stateDefinition.End, json: JSON.stringify(output), }; } processOutput(input, output, stateDefinition) { this.logger.debug(`MapExecutor - processOutput - stepOutputJSON - input`); this.logger.debug(typeof input); this.logger.debug(JSON.stringify(input)); this.logger.debug(`MapExecutor - processOutput - stepOutputJSON - output`); this.logger.debug(JSON.stringify(output)); this.logger.debug(typeof output); let stepOutputJSON = StateProcessor_1.StateProcessor.processResultSelector(JSON.stringify(output), stateDefinition.ResultSelector); stepOutputJSON = StateProcessor_1.StateProcessor.processResultPath(input, JSON.parse(stepOutputJSON), stateDefinition.ResultPath); this.logger.debug(stepOutputJSON); const outputJson = StateProcessor_1.StateProcessor.processOutputPath(stepOutputJSON, stateDefinition.OutputPath); this.logger.debug(outputJson); let processedOutput; try { processedOutput = JSON.parse(outputJson); this.logger.debug(`processedOutput`); this.logger.debug(typeof processedOutput); } catch (error) { this.logger.error(`MapExecutor.processInput: Could not parse JSON: "${outputJson}"`); throw error; } return processedOutput; } processInput(json, stateDefinition, context) { this.logger.debug(`MapExecutor - processInput1 - ${json}`); const processedInputJson = StateProcessor_1.StateProcessor.processInputPath(json, stateDefinition.InputPath); const processedItemsJson = StateProcessor_1.StateProcessor.processItemsPath(processedInputJson, stateDefinition.ItemsPath); let processedItems; try { processedItems = JSON.parse(processedItemsJson); } catch (error) { this.logger.error(`MapExecutor.processInput: Could not parse JSON for state ${context.State.Name}: "${processedItemsJson}"`); throw error; } if (!Array.isArray(processedItems)) { this.logger.error('Processed input & items is not an array ' + `with InputPath: ${stateDefinition.InputPath} & ItemsPaths: ${stateDefinition.ItemsPath} and input: ${json}`); throw new Error('Input is not an array'); } Logger_1.Logger.getInstance().debug('Finished processing Map input'); Logger_1.Logger.getInstance().debug(JSON.stringify(processedItems)); Logger_1.Logger.getInstance().debug(typeof processedItems[0]); return processedItems; } } exports.MapExecutor = MapExecutor;