feat(core): new worker workspace engine (#9257)

This commit is contained in:
EYHN
2025-01-17 00:22:18 +08:00
committed by GitHub
parent 7dc470e7ea
commit a2ffdb4047
219 changed files with 4267 additions and 7194 deletions

View File

@@ -0,0 +1,19 @@
import type { NamespaceHandlers } from '../type';
import { WorkerManager } from './pool';
export const workerHandlers = {
connectWorker: async (e, key: string, portId: string) => {
const { portForRenderer } = await WorkerManager.instance.connectWorker(
key,
portId,
e.sender
);
e.sender.postMessage('worker-connect', { portId }, [portForRenderer]);
return {
portId: portId,
};
},
disconnectWorker: async (_, key: string, portId: string) => {
WorkerManager.instance.disconnectWorker(key, portId);
},
} satisfies NamespaceHandlers;

View File

@@ -0,0 +1,96 @@
import { join } from 'node:path';
import { BrowserWindow, MessageChannelMain, type WebContents } from 'electron';
import { backgroundWorkerViewUrl } from '../constants';
import { ensureHelperProcess } from '../helper-process';
import { logger } from '../logger';
async function getAdditionalArguments() {
const { getExposedMeta } = await import('../exposed');
const mainExposedMeta = getExposedMeta();
const helperProcessManager = await ensureHelperProcess();
const helperExposedMeta = await helperProcessManager.rpc?.getMeta();
return [
`--main-exposed-meta=` + JSON.stringify(mainExposedMeta),
`--helper-exposed-meta=` + JSON.stringify(helperExposedMeta),
`--window-name=worker`,
];
}
export class WorkerManager {
static readonly instance = new WorkerManager();
workers = new Map<
string,
{ browserWindow: BrowserWindow; ports: Set<string>; key: string }
>();
private async getOrCreateWorker(key: string) {
const additionalArguments = await getAdditionalArguments();
const helperProcessManager = await ensureHelperProcess();
const exists = this.workers.get(key);
if (exists) {
return exists;
} else {
const worker = new BrowserWindow({
width: 1200,
height: 600,
webPreferences: {
preload: join(__dirname, './preload.js'),
additionalArguments: additionalArguments,
},
show: false,
});
let disconnectHelperProcess: (() => void) | null = null;
worker.on('close', e => {
e.preventDefault();
if (worker && !worker.isDestroyed()) {
worker.destroy();
this.workers.delete(key);
disconnectHelperProcess?.();
}
});
worker.loadURL(backgroundWorkerViewUrl).catch(e => {
logger.error('failed to load url', e);
});
worker.webContents.addListener('did-finish-load', () => {
disconnectHelperProcess = helperProcessManager.connectRenderer(
worker.webContents
);
});
const record = { browserWindow: worker, ports: new Set<string>(), key };
this.workers.set(key, record);
return record;
}
}
async connectWorker(
key: string,
portId: string,
bindWebContent: WebContents
) {
bindWebContent.addListener('destroyed', () => {
this.disconnectWorker(key, portId);
});
const worker = await this.getOrCreateWorker(key);
const { port1: portForWorker, port2: portForRenderer } =
new MessageChannelMain();
worker.browserWindow.webContents.postMessage('worker-connect', { portId }, [
portForWorker,
]);
return { portForRenderer, portId };
}
disconnectWorker(key: string, portId: string) {
const worker = this.workers.get(key);
if (worker) {
worker.ports.delete(portId);
if (worker.ports.size === 0) {
worker.browserWindow.destroy();
this.workers.delete(key);
}
}
}
}