import { env } from "cloudflare:workers";
import { first } from "../db";
import { loadRepoById } from "../repos";
import { notifyQuietly, quiet } from "./deliver";
import { accountAdmins, repoAdmins } from "./recipients";
const DEDUPE_TTL_SECONDS = 60 * 60;
type IntegrationInfo = { id: string; scope_type: "repo" | "org"; scope_id: string; kind: string; name: string };
/** Tells integration admins (repo admins or org owners) that a delivery or job died; at most once an hour each. */
async function notifyIntegrationDeadUnsafe(
source: { deliveryId: string } | { jobId: string },
what: string,
): Promise<void> {
const integration =
"deliveryId" in source
? await first<IntegrationInfo>(
`SELECT i.id, i.scope_type, i.scope_id, i.kind, i.name FROM integration_deliveries d
JOIN integrations i ON i.id = d.integration_id WHERE d.id = ?`,
source.deliveryId,
)
: await first<IntegrationInfo>(
`SELECT i.id, i.scope_type, i.scope_id, i.kind, i.name FROM integration_jobs j
JOIN integrations i ON i.id = j.integration_id WHERE j.id = ?`,
source.jobId,
);
if (!integration) return;
const dedupeKey = `notify:integration-dead:${integration.id}`;
if (await env.KV.get(dedupeKey)) return;
await env.KV.put(dedupeKey, "1", { expirationTtl: DEDUPE_TTL_SECONDS });
const details = [
`${what} for the ${integration.kind.replace(/_/g, " ")} integration "${integration.name}" gave up after repeated failures.`,
];
if (integration.scope_type === "repo") {
const repo = await loadRepoById(integration.scope_id);
if (!repo) return;
await notifyQuietly({
category: "integration",
repoId: repo.id,