UNPKG

@message-queue-toolkit/sns

Version:
96 lines 4.56 kB
import { SetSubscriptionAttributesCommand, SubscribeCommand } from '@aws-sdk/client-sns'; import { InternalError, isError, stringValueSerializer } from '@lokalise/node-core'; import { assertQueue } from '@message-queue-toolkit/sqs'; import { isCreateTopicCommand, isSNSTopicLocatorType, } from "../types/TopicTypes.js"; import { assertTopic, findSubscriptionByTopicAndQueue } from "./snsUtils.js"; import { buildTopicArn } from "./stsUtils.js"; async function resolveTopicArnToSubscribeTo(snsClient, stsClient, topicConfiguration, extraParams) { if (isSNSTopicLocatorType(topicConfiguration)) { if (topicConfiguration.topicArn) return topicConfiguration.topicArn; if (topicConfiguration.topicName) return buildTopicArn(stsClient, topicConfiguration.topicName); } if (isCreateTopicCommand(topicConfiguration)) { return await assertTopic(snsClient, stsClient, topicConfiguration, { queueUrlsWithSubscribePermissionsPrefix: extraParams?.queueUrlsWithSubscribePermissionsPrefix, allowedSourceOwner: extraParams?.allowedSourceOwner, forceTagUpdate: extraParams?.forceTagUpdate, }); } throw new InternalError({ errorCode: 'invalid_topic_configuration', message: 'Invalid topic configuration provided, cannot resolve topic ARN', details: { topicConfiguration: stringValueSerializer(topicConfiguration) }, }); } 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) { if (!isError(err)) throw err; const logger = extraParams?.logger ?? console; const errMessage = `Error while creating subscription for queue "${queueConfiguration.QueueName}", topic "${isCreateTopicCommand(topicConfiguration) ? topicConfiguration.Name : topicConfiguration.topicName}": ${err.message}`; logger.error(errMessage); if (subscriptionConfiguration.updateAttributesIfExists && err.message.indexOf('Subscription already exists with different attributes') !== -1) { const result = await tryToUpdateSubscription(snsClient, topicArn, queueArn, subscriptionConfiguration); if (result) { return { subscriptionArn: result.SubscriptionArn, topicArn, queueUrl, queueArn, }; } logger.error('Failed to update subscription'); } throw new InternalError({ errorCode: 'sns_subscription_creation_failed', message: errMessage, details: { queueName: queueConfiguration.QueueName, topicArn, originalError: err.message }, cause: 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