UNPKG

@webda/aws

Version:

Webda AWS Services implementation

172 lines 5.59 kB
import { SQS } from "@aws-sdk/client-sqs"; import { Queue, QueueParameters, WebdaError } from "@webda/core"; import { createHash } from "crypto"; import { AWSServiceParameters } from "./index.js"; export class SQSQueueParameters extends AWSServiceParameters(QueueParameters) { constructor(params) { super(params); this.WaitTimeSeconds = this.WaitTimeSeconds ?? 20; this.queue = this.queue ?? ""; } } /** * Implement SQS as queue for Webda * * @WebdaModda */ export default class SQSQueue extends Queue { /** * @inheritdoc */ loadParameters(params) { return new SQSQueueParameters(params); } /** * @inheritdoc */ async init() { await super.init(); this.sqs = new SQS(this.parameters); return this; } /** * @inheritdoc */ async size() { let res = await this.sqs.getQueueAttributes({ AttributeNames: ["ApproximateNumberOfMessages", "ApproximateNumberOfMessagesNotVisible"], QueueUrl: this.parameters.queue }); return (parseInt(res["Attributes"]["ApproximateNumberOfMessages"]) + parseInt(res["Attributes"]["ApproximateNumberOfMessagesNotVisible"])); } /** * @inheritdoc */ async sendMessage(params) { const sqsParams = { QueueUrl: this.parameters.queue, MessageBody: JSON.stringify(params) }; if (this.parameters.MessageGroupId) { sqsParams.MessageGroupId = this.parameters.MessageGroupId; } if (this.parameters.queue.endsWith(".fifo")) { sqsParams.MessageDeduplicationId = createHash("sha256").update(sqsParams.MessageBody).digest("hex"); } await this.sqs.sendMessage(sqsParams); } /** * @inheritdoc */ async receiveMessage(proto) { let queueArg = { QueueUrl: this.parameters.queue, WaitTimeSeconds: this.parameters.WaitTimeSeconds, MaxNumberOfMessages: this.parameters.maxConsumers > 10 ? 10 : this.parameters.maxConsumers }; let data = await this.sqs.receiveMessage(queueArg); data.Messages ?? (data.Messages = []); return data.Messages.map(m => ({ ReceiptHandle: m.ReceiptHandle, Message: this.unserialize(m.Body, proto) })); } /** * We will retrieve more than one message on receiveMessage if maxConsumers is higher * therefore we need to divide by 10 (the max number of group messaged) to get the number * of consumers * * @returns */ getMaxConsumers() { return Math.ceil(this.parameters.maxConsumers / 10); } /** * @inheritdoc */ async deleteMessage(receipt) { await this.sqs.deleteMessage({ QueueUrl: this.parameters.queue, ReceiptHandle: receipt }); } /** * @inheritdoc */ async __clean() { return this.__cleanWithRetry(false); } async __cleanWithRetry(fail) { try { await this.sqs.purgeQueue({ QueueUrl: this.parameters.queue }); } catch (err) { if (fail || err.name !== "AWS.SimpleQueueService.PurgeQueueInProgress") { throw err; } let delay = Math.floor(err.retryDelay * 1100); // 10% of margin return new Promise(resolve => { setTimeout(() => { resolve(this.__cleanWithRetry(true)); }, delay); }); } } _getQueueInfosFromUrl() { let found = this.parameters.queue.match(/.*sqs\.(.*)\.amazonaws.com\/(\d+)\/(.*)/i); if (!found) { // Check for LocalStack found = this.parameters.queue.match(/http:\/\/(localhost):\d+\/(.*)\/(.*)/i); if (!found) { throw new WebdaError.CodeError("SQS_PARAMETER_MALFORMED", "SQS Queue URL malformed"); } found[1] = "us-east-1"; } return { accountId: found[2], region: found[1], name: found[3] }; } getARNPolicy() { // Parse this._params.queue; let queue = this._getQueueInfosFromUrl(); return { Sid: this.constructor.name + this._name, Effect: "Allow", Action: [ "sqs:DeleteMessage", "sqs:DeleteMessageBatch", "sqs:ReceiveMessage", "sqs:SendMessage", "sqs:SendMessageBatch" ], Resource: ["arn:aws:sqs:" + queue.region + ":" + queue.accountId + ":" + queue.name] }; } getCloudFormation(deployer) { if (this.parameters.CloudFormationSkip) { return {}; } let { name: QueueName } = this._getQueueInfosFromUrl(); let resources = {}; this.parameters.CloudFormation = this.parameters.CloudFormation || {}; this.parameters.CloudFormation.Queue = this.parameters.CloudFormation.Queue || {}; resources[this._name + "Queue"] = { Type: "AWS::SQS::Queue", Properties: { ...this.parameters.CloudFormation.Queue, QueueName, Tags: deployer.getDefaultTags(this.parameters.CloudFormation.Queue.Tags) } }; // Add any Other resources with prefix of the service return resources; } } export { SQSQueue }; //# sourceMappingURL=sqsqueue.js.map