fix callback not working in self-hosted version (#234)

This commit is contained in:
KM Koushik
2025-09-17 17:38:12 +10:00
committed by GitHub
parent cbd97853b9
commit c8ef49f12c

View File

@@ -25,7 +25,7 @@ export class SesSettingsService {
private static initialized = false; private static initialized = false;
public static async getSetting( public static async getSetting(
region = env.AWS_DEFAULT_REGION, region = env.AWS_DEFAULT_REGION
): Promise<SesSetting | null> { ): Promise<SesSetting | null> {
await this.checkInitialized(); await this.checkInitialized();
@@ -75,13 +75,15 @@ export class SesSettingsService {
if (!usesendUrlValidation.isValid) { if (!usesendUrlValidation.isValid) {
throw new Error( throw new Error(
`Callback URL: ${usesendUrl} is not valid, status: ${usesendUrlValidation.code} message:${usesendUrlValidation.error}`, `Callback URL: ${usesendUrl} is not valid, status: ${usesendUrlValidation.code} message:${usesendUrlValidation.error}`
); );
} }
const idPrefix = smallNanoid(10); const idPrefix = smallNanoid(10);
let topicArn: string | undefined; let topicArn: string | undefined;
let settingId: string | undefined;
try { try {
const topicName = `${idPrefix}-${region}-unsend`; const topicName = `${idPrefix}-${region}-unsend`;
topicArn = await sns.createTopic(topicName, region); topicArn = await sns.createTopic(topicName, region);
@@ -89,28 +91,28 @@ export class SesSettingsService {
throw new Error("Failed to create SNS topic"); throw new Error("Failed to create SNS topic");
} }
const setting = await db.$transaction(async (tx) => { const setting = await db.sesSetting.create({
const setting = await tx.sesSetting.create({ data: {
data: { region,
region, callbackUrl: `${parsedUrl}/api/ses_callback`,
callbackUrl: `${parsedUrl}/api/ses_callback`, topic: topicName,
topic: topicName, topicArn,
topicArn, sesEmailRateLimit: sendingRateLimit,
sesEmailRateLimit: sendingRateLimit, transactionalQuota,
transactionalQuota, idPrefix,
idPrefix, },
},
});
await sns.subscribeEndpoint(
topicArn!,
`${setting.callbackUrl}`,
setting.region,
);
return setting;
}); });
settingId = setting.id;
await this.invalidateCache();
await sns.subscribeEndpoint(
topicArn!,
`${setting.callbackUrl}`,
setting.region
);
if (!setting) { if (!setting) {
throw new Error("Failed to create setting"); throw new Error("Failed to create setting");
} }
@@ -120,14 +122,14 @@ export class SesSettingsService {
EmailQueueService.initializeQueue( EmailQueueService.initializeQueue(
region, region,
setting.sesEmailRateLimit, setting.sesEmailRateLimit,
setting.transactionalQuota, setting.transactionalQuota
); );
logger.info( logger.info(
{ {
transactionalQueue: EmailQueueService.transactionalQueue, transactionalQueue: EmailQueueService.transactionalQueue,
marketingQueue: EmailQueueService.marketingQueue, marketingQueue: EmailQueueService.marketingQueue,
}, },
"Email queues initialized", "Email queues initialized"
); );
await this.invalidateCache(); await this.invalidateCache();
@@ -138,10 +140,18 @@ export class SesSettingsService {
} catch (deleteError) { } catch (deleteError) {
logger.error( logger.error(
{ err: deleteError }, { err: deleteError },
"Failed to delete SNS topic after error", "Failed to delete SNS topic after error"
); );
} }
} }
if (settingId) {
await db.sesSetting.delete({
where: {
id: settingId,
},
});
}
await this.invalidateCache();
logger.error({ err: error }, "Failed to create SES setting"); logger.error({ err: error }, "Failed to create SES setting");
throw error; throw error;
} }
@@ -172,13 +182,13 @@ export class SesSettingsService {
transactionalQueue: EmailQueueService.transactionalQueue, transactionalQueue: EmailQueueService.transactionalQueue,
marketingQueue: EmailQueueService.marketingQueue, marketingQueue: EmailQueueService.marketingQueue,
}, },
"Email queues before update", "Email queues before update"
); );
EmailQueueService.initializeQueue( EmailQueueService.initializeQueue(
setting.region, setting.region,
setting.sesEmailRateLimit, setting.sesEmailRateLimit,
setting.transactionalQuota, setting.transactionalQuota
); );
logger.info( logger.info(
@@ -186,7 +196,7 @@ export class SesSettingsService {
transactionalQueue: EmailQueueService.transactionalQueue, transactionalQueue: EmailQueueService.transactionalQueue,
marketingQueue: EmailQueueService.marketingQueue, marketingQueue: EmailQueueService.marketingQueue,
}, },
"Email queues after update", "Email queues after update"
); );
await this.invalidateCache(); await this.invalidateCache();
@@ -200,8 +210,9 @@ export class SesSettingsService {
} }
static async invalidateCache() { static async invalidateCache() {
this.cache = {};
const settings = await db.sesSetting.findMany(); const settings = await db.sesSetting.findMany();
this.cache = {};
this.topicArns = [];
settings.forEach((setting) => { settings.forEach((setting) => {
this.cache[setting.region] = setting; this.cache[setting.region] = setting;
if (setting.topicArn) { if (setting.topicArn) {
@@ -229,7 +240,7 @@ async function registerConfigurationSet(setting: SesSetting) {
configGeneral, configGeneral,
setting.topicArn, setting.topicArn,
GENERAL_EVENTS, GENERAL_EVENTS,
setting.region, setting.region
); );
const configClick = `${setting.idPrefix}-${setting.region}-unsend-click`; const configClick = `${setting.idPrefix}-${setting.region}-unsend-click`;
@@ -237,7 +248,7 @@ async function registerConfigurationSet(setting: SesSetting) {
configClick, configClick,
setting.topicArn, setting.topicArn,
[...GENERAL_EVENTS, "CLICK"], [...GENERAL_EVENTS, "CLICK"],
setting.region, setting.region
); );
const configOpen = `${setting.idPrefix}-${setting.region}-unsend-open`; const configOpen = `${setting.idPrefix}-${setting.region}-unsend-open`;
@@ -245,7 +256,7 @@ async function registerConfigurationSet(setting: SesSetting) {
configOpen, configOpen,
setting.topicArn, setting.topicArn,
[...GENERAL_EVENTS, "OPEN"], [...GENERAL_EVENTS, "OPEN"],
setting.region, setting.region
); );
const configFull = `${setting.idPrefix}-${setting.region}-unsend-full`; const configFull = `${setting.idPrefix}-${setting.region}-unsend-full`;
@@ -253,7 +264,7 @@ async function registerConfigurationSet(setting: SesSetting) {
configFull, configFull,
setting.topicArn, setting.topicArn,
[...GENERAL_EVENTS, "CLICK", "OPEN"], [...GENERAL_EVENTS, "CLICK", "OPEN"],
setting.region, setting.region
); );
return await db.sesSetting.update({ return await db.sesSetting.update({