Openstatus
www.openstatus.dev
1import { schema } from "@openstatus/db";
2import { and, eq, inArray, isNull, ne } from "drizzle-orm";
3import { Hono } from "hono";
4import { env } from "../env";
5import { db } from "../lib/db";
6
7export const incidentRoute = new Hono({ strict: false });
8
9incidentRoute.use("*", async (c, next) => {
10 if (c.req.header("authorization") !== env().CRON_SECRET) {
11 return c.text("Unauthorized", 401);
12 }
13
14 return next();
15});
16
17incidentRoute.get("/cleanup", async (c) => {
18 // Find monitors that have unresolved incidents but are active
19 const unresolvedIncidentMonitorIds = db
20 .select({ monitorId: schema.incidentTable.monitorId })
21 .from(schema.incidentTable)
22 .where(isNull(schema.incidentTable.resolvedAt));
23
24 const activeMonitorsWithUnresolvedIncidents = await db
25 .select({ id: schema.monitor.id })
26 .from(schema.monitor)
27 .where(
28 and(
29 inArray(schema.monitor.id, unresolvedIncidentMonitorIds),
30 eq(schema.monitor.active, true),
31 ne(schema.monitor.status, "error"),
32 ),
33 )
34 .all();
35
36 const monitorIds = activeMonitorsWithUnresolvedIncidents.map((m) => m.id);
37
38 if (monitorIds.length === 0) {
39 return c.json({ status: "ok", updated: 0 });
40 }
41
42 // Update incidents for these monitors: set resolvedAt to now and autoResolved to true
43 const result = await db
44 .update(schema.incidentTable)
45 .set({
46 resolvedAt: new Date(),
47 autoResolved: true,
48 })
49 .where(
50 and(
51 inArray(schema.incidentTable.monitorId, monitorIds),
52 isNull(schema.incidentTable.resolvedAt),
53 ),
54 )
55 .returning({ id: schema.incidentTable.id });
56
57 return c.json({ status: "ok", updated: result.length });
58});