feat(FN-1227): add mesh state and system metrics support to CentralCore
- Add SystemMetrics, PeerNode, NodeMeshState, and MeshDiscovery types and export new mesh/metrics APIs from @fusion/core - Introduce collectSystemMetrics with CPU, memory, storage, and uptime collection (including check-disk-space integration) plus dedicated unit tests - Bump central DB schema to v3 with nodes.systemMetrics/knownPeers and peerNodes table, including migration coverage for v2->v3 upgrades - Extend CentralCore with node metrics updates, peer register/unregister/list operations, mesh snapshot reporting, and event emissions backed by expanded test coverage
This commit is contained in:
@@ -39,7 +39,7 @@ describe("CentralDatabase", () => {
|
||||
|
||||
it("should initialize schema version", () => {
|
||||
db.init();
|
||||
expect(db.getSchemaVersion()).toBe(2);
|
||||
expect(db.getSchemaVersion()).toBe(3);
|
||||
});
|
||||
|
||||
it("should seed lastModified on init", () => {
|
||||
@@ -93,6 +93,7 @@ describe("CentralDatabase", () => {
|
||||
expect(tableNames).toContain("centralActivityLog");
|
||||
expect(tableNames).toContain("globalConcurrency");
|
||||
expect(tableNames).toContain("nodes");
|
||||
expect(tableNames).toContain("peerNodes");
|
||||
expect(tableNames).toContain("__meta");
|
||||
});
|
||||
|
||||
@@ -106,6 +107,39 @@ describe("CentralDatabase", () => {
|
||||
expect(columnNames).toContain("nodeId");
|
||||
});
|
||||
|
||||
it("should include systemMetrics and knownPeers columns on nodes table", () => {
|
||||
db.init();
|
||||
|
||||
const columns = db.prepare("PRAGMA table_info(nodes)").all() as Array<{
|
||||
name: string;
|
||||
}>;
|
||||
const columnNames = columns.map((column) => column.name);
|
||||
expect(columnNames).toContain("systemMetrics");
|
||||
expect(columnNames).toContain("knownPeers");
|
||||
});
|
||||
|
||||
it("should create peerNodes table with expected columns", () => {
|
||||
db.init();
|
||||
|
||||
const columns = db.prepare("PRAGMA table_info(peerNodes)").all() as Array<{
|
||||
name: string;
|
||||
}>;
|
||||
const columnNames = columns.map((column) => column.name);
|
||||
|
||||
expect(columnNames).toEqual(
|
||||
expect.arrayContaining([
|
||||
"id",
|
||||
"nodeId",
|
||||
"peerNodeId",
|
||||
"name",
|
||||
"url",
|
||||
"status",
|
||||
"lastSeen",
|
||||
"connectedAt",
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it("should create required indexes", () => {
|
||||
db.init();
|
||||
const indexes = db
|
||||
@@ -119,6 +153,71 @@ describe("CentralDatabase", () => {
|
||||
expect(indexNames).toContain("idxActivityLogProjectId");
|
||||
expect(indexNames).toContain("idxNodesStatus");
|
||||
expect(indexNames).toContain("idxNodesType");
|
||||
expect(indexNames).toContain("idxPeerNodesNodeId");
|
||||
});
|
||||
});
|
||||
|
||||
describe("schema migrations", () => {
|
||||
it("should migrate from v2 to v3 with mesh node columns and peer table", () => {
|
||||
const now = new Date().toISOString();
|
||||
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS projects (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
path TEXT NOT NULL UNIQUE,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
isolationMode TEXT NOT NULL DEFAULT 'in-process',
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL,
|
||||
lastActivityAt TEXT,
|
||||
nodeId TEXT,
|
||||
settings TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS nodes (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
type TEXT NOT NULL CHECK (type IN ('local', 'remote')),
|
||||
url TEXT,
|
||||
apiKey TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'offline',
|
||||
capabilities TEXT,
|
||||
maxConcurrent INTEGER NOT NULL DEFAULT 2,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS __meta (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT
|
||||
);
|
||||
`);
|
||||
|
||||
db.prepare("INSERT INTO __meta (key, value) VALUES ('schemaVersion', '2')").run();
|
||||
db.prepare("INSERT INTO __meta (key, value) VALUES ('lastModified', ?)").run(String(Date.now()));
|
||||
db.prepare(
|
||||
"INSERT INTO nodes (id, name, type, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?)",
|
||||
).run("node_legacy", "legacy", "local", now, now);
|
||||
|
||||
db.init();
|
||||
|
||||
expect(db.getSchemaVersion()).toBe(3);
|
||||
|
||||
const nodeColumns = db.prepare("PRAGMA table_info(nodes)").all() as Array<{ name: string }>;
|
||||
const nodeColumnNames = nodeColumns.map((column) => column.name);
|
||||
expect(nodeColumnNames).toContain("systemMetrics");
|
||||
expect(nodeColumnNames).toContain("knownPeers");
|
||||
|
||||
const peerTable = db
|
||||
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='peerNodes'")
|
||||
.get() as { name: string } | undefined;
|
||||
expect(peerTable?.name).toBe("peerNodes");
|
||||
|
||||
const peerIndexes = db
|
||||
.prepare("SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='peerNodes'")
|
||||
.all() as Array<{ name: string }>;
|
||||
expect(peerIndexes.map((index) => index.name)).toContain("idxPeerNodesNodeId");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user