docs: 为全部代码补充中文注释并加入 AGENTS 注释规范

This commit is contained in:
cat-shark
2026-08-13 22:09:55 +08:00
parent 77e9ac6b7e
commit ac41a9a6da
29 changed files with 472 additions and 2 deletions
+51
View File
@@ -1,3 +1,9 @@
"""SQLite 数据访问层。
所有持久化逻辑集中在本模块,业务代码只依赖 Database 提供的方法。后续切换
PostgreSQL 时只需替换本层实现,不修改调度器与路由的业务逻辑。
"""
from __future__ import annotations
import json
@@ -10,15 +16,21 @@ from wov_sdk.models import NodeManifest
class Database:
"""SQLite 数据库封装:负责建表以及节点/实例/工作流/任务/产物的 CRUD。"""
def __init__(self, path: Path) -> None:
"""打开数据库并确保父目录存在、表结构已初始化。"""
self.path = path
self.path.parent.mkdir(parents=True, exist_ok=True)
self._init_schema()
@contextmanager
def _connect(self) -> Iterator[sqlite3.Connection]:
"""提供带事务提交的数据库连接上下文。"""
conn = sqlite3.connect(self.path)
# 按列名读取结果,返回 dict 更直观。
conn.row_factory = sqlite3.Row
# 开启外键约束,保证子表记录引用有效。
conn.execute("PRAGMA foreign_keys = ON")
try:
yield conn
@@ -27,9 +39,11 @@ class Database:
conn.close()
def _init_schema(self) -> None:
"""创建全部业务表;已存在的表保持不变。"""
with self._connect() as conn:
conn.executescript(
"""
-- 节点注册表:保存节点的最新 manifest JSON。
CREATE TABLE IF NOT EXISTS nodes (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
@@ -39,6 +53,7 @@ class Database:
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- 节点实例表:记录 NodeManager 启动的进程及其状态。
CREATE TABLE IF NOT EXISTS node_instances (
id TEXT PRIMARY KEY,
node_id TEXT NOT NULL,
@@ -52,6 +67,7 @@ class Database:
FOREIGN KEY(node_id) REFERENCES nodes(id)
);
-- 工作流表:只保存概要信息,完整定义存版本表。
CREATE TABLE IF NOT EXISTS workflows (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
@@ -61,6 +77,7 @@ class Database:
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- 工作流版本表:每个版本保存一份 DAG 定义 JSON。
CREATE TABLE IF NOT EXISTS workflow_versions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
workflow_id TEXT NOT NULL,
@@ -71,6 +88,7 @@ class Database:
FOREIGN KEY(workflow_id) REFERENCES workflows(id)
);
-- 工作流运行表:记录任务从排队到完成/失败的状态机。
CREATE TABLE IF NOT EXISTS workflow_runs (
id TEXT PRIMARY KEY,
workflow_id TEXT NOT NULL,
@@ -85,6 +103,7 @@ class Database:
FOREIGN KEY(workflow_id) REFERENCES workflows(id)
);
-- 产物表:记录每个任务各节点的输出 URI,按名称唯一。
CREATE TABLE IF NOT EXISTS artifacts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
run_id TEXT NOT NULL,
@@ -101,6 +120,7 @@ class Database:
)
def upsert_node(self, manifest: NodeManifest) -> None:
"""插入或更新节点注册记录,同名 ID 覆盖为新版本。"""
with self._connect() as conn:
conn.execute(
"""
@@ -122,6 +142,7 @@ class Database:
)
def get_node(self, node_id: str) -> NodeManifest | None:
"""按 ID 读取节点并反序列化为 NodeManifest。"""
with self._connect() as conn:
row = conn.execute("SELECT manifest_json FROM nodes WHERE id = ?", (node_id,)).fetchone()
if row is None:
@@ -129,16 +150,20 @@ class Database:
return NodeManifest.from_dict(json.loads(row["manifest_json"]))
def list_nodes(self) -> list[NodeManifest]:
"""按 ID 顺序返回全部注册节点。"""
with self._connect() as conn:
rows = conn.execute("SELECT manifest_json FROM nodes ORDER BY id").fetchall()
return [NodeManifest.from_dict(json.loads(row["manifest_json"])) for row in rows]
def delete_node(self, node_id: str) -> None:
"""删除节点及其全部实例记录。"""
with self._connect() as conn:
# 先删实例再删节点,满足外键约束。
conn.execute("DELETE FROM node_instances WHERE node_id = ?", (node_id,))
conn.execute("DELETE FROM nodes WHERE id = ?", (node_id,))
def upsert_instance(self, instance: dict[str, Any]) -> None:
"""插入或更新节点实例状态记录。"""
with self._connect() as conn:
conn.execute(
"""
@@ -170,6 +195,7 @@ class Database:
)
def list_instances(self) -> list[dict[str, Any]]:
"""按启动时间倒序返回全部节点实例。"""
with self._connect() as conn:
rows = conn.execute(
"SELECT * FROM node_instances ORDER BY started_at DESC"
@@ -177,10 +203,12 @@ class Database:
return [dict(row) for row in rows]
def delete_instance(self, instance_id: str) -> None:
"""删除指定实例记录。"""
with self._connect() as conn:
conn.execute("DELETE FROM node_instances WHERE id = ?", (instance_id,))
def upsert_workflow(self, workflow: dict[str, Any]) -> None:
"""插入或更新工作流概要信息。"""
with self._connect() as conn:
conn.execute(
"""
@@ -202,23 +230,28 @@ class Database:
)
def get_workflow(self, workflow_id: str) -> dict[str, Any] | None:
"""按 ID 读取工作流概要。"""
with self._connect() as conn:
row = conn.execute("SELECT * FROM workflows WHERE id = ?", (workflow_id,)).fetchone()
return dict(row) if row else None
def list_workflows(self) -> list[dict[str, Any]]:
"""按创建时间倒序返回全部工作流。"""
with self._connect() as conn:
rows = conn.execute("SELECT * FROM workflows ORDER BY created_at DESC").fetchall()
return [dict(row) for row in rows]
def delete_workflow(self, workflow_id: str) -> None:
"""级联删除工作流相关的产物、任务、版本和概要记录。"""
with self._connect() as conn:
# 外键没有级联删除配置,手动按依赖顺序清理。
conn.execute("DELETE FROM artifacts WHERE run_id IN (SELECT id FROM workflow_runs WHERE workflow_id = ?)", (workflow_id,))
conn.execute("DELETE FROM workflow_runs WHERE workflow_id = ?", (workflow_id,))
conn.execute("DELETE FROM workflow_versions WHERE workflow_id = ?", (workflow_id,))
conn.execute("DELETE FROM workflows WHERE id = ?", (workflow_id,))
def create_workflow_version(self, workflow_id: str, version: int, definition: dict[str, Any]) -> None:
"""为工作流新增一个版本,definition 以 JSON 保存。"""
with self._connect() as conn:
conn.execute(
"""
@@ -229,6 +262,7 @@ class Database:
)
def get_latest_workflow_version(self, workflow_id: str) -> dict[str, Any] | None:
"""返回工作流最新版本,并把 definition_json 反序列化为 definition。"""
with self._connect() as conn:
row = conn.execute(
"""
@@ -242,10 +276,12 @@ class Database:
if row is None:
return None
result = dict(row)
# 对外统一暴露 definition 字典,隐藏 JSON 存储细节。
result["definition"] = json.loads(result.pop("definition_json"))
return result
def get_workflow_version(self, workflow_id: str, version: int) -> dict[str, Any] | None:
"""按版本号读取指定工作流版本。"""
with self._connect() as conn:
row = conn.execute(
"""
@@ -261,6 +297,7 @@ class Database:
return result
def list_workflow_versions(self, workflow_id: str) -> list[dict[str, Any]]:
"""按版本倒序返回工作流全部版本。"""
with self._connect() as conn:
rows = conn.execute(
"""
@@ -278,6 +315,7 @@ class Database:
return versions
def create_run(self, run: dict[str, Any]) -> None:
"""创建一条排队中的工作流运行记录。"""
with self._connect() as conn:
conn.execute(
"""
@@ -302,11 +340,13 @@ class Database:
)
def get_run(self, run_id: str) -> dict[str, Any] | None:
"""按 ID 读取任务运行记录。"""
with self._connect() as conn:
row = conn.execute("SELECT * FROM workflow_runs WHERE id = ?", (run_id,)).fetchone()
return dict(row) if row else None
def list_runs(self, limit: int = 20) -> list[dict[str, Any]]:
"""按创建时间倒序返回最近的运行记录。"""
with self._connect() as conn:
rows = conn.execute(
"SELECT * FROM workflow_runs ORDER BY created_at DESC LIMIT ?",
@@ -315,6 +355,8 @@ class Database:
return [dict(row) for row in rows]
def update_run(self, run_id: str, **fields: Any) -> None:
"""更新运行状态字段,同时刷新 updated_at;未知字段会被忽略。"""
# 只允许更新状态机相关字段,防止任意列被改写。
allowed = {
"status",
"current_node_id",
@@ -325,13 +367,16 @@ class Database:
if not updates:
return
updates["updated_at"] = fields.get("updated_at")
# 动态拼接 SET 子句,键来自白名单,不存在 SQL 注入风险。
assignments = ", ".join(f"{key} = ?" for key in updates)
values = list(updates.values()) + [run_id]
with self._connect() as conn:
conn.execute(f"UPDATE workflow_runs SET {assignments} WHERE id = ?", values)
def reset_run(self, run_id: str, updated_at: str) -> None:
"""把失败任务重置为 QUEUED,并清空进度与旧产物,供重试使用。"""
with self._connect() as conn:
# 清空错误和进度,恢复到首次排队时的状态。
conn.execute(
"""
UPDATE workflow_runs
@@ -341,9 +386,11 @@ class Database:
""",
(updated_at, run_id),
)
# 删除旧产物,避免重试后残留过期下载链接。
conn.execute("DELETE FROM artifacts WHERE run_id = ?", (run_id,))
def next_queued_run(self) -> dict[str, Any] | None:
"""按创建时间返回最早一条排队任务,供调度器轮询。"""
with self._connect() as conn:
row = conn.execute(
"""
@@ -356,6 +403,7 @@ class Database:
return dict(row) if row else None
def create_artifact(self, artifact: dict[str, Any]) -> None:
"""记录任务产物;同 run 与 name 冲突时覆盖。"""
with self._connect() as conn:
conn.execute(
"""
@@ -375,6 +423,7 @@ class Database:
)
def list_artifacts(self, run_id: str) -> list[dict[str, Any]]:
"""按创建时间返回任务的全部产物。"""
with self._connect() as conn:
rows = conn.execute(
"SELECT * FROM artifacts WHERE run_id = ? ORDER BY created_at",
@@ -383,6 +432,7 @@ class Database:
return [dict(row) for row in rows]
def get_artifact(self, run_id: str, name: str) -> dict[str, Any] | None:
"""按任务与产物名读取单个产物记录。"""
with self._connect() as conn:
row = conn.execute(
"SELECT * FROM artifacts WHERE run_id = ? AND name = ?",
@@ -391,5 +441,6 @@ class Database:
return dict(row) if row else None
def delete_run_artifacts(self, run_id: str) -> None:
"""删除任务的全部产物记录。"""
with self._connect() as conn:
conn.execute("DELETE FROM artifacts WHERE run_id = ?", (run_id,))