mm_os
Version:
MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。
371 lines (333 loc) • 9.64 kB
JavaScript
const {
Drive
} = require('mm_machine');
const { idGen } = require('../../ulits/id_gen.js');
/**
* 控制器基类
* 负责处理请求和响应
*/
class Controller extends Drive {
static config = {
name: 'default',
// 依赖的处理器
ctrl_list: [],
timeout: 30000,
perf_log: false, // 是否记录性能日志
};
/**
* 构造函数
* @param {object} config 配置参数
* @param {object} parent 父对象
*/
constructor(config, parent) {
super({ ...Controller.config, ...config || {} }, parent);
// 模型实例集合
this._model = {};
// 服务实例集合
this._service = {};
// 视图实例集合
this._view = {};
}
}
/**
* 预设
*/
Controller.prototype._preset = function () {
// 响应格式缓存对象
this._response_cache = {
error: {
code: 0,
message: '',
},
result: null
};
// 统计信息
this._stats = {
request_count: 0,
all_time: 0
};
};
/**
* 获取模板目录
* @returns {string} 模板目录
*/
Controller.prototype.getTplDir = function () {
return __dirname;
};
/**
* 初始化核心
* @param {object} model 模型实例集合
* @param {object} service 服务实例集合
* @param {object} view 视图实例集合
* @param {object} eventer 事件总线
* @param {object} logger 日志管理器
*/
Controller.prototype._initCore = async function (model, service, view, eventer, logger) {
// 初始化依赖项
if (logger) {
this.setLogger(logger);
}
if (eventer) {
this.getEventer = function () {
return eventer;
};
}
if (model) this._model = model;
if (service) this._service = service;
if (view) this._view = view;
// 验证依赖项
this._checkDeps();
};
/**
* 验证依赖项
*/
Controller.prototype._checkDeps = function () {
var { models, services, views } = this.config;
for (let name of models) {
if (!this._model[name]) {
this.log('error', `model ${name} not found`);
}
}
for (let name of services) {
if (!this._service[name]) {
this.log('error', `service ${name} not found`);
}
}
for (let name of views) {
if (!this._view[name]) {
this.log('error', `view ${name} not found`);
}
}
};
/**
* 启动处理器
* @returns {Promise<void>}
* @throws {Error} 启动失败时抛出异常
*/
Controller.prototype._start = async function () {
// 记录启动日志
this.log('info', 'started');
};
/**
* 停止处理器
* @returns {Promise<void>}
* @throws {Error} 停止失败时抛出异常
*/
Controller.prototype._stop = async function () {
// 记录停止日志
this.log('info', 'stopped');
};
/**
* 销毁处理器
* @returns {Promise<void>}
* @throws {Error} 销毁失败时抛出异常
*/
Controller.prototype._destroy = async function () {
this._stats = {
request_count: 0,
all_time: 0
};
// 移除所有监听器
this.removeAllListeners();
};
/**
* 创建处理Promise
* @param {object} req 请求对象
* @param {object} res 响应对象
* @param {object} event_context 事件上下文
* @returns {Promise<object>} 处理结果Promise
*/
Controller.prototype._createRun = async function (req, res, event_context) {
// 请求预处理
await this._before(req, res);
// 触发主处理开始事件
this.emitEvent('request:before', event_context);
// 请求主处理逻辑
let result = await this.main(req, res);
const UPDATED_CONTEXT = {
...event_context,
result
};
// 触发主处理完成事件
this.emitEvent('request:after', UPDATED_CONTEXT);
// 请求后处理
await this._after(req, res, result);
return result;
};
/**
* 创建超时Promise
* @param {number} timeout 超时时间
* @returns {Promise<object>} 超时Promise
*/
Controller.prototype._createTimeout = function (timeout) {
return new Promise((resolve, reject) => {
this.log('debug', '创建超时控制Promise', { timeout, resolve, reject });
let timer = setTimeout(() => {
const timeoutError = new Error(`Request timeout after ${timeout}ms`);
timeoutError.code = 408;
reject(timeoutError);
}, timeout);
timer.unref(); // 防止定时器阻止进程退出
});
};
/**
* 处理性能统计
* @param {Array} start_time 开始时间
* @param {object} event_context 事件上下文
* @returns {object} 更新后的事件上下文
*/
Controller.prototype._runPerfStats = function (start_time, event_context) {
// 性能统计结束
let diff = process.hrtime(start_time);
const TIME_MS = diff[0] * 1000 + diff[1] / 1e6;
this._stats.all_time += TIME_MS;
// 创建更新的事件上下文
const UPDATED_CONTEXT = {
...event_context,
process_time: TIME_MS
};
// 记录性能日志(如果开启)
if (this.config.perf_log) {
this.log('info',
`request processed in ${TIME_MS.toFixed(2)}ms`
);
}
return UPDATED_CONTEXT;
};
/**
* 验证请求参数
* @param {object} req 请求对象
* @param {object} res 响应对象
*/
Controller.prototype._validateReq = function (req, res) {
if (!req || typeof req !== 'object') {
throw new TypeError('请求对象不能为空且必须是对象');
}
if (!res || typeof res !== 'object') {
throw new TypeError('响应对象不能为空且必须是对象');
}
};
/**
* 创建事件上下文
* @param {object} req 请求对象
* @param {object} res 响应对象
* @returns {object} 事件上下文
*/
Controller.prototype._createEventContext = function (req, res) {
return {
request_id: req.id || idGen.genId('req'),
hdl_name: this.config.name,
req,
res
};
};
/**
* 处理请求主方法
* @param {object} req 请求对象
* @param {object} res 响应对象
* @returns {Promise<object>} 处理结果
*/
Controller.prototype.run = async function (req, res) {
this._validateReq(req, res);
var event_context = this._createEventContext(req, res);
this.emitEvent('request:before', event_context);
var start_time = process.hrtime();
this._stats.request_count++;
try {
var result = await this._execWithTimeout(req, res, event_context);
var response = this._formatResponse(result);
event_context.response = response;
this.emitEvent('request:success', event_context);
return response;
} catch (error) {
event_context.error = error;
this.emitEvent('request:error', event_context);
this.log('error', 'handle error:', error);
return this._formatError(error);
} finally {
var final_context = this._runPerfStats(start_time, event_context);
this.emitEvent('request:after', final_context);
}
};
/**
* 执行带超时的处理
* @param {object} req 请求对象
* @param {object} res 响应对象
* @param {object} event_context 事件上下文
* @returns {Promise<object>} 处理结果
*/
Controller.prototype._execWithTimeout = async function (req, res, event_context) {
var timeout = this.config.timeout;
var hdl_promise = this._createRun(req, res, event_context);
if (timeout > 0) {
var timeout_promise = this._createTimeout(timeout);
return await Promise.race([hdl_promise, timeout_promise]);
}
return await hdl_promise;
};
/**
* 请求预处理方法
* @param {object} req 请求对象
* @param {object} res 响应对象
* @returns {Promise<void>}
*/
Controller.prototype._before = async function (req, res) {
this.log('debug', '请求预处理', { req, res });
};
/**
* 请求主处理逻辑
* 核心业务逻辑应该在此方法中实现
* @param {object} req 请求对象
* @param {object} res 响应对象
* @returns {Promise<object>} 处理结果
*/
Controller.prototype.main = async function (req, res) {
this.log('debug', '默认请求处理,子类应重写此方法', { req, res });
// 默认实现,子类必须重写
throw new Error('main method must be overridden');
};
/**
* 请求后处理方法
* @param {object} req 请求对象
* @param {object} res 响应对象
* @param {object} result 处理结果
* @returns {Promise<void>}
*/
Controller.prototype._after = async function (req, res, result) {
this.log('debug', '请求后处理', { req, res, result });
// 后处理请求,不触发额外事件
};
/**
* 格式化响应
* 优化:复用响应对象,减少GC压力
* @param {object} result 响应数据
* @returns {object} 格式化后的响应对象
*/
Controller.prototype._formatResponse = function (result) {
// 返回新对象,避免外部修改影响缓存
return $.ret.ret(result);
};
/**
* 格式化错误响应
* @param {object} error 错误对象
* @returns {object} 格式化后的错误响应
*/
Controller.prototype._formatError = function (error) {
// 快速错误处理,减少属性访问
let code = error && error.code || 500;
let message = error && error.message || 'Internal Server Error';
return $.ret.error(code, message);
};
/**
* 获取性能统计信息
* @returns {object} 性能统计数据
*/
Controller.prototype.getStats = function () {
return {
request_count: this._stats.request_count,
all_time: this._stats.all_time,
average_time: this._stats.request_count > 0 ?
this._stats.all_time / this._stats.request_count : 0
};
};
exports.Controller = Controller;