sdg
Version:
pomelo ts
303 lines • 22.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const node_schedule_1 = tslib_1.__importDefault(require("node-schedule"));
const sdg_loader_1 = require("sdg-loader");
const base_1 = tslib_1.__importDefault(require("../base"));
const handlerService_1 = tslib_1.__importDefault(require("../common/service/handlerService"));
const filterService_1 = tslib_1.__importDefault(require("../common/service/filterService"));
const events_1 = tslib_1.__importDefault(require("../util/events"));
const Constants = tslib_1.__importStar(require("../util/constants"));
const pathUtil_1 = require("../util/pathUtil");
const { INIT, STARTED, STOPPED } = Constants.STATE;
class Server extends base_1.default {
constructor(app, opts) {
super(app, opts);
this.cronHandlers = {};
this.crons = [];
this.cronConfigs = {};
this.jobs = {};
this.state = INIT;
this.cronConfigs = opts.cronConfigs || {};
app.event.on(events_1.default.ADD_CRONS, this.addCrons.bind(this));
app.event.on(events_1.default.REMOVE_CRONS, this.removeCrons.bind(this));
}
start() {
if (this.state > INIT)
return;
this.handlerService = this.initHandler();
this.globalFilterService = this.initFilter();
this.filterService = this.initFilter(false);
this.initCrons(true, true);
this.state = STARTED;
}
afterStart() { }
stop() {
this.state = STOPPED;
}
/**
* 初始化crons
* @param manualReload 是否替换
* @param clear 是否清空
*/
initCrons(manualReload = false, clear = false) {
if (manualReload) {
this.app.logger.debug('loadCrons remove crons', { crons: this.crons });
this.removeCrons(this.crons.map(c => c.id));
if (clear) {
this.crons = [];
}
}
this.cronHandlers = this.loadCronHandlers(manualReload);
this.loadCrons(manualReload);
if (manualReload) {
this.createSchedule(this.crons);
}
}
/**
* 获取所有定时器
*/
getCrons() {
return this.crons.map(c => {
return Object.assign(Object.assign({}, c), { active: !!this.jobs[c.id] });
});
}
async globalHandle(msg, session) {
const routeRecord = this.parseRoute(msg.__route__);
if (!routeRecord)
throw `invalid route ${msg.__route__}`;
let res;
const errorHandler = this.app.get(Constants.RESERVED.GLOBAL_ERROR_HANDLER);
try {
await this.beforeFilter(true, routeRecord, msg, session);
// 校验路由,如果是本服,直接handle
if (this.app.getServerType() === routeRecord.serverType) {
res = await this.doHandle(msg, session, routeRecord);
}
else {
// 非本地路由,交给sysRpc处理
res = await this.doForward(msg, session, routeRecord);
}
}
catch (err) {
if (errorHandler)
err = await errorHandler(err, msg, session);
throw err;
}
finally {
await this.afterFilter(true, routeRecord, msg, session);
}
return res;
}
async handle(msg, session) {
if (this.state !== STARTED)
throw 'server not started';
const routeRecord = this.parseRoute(msg.__route__);
if (!routeRecord)
throw `[${msg.__route__}] is invalid`;
return this.doHandle(msg, session, routeRecord);
}
async doHandle(msg, session, routeRecord) {
let res;
const errHandler = this.app.get(Constants.RESERVED.ERROR_HANDLER);
try {
await this.beforeFilter(false, routeRecord, msg, session);
res = await this.handlerService.handle(routeRecord, msg, session);
}
catch (e) {
if (errHandler)
e = await errHandler(e, msg, session);
throw e;
}
finally {
await this.afterFilter(false, routeRecord, msg, session);
}
return res;
}
async doForward(msg, session, routeRecord) {
return this.app.sysRpc[routeRecord.serverType].msgRemote.forwardMessage(session, msg, session.export());
}
initHandler() {
return new handlerService_1.default(this.app, this.opts);
}
initFilter(isGlobal = true) {
const app = this.app;
let service = new filterService_1.default();
let befores, afters;
if (isGlobal) {
befores = app.get(Constants.KEYWORDS.GLOBAL_BEFORE_FILTER);
afters = app.get(Constants.KEYWORDS.GLOBAL_AFTER_FILTER);
}
else {
befores = app.get(Constants.KEYWORDS.BEFORE_FILTER);
afters = app.get(Constants.KEYWORDS.AFTER_FILTER);
}
if (befores)
befores.map(i => service.addBefore(i));
if (afters)
afters.map(i => service.addAfter(i));
return service;
}
async beforeFilter(isGlobal, routeRecord, msg, session) {
const fm = isGlobal ? this.globalFilterService : this.filterService;
if (fm) {
await fm.beforeFilter(routeRecord, msg, session);
}
}
async afterFilter(isGlobal, routeRecord, msg, session) {
const fm = isGlobal ? this.globalFilterService : this.filterService;
if (fm) {
if (isGlobal) {
// 全局filter,延迟执行afterFilter,防止影响res;
process.nextTick(() => fm.afterFilter(routeRecord, msg, session).then());
}
else {
await fm.afterFilter(routeRecord, msg, session);
}
}
}
/**
* 加载定时器handler
* @param manualReload
*/
loadCronHandlers(manualReload = false) {
const app = this.app;
let all = {};
let p = pathUtil_1.getCronPath(app.getBase(), app.getServerType());
if (p) {
const cron = sdg_loader_1.load(p, app, manualReload);
for (let name in cron) {
all[name] = cron[name];
}
}
for (let plugin of app.usedPlugins) {
if (plugin.cronPath) {
const cron = sdg_loader_1.load(plugin.cronPath, app, manualReload);
for (let name in cron) {
all[name] = cron[name];
}
}
}
return all;
}
/**
* 根据配置加载定时器
* @param manualReload 是否替换旧的
*/
loadCrons(manualReload = false) {
const cronConfigs = this.cronConfigs;
if (!cronConfigs)
return;
const app = this.app;
for (let serverType in cronConfigs) {
if (app.serverType === serverType) {
for (const c of cronConfigs[serverType]) {
if (!c.serverId) {
this.checkAndAdd(c, manualReload);
}
else if (c.serverId === app.serverId) {
this.checkAndAdd(c, manualReload);
}
}
}
}
}
/**
* 增加定时器
* @param crons
*/
addCrons(crons) {
this.app.logger.debug('add crons', { crons });
const newCrons = [];
crons.forEach(c => {
const nc = this.checkAndAdd(c, true);
// 记录符合条件的cron
if (nc)
newCrons.push(nc);
});
// 移除已存在的cron
this.removeCrons(newCrons.map(n => n.id));
this.createSchedule(newCrons);
}
/**
* 检查并添加cron
* @param cron
* @param replace
*/
checkAndAdd(cron, replace = false) {
const oldCron = lodash_1.default.find(this.crons, { id: cron.id });
if (!oldCron) {
this.crons.push(cron);
return cron;
}
if (replace) {
this.app.logger.debug('replace cron:', { cron });
oldCron.time = cron.time;
oldCron.action = cron.action;
return oldCron;
}
return null;
}
/**
* 生成schedule
*/
createSchedule(crons) {
this.app.logger.debug('create new schedule', { crons });
for (const cron of crons) {
const { id, action, time } = cron;
const [name, method] = action.split('.');
const handler = this.cronHandlers[name];
if (!handler) {
this.app.logger.warn('could not find handler', { cron });
continue;
}
if (typeof handler[method] !== 'function') {
this.app.logger.warn('could not find cron job', { cron, method });
continue;
}
const args = cron.args || [];
// @ts-ignore
this.jobs[id] = node_schedule_1.default.scheduleJob(time, handler[method].bind(handler, ...args));
}
}
/**
* 移除现有的cron
* @param ids
*/
removeCrons(ids) {
if (!lodash_1.default.isArray(ids))
ids = [ids];
this.app.logger.debug('remove old schedule', { ids });
for (const id of ids) {
if (this.jobs[id]) {
node_schedule_1.default.cancelJob(this.jobs[id]);
delete this.jobs[id];
}
else {
this.app.logger.warn(`cron is not in application: ${id}`);
}
}
}
/**
* 解析路由
* @param route eg: gate.gateHandler.login
*/
parseRoute(route) {
if (!route)
return null;
const ts = route.split('.');
if (ts.length !== 3)
return null;
return {
route,
serverType: ts[0],
handler: ts[1],
method: ts[2]
};
}
;
}
exports.default = Server;
;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcnZlci9zZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNERBQXVCO0FBQ3ZCLDBFQUFxQztBQUNyQywyQ0FBa0M7QUFFbEMsMkRBQTJCO0FBRTNCLDhGQUE4RDtBQUM5RCw0RkFBNEQ7QUFDNUQsb0VBQXVDO0FBSXZDLHFFQUErQztBQUMvQywrQ0FBK0M7QUFFL0MsTUFBTSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQztBQUVuRCxNQUFxQixNQUFPLFNBQVEsY0FBSTtJQVN0QyxZQUFhLEdBQWdCLEVBQUUsSUFBb0I7UUFDakQsS0FBSyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQU5aLGlCQUFZLEdBQTRELEVBQUUsQ0FBQztRQUMzRSxVQUFLLEdBQVksRUFBRSxDQUFDO1FBQ3BCLGdCQUFXLEdBQWlCLEVBQUUsQ0FBQztRQUMvQixTQUFJLEdBQXVDLEVBQUUsQ0FBQztRQUluRCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQztRQUVsQixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLElBQUksRUFBRSxDQUFDO1FBQzFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLGdCQUFTLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDNUQsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsZ0JBQVMsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNwRSxDQUFDO0lBRU0sS0FBSztRQUNWLElBQUcsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJO1lBQUUsT0FBTztRQUU3QixJQUFJLENBQUMsY0FBYyxH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