From 978845b55533976cecc9b1070e7491006d499eda Mon Sep 17 00:00:00 2001 From: tennisleng <83838474+tennisleng@users.noreply.github.com> Date: Wed, 10 Dec 2025 18:17:35 -0500 Subject: [PATCH] fix(lifecycle): Fix ObjectInfo fields and mod_time error handling (#1088) Co-authored-by: loverustfs --- crates/ahm/src/scanner/data_scanner.rs | 2 ++ .../ecstore/src/bucket/lifecycle/lifecycle.rs | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/crates/ahm/src/scanner/data_scanner.rs b/crates/ahm/src/scanner/data_scanner.rs index 900d40ce0..ebb9dcbb3 100644 --- a/crates/ahm/src/scanner/data_scanner.rs +++ b/crates/ahm/src/scanner/data_scanner.rs @@ -473,6 +473,8 @@ impl Scanner { size: usage.total_size as i64, delete_marker: !usage.has_live_object && usage.delete_markers_count > 0, mod_time: usage.last_modified_ns.and_then(Self::ns_to_offset_datetime), + // Set is_latest to true for live objects - required for lifecycle expiration evaluation + is_latest: usage.has_live_object, ..Default::default() } } diff --git a/crates/ecstore/src/bucket/lifecycle/lifecycle.rs b/crates/ecstore/src/bucket/lifecycle/lifecycle.rs index c435dca5f..a46620dee 100644 --- a/crates/ecstore/src/bucket/lifecycle/lifecycle.rs +++ b/crates/ecstore/src/bucket/lifecycle/lifecycle.rs @@ -283,7 +283,17 @@ impl Lifecycle for BucketLifecycleConfiguration { "eval_inner: object={}, mod_time={:?}, now={:?}, is_latest={}, delete_marker={}", obj.name, obj.mod_time, now, obj.is_latest, obj.delete_marker ); - if obj.mod_time.expect("err").unix_timestamp() == 0 { + + // Gracefully handle missing mod_time instead of panicking + let mod_time = match obj.mod_time { + Some(t) => t, + None => { + info!("eval_inner: mod_time is None for object={}, returning default event", obj.name); + return Event::default(); + } + }; + + if mod_time.unix_timestamp() == 0 { info!("eval_inner: mod_time is 0, returning default event"); return Event::default(); } @@ -323,7 +333,7 @@ impl Lifecycle for BucketLifecycleConfiguration { } if let Some(days) = expiration.days { - let expected_expiry = expected_expiry_time(obj.mod_time.unwrap(), days /*, date*/); + let expected_expiry = expected_expiry_time(mod_time, days /*, date*/); if now.unix_timestamp() >= expected_expiry.unix_timestamp() { events.push(Event { action: IlmAction::DeleteVersionAction, @@ -446,11 +456,11 @@ impl Lifecycle for BucketLifecycleConfiguration { }); } } else if let Some(days) = expiration.days { - let expected_expiry: OffsetDateTime = expected_expiry_time(obj.mod_time.unwrap(), days); + let expected_expiry: OffsetDateTime = expected_expiry_time(mod_time, days); info!( "eval_inner: expiration check - days={}, obj_time={:?}, expiry_time={:?}, now={:?}, should_expire={}", days, - obj.mod_time.expect("err!"), + mod_time, expected_expiry, now, now.unix_timestamp() > expected_expiry.unix_timestamp()