fa73ab07b0
- listMachineEvents (machine_events, 30 derniers, desc) + route GET /machines/:id/events - api machineEvents ; section repliable « Timeline » dans le panneau détail (badge sévérité + horodatage), exploite les events déjà enregistrés par recordEvent tsc 0 · 118 tests · build OK. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
76 lines
2.3 KiB
TypeScript
76 lines
2.3 KiB
TypeScript
// server/services/machineState.ts
|
|
import { randomUUID } from "node:crypto";
|
|
import { desc, eq } from "drizzle-orm";
|
|
import { db, schema } from "../db/client.js";
|
|
import type { UpdateSnapshot } from "@shared/types.js";
|
|
|
|
/** Derniers événements d'une machine (timeline), du plus récent au plus ancien. */
|
|
export function listMachineEvents(machineId: string, limit = 30) {
|
|
return db
|
|
.select()
|
|
.from(schema.machineEvents)
|
|
.where(eq(schema.machineEvents.machineId, machineId))
|
|
.orderBy(desc(schema.machineEvents.createdAt))
|
|
.limit(limit)
|
|
.all();
|
|
}
|
|
|
|
export interface AptDerivedState {
|
|
status: string;
|
|
aptStatus: string;
|
|
aptUpdatesCount: number;
|
|
aptRebootRequired: number;
|
|
aptLastAnalyzeAt: string;
|
|
}
|
|
|
|
/** Dérive le bloc APT de l'état courant depuis un snapshot (fonction pure). */
|
|
export function deriveAptState(snapshot: UpdateSnapshot): AptDerivedState {
|
|
return {
|
|
status: snapshot.status,
|
|
aptStatus: snapshot.status,
|
|
aptUpdatesCount: snapshot.apt.count,
|
|
aptRebootRequired: snapshot.apt.rebootRequired ? 1 : 0,
|
|
aptLastAnalyzeAt: snapshot.checkedAt,
|
|
};
|
|
}
|
|
|
|
type MachineStateInsert = typeof schema.machineState.$inferInsert;
|
|
|
|
/** Insère ou met à jour les champs fournis de machine_state pour une machine. */
|
|
export function upsertMachineState(
|
|
machineId: string,
|
|
fields: Partial<Omit<MachineStateInsert, "machineId" | "updatedAt" | "status">> & { status: string },
|
|
): void {
|
|
const now = new Date().toISOString();
|
|
db.insert(schema.machineState)
|
|
.values({ machineId, updatedAt: now, ...fields })
|
|
.onConflictDoUpdate({
|
|
target: schema.machineState.machineId,
|
|
set: { ...fields, updatedAt: now },
|
|
})
|
|
.run();
|
|
}
|
|
|
|
/** Ajoute une ligne à la timeline machine_events. */
|
|
export function recordEvent(input: {
|
|
machineId: string;
|
|
eventType: string;
|
|
severity: "info" | "warning" | "error";
|
|
actorType?: string;
|
|
snapshotId?: string;
|
|
executionId?: string;
|
|
message?: string;
|
|
}): void {
|
|
db.insert(schema.machineEvents).values({
|
|
id: randomUUID(),
|
|
machineId: input.machineId,
|
|
eventType: input.eventType,
|
|
severity: input.severity,
|
|
createdAt: new Date().toISOString(),
|
|
actorType: input.actorType ?? "system",
|
|
snapshotId: input.snapshotId,
|
|
executionId: input.executionId,
|
|
message: input.message,
|
|
}).run();
|
|
}
|