feat: 为每个action增加了一个after hook回调

用于实现监听网络中任意action的调用
pull/64/head
moonrailgun 2 years ago
parent fafb698784
commit 13134ce4e3

@ -7,13 +7,13 @@ import {
ServiceBroker,
ServiceDependency,
ServiceEvent,
ServiceEventHandler,
ServiceHooks,
ServiceSchema,
WaitForServicesResult,
} from 'moleculer';
import { once } from 'lodash';
import { TcDbService } from './mixins/db.mixin';
import type { TcContext, TcPureContext } from './types';
import type { PureContext, TcPureContext } from './types';
import type { TFunction } from 'i18next';
import { t } from './lib/i18n';
import type { ValidationRuleObject } from 'fastest-validator';
@ -62,6 +62,20 @@ type ServiceActionSchema = Pick<
disableSocket?: boolean;
};
/**
* AfterHook
*/
function generateAfterHookKey(actionName: string, serviceName = '') {
if (serviceName) {
return `${CONFIG_GATEWAY_AFTER_HOOK}.${serviceName}.${actionName}`.replaceAll(
'.',
'-'
);
} else {
return `${CONFIG_GATEWAY_AFTER_HOOK}.${actionName}`.replaceAll('.', '-');
}
}
interface TcServiceBroker extends ServiceBroker {
// 事件类型重写
emit<K extends string>(
@ -109,6 +123,7 @@ export abstract class TcService extends Service {
events: this._events,
started: this.onStart,
stopped: this.onStop,
hooks: this.buildHooks(),
});
}
@ -145,6 +160,33 @@ export abstract class TcService extends Service {
});
}
/**
* hooks
*/
protected buildHooks(): ServiceHooks {
return {
after: _.mapValues(this._actions, (action, name) => {
return (ctx: PureContext, res: unknown) => {
try {
const afterHooks =
this.globalConfig[generateAfterHookKey(name, this.serviceName)];
if (Array.isArray(afterHooks) && afterHooks.length > 0) {
for (const action of afterHooks) {
// 异步调用, 暂时不修改值
ctx.call(String(action), ctx.params, { meta: ctx.meta });
}
}
} catch (err) {
this.logger.error('Call action after hooks error:', err);
}
return res;
};
}),
};
}
registerMixin(mixin: Partial<ServiceSchema>): void {
this._mixins.push(mixin);
}
@ -298,10 +340,21 @@ export abstract class TcService extends Service {
});
}
async registryAfterActionHook(actionName: string, callbackAction: string) {
/**
* action
* @param fullActionName servicenameaction
* @param callbackAction actionservicename
*/
async registryAfterActionHook(
fullActionName: string,
callbackAction: string
) {
await this.waitForServices(['gateway', 'config']);
await this.broker.call('config.addToSet', {
key: `${CONFIG_GATEWAY_AFTER_HOOK}.${actionName}`,
key: `${CONFIG_GATEWAY_AFTER_HOOK}.${fullActionName}`.replaceAll(
'.',
'-'
),
value: `${this.serviceName}.${callbackAction}`,
});
}

@ -10,7 +10,6 @@ import {
parseLanguageFromHead,
builtinAuthWhitelist,
PureContext,
CONFIG_GATEWAY_AFTER_HOOK,
} from 'tailchat-server-sdk';
import { TcHealth } from '../../mixins/health.mixin';
import type { Readable } from 'stream';
@ -170,21 +169,8 @@ export default class ApiService extends TcService {
// Async function which return with Promise
res.setHeader('X-Node-ID', ctx.nodeID);
if (ctx.action.name) {
const afterHooks = this.getGlobalConfig(
`${CONFIG_GATEWAY_AFTER_HOOK}.${ctx.action.name}`
); // TODO: 这里actionName可能不对。需要调试
if (Array.isArray(afterHooks) && afterHooks.length > 0) {
for (const action of afterHooks) {
this.broker.call(String(action), {
route,
data,
});
}
}
}
if (data && data['__raw']) {
// 如果返回值有__raw, 则视为返回了html片段
if (data['header']) {
Object.entries(data['header']).forEach(([key, value]) => {
res.setHeader(key, String(value));

Loading…
Cancel
Save