diff --git a/AGENTS.md b/AGENTS.md index 4368c9d..592145c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3639,4 +3639,134 @@ cargo test -p markbase-core --lib --features smb-server # ✅ 229 passed, 0 fai --- **最后更新**:2026-06-21 -**版本**:1.43(SMB Oplocks + Lease Complete) +**版本**:1.44(WebDAV Phase 22 全面改進完成) + +## Phase 22:WebDAV 全面改進完成(2026-06-21)⭐⭐⭐⭐⭐ + +**完成時間**:约 2 小时 +**新增代码量**:约 2100 行 +**Git commits**:6 commits (9acd174, 5000ba7, ab11983, 43c135e, 0322e2d) + +### 改進清單 ⭐⭐⭐⭐⭐ + +| 等級 | 任務 | 內容 | +|------|------|------| +| **P0 #1** | flush 失敗修復 | `flushed` flag + Drop warning + proper error logging | +| **P0 #2** | RwLock 中毒修復 | `try_read/try_write` recovery | +| **P0 #3** | 過期鎖清理 | `cleanup_expired_locks()` + `is_expired()` | +| **P1 #4** | Props VFS 持久化 | `load_props/save_props/patch_props` via VFS | +| **P1 #5** | COPY/MOVE props | dead props sync on copy/rename | +| **P1 #6** | 原子 set_times | `set_atime/set_mtime` + `filetime` crate | +| **P2 #7** | Async props | `tokio::spawn_blocking` for persistence | +| **P2 #8** | Cache TTL | `CachedHandler` + 300s TTL eviction | +| **P3 #9** | MKCOL 405 | `vfs.exists()` check before create | +| **額外** | Dead props 清理 | filter empty entries before persisting | +| **額外** | Metadata 改進 | `accessed()` + `executable()` + `mode` field | +| **額外** | Error handling | `map_vfs_error()` helper | + +### 新增文件 ⭐⭐⭐⭐⭐ + +``` +markbase-core/src/webdav_locks.rs (新增 310 行) +├── PersistedLs (DavLockSystem 实现) +├── is_expired() + cleanup_expired_locks() +└── paths_overlap() 冲突检测 +``` + +### 修改文件 ⭐⭐⭐⭐⭐ + +``` +markbase-core/src/webdav.rs (~1500 行) +├── VfsDavFile::flush() 四阶段重构 +├── props_data RwLock error recovery +├── VfsDavMetaData: accessed/executable/mode +├── map_vfs_error() helper +└── patch_props: spawn_blocking + +markbase-core/src/server.rs (~2600 行) +├── CachedHandler struct + Instant timestamp +├── WEBDAV_CACHE_TTL_SECS = 300 +└── create_handler_for_user() helper + +markbase-core/src/vfs/mod.rs (+15 行) +├── set_atime() + set_mtime() trait methods + +markbase-core/src/vfs/local_fs.rs (+40 行) +├── filetime::set_file_atime() + set_file_mtime() +``` + +### 測試結果 ⭐⭐⭐⭐⭐ + +```bash +cargo test -p markbase-core --lib # 288 passed, 0 failed +``` + +### 未完成(架構性)⭐⭐⭐ + +| 任務 | 原因 | +|------|------| +| **P3 #10** Async VfsFile | 需要 VfsBackend trait 改為 async | + +--- + +## Phase 21:WebDAV 改进完成(2026-06-21)⭐⭐⭐⭐⭐ + +**完成時間**:约 3 小时 +**新增代码量**:约 200 行(tests)+ 重构 + +### 实施内容 ⭐⭐⭐⭐⭐ + +| P2 | 功能 | 状态 | +|----|------|------| +| **#2** | flush 四階段重構 | ✅ 完成 | +| **#3** | write_buf/write_bytes 緩衝 | ✅ 完成 | +| **#4** | Dead prop XML 持久化 | ✅ 完成 | +| **#5** | Version index 持久化 | ✅ 完成 | +| **#6** | Lock 持久化 | ✅ 完成 | +| **#7** | Quota property | ✅ 完成 | +| **#9** | Integration tests | ✅ 完成 | +| **#8** | ACL property | ✅ 完成(Phase 22)| +| **#11** | DavHandler caching | ✅ 完成(Phase 22)| + +### 關鍵實現 ⭐⭐⭐⭐⭐ + +**PersistedLs**(`webdav_locks.rs`,310 行): +- 基於 flat Vec 的 `DavLockSystem` 實現 +- 鎖狀態持久化到 `/.webdav_locks/.json` +- 支援 exclusive/shared/deep lock 衝突檢測(`paths_overlap()`) +- 使用 `uuid` crate 生成鎖令牌 + +**flush 四階段**(`VfsDavFile::flush()`): +1. Flush storage(`vfs_file` 或 `data` 寫入 VFS) +2. 從 `self.data` buffer 創建版本(無需磁碟 I/O) +3. 清空 `self.data` +4. 觸發 upload hook + +**Integration tests**(6 個 async tests): +- `test_put_get_roundtrip`:PUT + GET 驗證內容 +- `test_propfind`:PROPFIND 驗證 XML 列表 +- `test_mkcol_delete`:MKCOL 創建目錄 + DELETE 刪除 +- `test_copy_move`:COPY + MOVE 文件 +- `test_lock_unlock`:LOCK(exclusive write)+ UNLOCK 驗證 Lock-Token header +- `test_etag_header`:GET 驗證 ETag header 存在 + +### 相關文件 ⭐⭐⭐⭐⭐ + +``` +markbase-core/src/ +├── webdav.rs(1088 行)— 主要 WebDAV 實現(VfsDavFs + VfsDavFile + VfsDavMetaData) +│ ├── flush() 四階段重構 +│ ├── have_props() + get_quota() 新增 +│ └── integration_tests 模組(6 個 async tests) +├── webdav_locks.rs(310 行)— PersistedLs(NEW) +├── webdav_version.rs(410 行)— Version index 持久化重構 +├── server.rs — create_webdav_handler_persisted() 使用 PersistedLs +└── lib.rs — 新增 pub mod webdav_locks +``` + +### 需繼續的功能 ⭐⭐⭐ + +| 功能 | 位置 | 工作量 | 優先級 | +|------|------|--------|--------| +| **ACL property** | webdav.rs: `VfsDavFs::get_property()` 或 `VfsDavMetaData` | 2 小時 | P2 | +| **DavHandler 快取** | server.rs: 按 `(root, user_uuid)` 快取 | 1 小時 | P2 |