From 955577b66feaa1960049f1d10250f72a43a7fa31 Mon Sep 17 00:00:00 2001 From: houseme Date: Mon, 20 Jul 2026 14:31:48 +0800 Subject: [PATCH] test(ecstore): cover transition source dedupe (#5050) Refs rustfs/backlog#1355 Co-authored-by: heihutu --- .../bucket/lifecycle/bucket_lifecycle_ops.rs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/crates/ecstore/src/bucket/lifecycle/bucket_lifecycle_ops.rs b/crates/ecstore/src/bucket/lifecycle/bucket_lifecycle_ops.rs index 06db6dcc7..46ffb068e 100644 --- a/crates/ecstore/src/bucket/lifecycle/bucket_lifecycle_ops.rs +++ b/crates/ecstore/src/bucket/lifecycle/bucket_lifecycle_ops.rs @@ -4337,6 +4337,43 @@ mod tests { assert_eq!(state.transition_rx.len(), 1, "only one task must actually be queued"); } + #[tokio::test] + #[serial] + async fn queue_transition_task_dedupes_immediate_and_scanner_sources_for_same_version() { + let state = TransitionState::new_with_capacity(4); + let version_id = Uuid::new_v4(); + let object = ObjectInfo { + bucket: "bucket".to_string(), + name: "object".to_string(), + version_id: Some(version_id), + ..Default::default() + }; + let event = crate::bucket::lifecycle::lifecycle::Event { + action: IlmAction::TransitionAction, + ..Default::default() + }; + + let immediate = state.queue_transition_task(&object, &event, &LcEventSrc::S3PutObject).await; + let scanner = state.queue_transition_task(&object, &event, &LcEventSrc::Scanner).await; + + assert!(immediate, "immediate transition enqueue must succeed"); + assert!(scanner, "scanner duplicate is reported handled while already queued"); + assert_eq!( + state.transition_rx.len(), + 1, + "immediate transition plus scanner/backfill duplicate must queue one task" + ); + + let next_version = ObjectInfo { + version_id: Some(Uuid::new_v4()), + ..object + }; + let queued_next_version = state.queue_transition_task(&next_version, &event, &LcEventSrc::Scanner).await; + + assert!(queued_next_version, "a different version of the same object must enqueue independently"); + assert_eq!(state.transition_rx.len(), 2, "deduplication must be scoped to the exact object version"); + } + #[tokio::test] #[serial] async fn transition_state_init_honors_runtime_configured_worker_count() {