UNPKG

@aws-lambda-powertools/batch

Version:

The batch processing package for the Powertools for AWS Lambda (TypeScript) library.

178 lines (177 loc) 6.14 kB
import { BatchProcessingStore } from './BatchProcessingStore.js'; /** * Abstract class for batch processors. * * This class provides a common interface for processing records in a batch. * * Batch processors implementing this class should provide implementations for * a number of abstract methods that are specific to the type of processor or the * type of records being processed. * * The class comes with a few helper methods and hooks that can be used to prepare * the processor before processing records, clean up after processing records, and * handle records that succeed or fail processing. */ class BasePartialProcessor { /** * Store for managing invocation-specific state */ #store = new BatchProcessingStore(); get errors() { return this.#store.getErrors(); } set errors(errors) { this.#store.setErrors(errors); } get failureMessages() { return this.#store.getFailureMessages(); } set failureMessages(messages) { this.#store.setFailureMessages(messages); } get handler() { return this.#store.getHandler(); } set handler(handler) { this.#store.setHandler(handler); } get options() { return this.#store.getOptions(); } set options(options) { this.#store.setOptions(options); } get records() { return this.#store.getRecords(); } set records(records) { this.#store.setRecords(records); } get successMessages() { return this.#store.getSuccessMessages(); } set successMessages(messages) { this.#store.setSuccessMessages(messages); } get batchResponse() { return this.#store.getBatchResponse(); } set batchResponse(response) { this.#store.setBatchResponse(response); } /** * Method to handle a record that failed processing * * This method should be called when a record fails processing so that * the processor can keep track of the error and the record that failed. * * @param record - Record that failed processing * @param error - Error that was thrown */ failureHandler(record, error) { const entry = ['fail', error.message, record]; this.errors.push(error); this.failureMessages.push(record); return entry; } /** * Process all records with an asynchronous handler * * Once called, the processor will create an array of promises to process each record * and wait for all of them to settle before returning the results. * * Before and after processing, the processor will call the prepare and clean methods respectively. */ async process() { this.prepare(); // Default to `true` if `processInParallel` is not specified. const processInParallel = this.options?.processInParallel ?? true; const processedRecords = processInParallel ? await this.#processRecordsInParallel() : await this.#processRecordsSequentially(); this.clean(); return processedRecords; } /** * Orchestrate the processing of a batch of records synchronously * and sequentially. * * The method is responsible for calling the prepare method before * processing the records and the clean method after processing the records. * * In the middle, the method will iterate over the records and call the * processRecordSync method for each record. * * @returns List of processed records */ processSync() { /** * If this is an async processor, user should have called process instead, * so we call the method early to throw the error early thus failing fast. */ if (this.constructor.name === 'BatchProcessor') { this.processRecordSync(this.records[0]); } this.prepare(); const processedRecords = []; for (const record of this.records) { processedRecords.push(this.processRecordSync(record)); } this.clean(); return processedRecords; } /** * Set up the processor with the records and the handler * * This method should be called before processing the records to * bind the records and the handler for a specific invocation to * the processor. * * We use a separate method to do this rather than the constructor * to allow for reusing the processor instance across multiple invocations * by instantiating the processor outside the Lambda function handler. * * @param records - Array of records to be processed * @param handler - CallableFunction to process each record from the batch * @param options - Options to be used during processing (optional) */ register(records, handler, options) { this.records = records; this.handler = handler; if (options) { this.options = options; } return this; } /** * Method to handle a record that succeeded processing * * This method should be called when a record succeeds processing so that * the processor can keep track of the result and the record that succeeded. * * @param record - Record that succeeded processing * @param result - Result from record handler */ successHandler(record, result) { const entry = ['success', result, record]; this.successMessages.push(record); return entry; } /** * Processes records in parallel using `Promise.all`. */ #processRecordsInParallel() { return Promise.all(this.records.map((record) => this.processRecord(record))); } /** * Processes records sequentially, ensuring that each record is processed one after the other. */ async #processRecordsSequentially() { const processedRecords = []; for (const record of this.records) { processedRecords.push(await this.processRecord(record)); } return processedRecords; } } export { BasePartialProcessor };