♻️ Improvements to house-keeping webhook (#1063)

This commit is contained in:
Luke Vella 2024-03-16 11:56:07 +07:00 committed by GitHub
parent 0d82c158ce
commit 90f0d90fab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 173 additions and 104 deletions

View file

@ -0,0 +1,153 @@
import { prisma } from "@rallly/database";
import { headers } from "next/headers";
import { NextResponse } from "next/server";
export async function POST(req: Request, ctx: { params: { task: string } }) {
const headersList = headers();
const authorization = headersList.get("authorization");
if (authorization !== `Bearer ${process.env.API_SECRET}`) {
return NextResponse.json(
{ success: false },
{
status: 401,
},
);
}
switch (ctx.params.task) {
case "delete-inactive-polls": {
return await deleteInactivePolls();
}
case "remove-deleted-polls": {
return await removeDeletedPolls(req);
}
}
}
/**
* Marks inactive polls as deleted. Polls are inactive if they have not been
* touched in the last 30 days and all dates are in the past.
*/
async function deleteInactivePolls() {
const markedDeleted = await prisma.$executeRaw`
UPDATE polls p
SET
deleted = true,
deleted_at = NOW()
WHERE touched_at < NOW() - INTERVAL '30 days'
AND deleted = false
AND id NOT IN (
SELECT poll_id
FROM options
WHERE poll_id = p.id
AND start_time > NOW()
)
AND user_id NOT IN (
SELECT id
FROM users
WHERE id IN (
SELECT user_id
FROM user_payment_data
WHERE end_date > NOW()
)
OR subscription_id IN (
SELECT subscription_id
FROM subscriptions
WHERE active = true
)
);
`;
return NextResponse.json({
success: true,
summary: {
markedDeleted,
},
});
}
/**
* Remove polls and corresponding data that have been marked deleted for more than 7 days.
*/
async function removeDeletedPolls(req: Request) {
const options = (await req.json()) as { take?: number } | undefined;
// First get the ids of all the polls that have been marked as deleted for at least 7 days
const deletedPolls = await prisma.poll.findMany({
select: {
id: true,
},
where: {
deleted: true,
deletedAt: {
lt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
},
},
take: options?.take ?? 1000,
});
const deletedPollIds = deletedPolls.map((poll) => poll.id);
const { count: deletedWatcherCount } = await prisma.watcher.deleteMany({
where: {
pollId: {
in: deletedPollIds,
},
},
});
const { count: deletedVoteCount } = await prisma.vote.deleteMany({
where: {
pollId: {
in: deletedPollIds,
},
},
});
const { count: deletedParticipantCount } =
await prisma.participant.deleteMany({
where: {
pollId: {
in: deletedPollIds,
},
},
});
const { count: deletedOptionCount } = await prisma.option.deleteMany({
where: {
pollId: {
in: deletedPollIds,
},
},
});
const { count: deletedCommentCount } = await prisma.comment.deleteMany({
where: {
pollId: {
in: deletedPollIds,
},
},
});
const { count: deletedPollCount } = await prisma.poll.deleteMany({
where: {
id: {
in: deletedPollIds,
},
},
});
return NextResponse.json({
success: true,
summary: {
deleted: {
votes: deletedVoteCount,
options: deletedOptionCount,
participants: deletedParticipantCount,
comments: deletedCommentCount,
watchers: deletedWatcherCount,
polls: deletedPollCount,
},
},
});
}

View file

@ -1,53 +0,0 @@
import { prisma } from "@rallly/database";
import { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
if (req.method !== "POST") {
res.setHeader("Allow", "POST");
res.status(405).end("Method not allowed");
return;
}
const { authorization } = req.headers;
if (authorization !== `Bearer ${process.env.API_SECRET}`) {
res.status(401).json({ success: false });
return;
}
const deletedPolls = await prisma.$executeRaw`
UPDATE polls p
SET
deleted = true,
deleted_at = NOW()
WHERE touched_at < NOW() - INTERVAL '30 days'
AND deleted = false
AND id NOT IN (
SELECT poll_id
FROM options
WHERE poll_id = p.id
AND start_time > NOW()
)
AND user_id NOT IN (
SELECT id
FROM users
WHERE id IN (
SELECT user_id
FROM user_payment_data
WHERE end_date > NOW()
)
OR subscription_id IN (
SELECT subscription_id
FROM subscriptions
WHERE active = true
)
);
`;
res.status(200).json({
softDeleted: deletedPolls,
});
}