From b8d3a2ce735e2485df5feae9888e7a011cce06dc Mon Sep 17 00:00:00 2001 From: zsq1234 <41423998+zsq1234@users.noreply.github.com> Date: Sat, 29 Nov 2025 14:55:33 +0800 Subject: [PATCH] feat: add dispose for close univer worker (#6216) --- packages/rpc-node/src/plugin.ts | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/rpc-node/src/plugin.ts b/packages/rpc-node/src/plugin.ts index 1571e8f588..f9453d5d36 100644 --- a/packages/rpc-node/src/plugin.ts +++ b/packages/rpc-node/src/plugin.ts @@ -16,7 +16,7 @@ import type { Dependency } from '@univerjs/core'; import type { IMessageProtocol } from '@univerjs/rpc'; -import type { Serializable } from 'node:child_process'; +import type { ChildProcess, Serializable } from 'node:child_process'; import type { IUniverRPCNodeMainConfig, IUniverRPCNodeWorkerThreadConfig } from './controllers/config.schema'; import { fork } from 'node:child_process'; import process from 'node:process'; @@ -37,6 +37,8 @@ import { defaultPluginMainThreadConfig, defaultPluginWorkerThreadConfig, PLUGIN_ export class UniverRPCNodeMainPlugin extends Plugin { static override pluginName = 'UNIVER_RPC_NODE_MAIN_PLUGIN'; + private _child: ChildProcess | null = null; + constructor( private readonly _config: Partial = defaultPluginMainThreadConfig, @Inject(Injector) protected readonly _injector: Injector, @@ -59,7 +61,7 @@ export class UniverRPCNodeMainPlugin extends Plugin { throw new Error('[UniverRPCNodeMainPlugin] workerSrc is required for UniverRPCNodeMainPlugin'); } - const messageProtocol = createNodeMessagePortOnMain(this._injector, workerSrc); + const [messageProtocol, child] = createNodeMessagePortOnMain(this._injector, workerSrc); const dependencies: Dependency[] = [ [IRPCChannelService, { @@ -72,6 +74,21 @@ export class UniverRPCNodeMainPlugin extends Plugin { dependencies.forEach((dependency) => this._injector.add(dependency)); this._injector.get(DataSyncPrimaryController); + this._child = child; + } + + override dispose(): void { + super.dispose(); + + if (this._child) { + try { + this._child.kill(); + } + catch (e) { + console.error('Failed to kill child process:', e); + } + this._child = null; + } } } @@ -107,7 +124,7 @@ export class UniverRPCNodeWorkerPlugin extends Plugin { } } -function createNodeMessagePortOnMain(injector: Injector, path: string): IMessageProtocol { +function createNodeMessagePortOnMain(injector: Injector, path: string): [IMessageProtocol, ChildProcess] { const logService = injector.get(ILogService); const child = fork(path); @@ -128,7 +145,7 @@ function createNodeMessagePortOnMain(injector: Injector, path: string): IMessage }).pipe(shareReplay(1)), }; - return messageProtocol; + return [messageProtocol, child]; } function createNodeWorkerMessageProtocol(): IMessageProtocol {