From a69110c834b3e3a979265e67c5e21899f5c3f425 Mon Sep 17 00:00:00 2001 From: cfdaily Date: Sun, 17 May 2026 05:51:41 +0800 Subject: [PATCH] auto-sync: 2026-05-17 05:51:41 --- src/daemon/ticker.py | 87 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 19 deletions(-) diff --git a/src/daemon/ticker.py b/src/daemon/ticker.py index ecdde30..92834e4 100644 --- a/src/daemon/ticker.py +++ b/src/daemon/ticker.py @@ -51,6 +51,9 @@ class Ticker: self._running: bool = False self._task: Optional[asyncio.Task] = None + # 已初始化的 db_path 集合,避免每次 tick 重复 init_db + self._initialized_dbs: set = set() + # 每个项目上次 tick 的 event count(用于僵尸检测 F8) self._last_event_counts: Dict[str, int] = {} @@ -155,7 +158,13 @@ class Ticker: if not db_path.exists(): return {"status": "no_db"} - queries = Queries(db_path) + # 只在首次遇到该 db_path 时执行 init_db + db_key = str(db_path) + if db_key not in self._initialized_dbs: + from src.blackboard.db import init_db + init_db(db_path) + self._initialized_dbs.add(db_key) + result: Dict[str, Any] = { "status": "ok", "summary_before": {}, @@ -164,18 +173,25 @@ class Ticker: } # 1. 扫描当前状态 + queries = Queries(db_path) result["summary_before"] = queries.task_summary() # 2. 依赖推进 advanced = self._advance_dependencies(db_path) result["advanced"] = advanced - # 3. 写 daemon_tick 事件 - bb = Blackboard(db_path) - bb.add_event( - event_type="daemon_tick", - detail={"tick": self._tick_count, "advanced_count": len(advanced)}, - ) + # 3. 写 daemon_tick 事件(直接用 get_connection,不再 Blackboard() → init_db) + conn = get_connection(db_path) + try: + conn.execute("BEGIN IMMEDIATE") + conn.execute( + "INSERT INTO events (task_id, agent, event_type, detail) VALUES (?,?,?,?)", + (None, "daemon", "daemon_tick", + json.dumps({"tick": self._tick_count, "advanced_count": len(advanced)})), + ) + conn.commit() + finally: + conn.close() # 4. 扫描后状态 result["summary_after"] = queries.task_summary() @@ -199,21 +215,54 @@ class Ticker: if not blocked: return advanced - bb = Blackboard(db_path) - for item in blocked: - if item["all_deps_done"]: - task_id = item["task_id"] - ok = bb.update_task_status( - task_id, "pending", - agent="daemon", - detail={"reason": "all_dependencies_done"}, - ) - if ok: - advanced.append(task_id) - logger.info("Advanced %s: blocked → pending", task_id) + conn = get_connection(db_path) + try: + for item in blocked: + if item["all_deps_done"]: + task_id = item["task_id"] + ok = self._transition_status(conn, task_id, "pending", + agent="daemon", + detail={"reason": "all_dependencies_done"}) + if ok: + advanced.append(task_id) + logger.info("Advanced %s: blocked → pending", task_id) + finally: + conn.close() return advanced + def _transition_status(self, conn, task_id: str, new_status: str, + agent: str = "daemon", + detail: Optional[Dict] = None) -> bool: + """轻量状态转换(不走 Blackboard 类,避免 init_db)""" + from src.blackboard.db import VALID_TRANSITIONS, TERMINAL_STATUSES, EVENT_TYPES + from datetime import datetime + + conn.execute("BEGIN IMMEDIATE") + row = conn.execute("SELECT status FROM tasks WHERE id=?", (task_id,)).fetchone() + if not row: + return False + old_status = row["status"] + if old_status in TERMINAL_STATUSES or old_status == new_status: + return old_status == new_status + if new_status not in VALID_TRANSITIONS.get(old_status, set()): + return False + + now = datetime.utcnow().isoformat() + conn.execute( + "UPDATE tasks SET status=?, updated_at=? WHERE id=?", + (new_status, now, task_id), + ) + event_type = f"task_{new_status}" + if event_type not in EVENT_TYPES: + event_type = "daemon_tick" + conn.execute( + "INSERT INTO events (task_id, agent, event_type, detail) VALUES (?,?,?,?)", + (task_id, agent, event_type, json.dumps({"from": old_status, "to": new_status, **(detail or {})})), + ) + conn.commit() + return True + # ------------------------------------------------------------------ # 手动 tick(API 端点触发) # ------------------------------------------------------------------