chore: initial project import
Some checks failed
CI - Production Readiness / Verify (push) Has been cancelled
Some checks failed
CI - Production Readiness / Verify (push) Has been cancelled
This commit is contained in:
79
lib/campaign-utils.ts
Normal file
79
lib/campaign-utils.ts
Normal file
@ -0,0 +1,79 @@
|
||||
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
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user