109 lines
3.1 KiB
TypeScript
109 lines
3.1 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
|
|
import { env } from "@/lib/env";
|
|
import { syncPleskInstance } from "@/lib/plesk/sync";
|
|
import { createSupabaseAdminClient } from "@/lib/supabase/admin";
|
|
|
|
const JOB_NAME = "plesk_sync_all";
|
|
const MAX_INSTANCES_PER_RUN = 10;
|
|
|
|
export async function POST(req: Request) {
|
|
try {
|
|
const secret = req.headers.get("x-job-secret");
|
|
if (!env.jobSecret || !secret || secret !== env.jobSecret) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
|
|
const supabase = createSupabaseAdminClient() as any;
|
|
const lockOwner = `nextjs:${process.pid}:${Date.now()}`;
|
|
|
|
const { data: acquired, error: lockError } = await supabase.rpc(
|
|
"acquire_job_lock",
|
|
{
|
|
p_job_name: JOB_NAME,
|
|
p_locked_by: lockOwner,
|
|
p_ttl_seconds: 240,
|
|
},
|
|
);
|
|
|
|
if (lockError) {
|
|
throw new Error(`Unable to acquire job lock: ${lockError.message}`);
|
|
}
|
|
|
|
if (!acquired) {
|
|
return NextResponse.json({ skipped: true, reason: "already_running" });
|
|
}
|
|
|
|
try {
|
|
const { data: instances, error: instancesError } = await supabase
|
|
.from("plesk_instances")
|
|
.select(
|
|
"id, agency_id, base_url, auth_type, encrypted_secret, last_connected_at",
|
|
)
|
|
.eq("status", "connected")
|
|
.order("last_connected_at", { ascending: true, nullsFirst: true })
|
|
.limit(MAX_INSTANCES_PER_RUN);
|
|
|
|
if (instancesError) throw instancesError;
|
|
|
|
const results: Array<Record<string, unknown>> = [];
|
|
|
|
for (const instance of instances ?? []) {
|
|
try {
|
|
const result = await syncPleskInstance(
|
|
supabase,
|
|
instance,
|
|
null,
|
|
"plesk_sync_auto",
|
|
);
|
|
results.push(result);
|
|
} catch (error) {
|
|
const message =
|
|
error instanceof Error
|
|
? error.message.slice(0, 1000)
|
|
: "Auto sync failed";
|
|
|
|
await supabase
|
|
.from("plesk_instances")
|
|
.update({ status: "error", error_message: message })
|
|
.eq("id", instance.id)
|
|
.eq("agency_id", instance.agency_id);
|
|
|
|
await supabase.from("actions_log").insert({
|
|
agency_id: instance.agency_id,
|
|
actor_user_id: null,
|
|
target_type: "plesk_instance",
|
|
target_id: instance.id,
|
|
action: "plesk_sync_auto",
|
|
status: "failed",
|
|
error_message: message,
|
|
metadata: { auto: true },
|
|
});
|
|
|
|
results.push({
|
|
instanceId: instance.id,
|
|
agencyId: instance.agency_id,
|
|
skipped: false,
|
|
failed: true,
|
|
error: message,
|
|
});
|
|
}
|
|
}
|
|
|
|
return NextResponse.json({
|
|
skipped: false,
|
|
processed: results.length,
|
|
maxPerRun: MAX_INSTANCES_PER_RUN,
|
|
results,
|
|
});
|
|
} finally {
|
|
await supabase.rpc("release_job_lock", { p_job_name: JOB_NAME });
|
|
}
|
|
} catch (error) {
|
|
return NextResponse.json(
|
|
{ error: error instanceof Error ? error.message : "Job failed" },
|
|
{ status: 500 },
|
|
);
|
|
}
|
|
}
|