mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-11-11 17:00:22 +00:00
* perf(terminal): stop per-second churn while connecting and while idle - Connecting sessions: the 200 ms progress animation and 1 s countdown were Terminal state threaded into the TerminalView ctx, so every connecting session (hidden tabs and startup restores included) re-rendered Terminal + TerminalView up to six times a second. Terminal now only publishes the timeout deadline and real progress events; the connection dialog animates and counts down locally (connectionTicker.ts). HostConnectionTestDialog keeps passing progress/timeLeft as before. - Monitor runtime: polled every second unconditionally and woke every subscriber each time because takenAt always changes. It now polls at 1 s only while something is monitored (here or in another window), 10 s otherwise, and skips notifying for unchanged idle replies. - Auto-reconnect progress log: capped at the newest 300 lines (it grew by a few lines every 5 s retry for as long as an outage lasted). - App Lock: report activity at most once a second instead of an IPC per keystroke / wheel tick / pointer event. - Tray/Dock: the renderer resends hosts only when the host list changed, and the main process rebuilds the macOS Dock menu (sort + one native item per host) only then, not on every session status change. Real app, profiling build, main -> this change: 3 SSH sessions connecting (3 s) 14 commits / 35.3 ms -> 8 / 1.7 ms idle (10 s) 13 commits / 3.1 ms -> 2 / 0.1 ms Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(terminal): update observe-popup reconnect deps assertion for capped progress logs CI failed because #4118 wrapped setProgressLogs in useCallback to apply capConnectionProgressLogs and added it to scheduleAutoReconnect deps. The observe-popup source assertion still expected the old deps list. The attachExistingSession early-return behavior is unchanged; only the stale dependency regex needed updating. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
92 lines
2.6 KiB
TypeScript
92 lines
2.6 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import {
|
|
publishMonitorSnapshot,
|
|
getMonitorHistoryCursor,
|
|
} from "./monitorRuntimeStore";
|
|
import type { MonitorSnapshot } from "../../domain/monitorRuntime";
|
|
|
|
test("renderer cursor acknowledges GPU publication separately from CPU sample and history", () => {
|
|
const snapshot: MonitorSnapshot = {
|
|
historyMode: "replace",
|
|
runtimeId: "gpu-cursor-test",
|
|
epoch: 1,
|
|
takenAt: 1000,
|
|
running: ["panel"],
|
|
count: 1,
|
|
hostCount: 1,
|
|
activeSessions: [],
|
|
startedAt: { panel: 0 },
|
|
hosts: {
|
|
host: {
|
|
historyId: "history",
|
|
status: "live",
|
|
at: 1000,
|
|
statsAt: 1001,
|
|
points: [
|
|
{ at: 1000, cpu: 10, memory: 20, disk: null, rx: null, tx: null },
|
|
],
|
|
},
|
|
},
|
|
};
|
|
publishMonitorSnapshot(snapshot);
|
|
assert.deepEqual(getMonitorHistoryCursor().after.host, {
|
|
at: 1000,
|
|
statsAt: 1001,
|
|
historyId: "history",
|
|
});
|
|
publishMonitorSnapshot({
|
|
...snapshot,
|
|
historyMode: "append",
|
|
takenAt: 2000,
|
|
hosts: { host: { ...snapshot.hosts.host, statsAt: 2001, points: [] } },
|
|
});
|
|
assert.deepEqual(getMonitorHistoryCursor().after.host, {
|
|
at: 1000,
|
|
statsAt: 2001,
|
|
historyId: "history",
|
|
});
|
|
});
|
|
|
|
test("idle runtime polls do not notify subscribers until something changes", async () => {
|
|
const React = await import("react");
|
|
const { act, create } = await import("react-test-renderer");
|
|
const { useMonitorSnapshot } = await import("./monitorRuntimeStore");
|
|
Object.assign(globalThis, { IS_REACT_ACT_ENVIRONMENT: true });
|
|
const idle = (takenAt: number): MonitorSnapshot => ({
|
|
historyMode: "replace",
|
|
runtimeId: "idle-poll-test",
|
|
epoch: 7,
|
|
takenAt,
|
|
running: [],
|
|
count: 0,
|
|
hostCount: 0,
|
|
activeSessions: [],
|
|
startedAt: {},
|
|
hosts: {},
|
|
});
|
|
let renders = 0;
|
|
function Probe() {
|
|
useMonitorSnapshot();
|
|
renders += 1;
|
|
return null;
|
|
}
|
|
// Later than anything earlier tests published, so this baseline wins.
|
|
const base = 1_000_000_000;
|
|
publishMonitorSnapshot(idle(base));
|
|
let renderer!: ReturnType<typeof create>;
|
|
act(() => {
|
|
renderer = create(React.createElement(Probe));
|
|
});
|
|
const baseline = renders;
|
|
act(() => {
|
|
for (let at = base + 1000; at <= base + 5000; at += 1000) publishMonitorSnapshot(idle(at));
|
|
});
|
|
assert.equal(renders, baseline, "unchanged idle replies must not re-render subscribers");
|
|
act(() => {
|
|
publishMonitorSnapshot({ ...idle(base + 6000), running: ["panel"], count: 1 });
|
|
});
|
|
assert.equal(renders, baseline + 1, "a real change still notifies");
|
|
act(() => renderer.unmount());
|
|
});
|