80 lines
2.3 KiB
TypeScript
80 lines
2.3 KiB
TypeScript
import { CampaignStatus, DeliveryStatus } from "@prisma/client";
|
|
|
|
import { prisma } from "@/lib/prisma";
|
|
|
|
export const DEFAULT_MAX_SEND_ATTEMPTS = 3;
|
|
|
|
export const RETRY_BACKOFF_SECONDS = [10, 30, 120];
|
|
|
|
export function getRetryDelaySeconds(attempt: number) {
|
|
if (attempt <= 1) {
|
|
return RETRY_BACKOFF_SECONDS[0];
|
|
}
|
|
|
|
if (attempt - 1 < RETRY_BACKOFF_SECONDS.length) {
|
|
return RETRY_BACKOFF_SECONDS[attempt - 1];
|
|
}
|
|
|
|
return RETRY_BACKOFF_SECONDS[RETRY_BACKOFF_SECONDS.length - 1];
|
|
}
|
|
|
|
export function renderCampaignMessage(templateBody: string, values: Record<string, string>) {
|
|
return templateBody.replace(/\{\{\s*(\d+)\s*\}\}/g, (match, token) => {
|
|
const key = String(token);
|
|
return values[key] ?? match;
|
|
});
|
|
}
|
|
|
|
export async function recalculateCampaignTotals(campaignId: string) {
|
|
const recipients = await prisma.campaignRecipient.findMany({
|
|
where: { campaignId },
|
|
select: { sendStatus: true }
|
|
});
|
|
|
|
const totalRecipients = recipients.length;
|
|
const totalSent = recipients.filter((recipient) => recipient.sendStatus !== DeliveryStatus.QUEUED).length;
|
|
const totalDelivered = recipients.filter((recipient) =>
|
|
recipient.sendStatus === DeliveryStatus.DELIVERED || recipient.sendStatus === DeliveryStatus.READ
|
|
).length;
|
|
const totalRead = recipients.filter((recipient) => recipient.sendStatus === DeliveryStatus.READ).length;
|
|
const totalFailed = recipients.filter((recipient) => recipient.sendStatus === DeliveryStatus.FAILED).length;
|
|
const totalQueued = recipients.filter((recipient) => recipient.sendStatus === DeliveryStatus.QUEUED).length;
|
|
|
|
const isDone = totalQueued === 0;
|
|
const status = isDone
|
|
? totalFailed > 0
|
|
? totalSent > 0
|
|
? CampaignStatus.PARTIAL_FAILED
|
|
: CampaignStatus.FAILED
|
|
: CampaignStatus.COMPLETED
|
|
: totalFailed > 0
|
|
? CampaignStatus.PARTIAL_FAILED
|
|
: CampaignStatus.PROCESSING;
|
|
|
|
const updateData: {
|
|
totalRecipients: number;
|
|
totalSent: number;
|
|
totalDelivered: number;
|
|
totalRead: number;
|
|
totalFailed: number;
|
|
status: CampaignStatus;
|
|
finishedAt?: Date | null;
|
|
} = {
|
|
totalRecipients,
|
|
totalSent,
|
|
totalDelivered,
|
|
totalRead,
|
|
totalFailed,
|
|
status
|
|
};
|
|
|
|
if (isDone) {
|
|
updateData.finishedAt = new Date();
|
|
}
|
|
|
|
await prisma.broadcastCampaign.update({
|
|
where: { id: campaignId },
|
|
data: updateData
|
|
});
|
|
}
|