Skip to content

Commit b737ba3

Browse files
github-actions[bot]chasprowebdevMarfuen
authored
Create trigger.dev task to send policy email due to resend rate limit issue (#1633)
* fix(app): trigger 2 new-policy-email events per second at most due to resend rate limit * fix(app): create trigger.dev task to send policy email due to resend rate limit issue * fix(app): remove unused send-policy-email API --------- Co-authored-by: chasprowebdev <[email protected]> Co-authored-by: Mariano Fuentes <[email protected]>
1 parent f5fc56e commit b737ba3

File tree

3 files changed

+76
-73
lines changed

3 files changed

+76
-73
lines changed

apps/app/src/actions/policies/accept-requested-policy-changes.ts

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
'use server';
22

3+
import { sendNewPolicyEmail } from '@/jobs/tasks/email/new-policy-email';
34
import { db, PolicyStatus } from '@db';
5+
import { tasks } from '@trigger.dev/sdk';
46
import { revalidatePath, revalidateTag } from 'next/cache';
57
import { z } from 'zod';
68
import { authActionClient } from '../safe-action';
@@ -92,34 +94,36 @@ export const acceptRequestedPolicyChangesAction = authActionClient
9294
return roles.includes('employee');
9395
});
9496

95-
// Call /api/send-policy-email to send emails to employees
96-
9797
// Prepare the events array for the API
9898
const events = employeeMembers
9999
.filter((employee) => employee.user.email)
100-
.map((employee) => ({
101-
subscriberId: `${employee.user.id}-${session.activeOrganizationId}`,
102-
email: employee.user.email,
103-
userName: employee.user.name || employee.user.email || 'Employee',
104-
policyName: policy.name,
105-
organizationName: policy.organization.name,
106-
url: `${process.env.NEXT_PUBLIC_PORTAL_URL ?? 'https://portal.trycomp.ai'}/${session.activeOrganizationId}`,
107-
description: `The "${policy.name}" policy has been ${isNewPolicy ? 'created' : 'updated'}.`,
108-
}));
100+
.map((employee) => {
101+
let notificationType: 'new' | 're-acceptance' | 'updated';
102+
const wasAlreadySigned = policy.signedBy.includes(employee.id);
103+
if (isNewPolicy) {
104+
notificationType = 'new';
105+
} else if (wasAlreadySigned) {
106+
notificationType = 're-acceptance';
107+
} else {
108+
notificationType = 'updated';
109+
}
110+
111+
return {
112+
email: employee.user.email,
113+
userName: employee.user.name || employee.user.email || 'Employee',
114+
policyName: policy.name,
115+
organizationId: session.activeOrganizationId || '',
116+
organizationName: policy.organization.name,
117+
notificationType,
118+
};
119+
});
109120

110121
// Call the API route to send the emails
111-
try {
112-
await fetch(`${process.env.BETTER_AUTH_URL ?? ''}/api/send-policy-email`, {
113-
method: 'POST',
114-
headers: {
115-
'Content-Type': 'application/json',
116-
},
117-
body: JSON.stringify(events),
118-
});
119-
} catch (error) {
120-
console.error('Failed to call /api/send-policy-email:', error);
121-
// Don't throw, just log
122-
}
122+
await Promise.all(
123+
events.map((event) =>
124+
tasks.trigger<typeof sendNewPolicyEmail>('send-new-policy-email', event),
125+
),
126+
);
123127

124128
// If a comment was provided, create a comment
125129
if (comment && comment.trim() !== '') {

apps/app/src/app/api/send-policy-email/route.ts

Lines changed: 0 additions & 50 deletions
This file was deleted.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { sendPolicyNotificationEmail } from '@comp/email';
2+
import { logger, queue, task } from '@trigger.dev/sdk';
3+
4+
// Queue with concurrency limit of 1 to ensure rate limiting (1 email per second max)
5+
const policyEmailQueue = queue({
6+
name: 'policy-email-queue',
7+
concurrencyLimit: 2,
8+
});
9+
10+
interface PolicyEmailPayload {
11+
email: string;
12+
userName: string;
13+
policyName: string;
14+
organizationId: string;
15+
organizationName: string;
16+
notificationType: 'new' | 'updated' | 're-acceptance';
17+
}
18+
19+
export const sendNewPolicyEmail = task({
20+
id: 'send-new-policy-email',
21+
queue: policyEmailQueue,
22+
run: async (payload: PolicyEmailPayload) => {
23+
logger.info('Sending new policy email', {
24+
email: payload.email,
25+
policyName: payload.policyName,
26+
});
27+
28+
try {
29+
await sendPolicyNotificationEmail(payload);
30+
31+
logger.info('Successfully sent policy email', {
32+
email: payload.email,
33+
policyName: payload.policyName,
34+
});
35+
36+
return {
37+
success: true,
38+
email: payload.email,
39+
};
40+
} catch (error) {
41+
logger.error('Failed to send policy email', {
42+
email: payload.email,
43+
error: error instanceof Error ? error.message : String(error),
44+
});
45+
46+
throw error;
47+
}
48+
},
49+
});

0 commit comments

Comments
 (0)