UNPKG

mm_os

Version:

MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。

371 lines (333 loc) 9.64 kB
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;