Add account based multiplayer hosting and bug report retention
This commit is contained in:
146
lib/bug-cleanup-workflow.ts
Normal file
146
lib/bug-cleanup-workflow.ts
Normal file
@@ -0,0 +1,146 @@
|
||||
import {
|
||||
FatalError,
|
||||
RetryableError,
|
||||
getWorkflowMetadata,
|
||||
sleep,
|
||||
} from "workflow";
|
||||
import { admin, required } from "./supabase";
|
||||
import {
|
||||
LinearSupportClient,
|
||||
LinearPermissionError,
|
||||
} from "./linear-support-client";
|
||||
import { purgeClosedBugReport } from "./bug-retention";
|
||||
|
||||
const linearClient = () =>
|
||||
new LinearSupportClient(
|
||||
process.env.LINEAR_API_KEY!,
|
||||
process.env.LINEAR_TEAM_ID!,
|
||||
process.env.LINEAR_PROJECT_ID,
|
||||
);
|
||||
async function record(id: string) {
|
||||
const result = await admin()
|
||||
.from("bug_reports")
|
||||
.select("*")
|
||||
.eq("id", id)
|
||||
.maybeSingle();
|
||||
if (result.error) required(result);
|
||||
return result.data;
|
||||
}
|
||||
|
||||
export async function cleanupDoneBugReport(
|
||||
id: string,
|
||||
closedAt: string,
|
||||
claim: string,
|
||||
) {
|
||||
"use workflow";
|
||||
const run = getWorkflowMetadata().workflowRunId;
|
||||
try {
|
||||
const deadline = await markLinearDone(id, closedAt);
|
||||
if (deadline) {
|
||||
await sleep(new Date(deadline));
|
||||
await purgeDone(id, closedAt);
|
||||
}
|
||||
} catch {
|
||||
await releaseCleanup(id, closedAt, claim, run);
|
||||
throw new Error("Bug report cleanup paused; the saved report will retry.");
|
||||
}
|
||||
}
|
||||
async function markLinearDone(
|
||||
id: string,
|
||||
closedAt: string,
|
||||
): Promise<string | null> {
|
||||
"use step";
|
||||
try {
|
||||
const report = await record(id);
|
||||
if (!report || report.state !== "done" || report.closed_at !== closedAt)
|
||||
return null;
|
||||
if (!report.linear_done_synced) {
|
||||
await linearClient().done(id);
|
||||
required(
|
||||
await admin()
|
||||
.from("bug_reports")
|
||||
.update({ linear_done_synced: true, cleanup_error: null })
|
||||
.eq("id", id)
|
||||
.eq("state", "done")
|
||||
.eq("closed_at", closedAt)
|
||||
.select("id"),
|
||||
);
|
||||
}
|
||||
return report.delete_after ?? null;
|
||||
} catch (error) {
|
||||
if (error instanceof LinearPermissionError)
|
||||
throw new FatalError("The Linear key needs Write permission.");
|
||||
throw new RetryableError(
|
||||
"Could not move the Linear report to Done. Check the API key's Write permission.",
|
||||
{ retryAfter: "1m" },
|
||||
);
|
||||
}
|
||||
}
|
||||
markLinearDone.maxRetries = 10;
|
||||
|
||||
async function purgeDone(id: string, closedAt: string) {
|
||||
"use step";
|
||||
try {
|
||||
await purgeClosedBugReport(id, closedAt, {
|
||||
record: () => record(id),
|
||||
linear: linearClient(),
|
||||
begin: async () =>
|
||||
required(
|
||||
await admin().rpc("begin_bug_purge", {
|
||||
p_report: id,
|
||||
p_closed_at: closedAt,
|
||||
}),
|
||||
),
|
||||
reopen: async () => {
|
||||
required(
|
||||
await admin().rpc("set_bug_report_done", {
|
||||
p_report: id,
|
||||
p_done: false,
|
||||
}),
|
||||
);
|
||||
},
|
||||
removeFiles: async (paths) => {
|
||||
required(await admin().storage.from("minegeo-support").remove(paths));
|
||||
},
|
||||
finish: async () => {
|
||||
required(
|
||||
await admin().rpc("finish_bug_purge", {
|
||||
p_report: id,
|
||||
p_closed_at: closedAt,
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
} catch {
|
||||
throw new RetryableError(
|
||||
"Report deletion could not be confirmed. The saved record will retry.",
|
||||
{ retryAfter: "5m" },
|
||||
);
|
||||
}
|
||||
}
|
||||
purgeDone.maxRetries = 10;
|
||||
|
||||
async function releaseCleanup(
|
||||
id: string,
|
||||
closedAt: string,
|
||||
claim: string,
|
||||
run: string,
|
||||
) {
|
||||
"use step";
|
||||
required(
|
||||
await admin()
|
||||
.from("bug_reports")
|
||||
.update({
|
||||
cleanup_run_id: null,
|
||||
cleanup_lease_until: new Date(Date.now() + 60000).toISOString(),
|
||||
cleanup_error:
|
||||
"Support cleanup paused. Check Linear Write permission and retry.",
|
||||
})
|
||||
.eq("id", id)
|
||||
.eq("closed_at", closedAt)
|
||||
.in("cleanup_run_id", [claim, run])
|
||||
.select("id"),
|
||||
);
|
||||
console.error("Bug report cleanup paused", { id, run });
|
||||
}
|
||||
releaseCleanup.maxRetries = 10;
|
||||
Reference in New Issue
Block a user