码桶

发现社区成员的开源项目

奶狗 /

ng-webot

公开
main
ng-webot/lib/msg-events.js
msg-events.js1.9 KB
/**
 * 消息处理事件缓冲(内存)
 * 用于前端实时查看消息处理流水线:收到消息 → AI 思考 → 发送成功/失败
 * 不持久化,服务重启后清空
 */
const MAX_EVENTS = 200;            // 每个 bot 最多保留
const MAX_TOTAL_EVENTS = 2000;    // 全局上限

/**
 * @typedef {{
 *   id: number,
 *   bot_id: number,
 *   ts: number,
 *   type: 'inbound'|'processing'|'outbound_ok'|'outbound_fail'|'error'|'system',
 *   msg: string,
 *   detail?: string
 * }} MsgEvent
 */

/** @type {MsgEvent[]} */
const events = [];
let nextId = 1;

/**
 * 添加事件(单次遍历,O(n) 复杂度)
 * @param {number} botId
 * @param {'inbound'|'processing'|'outbound_ok'|'outbound_fail'|'error'|'system'} type
 * @param {string} msg
 * @param {string} [detail]
 */
function push(botId, type, msg, detail = '') {
  const entry = { id: nextId++, bot_id: botId, ts: Date.now(), type, msg, detail };
  events.push(entry);

  // 单次遍历:统计各 bot 事件数并清理超出上限的旧事件(倒序遍历方便 splice)
  const botCounts = {};
  for (let i = events.length - 1; i >= 0; i--) {
    const bid = events[i].bot_id;
    botCounts[bid] = (botCounts[bid] || 0) + 1;
    if (botCounts[bid] > MAX_EVENTS) {
      events.splice(i, 1);
      botCounts[bid]--;
    }
  }

  // 全局上限
  while (events.length > MAX_TOTAL_EVENTS) events.shift();
}

/**
 * 查询 bot 最近的事件
 * @param {number} botId
 * @param {number} [sinceId]  增量获取:只返回 id > sinceId 的
 * @returns {{ events: MsgEvent[], total: number }}
 */
function list(botId, sinceId) {
  let list = events.filter(e => e.bot_id === botId);
  if (sinceId != null) list = list.filter(e => e.id > sinceId);
  return { events: list.slice(-MAX_EVENTS), total: events.filter(e => e.bot_id === botId).length };
}

module.exports = { push, list };