feat(backend): persist memory to MongoDB

Replace the in-memory store with a real MongoDB-backed store. Adds memory/db.ts
(client singleton, typed collections, startup ping + indexes) and rewrites
record{Observation,Collision,Intervention,Outcome} to insert into Mongo
(best-effort — failures log, don't crash). Server connects on startup and
exposes GET /api/memory/stats for verification.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kartikeya
2026-06-27 15:34:57 -07:00
parent e8fb91232f
commit 3fc19194f2
3 changed files with 95 additions and 33 deletions
+51
View File
@@ -0,0 +1,51 @@
import { MongoClient, type Db, type Collection } from 'mongodb';
import type { EngineerContext, Collision, Intervention, InterventionOutcome } from '@podman/shared';
import { env } from '../env.js';
let clientPromise: Promise<MongoClient> | null = null;
function getClient(): Promise<MongoClient> {
if (!clientPromise) {
const client = new MongoClient(env.MONGODB_URI, { serverSelectionTimeoutMS: 3000 });
clientPromise = client.connect();
}
return clientPromise;
}
/** The PodMan database (name comes from the MONGODB_URI path, e.g. `podman`). */
export async function getDb(): Promise<Db> {
const client = await getClient();
return client.db();
}
export interface PodCollections {
observations: Collection<EngineerContext>;
collisions: Collection<Collision>;
interventions: Collection<Intervention>;
outcomes: Collection<InterventionOutcome>;
}
export async function collections(): Promise<PodCollections> {
const db = await getDb();
return {
observations: db.collection<EngineerContext>('observations'),
collisions: db.collection<Collision>('collisions'),
interventions: db.collection<Intervention>('interventions'),
outcomes: db.collection<InterventionOutcome>('outcomes'),
};
}
/** Connect, verify reachability, and create helpful indexes. Call once on startup. */
export async function initMemory(): Promise<void> {
const db = await getDb();
await db.command({ ping: 1 });
const c = await collections();
await Promise.all([
c.observations.createIndex({ podId: 1, observedAt: -1 }),
c.observations.createIndex({ engineerId: 1 }),
c.collisions.createIndex({ podId: 1, detectedAt: -1 }),
c.interventions.createIndex({ collisionId: 1 }),
c.outcomes.createIndex({ interventionId: 1 }),
]);
console.log(`[memory] mongo connected -> ${db.databaseName}`);
}