实现进程间通信

This commit is contained in:
cool 2024-03-21 08:51:02 +08:00
parent 22b8e56fca
commit 5c17142969
6 changed files with 185 additions and 34 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@cool-midway/core", "name": "@cool-midway/core",
"version": "7.1.10", "version": "7.1.12",
"description": "", "description": "",
"main": "dist/index.js", "main": "dist/index.js",
"typings": "index.d.ts", "typings": "index.d.ts",
@ -56,6 +56,7 @@
"lodash": "^4.17.21", "lodash": "^4.17.21",
"md5": "^2.3.0", "md5": "^2.3.0",
"moment": "^2.30.1", "moment": "^2.30.1",
"pm2": "^5.3.1",
"sqlstring": "^2.3.3", "sqlstring": "^2.3.3",
"uuid": "^9.0.1", "uuid": "^9.0.1",
"ws": "^8.16.0" "ws": "^8.16.0"

View File

@ -45,12 +45,8 @@ export class CoolConfiguration implements ILifeCycle {
this.coolEventManager.emit("onReady"); this.coolEventManager.emit("onReady");
// 处理模块配置 // 处理模块配置
await container.getAsync(CoolModuleConfig); await container.getAsync(CoolModuleConfig);
// 导入模块数据
await container.getAsync(CoolModuleImport);
// 常用函数处理 // 常用函数处理
await container.getAsync(FuncUtil); await container.getAsync(FuncUtil);
// 事件
await container.getAsync(CoolEventManager);
// 异常处理 // 异常处理
this.app.useFilter([CoolExceptionFilter]); this.app.useFilter([CoolExceptionFilter]);
// 装饰器 // 装饰器
@ -71,6 +67,10 @@ export class CoolConfiguration implements ILifeCycle {
) {} ) {}
async onServerReady(container: IMidwayContainer) { async onServerReady(container: IMidwayContainer) {
// 事件
await (await container.getAsync(CoolEventManager)).init();
// 导入模块数据
(await container.getAsync(CoolModuleImport)).init();
// 实体与路径 // 实体与路径
const eps: CoolEps = await container.getAsync(CoolEps); const eps: CoolEps = await container.getAsync(CoolEps);
eps.init(); eps.init();

View File

@ -1,19 +1,31 @@
import { import {
Scope,
ScopeEnum,
saveClassMetadata, saveClassMetadata,
saveModule, saveModule,
attachClassMetadata, attachClassMetadata,
} from "@midwayjs/decorator"; } from "@midwayjs/decorator";
import { Scope, ScopeEnum } from "@midwayjs/core";
export const COOL_CLS_EVENT_KEY = "decorator:cool:cls:event"; export const COOL_CLS_EVENT_KEY = "decorator:cool:cls:event";
export function CoolEvent(): ClassDecorator { /**
*
*/
export interface CoolEventOptions {
/** 是否全局 */
isGlobal: boolean;
}
/**
*
* @param options
* @returns
*/
export function CoolEvent(options = {} as CoolEventOptions): ClassDecorator {
return (target: any) => { return (target: any) => {
// 将装饰的类,绑定到该装饰器,用于后续能获取到 class // 将装饰的类,绑定到该装饰器,用于后续能获取到 class
saveModule(COOL_CLS_EVENT_KEY, target); saveModule(COOL_CLS_EVENT_KEY, target);
// 保存一些元数据信息,任意你希望存的东西 // 保存一些元数据信息,任意你希望存的东西
saveClassMetadata(COOL_CLS_EVENT_KEY, {}, target); saveClassMetadata(COOL_CLS_EVENT_KEY, options, target);
// 指定 IoC 容器创建实例的作用域,这里注册为请求作用域,这样能取到 ctx // 指定 IoC 容器创建实例的作用域,这里注册为请求作用域,这样能取到 ctx
Scope(ScopeEnum.Singleton)(target); Scope(ScopeEnum.Singleton)(target);
}; };

View File

@ -1,15 +1,16 @@
import { import {
App, App,
getClassMetadata, getClassMetadata,
Init,
listModule, listModule,
Provide, Provide,
Scope,
ScopeEnum,
} from "@midwayjs/decorator"; } from "@midwayjs/decorator";
import * as Events from "events"; import * as Events from "events";
import { IMidwayApplication } from "@midwayjs/core"; import { Scope, ScopeEnum, IMidwayApplication, Config } from "@midwayjs/core";
import { COOL_CLS_EVENT_KEY, COOL_EVENT_KEY } from "../decorator/event"; import { COOL_CLS_EVENT_KEY, COOL_EVENT_KEY } from "../decorator/event";
import * as pm2 from "pm2";
import * as _ from "lodash";
export const COOL_EVENT_MESSAGE = "cool:event:message";
/** /**
* *
@ -20,24 +21,169 @@ export class CoolEventManager extends Events {
@App() @App()
app: IMidwayApplication; app: IMidwayApplication;
@Init() @Config("keys")
keys: string;
// 事件数据 某个事件对应的模块对应的方法
eventData = {} as {
[key: string]: {
module: any;
method: string;
}[];
};
/**
*
*/
async init() { async init() {
const eventModules = listModule(COOL_CLS_EVENT_KEY); const eventModules = listModule(COOL_CLS_EVENT_KEY);
for (const module of eventModules) { for (const module of eventModules) {
this.handlerEvent(module); await this.handlerEvent(module);
} }
await this.commEvent();
await this.globalEvent();
} }
/**
*
* @param event
* @param args
* @returns
*/
emit(event: string | symbol, ...args: any[]): boolean {
return super.emit(COOL_EVENT_MESSAGE, {
type: COOL_EVENT_MESSAGE,
data: {
event,
args,
},
});
}
/**
*
* @param event
* @param random
* @param args
* @returns
*/
async globalEmit(event: string, random: boolean = false, ...args) {
// 如果是本地运行还是转普通模式
if (this.app.getEnv() === "local") {
this.emit(event, ...args);
return;
}
pm2.connect(() => {
pm2.list((err, list) => {
const ps = list.map((e) => {
return {
id: e.pm_id,
name: e.name,
};
});
// random 为 true 时随机发给同名称的一个进程
if (random) {
// 按名称分组
const group = _.groupBy(ps, "name");
const names = Object.keys(group);
// 遍历名称
names.forEach((name) => {
const pss = group[name];
// 随机一个
const index = _.random(0, pss.length - 1);
const ps = pss[index];
// 发给这个进程
// @ts-ignore
pm2.sendDataToProcessId(
{
type: "process:msg",
data: {
type: `${COOL_EVENT_MESSAGE}@${this.keys}`,
event,
args,
},
id: ps.id,
topic: "cool:event:topic",
},
(err, res) => {}
);
});
} else {
// 发给所有进程
ps.forEach((e) => {
// @ts-ignore
pm2.sendDataToProcessId(
{
type: "process:msg",
data: {
type: `${COOL_EVENT_MESSAGE}@${this.keys}`,
event,
args,
},
id: e.id,
topic: "cool:event:topic",
},
(err, res) => {}
);
});
}
});
});
}
/**
*
* @param module
*/
async handlerEvent(module) { async handlerEvent(module) {
const events = getClassMetadata(COOL_EVENT_KEY, module); const events = getClassMetadata(COOL_EVENT_KEY, module);
for (const event of events) { for (const event of events) {
const method = event.eventName ? event.eventName : event.propertyKey; const listen = event.eventName ? event.eventName : event.propertyKey;
this.on(method, async (...args) => { if (!this.eventData[listen]) {
const moduleInstance = await this.app this.eventData[listen] = [];
.getApplicationContext() }
.getAsync(module); this.eventData[listen].push({
moduleInstance[event.propertyKey](...args); module,
method: event.propertyKey,
}); });
} }
} }
/**
*
*/
async globalEvent() {
process.on("message", async (message: any) => {
const data = message.data;
if (data.type != `${COOL_EVENT_MESSAGE}@${this.keys}`) return;
await this.doAction(message);
});
}
/**
*
*/
async commEvent() {
this.on(COOL_EVENT_MESSAGE, async (message: any) => {
await this.doAction(message);
});
}
/**
*
* @param message
*/
async doAction(message) {
const data = message.data;
const method = data.event;
const args = data.args;
if (this.eventData[method]) {
for (const event of this.eventData[method]) {
const moduleInstance = await this.app
.getApplicationContext()
.getAsync(event.module);
moduleInstance[event.method](...args);
}
}
}
} }

View File

@ -1,14 +1,5 @@
import { ILogger, IMidwayApplication } from "@midwayjs/core"; import { ILogger, IMidwayApplication } from "@midwayjs/core";
import { import { App, Config, Inject, Logger, Provide } from "@midwayjs/decorator";
App,
Config,
Init,
Inject,
Logger,
Provide,
Scope,
ScopeEnum,
} from "@midwayjs/decorator";
import * as fs from "fs"; import * as fs from "fs";
import { CoolModuleConfig } from "./config"; import { CoolModuleConfig } from "./config";
import * as path from "path"; import * as path from "path";
@ -17,6 +8,7 @@ import { DataSource } from "typeorm";
import { CoolEventManager } from "../event"; import { CoolEventManager } from "../event";
import { CoolModuleMenu } from "./menu"; import { CoolModuleMenu } from "./menu";
import * as _ from "lodash"; import * as _ from "lodash";
import { Scope, ScopeEnum } from "@midwayjs/core";
/** /**
* sql * sql
@ -51,7 +43,6 @@ export class CoolModuleImport {
@Inject() @Inject()
coolModuleMenu: CoolModuleMenu; coolModuleMenu: CoolModuleMenu;
@Init()
async init() { async init() {
// 是否需要导入 // 是否需要导入
if (this.coolConfig.initDB) { if (this.coolConfig.initDB) {

View File

@ -1,6 +1,6 @@
{ {
"name": "@cool-midway/core", "name": "@cool-midway/core",
"version": "7.1.10", "version": "7.1.12",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"typings": "index.d.ts", "typings": "index.d.ts",
@ -56,6 +56,7 @@
"moment": "^2.30.1", "moment": "^2.30.1",
"sqlstring": "^2.3.3", "sqlstring": "^2.3.3",
"uuid": "^9.0.1", "uuid": "^9.0.1",
"ws": "^8.16.0" "ws": "^8.16.0",
"pm2": "^5.3.1"
} }
} }