mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-22 12:26:37 +00:00
fix(ecstore): distinguish active ILM target cleanup
This commit is contained in:
@@ -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) => {}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user