@message-queue-toolkit/sqs
Version:
SQS adapter for message-queue-toolkit
128 lines (127 loc) • 8.72 kB
TypeScript
import type { Either, ErrorResolver } from '@lokalise/node-core';
import { type BarrierResult, type MessageSchemaContainer, type PreHandlingOutputs, type Prehandler, type QueueConsumer, type QueueConsumerDependencies, type QueueConsumerOptions } from '@message-queue-toolkit/core';
import type { ConsumerOptions } from 'sqs-consumer';
import type { ZodSchema } from 'zod/v4';
import type { SQSMessage } from '../types/MessageTypes.ts';
import type { SQSCreationConfig, SQSDependencies, SQSQueueLocatorType } from './AbstractSqsService.ts';
import { AbstractSqsService } from './AbstractSqsService.ts';
type SQSDeadLetterQueueOptions = {
redrivePolicy: {
maxReceiveCount: number;
};
};
export type SQSConsumerDependencies = SQSDependencies & QueueConsumerDependencies;
type SQSConsumerCommonOptions<MessagePayloadSchemas extends object, ExecutionContext, PrehandlerOutput, CreationConfigType extends SQSCreationConfig = SQSCreationConfig, QueueLocatorType extends object = SQSQueueLocatorType> = QueueConsumerOptions<CreationConfigType, QueueLocatorType, SQSDeadLetterQueueOptions, MessagePayloadSchemas, ExecutionContext, PrehandlerOutput, SQSCreationConfig, SQSQueueLocatorType> & {
/**
* Omitting properties which will be set internally ins this class
* `visibilityTimeout` is also omitted to avoid conflicts with queue config
*/
consumerOverrides?: Omit<ConsumerOptions, 'sqs' | 'queueUrl' | 'handler' | 'handleMessageBatch' | 'visibilityTimeout' | 'messageAttributeNames' | 'messageSystemAttributeNames' | 'attributeNames'>;
concurrentConsumersAmount?: number;
};
type SQSConsumerFifoOptions = {
fifoQueue: true;
/**
* Interval in milliseconds between barrier re-checks during sleep period (FIFO queues only).
* FIFO queues sleep and recheck barriers instead of republishing messages to preserve order.
* The consumer will sleep and recheck for up to maxRetryDuration before moving to DLQ.
* Default: 5000 (5 seconds)
*/
barrierSleepCheckIntervalInMsecs?: number;
/**
* Interval in milliseconds between visibility timeout extensions during barrier sleep (FIFO queues only).
* Extensions happen BEFORE each sleep chunk to prevent message from becoming visible during long waits.
* Should be less than the VisibilityTimeout to prevent message reclaim.
* Default: 30000 (30 seconds)
*/
barrierVisibilityExtensionIntervalInMsecs?: number;
/**
* Duration in seconds to extend visibility timeout to during barrier sleep (FIFO queues only).
* Each extension sets visibility to this value from NOW (not cumulative).
* Should be significantly longer than barrierVisibilityExtensionIntervalInMsecs for safety buffer.
* Default: 90 (90 seconds, providing 60s buffer with 30s check interval)
*/
barrierVisibilityTimeoutInSeconds?: number;
};
type SQSConsumerStandardQueueOptions = {
fifoQueue?: false;
};
export type SQSConsumerOptions<MessagePayloadSchemas extends object, ExecutionContext, PrehandlerOutput, CreationConfigType extends SQSCreationConfig = SQSCreationConfig, QueueLocatorType extends object = SQSQueueLocatorType> = (SQSConsumerCommonOptions<MessagePayloadSchemas, ExecutionContext, PrehandlerOutput, CreationConfigType, QueueLocatorType> & SQSConsumerFifoOptions) | (SQSConsumerCommonOptions<MessagePayloadSchemas, ExecutionContext, PrehandlerOutput, CreationConfigType, QueueLocatorType> & SQSConsumerStandardQueueOptions);
export declare abstract class AbstractSqsConsumer<MessagePayloadType extends object, ExecutionContext, PrehandlerOutput = undefined, CreationConfigType extends SQSCreationConfig = SQSCreationConfig, QueueLocatorType extends object = SQSQueueLocatorType, ConsumerOptionsType extends SQSConsumerOptions<MessagePayloadType, ExecutionContext, PrehandlerOutput, CreationConfigType, QueueLocatorType> = SQSConsumerOptions<MessagePayloadType, ExecutionContext, PrehandlerOutput, CreationConfigType, QueueLocatorType>> extends AbstractSqsService<MessagePayloadType, QueueLocatorType, CreationConfigType, ConsumerOptionsType, SQSConsumerDependencies, ExecutionContext, PrehandlerOutput> implements QueueConsumer {
private consumers;
private readonly concurrentConsumersAmount;
private readonly transactionObservabilityManager?;
private readonly consumerOptionsOverride;
private readonly handlerContainer;
private readonly deadLetterQueueOptions?;
private readonly isDeduplicationEnabled;
private maxRetryDuration;
private cachedContentBasedDeduplication?;
private readonly barrierSleepCheckIntervalInMsecs;
private readonly barrierVisibilityExtensionIntervalInMsecs;
private readonly barrierVisibilityTimeoutInSeconds;
protected deadLetterQueueUrl?: string;
protected readonly errorResolver: ErrorResolver;
protected readonly executionContext: ExecutionContext;
readonly _messageSchemaContainer: MessageSchemaContainer<MessagePayloadType>;
protected constructor(dependencies: SQSConsumerDependencies, options: ConsumerOptionsType, executionContext: ExecutionContext);
init(): Promise<void>;
protected initDeadLetterQueue(): Promise<void>;
start(): Promise<void>;
close(abort?: boolean): Promise<void>;
private createConsumer;
private handleRetryLater;
/**
* Sleep and periodically recheck barrier for FIFO queues.
* This method implements the barrier sleep mechanism to avoid unnecessary AWS retries.
*/
private sleepAndRecheckBarrier;
/**
* Sleep for the specified duration while optionally extending visibility timeout to prevent message reclaim.
* AWS SQS will reclaim messages if visibility timeout expires during processing.
*
* Visibility extension strategy:
* - If heartbeatInterval is set and <= extension interval: rely on sqs-consumer's automatic extension
* - Otherwise: explicitly extend at configured intervals during sleep
*
* This prevents redundant API calls when heartbeatInterval already provides sufficient coverage.
*/
private sleepWithVisibilityTimeoutExtension;
/**
* Determines whether to use async or sync path for building retry message params.
* For FIFO queues with locatorConfig, we need to fetch ContentBasedDeduplication from SQS.
*/
private buildRetryMessageParamsWithDeduplicationCheck;
/**
* Builds SendMessageCommand parameters for retry, handling FIFO vs standard queues (synchronous)
*/
private buildRetryMessageParams;
/**
* Builds FIFO retry message params when ContentBasedDeduplication attribute needs to be fetched from SQS.
* This is only needed when using locatorConfig (queue not created by this service).
* Caches the ContentBasedDeduplication value after first fetch to avoid repeated API calls.
*/
private buildFifoRetryMessageParamsAsync;
private stopExistingConsumers;
private internalProcessMessage;
protected processMessage(message: MessagePayloadType, messageType: string, preHandlingOutputs: PreHandlingOutputs<PrehandlerOutput, any>): Promise<Either<'retryLater', 'success'>>;
protected processPrehandlers(message: MessagePayloadType, messageType: string): Promise<PrehandlerOutput>;
protected preHandlerBarrier<BarrierOutput>(message: MessagePayloadType, messageType: string, preHandlerOutput: PrehandlerOutput): Promise<BarrierResult<BarrierOutput>>;
protected resolveSchema(message: MessagePayloadType): Either<Error, ZodSchema<MessagePayloadType>>;
protected resolveNextFunction(preHandlers: Prehandler<MessagePayloadType, ExecutionContext, unknown>[], message: MessagePayloadType, index: number, preHandlerOutput: PrehandlerOutput, resolve: (value: PrehandlerOutput | PromiseLike<PrehandlerOutput>) => void, reject: (err: Error) => void): (preHandlerResult: import("@message-queue-toolkit/core").PrehandlerResult) => void;
protected resolveMessageLog(message: MessagePayloadType, messageType: string): unknown;
protected resolveMessage(message: SQSMessage): Either<import("@message-queue-toolkit/core").MessageInvalidFormatError | import("@message-queue-toolkit/core").MessageValidationError, import("@message-queue-toolkit/core").ResolvedMessage>;
protected isDeduplicationEnabledForMessage(message: MessagePayloadType): boolean;
protected resolveMaybeOffloadedPayloadMessage(message: SQSMessage): Promise<{
error?: never;
result: import("@message-queue-toolkit/core").ResolvedMessage;
} | {
error: "abort";
result?: never;
}>;
private tryToExtractId;
private deserializeMessage;
private failProcessing;
private getQueueVisibilityTimeout;
}
export {};