1+ import { join } from 'node:path'
12import process from 'node:process'
3+ import { fileURLToPath } from 'node:url'
24import { deserialize } from 'node:v8'
35
46import type { PhotoManifestItem } from '@afilmory/typing'
57
68import type { BuilderOptions } from './builder/builder.js'
79import { AfilmoryBuilder } from './builder/builder.js'
10+ import { loadBuilderConfig } from './config/index.js'
811import type { PluginRunState } from './plugins/manager.js'
912import type { StorageObject } from './storage/interfaces'
1013import type { BuilderConfig } from './types/config.js'
@@ -40,6 +43,17 @@ export async function runAsWorker() {
4043 let builder : AfilmoryBuilder
4144 let pluginRunState : PluginRunState
4245
46+ // 安全发送消息到主进程(防止 EPIPE 错误)
47+ const safeSend = ( message : unknown ) => {
48+ try {
49+ if ( process . send && process . connected ) {
50+ process . send ( message )
51+ }
52+ } catch {
53+ // 主进程已关闭 IPC 通道,静默忽略
54+ }
55+ }
56+
4357 // 初始化函数,从主进程接收共享数据
4458 const initializeWorker = async ( serializedData : WorkerInitMessage [ 'sharedData' ] ) => {
4559 if ( isInitialized ) return
@@ -52,7 +66,18 @@ export async function runAsWorker() {
5266 imageObjects = sharedData . imageObjects
5367 existingManifestMap = sharedData . existingManifestMap
5468 livePhotoMap = sharedData . livePhotoMap
55- builder = new AfilmoryBuilder ( sharedData . builderConfig )
69+
70+ // 主进程序列化时移除了 plugins(函数无法序列化),
71+ // 从配置文件重新加载以获取完整的插件配置
72+ const fullConfig = await loadBuilderConfig ( {
73+ cwd : join ( fileURLToPath ( import . meta. url ) , '../../../..' ) ,
74+ } )
75+ const builderConfig : BuilderConfig = {
76+ ...sharedData . builderConfig ,
77+ plugins : fullConfig . plugins ,
78+ }
79+
80+ builder = new AfilmoryBuilder ( builderConfig )
5681 await builder . ensurePluginsReady ( )
5782 pluginRunState = builder . createPluginRunState ( )
5883
@@ -133,9 +158,7 @@ export async function runAsWorker() {
133158 result,
134159 }
135160
136- if ( process . send ) {
137- process . send ( response )
138- }
161+ safeSend ( response )
139162 } catch ( error ) {
140163 // 发送错误回主进程
141164 const response : TaskResult = {
@@ -144,9 +167,7 @@ export async function runAsWorker() {
144167 error : error instanceof Error ? error . message : String ( error ) ,
145168 }
146169
147- if ( process . send ) {
148- process . send ( response )
149- }
170+ safeSend ( response )
150171 }
151172 }
152173
@@ -242,9 +263,7 @@ export async function runAsWorker() {
242263 results,
243264 }
244265
245- if ( process . send ) {
246- process . send ( response )
247- }
266+ safeSend ( response )
248267 } catch ( error ) {
249268 // 如果批量处理失败,为每个任务发送错误结果
250269 const results : TaskResult [ ] = message . tasks . map ( ( task ) => ( {
@@ -258,9 +277,7 @@ export async function runAsWorker() {
258277 results,
259278 }
260279
261- if ( process . send ) {
262- process . send ( response )
263- }
280+ safeSend ( response )
264281 }
265282 }
266283
@@ -275,19 +292,15 @@ export async function runAsWorker() {
275292
276293 if ( message . type === 'ping' ) {
277294 // 响应主进程的 ping,表示 worker 已准备好
278- if ( process . send ) {
279- process . send ( { type : 'pong' , workerId } )
280- }
295+ safeSend ( { type : 'pong' , workerId } )
281296 return
282297 }
283298
284299 if ( message . type === 'init' ) {
285300 // 处理初始化消息
286301 try {
287302 await initializeWorker ( message . sharedData )
288- if ( process . send ) {
289- process . send ( { type : 'init-complete' , workerId } )
290- }
303+ safeSend ( { type : 'init-complete' , workerId } )
291304 } catch ( error ) {
292305 console . error ( 'Worker initialization failed' , error )
293306 process . exit ( 1 )
@@ -323,7 +336,5 @@ export async function runAsWorker() {
323336 } )
324337
325338 // 告知主进程 worker 已准备好
326- if ( process . send ) {
327- process . send ( { type : 'ready' , workerId } )
328- }
339+ safeSend ( { type : 'ready' , workerId } )
329340}
0 commit comments