perf: reduce desktop quit risk polling
Refresh quit risk only when quitting Use in-process status for Electron local server Avoid repeated scheduled task status scans
This commit is contained in:
+20
-21
@@ -128,7 +128,6 @@ const state = {
|
||||
quitConfirmed: false,
|
||||
quitConfirmationPending: false,
|
||||
installingUpdate: false,
|
||||
quitRiskPollerStarted: false,
|
||||
pendingUpdate: null,
|
||||
unreachableHosts: new Set(),
|
||||
windowCounter: 1,
|
||||
@@ -138,7 +137,6 @@ const state = {
|
||||
sshLogs: new Map(),
|
||||
};
|
||||
|
||||
const QUIT_RISK_POLL_INTERVAL_MS = 5_000;
|
||||
const quitRisk = {
|
||||
hasActiveTunnel: false,
|
||||
hasRunningScheduledTasks: false,
|
||||
@@ -206,6 +204,8 @@ const performConfirmedQuit = () => {
|
||||
};
|
||||
|
||||
const requestQuitWithConfirmation = async () => {
|
||||
await refreshQuitRiskFlags();
|
||||
|
||||
if (!shouldRequireQuitConfirmation()) {
|
||||
performConfirmedQuit();
|
||||
return;
|
||||
@@ -247,6 +247,24 @@ const requestQuitWithConfirmation = async () => {
|
||||
};
|
||||
|
||||
const refreshQuitRiskFlags = async () => {
|
||||
if (state.serverHandle && typeof state.serverHandle.getQuitRiskStatus === 'function') {
|
||||
try {
|
||||
const status = await state.serverHandle.getQuitRiskStatus();
|
||||
const scheduled = status?.scheduledTasks;
|
||||
if (scheduled && typeof scheduled === 'object') {
|
||||
const enabledCount = Number(scheduled.enabledScheduledTasksCount ?? 0);
|
||||
const runningCount = Number(scheduled.runningScheduledTasksCount ?? 0);
|
||||
quitRisk.enabledScheduledTasksCount = Number.isFinite(enabledCount) ? enabledCount : 0;
|
||||
quitRisk.runningScheduledTasksCount = Number.isFinite(runningCount) ? runningCount : 0;
|
||||
quitRisk.hasEnabledScheduledTasks = Boolean(scheduled.hasEnabledScheduledTasks) || quitRisk.enabledScheduledTasksCount > 0;
|
||||
quitRisk.hasRunningScheduledTasks = Boolean(scheduled.hasRunningScheduledTasks) || quitRisk.runningScheduledTasksCount > 0;
|
||||
}
|
||||
quitRisk.hasActiveTunnel = Boolean(status?.tunnel?.active);
|
||||
return;
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
|
||||
const base = typeof state.sidecarUrl === 'string' ? state.sidecarUrl.trim().replace(/\/$/, '') : '';
|
||||
if (!base) return;
|
||||
|
||||
@@ -279,24 +297,6 @@ const refreshQuitRiskFlags = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const startQuitRiskPoller = () => {
|
||||
if (process.platform !== 'darwin') return;
|
||||
if (state.quitRiskPollerStarted) return;
|
||||
state.quitRiskPollerStarted = true;
|
||||
|
||||
const loop = async () => {
|
||||
while (!state.quitConfirmed && !state.quitRequested) {
|
||||
await refreshQuitRiskFlags();
|
||||
if (state.quitConfirmed || state.quitRequested) break;
|
||||
await new Promise((resolve) => {
|
||||
const timer = setTimeout(resolve, QUIT_RISK_POLL_INTERVAL_MS);
|
||||
if (typeof timer?.unref === 'function') timer.unref();
|
||||
});
|
||||
}
|
||||
};
|
||||
void loop();
|
||||
};
|
||||
|
||||
const settingsFilePath = () => {
|
||||
if (typeof process.env.OPENCHAMBER_DATA_DIR === 'string' && process.env.OPENCHAMBER_DATA_DIR.trim()) {
|
||||
return path.join(process.env.OPENCHAMBER_DATA_DIR.trim(), 'settings.json');
|
||||
@@ -2399,7 +2399,6 @@ app.whenReady().then(async () => {
|
||||
|
||||
const { initialUrl, localOrigin, bootOutcome } = await resolveInitialUrl();
|
||||
await activateMainWindow(initialUrl, localOrigin, bootOutcome);
|
||||
startQuitRiskPoller();
|
||||
|
||||
// Notify renderer on OS wake-from-sleep so the SSE event pipeline can
|
||||
// reconnect immediately instead of waiting for the heartbeat watchdog.
|
||||
|
||||
@@ -1233,6 +1233,12 @@ async function main(options = {}) {
|
||||
getPort: () => tunnelRuntimeContext.getActivePort(),
|
||||
getOpenCodePort: () => openCodePort,
|
||||
getTunnelUrl: () => tunnelService.getPublicUrl(),
|
||||
getQuitRiskStatus: () => ({
|
||||
tunnel: {
|
||||
active: Boolean(tunnelService.getPublicUrl()),
|
||||
},
|
||||
scheduledTasks: scheduledTasksRuntime.getStatus(),
|
||||
}),
|
||||
isReady: () => isOpenCodeReady,
|
||||
restartOpenCode: () => restartOpenCode(),
|
||||
stop: (shutdownOptions = {}) =>
|
||||
|
||||
@@ -156,6 +156,10 @@ export const registerScheduledTaskRoutes = (app, dependencies) => {
|
||||
|
||||
app.get('/api/openchamber/scheduled-tasks/status', async (_req, res) => {
|
||||
try {
|
||||
if (typeof scheduledTasksRuntime.getStatus === 'function') {
|
||||
return res.json(scheduledTasksRuntime.getStatus());
|
||||
}
|
||||
|
||||
const settings = await readSettingsFromDiskMigrated();
|
||||
const projects = sanitizeProjects(settings?.projects || []);
|
||||
|
||||
|
||||
@@ -739,11 +739,31 @@ export const createScheduledTasksRuntime = (deps) => {
|
||||
queue.length = 0;
|
||||
};
|
||||
|
||||
const getStatus = () => {
|
||||
let enabledCount = 0;
|
||||
for (const taskMap of tasksByProject.values()) {
|
||||
for (const task of taskMap.values()) {
|
||||
if (task?.enabled) {
|
||||
enabledCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const runningCount = runningTaskKeys.size;
|
||||
return {
|
||||
hasEnabledScheduledTasks: enabledCount > 0,
|
||||
hasRunningScheduledTasks: runningCount > 0,
|
||||
enabledScheduledTasksCount: enabledCount,
|
||||
runningScheduledTasksCount: runningCount,
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
start,
|
||||
stop,
|
||||
syncAllProjects,
|
||||
syncProject,
|
||||
runNow,
|
||||
getStatus,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user