实现进程间通信

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",
"version": "7.1.10",
"version": "7.1.12",
"description": "",
"main": "dist/index.js",
"typings": "index.d.ts",
@ -56,6 +56,7 @@
"lodash": "^4.17.21",
"md5": "^2.3.0",
"moment": "^2.30.1",
"pm2": "^5.3.1",
"sqlstring": "^2.3.3",
"uuid": "^9.0.1",
"ws": "^8.16.0"

View File

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

View File

@ -1,19 +1,31 @@
import {
Scope,
ScopeEnum,
saveClassMetadata,
saveModule,
attachClassMetadata,
} from "@midwayjs/decorator";
import { Scope, ScopeEnum } from "@midwayjs/core";
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) => {
// 将装饰的类,绑定到该装饰器,用于后续能获取到 class
saveModule(COOL_CLS_EVENT_KEY, target);
// 保存一些元数据信息,任意你希望存的东西
saveClassMetadata(COOL_CLS_EVENT_KEY, {}, target);
saveClassMetadata(COOL_CLS_EVENT_KEY, options, target);
// 指定 IoC 容器创建实例的作用域,这里注册为请求作用域,这样能取到 ctx
Scope(ScopeEnum.Singleton)(target);
};

View File

@ -1,15 +1,16 @@
import {
App,
getClassMetadata,
Init,
listModule,
Provide,
Scope,
ScopeEnum,
} from "@midwayjs/decorator";
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 * 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: IMidwayApplication;
@Init()
@Config("keys")
keys: string;
// 事件数据 某个事件对应的模块对应的方法
eventData = {} as {
[key: string]: {
module: any;
method: string;
}[];
};
/**
*
*/
async init() {
const eventModules = listModule(COOL_CLS_EVENT_KEY);
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) {
const events = getClassMetadata(COOL_EVENT_KEY, module);
for (const event of events) {
const method = event.eventName ? event.eventName : event.propertyKey;
this.on(method, async (...args) => {
const moduleInstance = await this.app
.getApplicationContext()
.getAsync(module);
moduleInstance[event.propertyKey](...args);
const listen = event.eventName ? event.eventName : event.propertyKey;
if (!this.eventData[listen]) {
this.eventData[listen] = [];
}
this.eventData[listen].push({
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 {
App,
Config,
Init,
Inject,
Logger,
Provide,
Scope,
ScopeEnum,
} from "@midwayjs/decorator";
import { App, Config, Inject, Logger, Provide } from "@midwayjs/decorator";
import * as fs from "fs";
import { CoolModuleConfig } from "./config";
import * as path from "path";
@ -17,6 +8,7 @@ import { DataSource } from "typeorm";
import { CoolEventManager } from "../event";
import { CoolModuleMenu } from "./menu";
import * as _ from "lodash";
import { Scope, ScopeEnum } from "@midwayjs/core";
/**
* sql
@ -51,7 +43,6 @@ export class CoolModuleImport {
@Inject()
coolModuleMenu: CoolModuleMenu;
@Init()
async init() {
// 是否需要导入
if (this.coolConfig.initDB) {

View File

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