fix(heal): preserve compatible listing EOF outcomes

Keep truncated heal listings without continuation tokens as complete compatibility EOFs and assert the canonical task outcome.

Co-Authored-By: heihutu <heihutu@gmail.com>

Co-Authored-By: zhi22915 <qiuzgang@gmail.com>
This commit is contained in:
houseme
2026-09-06 02:08:30 +08:00
parent 6b8489db92
commit 09947213fe
2 changed files with 10 additions and 2 deletions
+1 -1
View File
@@ -554,7 +554,7 @@ impl HealTask {
continuation_token = next_heal_listing_token(bucket, prefix, next_token, is_truncated)?;
if continuation_token.is_none() {
self.outcome.write().await.mark_untraversable();
// Truncated without a continuation token is a compatibility EOF.
break;
}
}
+9 -1
View File
@@ -1778,6 +1778,8 @@ async fn test_recursive_bucket_heal_skips_object_dir_candidates() {
#[tokio::test]
async fn test_recursive_bucket_heal_treats_missing_continuation_token_as_end() {
use crate::heal::outcome::{HealExecutionOutcome, HealTraversalCoverage};
// A version listing can report the final page as truncated with no
// continuation token. That is treated as end-of-listing (not an error),
// so the returned page is healed and the pass terminates cleanly instead
@@ -1799,10 +1801,16 @@ async fn test_recursive_bucket_heal_treats_missing_continuation_token_as_end() {
);
let task = HealTask::from_request(request, storage.clone());
task.heal_bucket("bucket-a")
task.execute()
.await
.expect("truncated-without-token must terminate cleanly, not loop or error");
assert_eq!(task.get_status().await, HealTaskStatus::Completed);
let outcome = task.get_outcome().await;
assert_eq!(outcome.execution, HealExecutionOutcome::Completed);
assert_eq!(outcome.coverage, HealTraversalCoverage::Complete);
assert_eq!(outcome.counters.processed, 1);
assert_eq!(
storage.healed_objects.lock().unwrap().as_slice(),
["object-a".to_string()],