fix(ecstore): distinguish active ILM target cleanup

This commit is contained in:
overtrue
2026-08-22 12:10:41 +08:00
parent 2a4021c3c5
commit 2f048466b4
3 changed files with 35 additions and 12 deletions
@@ -439,7 +439,7 @@ async fn process_committed_tier_delete_journal_entry(api: Arc<ECStore>, je: &Jen
.record_durable_ilm_decommission_terminal_target_pools(&path, &data) .record_durable_ilm_decommission_terminal_target_pools(&path, &data)
.await .await
.map_err(std::io::Error::other)?; .map_err(std::io::Error::other)?;
if !target_pool_indices.is_empty() { if let Some(target_pool_indices) = target_pool_indices {
for target_pool_idx in target_pool_indices { for target_pool_idx in target_pool_indices {
match config_boundary::delete_config(api.pools[target_pool_idx].clone(), &path).await { match config_boundary::delete_config(api.pools[target_pool_idx].clone(), &path).await {
Ok(()) | Err(Error::ConfigNotFound) => {} Ok(()) | Err(Error::ConfigNotFound) => {}
+9 -4
View File
@@ -5328,7 +5328,12 @@ impl ECStore {
} }
} }
async fn advance_durable_ilm_decommission_receipts(&self, path: &str, data: &[u8], terminal: bool) -> Result<Vec<usize>> { async fn advance_durable_ilm_decommission_receipts(
&self,
path: &str,
data: &[u8],
terminal: bool,
) -> Result<Option<Vec<usize>>> {
let active_runs = { let active_runs = {
let pool_meta = self.pool_meta.read().await; let pool_meta = self.pool_meta.read().await;
pool_meta pool_meta
@@ -5345,7 +5350,7 @@ impl ECStore {
.collect::<Vec<_>>() .collect::<Vec<_>>()
}; };
if active_runs.is_empty() { if active_runs.is_empty() {
return Ok(Vec::new()); return Ok(None);
} }
let stage = if terminal { "terminal" } else { "progress" }; let stage = if terminal { "terminal" } else { "progress" };
@@ -5378,7 +5383,7 @@ impl ECStore {
))); )));
} }
} }
Ok(terminal_target_pool_indices) Ok(Some(terminal_target_pool_indices))
} }
pub(crate) async fn record_durable_ilm_decommission_progress(&self, path: &str, data: &[u8]) -> Result<()> { pub(crate) async fn record_durable_ilm_decommission_progress(&self, path: &str, data: &[u8]) -> Result<()> {
@@ -5398,7 +5403,7 @@ impl ECStore {
&self, &self,
path: &str, path: &str,
data: &[u8], data: &[u8],
) -> Result<Vec<usize>> { ) -> Result<Option<Vec<usize>>> {
self.advance_durable_ilm_decommission_receipts(path, data, true).await self.advance_durable_ilm_decommission_receipts(path, data, true).await
} }
+25 -7
View File
@@ -3284,22 +3284,40 @@ mod tests {
let record = validate_durable_ilm_record(&path, &data).expect("tier journal should validate"); let record = validate_durable_ilm_record(&path, &data).expect("tier journal should validate");
let source_zero_receipt = store let source_zero_receipt = store
.persist_decommission_durable_ilm_receipt_for_test(0, 2, &path, &record, false)
.await
.expect("source pool zero receipt should persist on the target");
store
.persist_decommission_durable_ilm_receipt_for_test(0, 1, &path, &record, false) .persist_decommission_durable_ilm_receipt_for_test(0, 1, &path, &record, false)
.await .await
.expect("source pool zero receipt may reach another active source first"); .expect("source pool zero receipt should persist on the other active source");
let source_one_receipt = store let source_one_receipt = store
.persist_decommission_durable_ilm_receipt_for_test(1, 2, &path, &record, false) .persist_decommission_durable_ilm_receipt_for_test(1, 0, &path, &record, false)
.await .await
.expect("source pool one receipt should persist on the target"); .expect("source pool one receipt should persist on the other active source");
assert_ne!( assert_ne!(
source_zero_receipt, source_one_receipt, source_zero_receipt, source_one_receipt,
"active source runs must have distinct receipt paths" "active source runs must have distinct receipt paths"
); );
let stats = recover_tier_delete_journal_entries(store.clone(), 100, None)
.await
.expect("cross-source receipts should not remove active source journals");
assert_eq!((stats.scanned, stats.deleted, stats.failed), (1, 1, 0));
for pool in &store.pools {
assert_eq!(
com::read_config(pool.clone(), &path)
.await
.expect("cross-source receipts alone must retain every journal copy"),
data
);
}
store
.persist_decommission_durable_ilm_receipt_for_test(0, 2, &path, &record, false)
.await
.expect("source pool zero receipt should persist on the target");
store
.persist_decommission_durable_ilm_receipt_for_test(1, 2, &path, &record, false)
.await
.expect("source pool one receipt should persist on the target");
let stats = recover_tier_delete_journal_entries(store.clone(), 100, None) let stats = recover_tier_delete_journal_entries(store.clone(), 100, None)
.await .await
.expect("multi-source tier journal recovery should complete"); .expect("multi-source tier journal recovery should complete");