mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2025-12-08 12:36:44 +03:00
116 lines
3.7 KiB
TypeScript
116 lines
3.7 KiB
TypeScript
import type { APIRoute } from "astro";
|
|
import { db, mirrorJobs, events } from "@/lib/db";
|
|
import { eq, count } from "drizzle-orm";
|
|
|
|
export const POST: APIRoute = async ({ request }) => {
|
|
try {
|
|
let body;
|
|
try {
|
|
body = await request.json();
|
|
} catch (jsonError) {
|
|
console.error("Invalid JSON in request body:", jsonError);
|
|
return new Response(
|
|
JSON.stringify({ error: "Invalid JSON in request body." }),
|
|
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
);
|
|
}
|
|
|
|
const { userId } = body || {};
|
|
|
|
if (!userId) {
|
|
return new Response(
|
|
JSON.stringify({ error: "Missing 'userId' in request body." }),
|
|
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
);
|
|
}
|
|
|
|
// Start a transaction to ensure all operations succeed or fail together
|
|
const result = await db.transaction(async (tx) => {
|
|
// Count activities before deletion
|
|
const mirrorJobsCountResult = await tx
|
|
.select({ count: count() })
|
|
.from(mirrorJobs)
|
|
.where(eq(mirrorJobs.userId, userId));
|
|
|
|
const eventsCountResult = await tx
|
|
.select({ count: count() })
|
|
.from(events)
|
|
.where(eq(events.userId, userId));
|
|
|
|
const totalMirrorJobs = mirrorJobsCountResult[0]?.count || 0;
|
|
const totalEvents = eventsCountResult[0]?.count || 0;
|
|
|
|
console.log(`Found ${totalMirrorJobs} mirror jobs and ${totalEvents} events to delete for user ${userId}`);
|
|
|
|
// First, mark all in-progress jobs as completed/failed to allow deletion
|
|
await tx
|
|
.update(mirrorJobs)
|
|
.set({
|
|
inProgress: false,
|
|
completedAt: new Date(),
|
|
status: "failed",
|
|
message: "Job interrupted and cleaned up by user"
|
|
})
|
|
.where(eq(mirrorJobs.userId, userId));
|
|
|
|
console.log(`Updated in-progress jobs to allow deletion`);
|
|
|
|
// Delete all mirror jobs for the user (now that none are in progress)
|
|
await tx
|
|
.delete(mirrorJobs)
|
|
.where(eq(mirrorJobs.userId, userId));
|
|
|
|
// Delete all events for the user
|
|
await tx
|
|
.delete(events)
|
|
.where(eq(events.userId, userId));
|
|
|
|
return {
|
|
mirrorJobsDeleted: totalMirrorJobs,
|
|
eventsDeleted: totalEvents,
|
|
totalMirrorJobs,
|
|
totalEvents,
|
|
};
|
|
});
|
|
|
|
console.log(`Cleaned up activities for user ${userId}:`, result);
|
|
|
|
return new Response(
|
|
JSON.stringify({
|
|
success: true,
|
|
message: "All activities cleaned up successfully.",
|
|
result: {
|
|
mirrorJobsDeleted: result.mirrorJobsDeleted,
|
|
eventsDeleted: result.eventsDeleted,
|
|
},
|
|
}),
|
|
{ status: 200, headers: { "Content-Type": "application/json" } }
|
|
);
|
|
} catch (error) {
|
|
console.error("Error cleaning up activities:", error);
|
|
|
|
// Provide more specific error messages
|
|
let errorMessage = "An unknown error occurred.";
|
|
if (error instanceof Error) {
|
|
errorMessage = error.message;
|
|
|
|
// Check for common database errors
|
|
if (error.message.includes("FOREIGN KEY constraint failed")) {
|
|
errorMessage = "Cannot delete activities due to database constraints. Some jobs may still be referenced by other records.";
|
|
} else if (error.message.includes("database is locked")) {
|
|
errorMessage = "Database is currently locked. Please try again in a moment.";
|
|
} else if (error.message.includes("no such table")) {
|
|
errorMessage = "Database tables are missing. Please check your database setup.";
|
|
}
|
|
}
|
|
|
|
return new Response(
|
|
JSON.stringify({
|
|
success: false,
|
|
error: errorMessage,
|
|
}),
|
|
{ status: 500, headers: { "Content-Type": "application/json" } }
|
|
);
|
|
}
|
|
};
|