137 lines
4.3 KiB
TypeScript
137 lines
4.3 KiB
TypeScript
import { PrismaClient } from "../../apps/web/prisma/generated/client";
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
const TARGET_PREFIX = process.env.GITHUB_ISSUE_PREFIX || "GitHub Issue:";
|
|
const BATCH_SIZE = Math.max(parseInt(process.env.PURGE_BATCH_SIZE || "100", 10), 1);
|
|
const args = new Set(process.argv.slice(2));
|
|
const isDryRun = args.has("--dry-run");
|
|
const forceRun = args.has("--force");
|
|
|
|
function chunk<T>(items: T[], size: number): T[][] {
|
|
const output: T[][] = [];
|
|
for (let index = 0; index < items.length; index += size) {
|
|
output.push(items.slice(index, index + size));
|
|
}
|
|
return output;
|
|
}
|
|
|
|
function normalizeJudgeCount(value: unknown): number {
|
|
return typeof value === "number" ? value : 0;
|
|
}
|
|
|
|
async function main() {
|
|
if (!isDryRun && !forceRun) {
|
|
console.error(
|
|
"Refuse to run without explicit mode. Use --dry-run 先看影響筆數,或加上 --force 正式刪除。"
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
const targetTasks = await prisma.task.findMany({
|
|
where: {
|
|
title: {
|
|
startsWith: TARGET_PREFIX,
|
|
},
|
|
},
|
|
select: { id: true },
|
|
});
|
|
const targetTaskIds = targetTasks.map((task) => task.id);
|
|
|
|
if (targetTaskIds.length === 0) {
|
|
console.log(`No task with prefix "${TARGET_PREFIX}" found. done.`);
|
|
return;
|
|
}
|
|
|
|
const submissionIdsForAll = (
|
|
await prisma.submission.findMany({
|
|
where: { task_id: { in: targetTaskIds } },
|
|
select: { id: true },
|
|
})
|
|
).map((row) => row.id);
|
|
|
|
const [taskCount, submissionCount, claimCount, judgeCount, ledgerCount, auditCount, scoutDraftEvents] =
|
|
await Promise.all([
|
|
prisma.task.count({ where: { id: { in: targetTaskIds } } }),
|
|
prisma.submission.count({ where: { task_id: { in: targetTaskIds } } }),
|
|
prisma.claim.count({ where: { task_id: { in: targetTaskIds } } }),
|
|
submissionIdsForAll.length
|
|
? prisma.judgeResult.count({ where: { submission_id: { in: submissionIdsForAll } } })
|
|
: Promise.resolve(0),
|
|
prisma.ledgerEntry.count({ where: { task_id: { in: targetTaskIds } } }),
|
|
prisma.auditEvent.count({ where: { entityType: "TASK", entityId: { in: targetTaskIds } } }),
|
|
prisma.auditEvent.count({ where: { action: { startsWith: "SCOUT_DRAFT_" } } }),
|
|
]);
|
|
|
|
console.log("=== Purge Impact Preview ===");
|
|
console.log(`Task count: ${normalizeJudgeCount(taskCount)}`);
|
|
console.log(`Submission count: ${normalizeJudgeCount(submissionCount)}`);
|
|
console.log(`Claim count: ${normalizeJudgeCount(claimCount)}`);
|
|
console.log(`JudgeResult count: ${normalizeJudgeCount(judgeCount)}`);
|
|
console.log(`LedgerEntry count: ${normalizeJudgeCount(ledgerCount)}`);
|
|
console.log(`AuditEvent (entityType TASK) count: ${normalizeJudgeCount(auditCount)}`);
|
|
console.log(`AuditEvent (SCOUT_DRAFT_*) count: ${normalizeJudgeCount(scoutDraftEvents)}`);
|
|
console.log(`Target batch size: ${BATCH_SIZE}`);
|
|
|
|
if (isDryRun) {
|
|
console.log("Dry-run complete. No data was modified.");
|
|
return;
|
|
}
|
|
|
|
for (const idBatch of chunk(targetTaskIds, BATCH_SIZE)) {
|
|
await prisma.$transaction(async (tx) => {
|
|
const batchSubmissionIds = (
|
|
await tx.submission.findMany({
|
|
where: { task_id: { in: idBatch } },
|
|
select: { id: true },
|
|
})
|
|
).map((row) => row.id);
|
|
|
|
if (batchSubmissionIds.length > 0) {
|
|
await tx.judgeResult.deleteMany({
|
|
where: { submission_id: { in: batchSubmissionIds } },
|
|
});
|
|
}
|
|
|
|
await tx.submission.deleteMany({
|
|
where: { task_id: { in: idBatch } },
|
|
});
|
|
await tx.claim.deleteMany({
|
|
where: { task_id: { in: idBatch } },
|
|
});
|
|
await tx.ledgerEntry.deleteMany({
|
|
where: { task_id: { in: idBatch } },
|
|
});
|
|
await tx.auditEvent.deleteMany({
|
|
where: {
|
|
OR: [
|
|
{
|
|
entityType: "TASK",
|
|
entityId: { in: idBatch },
|
|
},
|
|
{
|
|
action: { startsWith: "SCOUT_DRAFT_" },
|
|
entityId: { in: idBatch },
|
|
},
|
|
],
|
|
},
|
|
});
|
|
await tx.task.deleteMany({
|
|
where: { id: { in: idBatch } },
|
|
});
|
|
});
|
|
}
|
|
|
|
console.log(`Deleted ${taskCount} GitHub Issue task entries.`);
|
|
}
|
|
|
|
main()
|
|
.catch((error) => {
|
|
console.error("Purge script failed:", error);
|
|
process.exit(1);
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect();
|
|
});
|
|
|