Files
dht/AGENTS.md
2026-08-10 19:34:30 +08:00

6.0 KiB

DHT 元数据搜索服务开发约定

项目目标

本项目用于持续或间歇地从 BitTorrent DHT 网络发现 infohash 获取元数据并提供本地全文搜索和高性能过滤能力

基础 DHT 协议和抓取能力保留在 src/crawler

面向最终用户运行的服务代码统一放在 src/search

Web 前端代码统一放在 src/web

技术方案

  • Tokio 负责异步任务调度网络任务和有界队列
  • RocksDB 负责权威数据持久化精确去重抓取状态和索引状态
  • Tantivy 负责可重建的全文搜索过滤排序和结果聚合
  • Axum 负责 HTTP 搜索接口详情接口和运行状态接口
  • BLAKE3 负责计算规范化内容结构指纹
  • Serde 负责配置领域对象和接口数据的序列化
  • Tracing 负责结构化日志和故障定位
  • SQLite 负责有保留上限的运行诊断历史且不得成为业务权威数据源

RocksDB 是唯一权威数据源

Tantivy 索引必须能够从 RocksDB 完整重建

数据处理流程

  1. DHT 采集器发现 infohash
  2. 内存近期缓存过滤高频重复
  3. RocksDB 精确判断 infohash 是否已处理
  4. 未处理的 infohash 进入有界 Metadata 下载队列
  5. Metadata 完成校验和规范化后计算内容指纹
  6. 使用 RocksDB WriteBatch 原子保存元数据去重映射和待索引状态
  7. 后台索引任务批量写入 Tantivy
  8. Tantivy 提交成功后将记录状态更新为已索引
  9. Axum 只通过搜索和存储抽象读取数据

所有任务队列必须有明确容量并在队列满时产生背压

禁止通过无限队列维持表面吞吐

去重规则

第一层以 infohash 做精确去重并阻止相同 Metadata 被重复下载

第二层根据规范化文件路径和文件大小计算 content key 将不同 infohash 的相同内容聚合展示

模糊名称相似度只用于搜索结果聚合不得直接删除数据

Bloom Filter 只能作为前置加速结构不得作为最终去重依据

再次发现已有 infohash 时只更新最后发现时间和发现次数

持久化和恢复

程序必须支持间歇运行和跨重启恢复

正常关闭时先停止接收新任务再排空或持久化队列最后提交搜索索引

异常退出后依靠 RocksDB WAL 恢复已提交数据

每条搜索文档必须具有待索引和已索引状态以便启动后补建索引

内存队列不得成为任何权威状态的唯一保存位置

数据目录必须通过配置指定且不得依赖当前工作目录

代码边界

  • crawler 只负责协调 DHT 事件和 Metadata 下载
  • domain 只定义领域模型规范化规则和内容指纹
  • storage 只负责 RocksDB 数据布局原子写入查询和恢复
  • search 只负责 Tantivy schema 文档转换索引和查询
  • api 只负责 HTTP 协议参数校验和响应转换
  • config 只负责读取校验和暴露配置
  • diagnostics 只负责采集聚合和查询可删除的运行指标历史
  • telemetry 只负责日志指标和运行观测
  • shutdown 只负责关闭信号和优雅退出协调

模块之间通过明确的数据结构和 trait 通信不得跨层直接访问内部实现

配置文件只是配置 DTO 的持久化适配器

用户配置 DTO 运行时解析结果和配置存储实现必须保持独立边界

配置更新必须先完整校验再通过同目录临时文件同步和原子替换保存

配置接口必须使用修订号阻止并发请求静默覆盖且不得假装未实际支持的在线热更新

领域层不得直接依赖 dht-crawler 的回调或传输 DTO

组合和文件边界

  • trait 只用于存储搜索网络回调等真实替换边界 不创建只有一个调用方的抽象基类或通用 Service 层
  • 应用入口只负责构造依赖启动任务选择退出原因和按顺序关闭 不承载 worker 循环和指标格式化
  • 每个长期任务独立拥有状态和取消令牌 通过明确句柄组合 不共享可变全局状态
  • 领域文件按 infohash Metadata 接纳内容聚合和种子状态演进划分 不按接口页面或数据库字段重复定义模型
  • 搜索 schema 查询条件文档映射索引执行分别维护 Tantivy 细节不得泄漏到 API 层
  • 基准和工具代码同样遵守职责拆分 不因不进入主服务而集中到单个大文件
  • 文件长度不是机械拆分标准 单一状态机或单一 adapter 可以集中维护 强拆会产生私有状态穿透时应保持内聚
  • 删除没有调用方的预留模块 新扩展在产生真实行为时再创建文件

测试分层位置默认验证命令和依赖规则统一记录在根目录 README.md

资源约束

  • Metadata 下载并发必须可配置
  • 单个 Metadata 大小文件数量和路径长度必须有限制
  • RocksDB 写入使用批处理并明确控制 block cache
  • Tantivy 写入使用批量提交并明确控制 IndexWriter 内存预算
  • 日志不得输出完整 Metadata 或大文件列表
  • 长期运行的集合必须有容量上限过期规则或磁盘持久化方案
  • 诊断历史必须使用独立 SQLite 数据库并通过采样降级和保留策略限制增长

开发规则

新业务代码写入 src/search

项目阶段任务完成状态和验收标准统一维护在根目录 TODOS.md

需求实现或技术决策发生变化时必须同步更新 TODOS.md

src/crawler 只接受可复用的 DHT 基础能力不得包含数据库搜索接口或部署逻辑

每个 Rust 文件顶部必须使用中文行注释描述该文件的功能边界且注释行尾不添加标点

新增行为必须包含与风险相称的测试

开发阶段修改持久化 key 或编码格式时经用户明确授权可以清理测试数据重新开始 正式格式冻结后必须提供兼容或迁移方案

不得把 opencodes 下的参考项目纳入 workspace 或修改其内容

构建准备

应用骨架默认不启用 RocksDB 原生构建

实现存储层时通过 rocksdb-storage feature 启用 RocksDB

Windows 构建 RocksDB 前需要安装 LLVM 并确保 LIBCLANG_PATH 指向包含 libclang.dll 的目录

启用后的检查命令为 cargo check -p dht-search --features rocksdb-storage