UNPKG

@message-queue-toolkit/sns

Version:
84 lines 4.08 kB
import { SetSubscriptionAttributesCommand, SubscribeCommand } from '@aws-sdk/client-sns'; import { assertQueue } from '@message-queue-toolkit/sqs'; import { isCreateTopicCommand, isSNSTopicLocatorType, } from "../types/TopicTypes.js"; import { assertTopic, findSubscriptionByTopicAndQueue, getTopicArnByName } from "./snsUtils.js"; async function resolveTopicArnToSubscribeTo(snsClient, stsClient, topicConfiguration, extraParams) { //If topicArn is present, let's use it and return early. if (isSNSTopicLocatorType(topicConfiguration) && topicConfiguration.topicArn) { return topicConfiguration.topicArn; } //If input configuration is capable of creating a topic, let's create it and return its ARN. if (isCreateTopicCommand(topicConfiguration)) { return await assertTopic(snsClient, stsClient, topicConfiguration, { queueUrlsWithSubscribePermissionsPrefix: extraParams?.queueUrlsWithSubscribePermissionsPrefix, allowedSourceOwner: extraParams?.allowedSourceOwner, forceTagUpdate: extraParams?.forceTagUpdate, }); } //Last option: let's not create a topic but resolve a ARN based on the desired topic name. return await getTopicArnByName(snsClient, topicConfiguration.topicName); } export async function subscribeToTopic(sqsClient, snsClient, stsClient, queueConfiguration, topicConfiguration, subscriptionConfiguration, extraParams) { const topicArn = await resolveTopicArnToSubscribeTo(snsClient, stsClient, topicConfiguration, extraParams); const { queueUrl, queueArn } = await assertQueue(sqsClient, queueConfiguration, { topicArnsWithPublishPermissionsPrefix: extraParams?.topicArnsWithPublishPermissionsPrefix, updateAttributesIfExists: extraParams?.updateAttributesIfExists, forceTagUpdate: extraParams?.forceTagUpdate, }); const subscribeCommand = new SubscribeCommand({ TopicArn: topicArn, Endpoint: queueArn, Protocol: 'sqs', ReturnSubscriptionArn: true, ...subscriptionConfiguration, }); try { const subscriptionResult = await snsClient.send(subscribeCommand); return { subscriptionArn: subscriptionResult.SubscriptionArn, topicArn, queueUrl, queueArn, }; } catch (err) { const logger = extraParams?.logger ?? console; // @ts-ignore logger.error(`Error while creating subscription for queue "${queueConfiguration.QueueName}", topic "${isCreateTopicCommand(topicConfiguration) ? topicConfiguration.Name : topicConfiguration.topicName}": ${err.message}`); if (subscriptionConfiguration.updateAttributesIfExists && err.message.indexOf('Subscription already exists with different attributes') !== -1) { const result = await tryToUpdateSubscription(snsClient, topicArn, queueArn, subscriptionConfiguration); if (!result) { logger.error('Failed to update subscription'); throw err; } return { subscriptionArn: result.SubscriptionArn, topicArn, queueUrl, queueArn, }; } throw err; } } async function tryToUpdateSubscription(snsClient, topicArn, queueArn, subscriptionConfiguration) { const subscription = await findSubscriptionByTopicAndQueue(snsClient, topicArn, queueArn); if (!subscription || !subscriptionConfiguration.Attributes) { return undefined; } const setSubscriptionAttributesCommands = Object.entries(subscriptionConfiguration.Attributes).map(([key, value]) => { return new SetSubscriptionAttributesCommand({ SubscriptionArn: subscription.SubscriptionArn, AttributeName: key, AttributeValue: value, }); }); for (const command of setSubscriptionAttributesCommands) { await snsClient.send(command); } return subscription; } //# sourceMappingURL=snsSubscriber.js.map