"""端到端验证任务池闭环:投递 → 发送完成移除 → 新消息重新投递。 覆盖用户核心诉求: 1. AI 回复成功(sent)后任务从队列移除 2. 对方发新消息 = 新 dedup_key → 重新投递新任务(不被 _recently 防抖挡住) 3. 同一消息不会被重复投递(防抖生效) 4. has_active_pending 对已移除任务返回 False → 允许新投递 """ import os import sys import time sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)) + "/..") from engine_b import DataEngine # noqa: E402 class FakeBot: """最小化 bot 桩:记录投递、模拟任务完成移除。""" def __init__(self): self.pending = {} # fp_hex -> state self.enqueued = [] self.removed = [] def has_active_pending(self, fp_hex): state = self.pending.get(fp_hex) if state is None: return False return str(state.get("stage") or "") not in { "sent", "cancelled", "expired", "cleared", } def enqueue_detected(self, fp_hex, dedup_key="", detected_by="engine_b", chat_text="", display_name="", last_lines=None): if fp_hex in self.pending and self.has_active_pending(fp_hex): return False, "已有活跃任务" self.pending[fp_hex] = { "stage": "queued", "dedup_key": dedup_key, "chat_text": chat_text, "display_name": display_name, } self.enqueued.append({ "fp_hex": fp_hex, "dedup_key": dedup_key, "chat_text": chat_text, "display_name": display_name, }) return True, "ok" def mark_sent_and_remove(self, fp_hex): """模拟发送成功 → 任务移除。""" self.pending.pop(fp_hex, None) self.removed.append(fp_hex) def run(): passed = 0 def check(name, cond): nonlocal passed if cond: passed += 1 print(f" [PASS] {name}") else: print(f" [FAIL] {name}") bot = FakeBot() eng = DataEngine.__new__(DataEngine) eng.bot = bot eng._recently = {} eng.processed_count = 0 eng.enqueued_count = 0 eng.last_error = "" fp = "ab" * 40 # 80 hex chars now = int(time.time()) print("== 场景1:新消息投递 ==") entry1 = { "display_name": "测试客户", "history": [{"content": "第一条", "ts": now - 300}], } last_user = entry1["history"][-1] eng._maybe_enqueue(fp, entry1, last_user) check("消息1 投递成功", len(bot.enqueued) == 1 and bot.enqueued[0]["chat_text"] == "第一条") check("任务已入队", bot.pending.get(fp, {}).get("stage") == "queued") print("== 场景2:同一消息重复轮询不重复投递(防抖) ==") eng._maybe_enqueue(fp, entry1, last_user) check("同 dedup_key 300s 内不重复投递", len(bot.enqueued) == 1) print("== 场景3:AI 回复成功 → 任务移除 ==") bot.mark_sent_and_remove(fp) check("发送成功任务被移除", fp not in bot.pending and fp in bot.removed) check("has_active_pending 返回 False", bot.has_active_pending(fp) is False) print("== 场景4:对方发新消息 → 重新投递新任务 ==") entry2 = { "display_name": "测试客户", "history": [ {"content": "第一条", "ts": now - 300}, {"content": "在吗", "ts": now - 60}, ], } last_user2 = entry2["history"][-1] eng._maybe_enqueue(fp, entry2, last_user2) check("新消息(新时间戳)重新投递", len(bot.enqueued) == 2) check("新任务入队", bot.pending.get(fp, {}).get("chat_text") == "在吗") check("新 dedup_key 不同", bot.enqueued[0]["dedup_key"] != bot.enqueued[1]["dedup_key"]) print("== 场景5:消息B在防抖窗口内第二次轮询不重复 ==") eng._maybe_enqueue(fp, entry2, last_user2) check("消息2 防抖生效", len(bot.enqueued) == 2) print("== 场景6:队列已有活跃任务时引擎B只补标记不重复投递 ==") # 场景4 后任务已入队(活跃),此时再检测到同一条消息不应重复投递 bot.enqueued_count_before = len(bot.enqueued) eng._maybe_enqueue(fp, entry2, last_user2) check("活跃任务存在时不重复投递", len(bot.enqueued) == 2) print(f"\n结果: {passed}/10 通过") return passed == 10 if __name__ == "__main__": ok = run() sys.exit(0 if ok else 1)