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<String>, 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<T>
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 <noreply@anthropic.com>
This commit is contained in:
Chris
2026-10-15 22:48:01 +08:00
committed by GitHub
parent 7a32ca2adb
commit 69e987b4de
+24 -22
View File
@@ -1721,7 +1721,7 @@ pub enum CurrentDeleteGeneration {
delete_marker: bool,
etag: String,
#[serde(default)]
transition: Option<CurrentDeleteTransition>,
transition: Option<Box<CurrentDeleteTransition>>,
},
}
@@ -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!(