UNPKG

@gp_jcisneros/aws-utils

Version:

AWS SDK utilities for GreenPay microservices

194 lines (170 loc) 6.55 kB
const { SQSClient, SendMessageCommand, ReceiveMessageCommand, DeleteMessageCommand } = require('@aws-sdk/client-sqs'); const { AWSError, IntegrationError } = require('@gp_jcisneros/errors'); /** * Utilities for AWS SQS operations */ class SQSUtils { constructor(region = process.env.AWS_REGION || 'us-east-1') { this.client = new SQSClient({ region }); } /** * Send a message to SQS queue * @param {string} queueUrl - URL of the SQS queue * @param {Object|string} messageBody - Message to send * @param {Object} options - Additional options (delaySeconds, messageAttributes, etc.) * @returns {Promise<Object>} - Send result */ async sendMessage(queueUrl, messageBody, options = {}) { try { const command = new SendMessageCommand({ QueueUrl: queueUrl, MessageBody: typeof messageBody === 'string' ? messageBody : JSON.stringify(messageBody), DelaySeconds: options.delaySeconds || 0, MessageAttributes: options.messageAttributes || {}, MessageGroupId: options.messageGroupId, MessageDeduplicationId: options.messageDeduplicationId }); const result = await this.client.send(command); return { success: true, messageId: result.MessageId, sequenceNumber: result.SequenceNumber, md5OfMessageBody: result.MD5OfMessageBody }; } catch (error) { // Si ya es un error personalizado, lo relanzamos if (error instanceof AWSError || error instanceof IntegrationError) { throw error; } throw new IntegrationError(`SQS send failed for ${queueUrl}: ${error.message}`, 'SQS_SEND_ERROR', 'sqs', { queueUrl, messageBody: typeof messageBody === 'string' ? messageBody : JSON.stringify(messageBody) }); } } /** * Receive messages from SQS queue * @param {string} queueUrl - URL of the SQS queue * @param {Object} options - Receive options (maxNumberOfMessages, waitTimeSeconds, etc.) * @returns {Promise<Array>} - Array of received messages */ async receiveMessages(queueUrl, options = {}) { try { const command = new ReceiveMessageCommand({ QueueUrl: queueUrl, MaxNumberOfMessages: options.maxNumberOfMessages || 10, WaitTimeSeconds: options.waitTimeSeconds || 20, VisibilityTimeout: options.visibilityTimeout || 30, MessageAttributeNames: options.messageAttributeNames || ['All'], AttributeNames: options.attributeNames || ['All'] }); const result = await this.client.send(command); return result.Messages || []; } catch (error) { // Si ya es un error personalizado, lo relanzamos if (error instanceof AWSError || error instanceof IntegrationError) { throw error; } throw new IntegrationError(`SQS receive failed for ${queueUrl}: ${error.message}`, 'SQS_RECEIVE_ERROR', 'sqs', { queueUrl, options }); } } /** * Delete a message from SQS queue * @param {string} queueUrl - URL of the SQS queue * @param {string} receiptHandle - Receipt handle of the message to delete * @returns {Promise<Object>} - Delete result */ async deleteMessage(queueUrl, receiptHandle) { try { const command = new DeleteMessageCommand({ QueueUrl: queueUrl, ReceiptHandle: receiptHandle }); await this.client.send(command); return { success: true }; } catch (error) { // Si ya es un error personalizado, lo relanzamos if (error instanceof AWSError || error instanceof IntegrationError) { throw error; } throw new IntegrationError(`SQS delete failed for ${queueUrl}: ${error.message}`, 'SQS_DELETE_ERROR', 'sqs', { queueUrl, receiptHandle }); } } /** * Send JSON message to SQS queue * @param {string} queueUrl - URL of the SQS queue * @param {Object} jsonData - JSON data to send * @param {Object} options - Additional options * @returns {Promise<Object>} - Send result */ async sendJsonMessage(queueUrl, jsonData, options = {}) { return this.sendMessage(queueUrl, jsonData, options); } /** * Process messages from SQS queue with a handler function * @param {string} queueUrl - URL of the SQS queue * @param {Function} messageHandler - Function to handle each message * @param {Object} options - Processing options * @returns {Promise<Object>} - Processing result */ async processMessages(queueUrl, messageHandler, options = {}) { try { const messages = await this.receiveMessages(queueUrl, options); const results = []; for (const message of messages) { try { const result = await messageHandler(message); await this.deleteMessage(queueUrl, message.ReceiptHandle); results.push({ success: true, messageId: message.MessageId, result }); } catch (error) { results.push({ success: false, messageId: message.MessageId, error: error.message }); } } return { processed: results.length, successful: results.filter(r => r.success).length, failed: results.filter(r => !r.success).length, results }; } catch (error) { // Si ya es un error personalizado, lo relanzamos if (error instanceof AWSError || error instanceof IntegrationError) { throw error; } throw new IntegrationError(`SQS message processing failed for ${queueUrl}: ${error.message}`, 'SQS_PROCESS_ERROR', 'sqs', { queueUrl, options }); } } // Static methods for convenience static async sendMessage(queueUrl, messageBody, options = {}) { const utils = new SQSUtils(); return utils.sendMessage(queueUrl, messageBody, options); } static async receiveMessages(queueUrl, options = {}) { const utils = new SQSUtils(); return utils.receiveMessages(queueUrl, options); } static async deleteMessage(queueUrl, receiptHandle) { const utils = new SQSUtils(); return utils.deleteMessage(queueUrl, receiptHandle); } static async sendJsonMessage(queueUrl, jsonData, options = {}) { const utils = new SQSUtils(); return utils.sendJsonMessage(queueUrl, jsonData, options); } static async processMessages(queueUrl, messageHandler, options = {}) { const utils = new SQSUtils(); return utils.processMessages(queueUrl, messageHandler, options); } } module.exports = { SQSUtils };