UNPKG

@aws-lambda-powertools/batch

Version:

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

182 lines (181 loc) 6.44 kB
import { getStringFromEnv } from '@aws-lambda-powertools/commons/utils/env'; import { BasePartialProcessor } from './BasePartialProcessor.js'; import { DATA_CLASS_MAPPING, DEFAULT_RESPONSE, EventType, } from './constants.js'; import { FullBatchFailureError } from './errors.js'; /** * Base abstract class for processing batch records with partial failure handling * * This class extends the {@link BasePartialProcessor} class and adds additional * functionality to handle batch processing. Specifically, it provides methods * to collect failed records and build the partial failure response. */ class BasePartialBatchProcessor extends BasePartialProcessor { /** * Mapping of event types to their respective failure collectors * * Each service expects a different format for partial failure reporting, * this mapping ensures that the correct format is used for each event type. */ COLLECTOR_MAPPING; /** * Type of event that the processor is handling */ eventType; /** * A logger instance to be used for logging debug, warning, and error messages. * * When no logger is provided, we'll only log warnings and errors using the global `console` object. */ logger; /** * The configuration options for the parser integration */ parserConfig; /** * Initializes base batch processing class * * @param eventType The type of event to process (SQS, Kinesis, DynamoDB) */ constructor(eventType, parserConfig) { super(); this.eventType = eventType; this.batchResponse = DEFAULT_RESPONSE; this.COLLECTOR_MAPPING = { [EventType.SQS]: () => this.collectSqsFailures(), [EventType.KinesisDataStreams]: () => this.collectKinesisFailures(), [EventType.DynamoDBStreams]: () => this.collectDynamoDBFailures(), }; this.parserConfig = parserConfig; const alcLogLevel = getStringFromEnv({ key: 'AWS_LAMBDA_LOG_LEVEL', defaultValue: '', }); this.logger = parserConfig?.logger ?? { debug: alcLogLevel === 'DEBUG' ? console.debug : () => undefined, error: console.error, warn: console.warn, }; } /** * Clean up logic to be run after processing a batch * * If the entire batch failed this method will throw a {@link FullBatchFailureError | `FullBatchFailureError`} with the list of * errors that occurred during processing, unless the `throwOnFullBatchFailure` option is set to `false`. * * Otherwise, it will build the partial failure response based on the event type. */ clean() { if (!this.hasMessagesToReport()) { return; } if (this.options?.throwOnFullBatchFailure !== false && this.entireBatchFailed()) { throw new FullBatchFailureError(this.errors); } const messages = this.getMessagesToReport(); this.batchResponse = { batchItemFailures: messages }; } /** * Collect the identifiers of failed items for a DynamoDB stream * * The failures are collected based on the sequence number of the record * and formatted as a list of objects with the key `itemIdentifier` as * expected by the service. */ collectDynamoDBFailures() { const failures = []; for (const msg of this.failureMessages) { const msgId = msg.dynamodb?.SequenceNumber; /* v8 ignore else -- @preserve */ if (msgId) { failures.push({ itemIdentifier: msgId }); } } return failures; } /** * Collect identifiers of failed items for a Kinesis batch * * The failures are collected based on the sequence number of the record * and formatted as a list of objects with the key `itemIdentifier` as * expected by the service. */ collectKinesisFailures() { const failures = []; for (const msg of this.failureMessages) { const msgId = msg.kinesis.sequenceNumber; failures.push({ itemIdentifier: msgId }); } return failures; } /** * Collect identifiers of failed items for an SQS batch * * The failures are collected based on the message ID of the record * and formatted as a list of objects with the key `itemIdentifier` as * expected by the service. */ collectSqsFailures() { const failures = []; for (const msg of this.failureMessages) { const msgId = msg.messageId; failures.push({ itemIdentifier: msgId }); } return failures; } /** * Determine if the entire batch failed * * If the number of errors is equal to the number of records, then the * entire batch failed and this method will return `true`. */ entireBatchFailed() { return this.errors.length === this.records.length; } /** * Collect identifiers for failed batch items * * The method will call the appropriate collector based on the event type * and return the list of failed items. */ getMessagesToReport() { return this.COLLECTOR_MAPPING[this.eventType](); } /** * Determine if there are any failed records to report * * If there are no failed records, then the batch was successful * and this method will return `false`. */ hasMessagesToReport() { return this.failureMessages.length !== 0; } /** * Set up the processor with the initial state ready for processing */ prepare() { this.successMessages = []; this.failureMessages = []; this.errors = []; this.batchResponse = DEFAULT_RESPONSE; } /** * Get the response from the batch processing */ response() { return this.batchResponse; } /** * Forward a record to the appropriate batch type * * Based on the event type that the processor was initialized with, this method * will cast the record to the appropriate batch type handler. * * @param record The record to be processed * @param eventType The type of event to process */ toBatchType(record, eventType) { return DATA_CLASS_MAPPING[eventType](record); } } export { BasePartialBatchProcessor };