perf: optimize app startup and background lifecycles

This commit is contained in:
inman committed 2026-08-19 00:56:15 +08:00
1 parent 31332f6d76
commit 927e13349b
121 files changed
+4359 -1400

No files matched your search

+48 -1
View File
@@ -36,6 +36,9 @@ import { createLearningSpeechClient, type LearningSpeechRequest } from '../servi
import { createLearningGenerationClient } from '../services/learning-generation-client';
import { createLearningRuntimeBridge } from '../services/learning-runtime-bridge';
import type { LearningGenerationUploadRequest, LearningRuntimeBridgeRequest } from '../../shared/learning';
import type { BackgroundLifecycleController, DesktopActivity } from './background-lifecycle';
import { collectPerformanceSnapshot } from './performance-diagnostics';
import type { HostApiContext } from '../api/context';
type UnifiedRequest = {
id?: string;
@@ -372,9 +375,22 @@ export function registerIpcHandlers(
opencodeManager: OpencodeManager,
_legacyMarketplaceService: unknown,
mainWindow: BrowserWindow,
lifecycle?: BackgroundLifecycleController,
hostApiContext?: HostApiContext,
): void {
registerHostApiProxyHandlers();
registerHostApiProxyHandlers(hostApiContext);
registerTranscriptExportHandler(mainWindow);
const rendererLeases = new Set<string>();
const releaseRendererLeases = (): void => {
if (rendererLeases.size === 0) return;
for (const id of rendererLeases) lifecycle?.releaseLease(id);
rendererLeases.clear();
};
const rendererWebContents = mainWindow.webContents;
if (rendererWebContents && typeof rendererWebContents.on === 'function') {
rendererWebContents.on('render-process-gone', releaseRendererLeases);
rendererWebContents.on('destroyed', releaseRendererLeases);
}
const learningCourseLibrary = createLearningCourseLibrary({ rootDirectory: app.getPath('userData') });
let learningAgentClient = createLearningAgentClient();
const learningSpeechClient = createLearningSpeechClient();
@@ -415,6 +431,7 @@ export function registerIpcHandlers(
assertCurrentAccount();
return (await getLearningPlayerServer(binding.accountKey)).url;
}));
ipcMain.handle('learning:closePlayer', () => closeLearningPlayerServer());
ipcMain.handle('learning:agentAsk', (_event, request: unknown) => withLearningBinding(
async (binding, assertCurrentAccount) => {
const identity = requireLearningAgentIdentity(request);
@@ -508,6 +525,7 @@ export function registerIpcHandlers(
app.relaunch();
app.exit(0);
});
ipcMain.handle('app:performance', () => collectPerformanceSnapshot(lifecycle));
ipcMain.handle('opencode:status', () => opencodeManager.getStatus());
ipcMain.handle('opencode:start', () => opencodeManager.start());
@@ -518,6 +536,35 @@ export function registerIpcHandlers(
ipcMain.handle('opencode:restart', () => opencodeManager.restart());
ipcMain.handle('opencode:health', () => opencodeManager.checkHealth());
ipcMain.handle('lifecycle:activity', (_event, activity: DesktopActivity) => {
const nextActivity = activity && typeof activity === 'object'
? activity
: { visible: true, module: null };
lifecycle?.setActivity(nextActivity);
if ((!nextActivity.visible || nextActivity.module !== 'painting')
&& !mainWindow.isDestroyed()
&& !mainWindow.webContents.isDestroyed()) {
mainWindow.webContents.send('lifecycle:pause');
}
return lifecycle?.getActivity() ?? nextActivity;
});
ipcMain.handle('lifecycle:lease', (_event, input: { id: string; kind: string; active: boolean }) => {
if (!lifecycle) return { count: 0 };
const id = typeof input?.id === 'string' ? input.id.trim() : '';
if (!id) return { count: lifecycle.getLeaseCount() };
if (input?.active) {
lifecycle.acquireLease({
id,
kind: typeof input.kind === 'string' && input.kind.trim() ? input.kind.trim() : 'unknown',
});
rendererLeases.add(id);
} else {
lifecycle.releaseLease(id);
rendererLeases.delete(id);
}
return { count: lifecycle.getLeaseCount() };
});
ipcMain.handle('settings:getAll', () => getAllSettings());
ipcMain.handle('settings:get', (_event, payload: { key?: keyof AppSettings } | keyof AppSettings) => {
const key = typeof payload === 'string' ? payload : payload?.key;