import { pgTable, uuid, text, timestamp, real, pgEnum, index } from "drizzle-orm/pg-core"; import { farms } from "./farms"; import { printers } from "./printers"; export const alertKindEnum = pgEnum("alert_kind", [ "print_failed", "print_paused", "printer_error", "ai_detection", ]); /** * The permanent record of something an operator should look at. * * A table and not a channel: Valkey PUBLISH keeps nothing, so an alert raised * while no console was open would otherwise be gone for good. The console * lists open (unacknowledged) rows, which is also what makes "I was away, * what happened" answerable. */ export const printerAlerts = pgTable( "printer_alerts", { id: uuid("id").primaryKey().defaultRandom(), farmId: uuid("farm_id") .notNull() .references(() => farms.id, { onDelete: "cascade" }), // Set null rather than cascade: the history of why a deleted printer was // flagged is still worth having, and the farm cascade bounds it anyway. printerId: uuid("printer_id").references(() => printers.id, { onDelete: "set null" }), kind: alertKindEnum("kind").notNull(), message: text("message").notNull(), // Only for ai_detection; null is "not applicable", not zero confidence. confidence: real("confidence"), // Where the frame the detection came from lives, for ai_detection. objectKey: text("object_key"), acknowledgedBy: uuid("acknowledged_by"), acknowledgedAt: timestamp("acknowledged_at", { withTimezone: true }), createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(), }, (table) => ({ farmOpen: index("printer_alerts_farm_open_idx").on(table.farmId, table.acknowledgedAt), }), ); export type PrinterAlert = typeof printerAlerts.$inferSelect;