From 69e987b4de88ab548c96f6ef61deaab2fa35608c Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 15 Oct 2026 22:48:01 +0800 Subject: [PATCH] fix(ecstore): box the transition payload of CurrentDeleteGeneration (#8581) `cargo clippy --all-targets -- -D warnings` fails on main since #8535: `CurrentDeleteGeneration::Present` carries a `CurrentDeleteTransition` (three Strings, an Option, a 32-byte identity and two small fields, ~211 bytes) while `Absent` carries nothing, which trips clippy::large_enum_variant. The workflow only runs clippy on pushes to main (`if: github.event_name != 'pull_request'`), so the PR CI stayed green and main's CI has been red since 606d8a3a. Store the transition behind a Box so the enum is pointer-sized plus the small fields. The value is transient ("never persisted in object metadata") and its serde form is unchanged, because serde treats Box transparently; PartialEq/Clone/Debug derive through it. The two tests that matched the struct through the Option now bind the Box and check the same fields in a guard. Claude-Session: https://claude.ai/code/session_01CezCdjE9AdShFUi9tNk797 Co-authored-by: Claude Fable 5.1 --- crates/ecstore/src/disk/mod.rs | 46 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/crates/ecstore/src/disk/mod.rs b/crates/ecstore/src/disk/mod.rs index 7b32c9253..22e082c39 100644 --- a/crates/ecstore/src/disk/mod.rs +++ b/crates/ecstore/src/disk/mod.rs @@ -1721,7 +1721,7 @@ pub enum CurrentDeleteGeneration { delete_marker: bool, etag: String, #[serde(default)] - transition: Option, + transition: Option>, }, } @@ -1749,14 +1749,16 @@ impl CurrentDeleteGeneration { || remote_version.is_some() || fi.transition_version_state != rustfs_filemeta::TransitionVersionState::Unknown || destination_id.is_some()) - .then(|| CurrentDeleteTransition { - status: fi.transition_status.clone(), - tier: fi.transition_tier.clone(), - remote_object: fi.transitioned_objname.clone(), - remote_version, - version_state: fi.transition_version_state, - destination_id, - remote_only, + .then(|| { + Box::new(CurrentDeleteTransition { + status: fi.transition_status.clone(), + tier: fi.transition_tier.clone(), + remote_object: fi.transitioned_objname.clone(), + remote_version, + version_state: fi.transition_version_state, + destination_id, + remote_only, + }) }); Ok(Self::Present { version_id: fi.version_id.filter(|id| !id.is_nil()), @@ -2369,15 +2371,12 @@ mod tests { CurrentDeleteGeneration::from_file_info(&fi), Ok(CurrentDeleteGeneration::Present { data_dir: None, - transition: Some(CurrentDeleteTransition { - remote_version: None, - version_state: rustfs_filemeta::TransitionVersionState::Unknown, - destination_id: None, - remote_only: true, - .. - }), + transition: Some(transition), .. - }) + }) if transition.remote_version.is_none() + && transition.version_state == rustfs_filemeta::TransitionVersionState::Unknown + && transition.destination_id.is_none() + && transition.remote_only ), "legacy unversioned remote metadata remains usable" ); @@ -2443,11 +2442,14 @@ mod tests { rustfs_protos::decode_delete_recovery_payload(&encoded).expect("decode remote guarded request"); assert_eq!(decoded.versions[0].expected_current, generation); assert!( - matches!(generation, CurrentDeleteGeneration::Present { transition: Some(CurrentDeleteTransition { - status, tier, remote_object, remote_version: Some(remote_version), - version_state: rustfs_filemeta::TransitionVersionState::Exact, destination_id: Some(identity), remote_only: true, - }), .. } if status == rustfs_filemeta::TRANSITION_COMPLETE && tier == "WARM" && remote_object == "opaque/object+name" - && remote_version == "opaque/version+id==" && identity == [0xab; 32]) + matches!(&generation, CurrentDeleteGeneration::Present { transition: Some(transition), .. } + if transition.status == rustfs_filemeta::TRANSITION_COMPLETE + && transition.tier == "WARM" + && transition.remote_object == "opaque/object+name" + && transition.remote_version.as_deref() == Some("opaque/version+id==") + && transition.version_state == rustfs_filemeta::TransitionVersionState::Exact + && transition.destination_id == Some([0xab; 32]) + && transition.remote_only) ); insert_str(&mut fi.metadata, SUFFIX_TRANSITION_TIER_DESTINATION_ID, format!("a{}", "€".repeat(21))); assert_eq!(