# 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] 删除被内容组索引替代的旧状态和无效兼容代码 - [x] 收紧仅供测试或存储内部使用的接口和依赖 - [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` 和内容组索引状态 - [x] 校验名称文件列表文件总大小和 infohash - [x] 使用 BLAKE3 计算规范化内容指纹 - [x] 规范化 Unicode 路径分隔符大小写和文件顺序 - [x] 保留真实子目录避免内容指纹碰撞 - [x] 定义 RocksDB 二进制键空间 - [x] 实现数据库格式检查 - [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 - [x] 设计中英文数字和文件名子串 tokenizer - [x] 实现待索引任务批量消费 - [x] 实现按数量和时间间隔批量 commit - [x] commit 成功后原子更新 RocksDB 索引状态 - [x] 实现关键词短语和精确 infohash 查询 - [x] 实现大小时间扩展名文件数热度和可用性过滤 - [x] 实现大小范围和扩展名过滤 - [x] 实现相关性时间热度大小和发现次数排序 - [x] 建立带时间衰减的 DHT 活跃度分数和用户可读等级 - [x] 实现分页并限制最大翻页成本 - [x] 实现相同 `content_key` 结果精确折叠和变体分页 - [x] 实现从 RocksDB 全量重建 Tantivy 索引 - [x] 支持索引结构不兼容时直接重建 ### 验收标准 - [x] 新写入记录在目标延迟内可搜索 - [x] 搜索索引删除后可以从 RocksDB 完整重建 - [x] 索引过程中异常退出不会永久丢失文档 - [x] 百万级测试数据常用查询延迟达到 `BENCHMARKS.md` 约定目标 ## 阶段四 HTTP 搜索服务 ### 目标 提供稳定可验证并且资源受限的搜索和详情接口 ### 任务 - [x] 使用 Axum 建立 HTTP 服务 - [x] 实现 `/health` 和 `/ready` 接口 - [x] 实现 `/stats` 运行状态接口 - [x] 实现 `/search` 搜索过滤和分页接口 - [x] 实现 `/torrents/{infohash}` 详情接口 - [x] 实现 `/contents/{content_key}` 内容变体接口 - [x] 使用 Bun Vue TypeScript Vite Tailwind CSS 和 shadcn-vue 建立 Web 基础环境 - [x] 实现简单现代并适配移动端的单页搜索界面 - [x] 接入搜索排序分页详情内容变体和磁力链接复制 - [x] 实现名称别名和文件路径的有限状态自动机正则搜索 - [x] 实现种子详情文件列表后端分页并限制浏览器单页节点数量 - [x] 保留种子详情顶部结构并使用 reka-ui 数字分页重构文件条目 - [x] 支持用户选择并持久化文件列表每页数量 - [x] 统一搜索结果数字分页并支持用户选择每页数量 - [x] 接入采集索引持久化和验证运行状态展示 - [x] 实现运行状态每秒刷新点击外部关闭和浏览器持久化明暗主题 - [x] 为加载空结果接口错误和失败重试提供明确界面状态 - [x] 将生产静态资源交给 Axum 提供并支持单页回退 - [x] 提供 Windows 一键启动后端和 Web 开发服务的脚本 - [x] 修复一键启动脚本只停止父进程导致 Vite 子进程残留的问题 - [x] 定义统一错误响应 - [x] 限制查询长度分页大小和最大 offset - [ ] 增加请求延迟错误率和并发指标 - [x] 增加搜索详情字段和按需验证入队 API 端到端测试 - [x] 增加搜索过滤折叠精确哈希和变体接口测试 ### 验收标准 - [x] API 能搜索真实采集数据 - [x] 非法参数返回稳定的客户端错误 - [x] 搜索查询在独立阻塞任务执行不会阻塞异步 worker - [x] 健康检查能区分进程存活和服务可用 ## 阶段五 质量过滤和重复内容控制 ### 目标 减少垃圾数据和重复展示同时避免不可恢复的误删 ### 任务 - [x] 将种子可用性定义为最近通过 DHT 找到并完成 BitTorrent 握手 - [x] 区分 Metadata 结构有效和 swarm 当前可用性 - [x] 实现未验证活跃和可能失效三态模型 - [x] 实现详情高优先级和搜索普通优先级的仅按需验证 - [x] 使用持久化有界验证队列租约恢复去重和失败退避 - [x] Metadata 与验证握手共享 TCP 建连总预算 - [x] 开发阶段清理测试数据库并以当前数据结构重新采集 - [x] 搜索和详情接口返回热度与可用性数据 - [x] `/stats` 返回验证队列发现握手成功失败和拒绝指标 - [ ] 统计真实数据的 infohash 重复率和内容重复率 - [ ] 定义可配置的名称路径扩展名和大小过滤规则 - [x] 定义可配置的 Metadata 最大大小文件数名称路径长度和目录层级限制 - [x] 识别空名称控制字符异常路径大小溢出总大小不一致和文件数量攻击 - [ ] 设计可解释的名称标准化规则 - [ ] 为模糊相似结果生成聚合候选但不自动删除 - [ ] 支持黑名单规则版本和命中原因 - [x] 使用带规则指纹的 RocksDB 轻量拒绝记录阻止相同异常 infohash 重复下载 - [x] 保留按原因分类的过滤指标但避免保存名称和大文件列表 - [ ] 增加误判测试和边界数据集 ### 验收标准 - [x] 搜索和详情响应不等待 DHT 或 Peer 网络验证 - [x] 进程重启后已接受的验证任务能够通过租约恢复 - [x] 一次验证失败不会删除记录或标记为绝对失效 - [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] 对照 Bitmagnet 默认并发将运行模板调整为受全局预算约束的高吞吐配置 - [x] 修复 Windows 临时索引文件占用导致整个服务退出的问题 - [x] 验证极保守配置运行三分钟不影响同机代理网络并安全退出 - [x] 将 BEP-51 采样准入压力反向传递到采样查询调度 - [x] 实现样本来源节点单点 `get_peers` 优先和失败后有限递归降级 - [x] 完成首轮三分钟对比并验证 Peer Lookup UDP 从 `278` 降至 `254` 且网络稳定 - [ ] 通过多轮或更长时间运行评估随机 DHT 样本下的 Metadata 成功率 - [ ] 统计按需验证的 Peer 发现率握手成功率和平均验证耗时 - [x] 完成首轮真实按需验证并确认旧记录两次握手均成功更新为活跃 - [x] 验证新 Metadata 记录直接继承成功来源 Peer 的活跃状态 - [x] 验证启用按需可用性功能后保守预算运行三分钟并安全停止 - [ ] 根据真实验证数据校准热度权重等级边界和失败退避时间 - [ ] 根据公网设备长期实测设计超时率自动降速 - [x] 建立可重复的采集存储索引和查询规模基准工具 - [x] 完成一万十万和一百万条 release 基线并记录查询 P50 P95 P99 - [x] 记录每条元数据和每个索引文档的平均磁盘占用 - [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 旁路只影响爬虫进程 - [ ] 更新失败时可以恢复上一版本二进制和数据 ## 当前下一步 使用真实采集数据进行一小时持续运行并记录内存队列磁盘网络和验证指标 随后扩展为二十四小时持续运行并根据数据决定资源参数和正则查询优化优先级