Initial boilerplate scaffold for continuum-backend
Bun + ElysiaJS control plane: Drizzle/Postgres schema (printers, farms, print_jobs, pgvector frame_embeddings), R2 presigned URLs, Redis Streams frame ingestion queue, REST routes, and the /ws/edge/v1 edge-gateway WebSocket uplink.
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
import { drizzle } from "drizzle-orm/postgres-js";
|
||||
import postgres from "postgres";
|
||||
import * as schema from "./schema";
|
||||
|
||||
// Points at pgCat/PgBouncer, not Postgres directly, so keep prepared
|
||||
// statements disabled and cap the pool per-instance connections low.
|
||||
const connectionString = process.env.DATABASE_URL;
|
||||
if (!connectionString) {
|
||||
throw new Error("DATABASE_URL is not set");
|
||||
}
|
||||
|
||||
const client = postgres(connectionString, {
|
||||
prepare: false,
|
||||
max: Number(process.env.DATABASE_POOL_MAX ?? 10),
|
||||
});
|
||||
|
||||
export const db = drizzle(client, { schema });
|
||||
export type Database = typeof db;
|
||||
@@ -0,0 +1,48 @@
|
||||
import { pgTable, uuid, text, timestamp, customType, index } from "drizzle-orm/pg-core";
|
||||
import { printers } from "./printers";
|
||||
import { printJobs } from "./print_jobs";
|
||||
|
||||
const vector = customType<{ data: number[]; driverData: string }>({
|
||||
dataType(config) {
|
||||
const dims = (config as { dimensions?: number } | undefined)?.dimensions ?? 512;
|
||||
return `vector(${dims})`;
|
||||
},
|
||||
toDriver(value) {
|
||||
return `[${value.join(",")}]`;
|
||||
},
|
||||
fromDriver(value) {
|
||||
return value
|
||||
.slice(1, -1)
|
||||
.split(",")
|
||||
.filter(Boolean)
|
||||
.map(Number);
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* CLIP-style embeddings of camera frames captured during a print job, used for
|
||||
* nearest-neighbour failure-pattern search (pgvector, cosine distance).
|
||||
*/
|
||||
export const frameEmbeddings = pgTable(
|
||||
"frame_embeddings",
|
||||
{
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
printJobId: uuid("print_job_id")
|
||||
.notNull()
|
||||
.references(() => printJobs.id, { onDelete: "cascade" }),
|
||||
printerId: uuid("printer_id")
|
||||
.notNull()
|
||||
.references(() => printers.id, { onDelete: "cascade" }),
|
||||
r2ObjectKey: text("r2_object_key").notNull(),
|
||||
embedding: vector("embedding", { dimensions: 512 }).notNull(),
|
||||
capturedAt: timestamp("captured_at", { withTimezone: true }).defaultNow().notNull(),
|
||||
},
|
||||
(table) => ({
|
||||
embeddingIvfflatIdx: index("frame_embeddings_embedding_ivfflat_idx")
|
||||
.using("ivfflat", table.embedding.op("vector_cosine_ops"))
|
||||
.with({ lists: 100 }),
|
||||
}),
|
||||
);
|
||||
|
||||
export type FrameEmbedding = typeof frameEmbeddings.$inferSelect;
|
||||
export type NewFrameEmbedding = typeof frameEmbeddings.$inferInsert;
|
||||
@@ -0,0 +1,15 @@
|
||||
import { pgTable, uuid, text, timestamp, jsonb } from "drizzle-orm/pg-core";
|
||||
|
||||
export const farms = pgTable("farms", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
name: text("name").notNull(),
|
||||
ownerId: uuid("owner_id").notNull(),
|
||||
edgeProxyToken: text("edge_proxy_token").notNull(),
|
||||
location: text("location"),
|
||||
settings: jsonb("settings").$type<Record<string, unknown>>().default({}),
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
|
||||
});
|
||||
|
||||
export type Farm = typeof farms.$inferSelect;
|
||||
export type NewFarm = typeof farms.$inferInsert;
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from "./farms";
|
||||
export * from "./printers";
|
||||
export * from "./print_jobs";
|
||||
export * from "./embeddings";
|
||||
@@ -0,0 +1,36 @@
|
||||
import { pgTable, uuid, text, timestamp, jsonb, pgEnum, real } from "drizzle-orm/pg-core";
|
||||
import { printers } from "./printers";
|
||||
import { farms } from "./farms";
|
||||
|
||||
export const printJobStatusEnum = pgEnum("print_job_status", [
|
||||
"queued",
|
||||
"uploading",
|
||||
"printing",
|
||||
"paused",
|
||||
"completed",
|
||||
"failed",
|
||||
"cancelled",
|
||||
]);
|
||||
|
||||
export const printJobs = pgTable("print_jobs", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
farmId: uuid("farm_id")
|
||||
.notNull()
|
||||
.references(() => farms.id, { onDelete: "cascade" }),
|
||||
printerId: uuid("printer_id").references(() => printers.id, { onDelete: "set null" }),
|
||||
fileName: text("file_name").notNull(),
|
||||
r2ObjectKey: text("r2_object_key").notNull(),
|
||||
status: printJobStatusEnum("status").notNull().default("queued"),
|
||||
progressPct: real("progress_pct").notNull().default(0),
|
||||
estimatedTimeS: real("estimated_time_s"),
|
||||
elapsedTimeS: real("elapsed_time_s"),
|
||||
submittedBy: uuid("submitted_by").notNull(),
|
||||
metadata: jsonb("metadata").$type<Record<string, unknown>>().default({}),
|
||||
startedAt: timestamp("started_at", { withTimezone: true }),
|
||||
completedAt: timestamp("completed_at", { withTimezone: true }),
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
|
||||
});
|
||||
|
||||
export type PrintJob = typeof printJobs.$inferSelect;
|
||||
export type NewPrintJob = typeof printJobs.$inferInsert;
|
||||
@@ -0,0 +1,34 @@
|
||||
import { pgTable, uuid, text, timestamp, jsonb, pgEnum, real } from "drizzle-orm/pg-core";
|
||||
import { farms } from "./farms";
|
||||
|
||||
export const printerVendorEnum = pgEnum("printer_vendor", ["bambu", "prusa", "klipper"]);
|
||||
export const printerStatusEnum = pgEnum("printer_status", [
|
||||
"offline",
|
||||
"idle",
|
||||
"printing",
|
||||
"paused",
|
||||
"error",
|
||||
"maintenance",
|
||||
]);
|
||||
|
||||
export const printers = pgTable("printers", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
farmId: uuid("farm_id")
|
||||
.notNull()
|
||||
.references(() => farms.id, { onDelete: "cascade" }),
|
||||
name: text("name").notNull(),
|
||||
vendor: printerVendorEnum("vendor").notNull(),
|
||||
status: printerStatusEnum("status").notNull().default("offline"),
|
||||
lanAddress: text("lan_address"),
|
||||
serialNumber: text("serial_number"),
|
||||
accessCode: text("access_code"),
|
||||
nozzleTempC: real("nozzle_temp_c"),
|
||||
bedTempC: real("bed_temp_c"),
|
||||
metadata: jsonb("metadata").$type<Record<string, unknown>>().default({}),
|
||||
lastSeenAt: timestamp("last_seen_at", { withTimezone: true }),
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
|
||||
});
|
||||
|
||||
export type Printer = typeof printers.$inferSelect;
|
||||
export type NewPrinter = typeof printers.$inferInsert;
|
||||
Reference in New Issue
Block a user