mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-01-18 14:30:29 +00:00
Added the ability to pass a JWT secret key when restarting the worker process by updating environment variable handling and message passing. Improved port retry logic in the backend to allow multiple attempts on the same port before incrementing. Also refactored process API to use getter for pid property. Ensure Electron app is ready before creating process manager Adds a check to await electron.app.whenReady() if the Electron app is not yet ready before instantiating the ElectronProcessManager. This prevents potential issues when accessing Electron APIs before the app is fully initialized. Add mirror selection support for version updates Introduces the ability to specify and select GitHub mirror sources for fetching tags, releases, and action artifacts throughout the backend and frontend. Updates API endpoints, internal helper functions, and UI components to allow users to choose a mirror for version queries and updates, improving reliability in regions with limited GitHub access. Also enhances version comparison logic and improves artifact metadata display. Refactor artifact fetching to use HTML parsing only Removed all GitHub API dependencies for fetching workflow runs and artifacts. Now, workflow runs are parsed directly from the HTML of the Actions page, and artifact URLs are constructed using nightly.link. Also added workflow title and mirror fields to ActionArtifact, and simplified mirror list without latency comments.
182 lines
4.6 KiB
TypeScript
182 lines
4.6 KiB
TypeScript
import type { Readable } from 'stream';
|
|
import type { fork as forkType } from 'child_process';
|
|
|
|
// 扩展 Process 类型以支持 parentPort
|
|
declare global {
|
|
namespace NodeJS {
|
|
interface Process {
|
|
parentPort?: {
|
|
on (event: 'message', listener: (e: { data: unknown; }) => void): void;
|
|
postMessage (message: unknown): void;
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 统一的进程接口
|
|
*/
|
|
export interface IWorkerProcess {
|
|
readonly pid: number | undefined;
|
|
readonly stdout: Readable | null;
|
|
readonly stderr: Readable | null;
|
|
|
|
postMessage (message: unknown): void;
|
|
kill (): boolean;
|
|
on (event: string, listener: (...args: unknown[]) => void): void;
|
|
once (event: string, listener: (...args: unknown[]) => void): void;
|
|
}
|
|
|
|
/**
|
|
* 进程创建选项
|
|
*/
|
|
export interface ProcessOptions {
|
|
env: NodeJS.ProcessEnv;
|
|
stdio: 'pipe' | 'ignore' | 'inherit' | Array<'pipe' | 'ignore' | 'inherit' | 'ipc'>;
|
|
}
|
|
|
|
/**
|
|
* 进程管理器接口
|
|
*/
|
|
export interface IProcessManager {
|
|
createWorker (modulePath: string, args: string[], options: ProcessOptions): IWorkerProcess;
|
|
onParentMessage (handler: (message: unknown) => void): void;
|
|
sendToParent (message: unknown): boolean;
|
|
}
|
|
|
|
/**
|
|
* Electron utilityProcess 包装器
|
|
*/
|
|
class ElectronProcessManager implements IProcessManager {
|
|
private utilityProcess: {
|
|
fork (modulePath: string, args: string[], options: unknown): unknown;
|
|
};
|
|
|
|
constructor (utilityProcess: { fork (modulePath: string, args: string[], options: unknown): unknown; }) {
|
|
this.utilityProcess = utilityProcess;
|
|
}
|
|
|
|
createWorker (modulePath: string, args: string[], options: ProcessOptions): IWorkerProcess {
|
|
const child: any = this.utilityProcess.fork(modulePath, args, options);
|
|
|
|
return {
|
|
get pid () { return child.pid as number | undefined; },
|
|
stdout: child.stdout as Readable | null,
|
|
stderr: child.stderr as Readable | null,
|
|
|
|
postMessage (message: unknown): void {
|
|
child.postMessage(message);
|
|
},
|
|
|
|
kill (): boolean {
|
|
return child.kill() as boolean;
|
|
},
|
|
|
|
on (event: string, listener: (...args: unknown[]) => void): void {
|
|
child.on(event, listener);
|
|
},
|
|
|
|
once (event: string, listener: (...args: unknown[]) => void): void {
|
|
child.once(event, listener);
|
|
},
|
|
};
|
|
}
|
|
|
|
onParentMessage (handler: (message: unknown) => void): void {
|
|
if (process.parentPort) {
|
|
process.parentPort.on('message', (e: { data: unknown; }) => {
|
|
handler(e.data);
|
|
});
|
|
}
|
|
}
|
|
|
|
sendToParent (message: unknown): boolean {
|
|
if (process.parentPort) {
|
|
process.parentPort.postMessage(message);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Node.js child_process 包装器
|
|
*/
|
|
class NodeProcessManager implements IProcessManager {
|
|
private forkFn: typeof forkType;
|
|
|
|
constructor (forkFn: typeof forkType) {
|
|
this.forkFn = forkFn;
|
|
}
|
|
|
|
createWorker (modulePath: string, args: string[], options: ProcessOptions): IWorkerProcess {
|
|
const child = this.forkFn(modulePath, args, options as any);
|
|
|
|
return {
|
|
get pid () { return child.pid; },
|
|
stdout: child.stdout,
|
|
stderr: child.stderr,
|
|
|
|
postMessage (message: unknown): void {
|
|
if (child.send) {
|
|
child.send(message as any);
|
|
}
|
|
},
|
|
|
|
kill (): boolean {
|
|
return child.kill();
|
|
},
|
|
|
|
on (event: string, listener: (...args: unknown[]) => void): void {
|
|
child.on(event, listener);
|
|
},
|
|
|
|
once (event: string, listener: (...args: unknown[]) => void): void {
|
|
child.once(event, listener);
|
|
},
|
|
};
|
|
}
|
|
|
|
onParentMessage (handler: (message: unknown) => void): void {
|
|
process.on('message', (message: unknown) => {
|
|
handler(message);
|
|
});
|
|
}
|
|
|
|
sendToParent (message: unknown): boolean {
|
|
if (process.send) {
|
|
process.send(message as any);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 检测运行环境并创建对应的进程管理器
|
|
*/
|
|
export async function createProcessManager (): Promise<{
|
|
manager: IProcessManager;
|
|
isElectron: boolean;
|
|
}> {
|
|
const isElectron = typeof process.versions['electron'] !== 'undefined';
|
|
|
|
if (isElectron) {
|
|
// @ts-ignore - electron 运行时存在但类型声明可能缺失
|
|
const electron = await import('electron');
|
|
if (electron.app && !electron.app.isReady()) {
|
|
await electron.app.whenReady();
|
|
}
|
|
return {
|
|
manager: new ElectronProcessManager(electron.utilityProcess),
|
|
isElectron: true,
|
|
};
|
|
} else {
|
|
const { fork } = await import('child_process');
|
|
return {
|
|
manager: new NodeProcessManager(fork),
|
|
isElectron: false,
|
|
};
|
|
}
|
|
}
|