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

View File

@ -1,7 +1,6 @@
import { execFileSync } from "node:child_process"; import { execFileSync } from "node:child_process";
import { resolve } from "node:path"; import { resolve } from "node:path";
import type { LibSQLDatabase } from "drizzle-orm/libsql"; export { snapshots as table } from "./schema.ts";
import { snapshots } from "./schema.ts";
const GIT_TIMEOUT_MS = 15_000; 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; 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 root = workspaceRoot();
const ts = Date.now(); 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(); const inside = runGit(root, ["rev-parse", "--is-inside-work-tree"]).trim();
if (inside !== "true") { if (inside !== "true") {
gitError = "not a git work tree"; gitError = "not a git work tree";
await db.insert(snapshots).values({ return {
ts, ts,
branch, branch,
headShort, headShort,
@ -57,16 +56,6 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
aheadCount, aheadCount,
behindCount, behindCount,
gitError, 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); gitError = gitErrorMessage(e);
} }
await db.insert(snapshots).values({ return {
ts, ts,
branch, branch,
headShort, headShort,
@ -101,16 +90,5 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
aheadCount, aheadCount,
behindCount, behindCount,
gitError, 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; return 0;
} }
} }
async function compute(db, _peers) { async function compute(_signal) {
const ts = Date.now(); const ts = Date.now();
let mainPid = 0; let mainPid = 0;
let systemdActiveRunning = false; let systemdActiveRunning = false;
@ -353,22 +353,9 @@ async function compute(db, _peers) {
httpLatencyMs, httpLatencyMs,
httpError httpError
}; };
await db.insert(hermesGatewayHealth).values(row); return 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
};
} }
export { export {
compute compute,
hermesGatewayHealth as table
}; };

View File

@ -1,6 +1,5 @@
import { execFile } from "node:child_process"; import { execFile } from "node:child_process";
import type { LibSQLDatabase } from "drizzle-orm/libsql"; export { hermesGatewayHealth as table } from "./schema.ts";
import { hermesGatewayHealth } from "./schema.ts";
/** Keep subprocess deadlines slightly under typical sense timeout (30s). */ /** Keep subprocess deadlines slightly under typical sense timeout (30s). */
const EXEC_TIMEOUT_MS = 25_000; 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(); const ts = Date.now();
let mainPid = 0; let mainPid = 0;
@ -405,20 +404,5 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
httpError, httpError,
}; };
await db.insert(hermesGatewayHealth).values(row); return 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,
};
} }

View File

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

View File

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

View File

@ -53,7 +53,7 @@ function parseSockstat(content) {
} }
return { socketsUsed, tcpInuse, tcpOrphan, tcpTw, tcpAlloc, tcpMemPages }; return { socketsUsed, tcpInuse, tcpOrphan, tcpTw, tcpAlloc, tcpMemPages };
} }
async function compute(db, _peers) { async function compute(_signal) {
const [load1, load5, load15] = loadavg(); const [load1, load5, load15] = loadavg();
const memTotal = totalmem(); const memTotal = totalmem();
const memFree = freemem(); const memFree = freemem();
@ -80,7 +80,7 @@ async function compute(db, _peers) {
} }
const ts = Date.now(); const ts = Date.now();
const uptimeSec = Math.round(uptime()); const uptimeSec = Math.round(uptime());
await db.insert(snapshots).values({ return {
ts, ts,
cpuLoad1m: load1, cpuLoad1m: load1,
cpuLoad5m: load5, cpuLoad5m: load5,
@ -98,15 +98,9 @@ async function compute(db, _peers) {
tcpTw: tcp.tcpTw, tcpTw: tcp.tcpTw,
tcpAlloc: tcp.tcpAlloc, tcpAlloc: tcp.tcpAlloc,
tcpMemPages: tcp.tcpMemPages 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 { export {
compute compute,
snapshots as table
}; };

View File

@ -1,8 +1,7 @@
import { loadavg, totalmem, freemem, uptime } from "node:os"; import { loadavg, totalmem, freemem, uptime } from "node:os";
import { execSync } from "node:child_process"; import { execSync } from "node:child_process";
import { readFile } from "node:fs/promises"; import { readFile } from "node:fs/promises";
import type { LibSQLDatabase } from "drizzle-orm/libsql"; export { snapshots as table } from "./schema.ts";
import { snapshots } from "./schema.ts";
const SOCKSTAT_PATH = "/proc/net/sockstat"; const SOCKSTAT_PATH = "/proc/net/sockstat";
@ -43,7 +42,7 @@ function parseSockstat(content: string): SockstatResult {
return { socketsUsed, tcpInuse, tcpOrphan, tcpTw, tcpAlloc, tcpMemPages }; 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 [load1, load5, load15] = loadavg();
const memTotal = totalmem(); const memTotal = totalmem();
@ -73,7 +72,7 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
const ts = Date.now(); const ts = Date.now();
const uptimeSec = Math.round(uptime()); const uptimeSec = Math.round(uptime());
await db.insert(snapshots).values({ return {
ts, cpuLoad1m: load1, cpuLoad5m: load5, cpuLoad15m: load15, ts, cpuLoad1m: load1, cpuLoad5m: load5, cpuLoad15m: load15,
memTotalMB, memUsedMB, memUsedPct, memTotalMB, memUsedMB, memUsedPct,
diskTotalGB, diskUsedGB, diskUsedPct, diskTotalGB, diskUsedGB, diskUsedPct,
@ -84,13 +83,5 @@ export async function compute(db: LibSQLDatabase, _peers: unknown) {
tcpTw: tcp.tcpTw, tcpTw: tcp.tcpTw,
tcpAlloc: tcp.tcpAlloc, tcpAlloc: tcp.tcpAlloc,
tcpMemPages: tcp.tcpMemPages, 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) { function round2(n) {
return Math.round(n * 100) / 100; return Math.round(n * 100) / 100;
} }
async function compute(db, _peers) { async function compute(_signal) {
const ts = Date.now(); const ts = Date.now();
const pid = process.pid; const pid = process.pid;
const uptimeSec = process.uptime(); const uptimeSec = process.uptime();
@ -29,16 +29,9 @@ async function compute(db, _peers) {
rssMB, rssMB,
externalMB externalMB
}; };
await db.insert(workerProcessMetrics).values(row); return row;
return {
ts: row.ts,
pid: row.pid,
uptimeSec: row.uptimeSec,
heapUsedMB: row.heapUsedMB,
rssMB: row.rssMB,
externalMB: row.externalMB
};
} }
export { export {
compute compute,
workerProcessMetrics as table
}; };

View File

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