mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-07-22 06:56:44 +08:00
fix(cas): exists 返回 Result 以区分不存在与存储故障
CasRepository::exists(core trait)与底层 Storage::exists 原返回裸 bool, FileSystemStorage 用 try_exists(...).unwrap_or(false)、infra 适配层吞掉解析/ 初始化错误返回 false,调用方无法区分“对象不存在”和权限/IO/初始化故障。 将整条链改为 Result<bool>: - storage trait 与 FileSystemStorage:try_exists 的 IO 错误经 ? 传播; - repository FileSystemCasRepository::exists 及 store/add_reference 内部调用; - core CasRepository::exists trait; - infra 适配层:解析失败→InvalidArgument、初始化/引擎错误经 map_error 传播。 Ok(false) 仅表示确实不存在。 新增单测:合法但不存在的对象返回 Ok(false),非法 ObjectId 返回 Err(而非静默 false);同步更新各层 exists 断言。 对应 issue #18 维护清单 2-1。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -92,14 +92,13 @@ impl CasRepository for FileSystemCasRepository {
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
async fn exists(&self, id: &ObjectId) -> bool {
|
||||
let Ok(hash) = Self::parse_object_id(id) else {
|
||||
return false;
|
||||
};
|
||||
let Ok(engine) = self.engine().await else {
|
||||
return false;
|
||||
};
|
||||
engine.exists(&hash).await
|
||||
async fn exists(&self, id: &ObjectId) -> bat_core::Result<bool> {
|
||||
let hash = Self::parse_object_id(id)?;
|
||||
self.engine()
|
||||
.await?
|
||||
.exists(&hash)
|
||||
.await
|
||||
.map_err(Self::map_error)
|
||||
}
|
||||
|
||||
async fn add_reference(&self, id: &ObjectId) -> bat_core::Result<u64> {
|
||||
@@ -176,7 +175,7 @@ mod tests {
|
||||
assert_eq!(repo.remove_reference(&id).await.unwrap(), 0);
|
||||
assert_eq!(repo.gc().await.unwrap(), 1);
|
||||
|
||||
assert!(!repo.exists(&id).await);
|
||||
assert!(!repo.exists(&id).await.unwrap());
|
||||
let missing = repo.get(&id).await;
|
||||
assert!(matches!(missing, Err(bat_core::Error::NotFound(_))));
|
||||
}
|
||||
@@ -191,6 +190,23 @@ mod tests {
|
||||
assert!(matches!(error, bat_core::Error::InvalidArgument(_)));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn exists_distinguishes_missing_from_invalid_id() {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
let repo = FileSystemCasRepository::new(temp_dir.path());
|
||||
repo.init().await.unwrap();
|
||||
|
||||
// 合法但不存在的对象:Ok(false),而非静默错误。
|
||||
let absent = repo.store(b"absent-seed").await.unwrap();
|
||||
repo.remove_reference(&absent).await.unwrap();
|
||||
repo.gc().await.unwrap();
|
||||
assert!(!repo.exists(&absent).await.unwrap());
|
||||
|
||||
// 非法 ObjectId:返回 Err 而非 Ok(false),让调用方能区分故障。
|
||||
let error = repo.exists(&"not-a-hash".to_string()).await.unwrap_err();
|
||||
assert!(matches!(error, bat_core::Error::InvalidArgument(_)));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn store_returns_blake3_hex_object_id() {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
|
||||
@@ -576,7 +576,7 @@ mod tests {
|
||||
|
||||
assert_eq!(report.imported.len(), 4);
|
||||
assert_eq!(report.skipped, vec!["synthetic/catalog.json".to_string()]);
|
||||
assert!(cas.exists(&report.imported[0].object_id).await);
|
||||
assert!(cas.exists(&report.imported[0].object_id).await.unwrap());
|
||||
assert_eq!(report.imported[0].resource_type, ResourceType::AssetBundle);
|
||||
assert_eq!(
|
||||
report.imported[0].category,
|
||||
|
||||
Reference in New Issue
Block a user