feat(email): send trial ending soon mails
This commit is contained in:
@@ -4,6 +4,7 @@ import { Worker } from 'bullmq';
|
||||
import {
|
||||
cronQueue,
|
||||
eventsQueue,
|
||||
miscQueue,
|
||||
notificationQueue,
|
||||
sessionsQueue,
|
||||
} from '@openpanel/queue';
|
||||
@@ -13,6 +14,7 @@ import { performance } from 'node:perf_hooks';
|
||||
import { setTimeout as sleep } from 'node:timers/promises';
|
||||
import { cronJob } from './jobs/cron';
|
||||
import { eventsJob } from './jobs/events';
|
||||
import { miscJob } from './jobs/misc';
|
||||
import { notificationJob } from './jobs/notification';
|
||||
import { sessionsJob } from './jobs/sessions';
|
||||
import { logger } from './utils/logger';
|
||||
@@ -35,12 +37,14 @@ export async function bootWorkers() {
|
||||
notificationJob,
|
||||
workerOptions,
|
||||
);
|
||||
const miscWorker = new Worker(miscQueue.name, miscJob, workerOptions);
|
||||
|
||||
const workers = [
|
||||
sessionsWorker,
|
||||
eventsWorker,
|
||||
cronWorker,
|
||||
notificationWorker,
|
||||
miscWorker,
|
||||
];
|
||||
|
||||
workers.forEach((worker) => {
|
||||
@@ -105,12 +109,7 @@ export async function bootWorkers() {
|
||||
try {
|
||||
const time = performance.now();
|
||||
await waitForQueueToEmpty(cronQueue);
|
||||
await Promise.all([
|
||||
cronWorker.close(),
|
||||
eventsWorker.close(),
|
||||
sessionsWorker.close(),
|
||||
notificationWorker.close(),
|
||||
]);
|
||||
await Promise.all(workers.map((worker) => worker.close()));
|
||||
logger.info('workers closed successfully', {
|
||||
elapsed: performance.now() - time,
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@ import { createInitialSalts } from '@openpanel/db';
|
||||
import {
|
||||
cronQueue,
|
||||
eventsQueue,
|
||||
miscQueue,
|
||||
notificationQueue,
|
||||
sessionsQueue,
|
||||
} from '@openpanel/queue';
|
||||
@@ -36,6 +37,7 @@ async function start() {
|
||||
new BullMQAdapter(sessionsQueue),
|
||||
new BullMQAdapter(cronQueue),
|
||||
new BullMQAdapter(notificationQueue),
|
||||
new BullMQAdapter(miscQueue),
|
||||
],
|
||||
serverAdapter: serverAdapter,
|
||||
});
|
||||
|
||||
50
apps/worker/src/jobs/misc.trail-ending-soon.ts
Normal file
50
apps/worker/src/jobs/misc.trail-ending-soon.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { db } from '@openpanel/db';
|
||||
import { sendEmail } from '@openpanel/email';
|
||||
import type { MiscQueuePayloadTrialEndingSoon } from '@openpanel/queue';
|
||||
import type { Job } from 'bullmq';
|
||||
|
||||
export async function trialEndingSoonJob(
|
||||
job: Job<MiscQueuePayloadTrialEndingSoon>,
|
||||
) {
|
||||
const { organizationId } = job.data.payload;
|
||||
|
||||
const organization = await db.organization.findUnique({
|
||||
where: {
|
||||
id: organizationId,
|
||||
},
|
||||
include: {
|
||||
createdBy: {
|
||||
select: {
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
projects: {
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!organization) {
|
||||
return;
|
||||
}
|
||||
|
||||
const project = organization.projects[0];
|
||||
|
||||
if (!organization.createdBy?.email) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!project) {
|
||||
return;
|
||||
}
|
||||
|
||||
return sendEmail('trial-ending-soon', {
|
||||
to: organization.createdBy?.email,
|
||||
data: {
|
||||
organizationName: organization.name,
|
||||
url: `https://dashboard.openpanel.dev/${organization.id}/${project.id}/settings/organization?tab=billing`,
|
||||
},
|
||||
});
|
||||
}
|
||||
13
apps/worker/src/jobs/misc.ts
Normal file
13
apps/worker/src/jobs/misc.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { Job } from 'bullmq';
|
||||
|
||||
import type { MiscQueuePayloadTrialEndingSoon } from '@openpanel/queue';
|
||||
|
||||
import { trialEndingSoonJob } from './misc.trail-ending-soon';
|
||||
|
||||
export async function miscJob(job: Job<MiscQueuePayloadTrialEndingSoon>) {
|
||||
switch (job.data.type) {
|
||||
case 'trialEndingSoon': {
|
||||
return await trialEndingSoonJob(job);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user