Files
Netcatty/application/state/monitorRuntimeStore.ts
T
陈大猫 b5fee9632e feat(monitor): enrich and virtualize Vault monitoring views (#3713)
* feat(monitor): enrich and virtualize vault monitoring views

* fix(monitor): preserve outer gutter around sticky terminal actions

* fix(monitor): mask scrolled content behind action column corners

* feat(monitor): customize columns and clarify unavailable hosts

* fix(monitor): collect GPU data without delaying primary samples
2026-10-18 04:19:55 +08:00

57 lines
1.5 KiB
TypeScript

import { useSyncExternalStore } from "react";
import { mergeMonitorSnapshotHistory, type MonitorSnapshot, type MonitorHistoryCursor } from "../../domain/monitorRuntime";
const empty: MonitorSnapshot = {
historyMode: "replace",
running: [],
count: 0,
hostCount: 0,
epoch: 0,
runtimeId: "",
takenAt: 0,
activeSessions: [],
startedAt: {},
hosts: {},
};
let snapshot = empty;
const listeners = new Set<() => void>();
export function publishMonitorSnapshot(next: MonitorSnapshot) {
snapshot = mergeMonitorSnapshotHistory(snapshot, next);
for (const l of listeners) l();
}
export function getMonitorHistoryCursor(): MonitorHistoryCursor {
return {
runtimeId: snapshot.runtimeId,
epoch: snapshot.epoch,
after: Object.fromEntries(Object.entries(snapshot.hosts).map(([id, host]) => [id, { at: host.points.at(-1)?.at ?? 0, statsAt: host.statsAt ?? host.at, historyId: host.historyId }])),
};
}
export function publishMonitorUnavailable() {
publishMonitorSnapshot({ ...empty, unavailable: true });
}
export function useMonitorSnapshot() {
return useSyncExternalStore(
(l) => {
listeners.add(l);
return () => {
listeners.delete(l);
};
},
() => snapshot,
() => empty,
);
}
export const monitorActions: {
start: (id: string) => void;
stop: (id: string) => void;
stopAll: () => void;
retry: (
id: string,
credentials?: { username: string; password: string },
) => void;
} = {
start: () => {},
stop: () => {},
stopAll: () => {},
retry: () => {},
};