Skip to content

Commit c8ef49f

Browse files
authored
fix callback not working in self-hosted version (#234)
1 parent cbd9785 commit c8ef49f

1 file changed

Lines changed: 43 additions & 32 deletions

File tree

apps/web/src/server/service/ses-settings-service.ts

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export class SesSettingsService {
2525
private static initialized = false;
2626

2727
public static async getSetting(
28-
region = env.AWS_DEFAULT_REGION,
28+
region = env.AWS_DEFAULT_REGION
2929
): Promise<SesSetting | null> {
3030
await this.checkInitialized();
3131

@@ -75,41 +75,43 @@ export class SesSettingsService {
7575

7676
if (!usesendUrlValidation.isValid) {
7777
throw new Error(
78-
`Callback URL: ${usesendUrl} is not valid, status: ${usesendUrlValidation.code} message:${usesendUrlValidation.error}`,
78+
`Callback URL: ${usesendUrl} is not valid, status: ${usesendUrlValidation.code} message:${usesendUrlValidation.error}`
7979
);
8080
}
8181

8282
const idPrefix = smallNanoid(10);
8383
let topicArn: string | undefined;
8484

85+
let settingId: string | undefined;
86+
8587
try {
8688
const topicName = `${idPrefix}-${region}-unsend`;
8789
topicArn = await sns.createTopic(topicName, region);
8890
if (!topicArn) {
8991
throw new Error("Failed to create SNS topic");
9092
}
9193

92-
const setting = await db.$transaction(async (tx) => {
93-
const setting = await tx.sesSetting.create({
94-
data: {
95-
region,
96-
callbackUrl: `${parsedUrl}/api/ses_callback`,
97-
topic: topicName,
98-
topicArn,
99-
sesEmailRateLimit: sendingRateLimit,
100-
transactionalQuota,
101-
idPrefix,
102-
},
103-
});
94+
const setting = await db.sesSetting.create({
95+
data: {
96+
region,
97+
callbackUrl: `${parsedUrl}/api/ses_callback`,
98+
topic: topicName,
99+
topicArn,
100+
sesEmailRateLimit: sendingRateLimit,
101+
transactionalQuota,
102+
idPrefix,
103+
},
104+
});
104105

105-
await sns.subscribeEndpoint(
106-
topicArn!,
107-
`${setting.callbackUrl}`,
108-
setting.region,
109-
);
106+
settingId = setting.id;
110107

111-
return setting;
112-
});
108+
await this.invalidateCache();
109+
110+
await sns.subscribeEndpoint(
111+
topicArn!,
112+
`${setting.callbackUrl}`,
113+
setting.region
114+
);
113115

114116
if (!setting) {
115117
throw new Error("Failed to create setting");
@@ -120,14 +122,14 @@ export class SesSettingsService {
120122
EmailQueueService.initializeQueue(
121123
region,
122124
setting.sesEmailRateLimit,
123-
setting.transactionalQuota,
125+
setting.transactionalQuota
124126
);
125127
logger.info(
126128
{
127129
transactionalQueue: EmailQueueService.transactionalQueue,
128130
marketingQueue: EmailQueueService.marketingQueue,
129131
},
130-
"Email queues initialized",
132+
"Email queues initialized"
131133
);
132134

133135
await this.invalidateCache();
@@ -138,10 +140,18 @@ export class SesSettingsService {
138140
} catch (deleteError) {
139141
logger.error(
140142
{ err: deleteError },
141-
"Failed to delete SNS topic after error",
143+
"Failed to delete SNS topic after error"
142144
);
143145
}
144146
}
147+
if (settingId) {
148+
await db.sesSetting.delete({
149+
where: {
150+
id: settingId,
151+
},
152+
});
153+
}
154+
await this.invalidateCache();
145155
logger.error({ err: error }, "Failed to create SES setting");
146156
throw error;
147157
}
@@ -172,21 +182,21 @@ export class SesSettingsService {
172182
transactionalQueue: EmailQueueService.transactionalQueue,
173183
marketingQueue: EmailQueueService.marketingQueue,
174184
},
175-
"Email queues before update",
185+
"Email queues before update"
176186
);
177187

178188
EmailQueueService.initializeQueue(
179189
setting.region,
180190
setting.sesEmailRateLimit,
181-
setting.transactionalQuota,
191+
setting.transactionalQuota
182192
);
183193

184194
logger.info(
185195
{
186196
transactionalQueue: EmailQueueService.transactionalQueue,
187197
marketingQueue: EmailQueueService.marketingQueue,
188198
},
189-
"Email queues after update",
199+
"Email queues after update"
190200
);
191201

192202
await this.invalidateCache();
@@ -200,8 +210,9 @@ export class SesSettingsService {
200210
}
201211

202212
static async invalidateCache() {
203-
this.cache = {};
204213
const settings = await db.sesSetting.findMany();
214+
this.cache = {};
215+
this.topicArns = [];
205216
settings.forEach((setting) => {
206217
this.cache[setting.region] = setting;
207218
if (setting.topicArn) {
@@ -229,31 +240,31 @@ async function registerConfigurationSet(setting: SesSetting) {
229240
configGeneral,
230241
setting.topicArn,
231242
GENERAL_EVENTS,
232-
setting.region,
243+
setting.region
233244
);
234245

235246
const configClick = `${setting.idPrefix}-${setting.region}-unsend-click`;
236247
const clickStatus = await ses.addWebhookConfiguration(
237248
configClick,
238249
setting.topicArn,
239250
[...GENERAL_EVENTS, "CLICK"],
240-
setting.region,
251+
setting.region
241252
);
242253

243254
const configOpen = `${setting.idPrefix}-${setting.region}-unsend-open`;
244255
const openStatus = await ses.addWebhookConfiguration(
245256
configOpen,
246257
setting.topicArn,
247258
[...GENERAL_EVENTS, "OPEN"],
248-
setting.region,
259+
setting.region
249260
);
250261

251262
const configFull = `${setting.idPrefix}-${setting.region}-unsend-full`;
252263
const fullStatus = await ses.addWebhookConfiguration(
253264
configFull,
254265
setting.topicArn,
255266
[...GENERAL_EVENTS, "CLICK", "OPEN"],
256-
setting.region,
267+
setting.region
257268
);
258269

259270
return await db.sesSetting.update({

0 commit comments

Comments
 (0)