feat(desktop): add hot view retain/release lifecycle and process metrics

Replace single-shot acquireHotView with retainHotView/releaseHotView
plus a minute-level reaper that closes views idle beyond 5 minutes and
never evicts a view while it still has live retainers. Wrap adapter
calls in try/finally so a failing publish/query still releases the
view. Sample process metrics every minute and expose hot-view policy
and process snapshot via the runtime snapshot for diagnostics.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-20 11:07:58 +08:00
parent a46ed4b9f6
commit ef868f81a1
5 changed files with 261 additions and 43 deletions
@@ -8,6 +8,7 @@ import type {
import type { DesktopAccountInfo, DesktopRuntimeSessionSyncRequest } from "@geo/shared-types";
import { bindPublishAccount, openPublishAccountConsole } from "./account-binder";
import { initProcessMetricsSampler } from "./process-metrics";
import { registerRendererDevtoolsProxyTarget } from "./renderer-devtools-proxy";
import {
refreshRuntimeAccounts,
@@ -22,6 +23,7 @@ import { initSingleInstance } from "./single-instance";
import { initTransport, listDesktopPublishTasks, retryDesktopPublishTask } from "./transport/api-client";
import { initTray } from "./tray";
import { STANDARD_USER_AGENT } from "./user-agent";
import { startHotViewReaper } from "./view-pool";
app.commandLine.appendSwitch(
"disable-features",
@@ -183,6 +185,8 @@ app.whenReady().then(async () => {
await initSessionRegistry();
initTransport();
initScheduler();
initProcessMetricsSampler();
startHotViewReaper();
mainWindow = await createMainWindow();
initTray(() => {
if (!mainWindow) {