import "server-only"; import { randomUUID } from "node:crypto"; import { start } from "workflow/api"; import { admin, required } from "./supabase"; import { LinearSupportClient } from "./linear-support-client"; import { cleanupDoneBugReport } from "./bug-cleanup-workflow"; export async function scheduleBugCleanup(id: string) { if (!process.env.LINEAR_API_KEY || !process.env.LINEAR_TEAM_ID) return; const db = admin(), claim = `starting:${randomUUID()}`; const rows = required( await db.rpc("claim_bug_cleanup", { p_report: id, p_worker: claim }), ); for (const report of rows) { try { const run = await start(cleanupDoneBugReport, [ id, report.closed_at!, claim, ]); required( await db .from("bug_reports") .update({ cleanup_run_id: run.runId, cleanup_lease_until: null }) .eq("id", id) .eq("cleanup_run_id", claim) .select("id"), ); } catch { console.error("Bug report cleanup remains saved for retry."); } } } export async function reconcileBugStatus(id: string, force = false) { const db = admin(); const lookup = await db .from("bug_reports") .select("*") .eq("id", id) .maybeSingle(); if (lookup.error) required(lookup); const report = lookup.data; if (!report?.issue_synced || report.purge_started_at) return; if (report.state === "done" && !report.linear_done_synced) { await scheduleBugCleanup(id); return; } if ( !force && report.status_checked_at && Date.parse(report.status_checked_at) > Date.now() - 60000 ) return; required( await db .from("bug_reports") .update({ status_checked_at: new Date().toISOString() }) .eq("id", id) .select("id"), ); const linear = new LinearSupportClient( process.env.LINEAR_API_KEY!, process.env.LINEAR_TEAM_ID!, process.env.LINEAR_PROJECT_ID, ); const issue = await linear.issue(id); if (!issue) { if (report.state === "done") await scheduleBugCleanup(id); return; } if (issue.state?.type === "completed") { required( await db.rpc("set_bug_report_done", { p_report: id, p_done: true, p_closed_at: issue.completedAt ?? null, }), ); // An external completed status may need normalizing to the team's Done status. required( await db .from("bug_reports") .update({ linear_done_synced: issue.state.name.toLowerCase() === "done", }) .eq("id", id) .eq("state", "done") .select("id"), ); await scheduleBugCleanup(id); } else if (report.state === "done") { required( await db.rpc("set_bug_report_done", { p_report: id, p_done: false }), ); } }