# DHT 元数据搜索服务计划 本文档记录项目当前规划实施顺序和完成状态 它是随需求实现结果性能数据和部署条件持续调整的活文档 ## 维护规则 - 已经通过验收的任务使用 `[x]` 标记 - 正在规划但尚未完成的任务使用 `[ ]` 标记 - 需求变化时允许新增删除拆分合并或调整阶段顺序 - 调整计划时同步修改任务说明依赖关系和验收标准 - 不因代码已经存在就标记完成必须满足对应验收标准 - 发现原方案不合适时记录新决策并更新后续阶段 - 每次完成一个可交付功能时同步更新本文档 ## 当前技术方向 - `dht-crawler` 负责可复用的 DHT 协议节点发现 Peer 查找和 Metadata 下载 - `dht-search` 负责持久化去重索引搜索接口配置和运行生命周期 - RocksDB 保存权威数据去重信息和任务状态 - Tantivy 保存可以从 RocksDB 重建的搜索索引 - Axum 提供搜索详情统计和健康检查接口 - 所有长期任务通过有界队列和背压控制资源占用 如果实际运行证明 RocksDB 的构建部署或资源成本不合适可以重新评估 redb SQLite 或其他存储方案 ## 阶段零 项目基础 ### 目标 建立清晰的 workspace 边界开发规则和可持续验证的基础库 ### 任务 - [x] 将 workspace 扁平化为 `dht-crawler` 和 `dht-search` - [x] 使用当前 Git 配置统一作者仓库许可证和 edition 元数据 - [x] 编写 `AGENTS.md` 记录架构边界和开发约定 - [x] 将最终应用与可复用 DHT 基础库分离 - [x] 实现 BEP-51 `sample_infohashes` 主动发现 - [x] 实现主动 Peer 查找和 Metadata 获取 - [x] 验证远程公网设备能够持续获取 Metadata - [x] 确认 Xray 全局代理会影响 Metadata TCP 连接并完成旁路验证 - [x] 保持基础库测试通过 ### 验收标准 - [x] `cargo check --workspace --all-targets` 通过 - [x] `dht-crawler` 单元测试通过 - [x] `opencodes` 参考项目不参与 workspace 构建 ## 阶段一 本地持久化基础 ### 目标 建立跨重启保留的权威数据源并完成精确去重和内容聚合基础 ### 任务 - [x] 定义二十字节 `InfoHash` 类型和十六进制转换 - [x] 定义 `TorrentRecord` `TorrentFile` 和 `IndexState` - [x] 校验名称文件列表文件总大小和 infohash - [x] 使用 BLAKE3 计算版本化内容指纹 - [x] 规范化 Unicode 路径分隔符大小写和文件顺序 - [x] 保留真实子目录避免内容指纹碰撞 - [x] 定义版本化 RocksDB 二进制键空间 - [x] 实现数据库 schema 版本检查 - [x] 实现 infohash 精确查询和存在性判断 - [x] 实现新记录 WriteBatch 原子写入 - [x] 实现重复 infohash 的 `last_seen` `seen_count` 和 Peer 更新 - [x] 实现相同内容不同 infohash 的聚合映射 - [x] 实现待索引记录查询和索引完成标记 - [x] 配置 Bloom Filter LZ4 压缩和有限 block cache - [x] 准备 Windows 本地 RocksDB 构建所需的 libclang - [x] 将本地构建工具目录排除出 Git ### 验收标准 - [x] 数据库关闭并重新打开后记录仍可读取 - [x] 重复写入不会创建第二条 torrent 记录 - [x] 重复写入会正确增加发现次数 - [x] 相同内容的不同 infohash 可以独立保存并聚合查询 - [x] Metadata 主体内容映射和待索引标记原子写入 - [x] RocksDB 功能测试通过 - [x] `dht-search` Clippy `-D warnings` 通过 ## 阶段二 采集持久化闭环 ### 目标 让 DHT 获取的真实 Metadata 自动进入有界持久化管线并支持安全停止和重新启动 ### 任务 - [x] 定义应用配置结构和默认配置文件 - [x] 支持通过配置指定固定数据目录 - [x] 支持配置 DHT 端口并发队列容量和 Metadata 限制 - [x] 初始化 RocksDB repository 并处理启动错误 - [x] 将 `TorrentInfo` callback 转换为 `TorrentRecord` - [x] 建立有界持久化队列并实现背压 - [x] 使用专用阻塞任务执行 RocksDB 操作避免阻塞 Tokio worker - [x] 在 Metadata 下载前查询持久化 infohash 状态减少重复下载 - [x] 在 BEP-51 Peer Lookup 前批量查询 RocksDB 并更新已有 infohash 发现状态 - [x] 将已存在记录更新为再次发现而不是重复创建 - [x] 增加接收写入重复拒绝失败和队列深度指标 - [x] 实现 `Ctrl+C` `SIGINT` 和 `SIGTERM` 优雅退出 - [x] 退出时停止接收新任务并排空或持久化剩余任务 - [x] 支持重新启动后继续使用原数据库 - [x] 将 example 运行方式替换为正式 `dht-search` 二进制 - [x] 支持通过运行时长参数进行间歇运行 ### 验收标准 - [x] 本地运行可以持续向 RocksDB 写入真实 Metadata - [x] 停止并重启后旧 infohash 不会作为新记录重复写入 - [x] 队列达到容量时内存不继续无界增长 - [x] 正常退出后已接受的任务不会静默丢失 - [ ] 远程设备运行一小时没有持续内存增长 - [x] 记录采集速度重复率数据库增长和写入延迟 ## 阶段三 Tantivy 搜索索引 ### 目标 让持久化 Metadata 支持快速全文搜索过滤排序和索引恢复 ### 任务 - [x] 定义 Tantivy schema 和索引版本 - [x] 索引名称文件路径扩展名 infohash 和内容指纹 - [x] 将大小文件数时间和发现次数定义为 fast fields - [ ] 设计中英文数字和文件名 tokenizer - [x] 实现待索引任务批量消费 - [x] 实现按数量和时间间隔批量 commit - [x] commit 成功后原子更新 RocksDB 索引状态 - [x] 实现关键词短语和精确 infohash 查询 - [ ] 实现大小时间扩展名和文件数过滤 - [x] 实现大小范围和扩展名过滤 - [ ] 实现相关性时间热度和大小排序 - [x] 建立带时间衰减的 DHT 活跃度分数和用户可读等级 - [x] 实现分页并限制最大翻页成本 - [ ] 实现相同 `content_key` 结果折叠 - [x] 实现从 RocksDB 全量重建 Tantivy 索引 - [ ] 支持索引 schema 不兼容时安全重建 ### 验收标准 - [x] 新写入记录在目标延迟内可搜索 - [ ] 搜索索引删除后可以从 RocksDB 完整重建 - [x] 索引过程中异常退出不会永久丢失文档 - [ ] 百万级测试数据常用查询延迟达到约定目标 ## 阶段四 HTTP 搜索服务 ### 目标 提供稳定可验证并且资源受限的搜索和详情接口 ### 任务 - [x] 使用 Axum 建立 HTTP 服务 - [x] 实现 `/health` 和 `/ready` 接口 - [x] 实现 `/stats` 运行状态接口 - [x] 实现 `/search` 搜索过滤和分页接口 - [x] 实现 `/torrents/{infohash}` 详情接口 - [x] 定义统一错误响应 - [x] 限制查询长度分页大小和最大 offset - [ ] 增加请求延迟错误率和并发指标 - [x] 增加搜索详情字段和按需验证入队 API 端到端测试 - [ ] 增加其余 API 单元测试和端到端测试 ### 验收标准 - [x] API 能搜索真实采集数据 - [x] 非法参数返回稳定的客户端错误 - [x] 搜索查询在独立阻塞任务执行不会阻塞异步 worker - [x] 健康检查能区分进程存活和服务可用 ## 阶段五 质量过滤和重复内容控制 ### 目标 减少垃圾数据和重复展示同时避免不可恢复的误删 ### 任务 - [x] 将种子可用性定义为最近通过 DHT 找到并完成 BitTorrent 握手 - [x] 区分 Metadata 结构有效和 swarm 当前可用性 - [x] 实现未验证活跃和可能失效三态模型 - [x] 实现详情高优先级和搜索普通优先级的仅按需验证 - [x] 使用持久化有界验证队列租约恢复去重和失败退避 - [x] Metadata 与验证握手共享 TCP 建连总预算 - [x] RocksDB schema v1 到 v2 可恢复迁移并触发安全重建索引 - [x] 搜索和详情接口返回热度与可用性数据 - [x] `/stats` 返回验证队列发现握手成功失败和拒绝指标 - [ ] 统计真实数据的 infohash 重复率和内容重复率 - [ ] 定义可配置的名称路径扩展名和大小过滤规则 - [ ] 定义 Metadata 最大大小文件数和路径长度限制 - [ ] 识别空名称异常路径大小溢出和文件数量攻击 - [ ] 设计可解释的名称标准化规则 - [ ] 为模糊相似结果生成聚合候选但不自动删除 - [ ] 支持黑名单规则版本和命中原因 - [ ] 保留被过滤记录的计数指标但避免保存大内容 - [ ] 增加误判测试和边界数据集 ### 验收标准 - [x] 搜索和详情响应不等待 DHT 或 Peer 网络验证 - [x] 进程重启后已接受的验证任务能够通过租约恢复 - [x] 一次验证失败不会删除记录或标记为绝对失效 - [x] 旧数据库记录能够迁移并重新建立搜索文档 - [ ] 精确重复不会重复下载和重复展示 - [ ] 内容重复可以折叠并保留全部 infohash - [ ] 过滤规则可以配置更新和回滚 - [ ] 模糊去重不会直接造成数据丢失 ## 阶段六 性能资源和长期运行 ### 目标 以真实数据验证持续运行时的吞吐延迟磁盘放大和资源上限 ### 任务 - [x] 增加 `find_node` Peer Lookup 新目标和 Metadata 建连的显式配置 - [x] 为主动 `find_node` `get_peers` 和 `sample_infohashes` 增加共享 UDP 查询总预算 - [x] 为 Metadata TCP 建连增加独立每秒速率限制 - [x] 将桌面默认配置调整为保守网络预算 - [x] 根据本机首次验证将主动 UDP 从 `40/s` 下调至 `10/s` 并将 Metadata 建连从 `5/s` 下调至 `2/s` - [x] 验证极保守配置运行三分钟不影响同机代理网络并安全退出 - [x] 将 BEP-51 采样准入压力反向传递到采样查询调度 - [x] 实现样本来源节点单点 `get_peers` 优先和失败后有限递归降级 - [x] 完成首轮三分钟对比并验证 Peer Lookup UDP 从 `278` 降至 `254` 且网络稳定 - [ ] 通过多轮或更长时间运行评估随机 DHT 样本下的 Metadata 成功率 - [ ] 统计按需验证的 Peer 发现率握手成功率和平均验证耗时 - [x] 完成首轮真实按需验证并确认旧记录两次握手均成功更新为活跃 - [x] 验证新 Metadata 记录直接继承成功来源 Peer 的活跃状态 - [x] 验证启用按需可用性功能后保守预算运行三分钟并安全停止 - [ ] 根据真实验证数据校准热度权重等级边界和失败退避时间 - [ ] 根据公网设备长期实测设计超时率自动降速 - [ ] 建立采集存储索引和查询基准测试 - [ ] 记录每条元数据和每个索引文档的平均磁盘占用 - [ ] 记录 RocksDB block cache memtable 和 compaction 指标 - [ ] 记录 Tantivy IndexWriter 内存和 commit 延迟 - [ ] 根据实测调整批量大小队列容量和并发 - [ ] 增加磁盘剩余空间保护和只读降级策略 - [ ] 增加数据库备份检查点和恢复验证 - [ ] 增加日志轮转和保留策略 - [x] 验证间歇运行和正常退出恢复 - [ ] 验证二十四小时和七天连续运行 - [ ] 根据规模决定是否继续使用 RocksDB ### 验收标准 - [ ] 内存使用在目标上限内稳定 - [ ] 队列和缓存不会随运行时间无限增长 - [ ] 磁盘不足时能够安全停止写入 - [ ] 备份可以在独立目录恢复并搜索 - [ ] 连续运行期间没有数据格式损坏和不可恢复任务 ## 阶段七 部署和运维 ### 目标 让应用可以在公网 Linux 设备上重复构建部署监控停止和恢复 ### 任务 - [x] 固化 Linux 目标构建方式和 RocksDB 构建依赖 - [x] 生成 release 二进制并使用 SHA-256 校验部署 - [ ] 定义配置数据日志和索引目录布局 - [ ] 编写 systemd service - [ ] 编写 systemd timer 支持间歇运行 - [x] 使用专用低权限 UID 运行验证 - [x] 固化 Xray 环境下的最小范围网络旁路 - [x] 验证高并发运行需要 `LimitNOFILE=65536` - [ ] 实现启动前数据目录权限检查 - [ ] 实现优雅升级和回滚流程 - [ ] 编写备份恢复和故障排查文档 ### 验收标准 - [ ] 新设备可以按文档完成部署 - [ ] 服务重启不会丢失已提交数据 - [ ] Xray 旁路只影响爬虫进程 - [ ] 更新失败时可以恢复上一版本二进制和数据 ## 当前下一步 验证新可用性管线的真实运行数据并继续完善阶段三和阶段四 下一步运行更长时间的按需验证采样并实现时间文件数过滤排序策略和内容聚合展示