refactor: pure sense compute — return data instead of db.insert

All 5 senses updated to new API:
- compute(signal: AbortSignal) => Promise<T | null>
- Export table for runtime-side insert
- Remove drizzle-orm/libsql imports

Refs uncaged/nerve#264

— 小橘 🍊(NEKO Team)
This commit is contained in:
小橘 2026-04-30 00:15:03 +00:00
parent 60979aaa6a
commit 252162ea8e
10 changed files with 37 additions and 158 deletions

View File

@ -41,7 +41,7 @@ function countPorcelainLines(output) {
if (!output) return 0;
return output.split("\n").filter((line) => line.length > 0).length;
}
async function compute(db, _peers) {
async function compute(_signal) {
const root = workspaceRoot();
const ts = Date.now();
let branch = "";
@ -55,7 +55,7 @@ async function compute(db, _peers) {
const inside = runGit(root, ["rev-parse", "--is-inside-work-tree"]).trim();
if (inside !== "true") {
gitError = "not a git work tree";
await db.insert(snapshots).values({
return {
ts,
branch,
headShort,
@ -64,16 +64,6 @@ async function compute(db, _peers) {
aheadCount,
behindCount,
gitError
});
return {
workspaceRoot: root,
branch,
headShort,
porcelainLines,
hasUpstream: false,
aheadCount,
behindCount,
gitError
};
}
branch = runGit(root, ["rev-parse", "--abbrev-ref", "HEAD"]);
@ -96,7 +86,7 @@ async function compute(db, _peers) {
} catch (e) {
gitError = gitErrorMessage(e);
}
await db.insert(snapshots).values({
return {
ts,
branch,
headShort,
@ -105,18 +95,9 @@ async function compute(db, _peers) {
aheadCount,
behindCount,
gitError
});
return {
workspaceRoot: root,
branch,
headShort,
porcelainLines,
hasUpstream: hasUpstream === 1,
aheadCount,
behindCount,
gitError: gitError || void 0
};
}
export {
compute
compute,
snapshots as table
};

View File

@ -1,7 +1,6 @@
import { execFileSync } from "node:child_process";
import { resolve } from "node:path";
import type { LibSQLDatabase } from "drizzle-orm/libsql";
import { snapshots } from "./schema.ts";
export { snapshots as table } from "./schema.ts";
const GIT_TIMEOUT_MS = 15_000;
@ -32,7 +31,7 @@ function countPorcelainLines(output: string): number {
return output.split("\n").filter((line) => line.length > 0).length;
}
export async function compute(db: LibSQLDatabase, _peers: unknown) {
export async function compute(_signal: AbortSignal) {
const root = workspaceRoot();
const ts = Date.now();
@ -48,7 +47,7 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
const inside = runGit(root, ["rev-parse", "--is-inside-work-tree"]).trim();
if (inside !== "true") {
gitError = "not a git work tree";
await db.insert(snapshots).values({
return {
ts,
branch,
headShort,
@ -57,16 +56,6 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
aheadCount,
behindCount,
gitError,
});
return {
workspaceRoot: root,
branch,
headShort,
porcelainLines,
hasUpstream: false,
aheadCount,
behindCount,
gitError,
};
}
@ -92,7 +81,7 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
gitError = gitErrorMessage(e);
}
await db.insert(snapshots).values({
return {
ts,
branch,
headShort,
@ -101,16 +90,5 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
aheadCount,
behindCount,
gitError,
});
return {
workspaceRoot: root,
branch,
headShort,
porcelainLines,
hasUpstream: hasUpstream === 1,
aheadCount,
behindCount,
gitError: gitError || undefined,
};
}

View File

@ -274,7 +274,7 @@ async function countDirectChildren(mainPid) {
return 0;
}
}
async function compute(db, _peers) {
async function compute(_signal) {
const ts = Date.now();
let mainPid = 0;
let systemdActiveRunning = false;
@ -353,22 +353,9 @@ async function compute(db, _peers) {
httpLatencyMs,
httpError
};
await db.insert(hermesGatewayHealth).values(row);
return {
ts: row.ts,
alive: row.alive,
mainPid: row.mainPid,
rssBytes: row.rssBytes,
cpuPercent: row.cpuPercent,
uptimeSec: row.uptimeSec,
activeSessions: row.activeSessions,
childProcessCount: row.childProcessCount,
httpOk: row.httpOk,
httpStatusCode: row.httpStatusCode,
httpLatencyMs: row.httpLatencyMs,
httpError: row.httpError
};
return row;
}
export {
compute
compute,
hermesGatewayHealth as table
};

View File

@ -1,6 +1,5 @@
import { execFile } from "node:child_process";
import type { LibSQLDatabase } from "drizzle-orm/libsql";
import { hermesGatewayHealth } from "./schema.ts";
export { hermesGatewayHealth as table } from "./schema.ts";
/** Keep subprocess deadlines slightly under typical sense timeout (30s). */
const EXEC_TIMEOUT_MS = 25_000;
@ -315,7 +314,7 @@ async function countDirectChildren(mainPid: number): Promise<number> {
}
}
export async function compute(db: LibSQLDatabase, _peers: unknown) {
export async function compute(_signal: AbortSignal) {
const ts = Date.now();
let mainPid = 0;
@ -405,20 +404,5 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
httpError,
};
await db.insert(hermesGatewayHealth).values(row);
return {
ts: row.ts,
alive: row.alive,
mainPid: row.mainPid,
rssBytes: row.rssBytes,
cpuPercent: row.cpuPercent,
uptimeSec: row.uptimeSec,
activeSessions: row.activeSessions,
childProcessCount: row.childProcessCount,
httpOk: row.httpOk,
httpStatusCode: row.httpStatusCode,
httpLatencyMs: row.httpLatencyMs,
httpError: row.httpError,
};
return row;
}

View File

@ -61,7 +61,7 @@ async function aggregateJsonlFile(filePath, cutoffMs, nowMs) {
}
return { user, assistant, tool, fileHadActivity };
}
async function compute(db, _peers) {
async function compute(_signal) {
const nowMs = Date.now();
const cutoffMs = nowMs - MEASUREMENT_WINDOW_MS;
const ts = nowMs;
@ -102,17 +102,9 @@ async function compute(db, _peers) {
activeSessions,
measurementWindowSeconds: MEASUREMENT_WINDOW_SECONDS
};
await db.insert(hermesSessionMessageStats).values(row);
return {
ts: row.ts,
totalUserMessages: row.totalUserMessages,
totalAssistantMessages: row.totalAssistantMessages,
totalToolMessages: row.totalToolMessages,
totalMessages: row.totalMessages,
activeSessions: row.activeSessions,
measurementWindowSeconds: row.measurementWindowSeconds
};
return row;
}
export {
compute
compute,
hermesSessionMessageStats as table
};

View File

@ -3,8 +3,7 @@ import { readdir } from "node:fs/promises";
import { homedir } from "node:os";
import { join } from "node:path";
import { createInterface } from "node:readline";
import type { LibSQLDatabase } from "drizzle-orm/libsql";
import { hermesSessionMessageStats } from "./schema.ts";
export { hermesSessionMessageStats as table } from "./schema.ts";
const MEASUREMENT_WINDOW_MS = 900_000;
const MEASUREMENT_WINDOW_SECONDS = 900;
@ -64,7 +63,7 @@ async function aggregateJsonlFile(filePath: string, cutoffMs: number, nowMs: num
return { user, assistant, tool, fileHadActivity };
}
export async function compute(db: LibSQLDatabase, _peers: unknown) {
export async function compute(_signal: AbortSignal) {
const nowMs = Date.now();
const cutoffMs = nowMs - MEASUREMENT_WINDOW_MS;
const ts = nowMs;
@ -114,15 +113,5 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
measurementWindowSeconds: MEASUREMENT_WINDOW_SECONDS,
};
await db.insert(hermesSessionMessageStats).values(row);
return {
ts: row.ts,
totalUserMessages: row.totalUserMessages,
totalAssistantMessages: row.totalAssistantMessages,
totalToolMessages: row.totalToolMessages,
totalMessages: row.totalMessages,
activeSessions: row.activeSessions,
measurementWindowSeconds: row.measurementWindowSeconds,
};
return row;
}

View File

@ -53,7 +53,7 @@ function parseSockstat(content) {
}
return { socketsUsed, tcpInuse, tcpOrphan, tcpTw, tcpAlloc, tcpMemPages };
}
async function compute(db, _peers) {
async function compute(_signal) {
const [load1, load5, load15] = loadavg();
const memTotal = totalmem();
const memFree = freemem();
@ -80,7 +80,7 @@ async function compute(db, _peers) {
}
const ts = Date.now();
const uptimeSec = Math.round(uptime());
await db.insert(snapshots).values({
return {
ts,
cpuLoad1m: load1,
cpuLoad5m: load5,
@ -98,15 +98,9 @@ async function compute(db, _peers) {
tcpTw: tcp.tcpTw,
tcpAlloc: tcp.tcpAlloc,
tcpMemPages: tcp.tcpMemPages
});
return {
cpu: { load1m: load1, load5m: load5, load15m: load15 },
memory: { totalMB: memTotalMB, usedMB: memUsedMB, usedPct: memUsedPct },
disk: { totalGB: diskTotalGB, usedGB: diskUsedGB, usedPct: diskUsedPct },
tcp: { socketsUsed: tcp.socketsUsed, inuse: tcp.tcpInuse, orphan: tcp.tcpOrphan, tw: tcp.tcpTw, alloc: tcp.tcpAlloc, memPages: tcp.tcpMemPages },
uptimeSec
};
}
export {
compute
compute,
snapshots as table
};

View File

@ -1,8 +1,7 @@
import { loadavg, totalmem, freemem, uptime } from "node:os";
import { execSync } from "node:child_process";
import { readFile } from "node:fs/promises";
import type { LibSQLDatabase } from "drizzle-orm/libsql";
import { snapshots } from "./schema.ts";
export { snapshots as table } from "./schema.ts";
const SOCKSTAT_PATH = "/proc/net/sockstat";
@ -43,7 +42,7 @@ function parseSockstat(content: string): SockstatResult {
return { socketsUsed, tcpInuse, tcpOrphan, tcpTw, tcpAlloc, tcpMemPages };
}
export async function compute(db: LibSQLDatabase, _peers: unknown) {
export async function compute(_signal: AbortSignal) {
const [load1, load5, load15] = loadavg();
const memTotal = totalmem();
@ -73,7 +72,7 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
const ts = Date.now();
const uptimeSec = Math.round(uptime());
await db.insert(snapshots).values({
return {
ts, cpuLoad1m: load1, cpuLoad5m: load5, cpuLoad15m: load15,
memTotalMB, memUsedMB, memUsedPct,
diskTotalGB, diskUsedGB, diskUsedPct,
@ -84,13 +83,5 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
tcpTw: tcp.tcpTw,
tcpAlloc: tcp.tcpAlloc,
tcpMemPages: tcp.tcpMemPages,
});
return {
cpu: { load1m: load1, load5m: load5, load15m: load15 },
memory: { totalMB: memTotalMB, usedMB: memUsedMB, usedPct: memUsedPct },
disk: { totalGB: diskTotalGB, usedGB: diskUsedGB, usedPct: diskUsedPct },
tcp: { socketsUsed: tcp.socketsUsed, inuse: tcp.tcpInuse, orphan: tcp.tcpOrphan, tw: tcp.tcpTw, alloc: tcp.tcpAlloc, memPages: tcp.tcpMemPages },
uptimeSec,
};
}

View File

@ -13,7 +13,7 @@ var workerProcessMetrics = sqliteTable("worker_process_metrics", {
function round2(n) {
return Math.round(n * 100) / 100;
}
async function compute(db, _peers) {
async function compute(_signal) {
const ts = Date.now();
const pid = process.pid;
const uptimeSec = process.uptime();
@ -29,16 +29,9 @@ async function compute(db, _peers) {
rssMB,
externalMB
};
await db.insert(workerProcessMetrics).values(row);
return {
ts: row.ts,
pid: row.pid,
uptimeSec: row.uptimeSec,
heapUsedMB: row.heapUsedMB,
rssMB: row.rssMB,
externalMB: row.externalMB
};
return row;
}
export {
compute
compute,
workerProcessMetrics as table
};

View File

@ -1,11 +1,10 @@
import type { LibSQLDatabase } from "drizzle-orm/libsql";
import { workerProcessMetrics } from "./schema.ts";
export { workerProcessMetrics as table } from "./schema.ts";
function round2(n: number): number {
return Math.round(n * 100) / 100;
}
export async function compute(db: LibSQLDatabase, _peers: unknown) {
export async function compute(_signal: AbortSignal) {
const ts = Date.now();
const pid = process.pid;
const uptimeSec = process.uptime();
@ -23,14 +22,5 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
externalMB,
};
await db.insert(workerProcessMetrics).values(row);
return {
ts: row.ts,
pid: row.pid,
uptimeSec: row.uptimeSec,
heapUsedMB: row.heapUsedMB,
rssMB: row.rssMB,
externalMB: row.externalMB,
};
return row;
}