Repository navigation
TSI-4327: fix(db): 修复跨父目录移动后投影仍留在旧位置 - #166
Conversation
|
Sorry @multica-tsic404[bot], you've used your own review budget of 250,000 diff characters for the last 7 days. You can request another review in 14 hours and 30 minutes by commenting |
Reviewer's GuideFix cross-parent metadata directory moves by updating the moved directory’s parent_id alongside its path, so data/ projections immediately disappear from the old parent and appear under the new parent while descendants and torrent contents remain intact. The PR adds database persistence tests and an acceptance test covering successful moves, missing-parent failures, root moves, and reopen behavior. Sequence diagram for cross-parent metadata directory movesequenceDiagram
participant Client
participant Database
participant MetadataDirectories
participant TorrentSources
Client->>Database: rename_metadata_directory(old_path, new_path, new_name)
Database->>MetadataDirectories: SELECT id WHERE path = parent_path
MetadataDirectories-->>Database: new_parent_id
Database->>MetadataDirectories: UPDATE name, path, parent_id
Database->>MetadataDirectories: UPDATE descendant paths
Database->>TorrentSources: UPDATE exact and prefixed source_path values
Database-->>Client: commit transaction
Entity relationship diagram for metadata directory reparentingerDiagram
metadata_directories {
INTEGER id PK
TEXT path
TEXT name
INTEGER parent_id FK
}
torrent_sources {
TEXT source_path
}
metadata_directories ||--o{ metadata_directories : parent_of
metadata_directories ||--o{ torrent_sources : projects
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
`data/` 投影按 `parent_id` 枚举目录的子项,而改名只更新了名称、路径与 来源路径。跨父目录移动后父链接仍指向旧父目录,子树无论重读多少次都留在 旧位置,重新挂载还会把它恢复到旧父目录下。 改名现在在同一事务内把父链接指向新父目录路径对应的行(移动到根目录时 置空)。旧位置立即不再列出该目录,新位置立即列出,重挂载后层级保持。
b456897 to
61e07b4
Compare
tsic404
left a comment
There was a problem hiding this comment.
审查摘要(APPROVED,零发现)
- 规模:L2 — 245 insertions / 9 deletions,5 文件 · 类型:Bug 修复(落库层父链接)
- 覆盖维度:代码质量 ✓ | 安全 ✓ | 架构 ✓ | 规范 ✓ | 性能 ✓ | 并发 ✓ | API 兼容 ✓ | 测试判别力 ✓ | Rust 专项 ✓
- 其他审查者反馈:无(
reviews为空,无 CHANGES_REQUESTED 需承接) - 无法锚定的发现:无
设计依据:tsic/torrentfs-design@5b622b6(等于 issue 冻结锚点 design_anchor)
核对结论
parent_id解析(src/infrastructure/db/metadata_ops.rs:85)覆盖两种边界:「移到根目录」→rsplit_once返回None→parent_id = NULL;「目标父目录不存在」→ 该分支在 DB 层取不到行时会落为None,但路径不可达:FsService::rename在进入服务层前按 inode 存在性返回ENOENT(src/fuse/fs_service.rs:1501-1505),验收用例失败面tests/acceptance/test_tc_ingest_04.rs:72-91断言ENOENT且两侧投影不变。- 与同一事务内
path前缀替换一致:父链接在步骤 1(:85)写入,前缀替换在步骤 2(:107);合法改名下被移动行在步骤 1 后已不匹配old_path/,两者不交叉;后代parent_id不变(标识不变),故metadata_directory_closure不重建的前提成立——该表全仓只有建表/索引与 INSERT,无 SELECT 读路径,无可观察影响。 ## 设计实现七行逐行对 diff:均有支撑(明细见 issue 评论的契约符合性核对表)。
点赞
- 父链接与
name/path同事务、同一条 UPDATE 写入,metadata_directories行自洽(path蕴含的父路径与parent_id一致);挂载恢复restore_metadata_inodes正是按parent_id建树(src/fuse/inodes.rs:415-419),因此修复同时堵住「重挂载回落旧父目录」。 rsplit_once('/')用None表达根级,不构造空路径再查库;.optional()?让 DB 错误上抛,未引入unwrap。- 两侧测试都能失败(作者已做反向验证):DB 测试断言旧父为空、新父单条、自身子项不变并重开库(
src/infrastructure/db/tests.rs:1512);验收测试同时压失败面与成功面,改名后立即读取,不靠 entry TTL 过期(readdir 快照键为total_changes,见src/fuse/lookup.rs:501)。
Closes TSI-4327
Issue: https://multica.tsic.top/issues/01a17488-d8e2-777d-b70d-11f5562588e3
设计依据
tsic/torrentfs-design@5b622b6
设计实现
src/infrastructure/db/metadata_ops.rs:85· 同一事务内按新路径的父路径解析metadata_directories.id,与name/path一并写入parent_id(移到根目录时置空)src/infrastructure/db/metadata_ops.rs:107· 前缀替换更新全部后代path(既有语句未改动,新测试覆盖其与新父链接的一致性)src/infrastructure/db/metadata_ops.rs:113·torrent_sources.source_path = old_path的整行更新(既有语句)src/infrastructure/db/metadata_ops.rs:119· 前缀替换更新子树来源路径(既有语句)metadata_directory_closure(落库语句只涉及metadata_directories与torrent_sources)tests/acceptance/test_tc_ingest_04.rs(tests/acceptance/main.rs:38,135注册);落库层回归src/infrastructure/db/tests.rs:1512data/接受变更操作metadata/改名落库、DB 测试与验收载体,data/无写入口)验证
cargo test全量(rebase 到main的20a627d之后,含新并入的 negative 载体):642 passed, 0 failed, 5 ignored。tc_ingest_04_cross_parent_move_swaps_both_projections在「the old location must stop listing the moved directory」失败;test_rename_metadata_directory_across_parents_reparents在「the old parent must no longer list the moved directory」失败。恢复修复后两者通过。get_source_path_prefixes按parent_id枚举子项,与内核缓存无关,故本修复不依赖另一个改名的缓存失效通道,两者可独立成立。main(20a627d),冲突仅在tests/acceptance/main.rs的模块/注册表插入点:两边的模块声明与LANDED条目全部保留(negative 01–04 + ingest-04)。