perf: 优化监听进程

This commit is contained in:
2026-02-04 02:36:12 +08:00
parent 08696dedd8
commit 15db8515d6
8 changed files with 67 additions and 52 deletions

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package",
"name": "@kevisual/router",
"version": "0.0.69",
"version": "0.0.70",
"description": "",
"type": "module",
"main": "./dist/router.js",
@@ -29,7 +29,7 @@
"@kevisual/local-proxy": "^0.0.8",
"@kevisual/query": "^0.0.39",
"@kevisual/use-config": "^1.0.30",
"@opencode-ai/plugin": "^1.1.48",
"@opencode-ai/plugin": "^1.1.49",
"@rollup/plugin-alias": "^6.0.0",
"@rollup/plugin-commonjs": "29.0.0",
"@rollup/plugin-node-resolve": "^16.0.3",
@@ -41,6 +41,7 @@
"@types/xml2js": "^0.4.14",
"eventemitter3": "^5.0.4",
"fast-glob": "^3.3.3",
"hono": "^4.11.7",
"nanoid": "^5.1.6",
"path-to-regexp": "^8.3.0",
"rollup": "^4.57.1",
@@ -53,14 +54,15 @@
"typescript": "^5.9.3",
"ws": "npm:@kevisual/ws",
"xml2js": "^0.6.2",
"zod": "^4.3.6",
"hono": "^4.11.7"
"zod": "^4.3.6"
},
"repository": {
"type": "git",
"url": "git+https://github.com/abearxiong/kevisual-router.git"
},
"dependencies": {},
"dependencies": {
"es-toolkit": "^1.44.0"
},
"publishConfig": {
"access": "public"
},

9
pnpm-lock.yaml generated
View File

@@ -7,6 +7,10 @@ settings:
importers:
.:
dependencies:
es-toolkit:
specifier: ^1.44.0
version: 1.44.0
devDependencies:
'@kevisual/context':
specifier: ^0.0.4
@@ -775,6 +779,9 @@ packages:
es-module-lexer@2.0.0:
resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==}
es-toolkit@1.44.0:
resolution: {integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==}
esbuild@0.27.2:
resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==}
engines: {node: '>=18'}
@@ -1725,6 +1732,8 @@ snapshots:
es-module-lexer@2.0.0: {}
es-toolkit@1.44.0: {}
esbuild@0.27.2:
optionalDependencies:
'@esbuild/aix-ppc64': 0.27.2

View File

@@ -14,5 +14,5 @@ export { CustomError } from './result/error.ts';
export * from './router-define.ts';
export { MockProcess } from './utils/listen-process.ts'
export { MockProcess, type ListenProcessParams, type ListenProcessResponse } from './utils/listen-process.ts'
// --- 以上同步更新至 browser.ts ---

View File

@@ -14,7 +14,7 @@ export { CustomError } from './result/error.ts';
export * from './router-define.ts';
export { MockProcess } from './utils/listen-process.ts'
export { MockProcess, type ListenProcessParams, type ListenProcessResponse } from './utils/listen-process.ts'
// --- 以上同步更新至 browser.ts ---
export { ServerNode, handleServer } from './server/index.ts';

View File

@@ -61,7 +61,7 @@ export type RouteContext<T = { code?: number }, S = any> = {
} & T;
export type SimpleObject = Record<string, any>;
export type Run<T extends SimpleObject = {}> = (ctx: Required<RouteContext<T>>) => Promise<typeof ctx | null | void>;
export type RunMessage = { path?: string; key?: string; id?: string; payload?: any; };
export type NextRoute = Pick<Route, 'id' | 'path' | 'key'>;
export type RouteMiddleware =
| {
@@ -262,17 +262,17 @@ export const toJSONSchema = (route: RouteInfo) => {
return pickValues;
}
export const fromJSONSchema = (route: RouteInfo): {
[key: string]: z.ZodTypeAny
} => {
const args = route?.metadata?.args || {};
export const fromJSONSchema = (route: RouteInfo): RouteInfo => {
const args = route?.metadata?.args;
if (!args) return route;
const keys = Object.keys(args);
const newArgs: { [key: string]: any } = {};
for (let key of keys) {
const item = args[key];
newArgs[key] = z.fromJSONSchema(item);
}
return newArgs;
route.metadata.args = newArgs;
return route;
}
/**
@@ -680,7 +680,7 @@ export class QueryRouter {
* -- .on
* -- .send
*/
wait(params?: { path?: string; key?: string; payload?: any }, opts?: {
wait(params?: { message: RunMessage }, opts?: {
mockProcess?: MockProcess,
timeout?: number,
getList?: boolean
@@ -693,8 +693,8 @@ export class QueryRouter {
}
return listenProcess({ app: this as any, params, ...opts });
}
static toJSONSchema = toJSONSchema;
static fromJSONSchema = fromJSONSchema;
toJSONSchema = toJSONSchema;
fromJSONSchema = fromJSONSchema;
}
type QueryRouterServerOpts = {

View File

@@ -1,25 +1,7 @@
import { fork } from 'child_process'
export type RunCodeParams = {
path?: string;
key?: string;
payload?: string;
[key: string]: any
}
type RunCode = {
// 调用进程的功能
success?: boolean
data?: {
// 调用router的结果
code?: number
data?: any
message?: string
[key: string]: any
};
error?: any
timestamp?: string
[key: string]: any
}
import { ListenProcessParams, ListenProcessResponse } from '@/utils/listen-process.ts';
export type RunCodeParams = ListenProcessParams
export type RunCode = ListenProcessResponse
export const runCode = async (tsPath: string, params: RunCodeParams = {}): Promise<RunCode> => {
return new Promise((resolve, reject) => {
// 使用 Bun 的 fork 模式启动子进程
@@ -52,8 +34,11 @@ import path from 'node:path'
const res = await runCode(path.join(process.cwd(), './src/test/mini.ts'), {
// path: 'main'
// id: 'abc'
message: {
path: 'router',
key: 'list'
}
})
console.log('res', res.data.data.list)
console.log('success', res)
console.log('res', res.data?.data?.list)

View File

@@ -1,7 +1,6 @@
import { App } from "../app.ts";
const app = new App({
io: true
});
app

View File

@@ -1,5 +1,6 @@
import { EventEmitter } from "eventemitter3";
import { QueryRouterServer } from "../route.ts"
import { QueryRouterServer, RouterContextT, RunMessage } from "../route.ts"
import { merge } from 'es-toolkit'
export class MockProcess {
emitter?: EventEmitter
process?: NodeJS.Process;
@@ -37,13 +38,31 @@ export class MockProcess {
this.process = undefined;
}
}
export type ListenProcessParams = {
message?: RunMessage,
context?: any
}
export type ListenProcessResponse = {
// 调用进程的功能
success?: boolean
data?: {
// 调用router的结果
code?: number
data?: any
message?: string
[key: string]: any
};
error?: any
timestamp?: string
[key: string]: any
}
export type ListenProcessOptions = {
app?: QueryRouterServer; // 传入的应用实例
mockProcess?: MockProcess; // 可选的事件发射器
params?: any; // 可选的参数
params?: ListenProcessParams; // 可选的参数
timeout?: number; // 可选的超时时间 (单位: 毫秒) 默认 10 分钟
};
export const listenProcess = async ({ app, mockProcess, params, timeout = 10 * 60 * 60 * 1000 }: ListenProcessOptions) => {
export const listenProcess = async ({ app, mockProcess, params = {}, timeout = 10 * 60 * 60 * 1000 }: ListenProcessOptions) => {
const process = mockProcess || new MockProcess();
let isEnd = false;
const timer = setTimeout(() => {
@@ -57,11 +76,11 @@ export const listenProcess = async ({ app, mockProcess, params, timeout = 10 * 6
// 监听来自主进程的消息
const getParams = async (): Promise<any> => {
return new Promise((resolve) => {
process.on((msg) => {
process.on((params) => {
if (isEnd) return;
isEnd = true;
clearTimeout(timer);
resolve(msg)
resolve(params || {})
})
})
}
@@ -70,11 +89,11 @@ export const listenProcess = async ({ app, mockProcess, params, timeout = 10 * 6
/**
* 如果不提供path默认是main
*/
const {
payload = {},
...rest
} = await getParams()
const msg = { ...params, ...rest, payload: { ...params?.payload, ...payload } }
const _params = await getParams()
const mergeParams = merge(params, _params)
const msg = mergeParams?.message || {};
const ctx: RouterContextT = mergeParams?.context || {}
/**
* 如果没有提供path和id默认取第一个路由, 而且路由path不是router的
*/
@@ -83,7 +102,7 @@ export const listenProcess = async ({ app, mockProcess, params, timeout = 10 * 6
msg.id = route?.id
}
// 执行主要逻辑
const result = await app.run(msg)
const result = await app.run(msg, ctx);
// 发送结果回主进程
const response = {
success: true,
@@ -95,6 +114,7 @@ export const listenProcess = async ({ app, mockProcess, params, timeout = 10 * 6
process.exit?.(0)
})
} catch (error) {
console.error('Error in listenProcess:', error);
process.send?.({
success: false,
error: error.message