mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-19 02:56:18 +00:00
fix(lifecycle): count the first transition sample for each tier (#5612)
This commit is contained in:
@@ -1764,10 +1764,7 @@ impl TransitionState {
|
|||||||
|
|
||||||
pub fn add_lastday_stats(&self, tier: &str, ts: TierStats) {
|
pub fn add_lastday_stats(&self, tier: &str, ts: TierStats) {
|
||||||
let mut tier_stats = self.lock_last_day_stats();
|
let mut tier_stats = self.lock_last_day_stats();
|
||||||
tier_stats
|
tier_stats.entry(tier.to_string()).or_default().add_stats(ts);
|
||||||
.entry(tier.to_string())
|
|
||||||
.and_modify(|e| e.add_stats(ts))
|
|
||||||
.or_default();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_daily_all_tier_stats(&self) -> DailyAllTierStats {
|
pub fn get_daily_all_tier_stats(&self) -> DailyAllTierStats {
|
||||||
@@ -7277,6 +7274,48 @@ mod tests {
|
|||||||
assert!(stats.contains_key("fresh"), "statistics must accept new samples after recovery");
|
assert!(stats.contains_key("fresh"), "statistics must accept new samples after recovery");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn first_tier_sample_is_not_dropped() {
|
||||||
|
// The first completed transition to a tier both creates the map entry
|
||||||
|
// and carries a sample. Creating the entry must not discard that
|
||||||
|
// sample, or the admin GetTierInfo response undercounts every tier by
|
||||||
|
// its first transition while reporting later ones correctly.
|
||||||
|
let state = TransitionState::new_with_capacity(1);
|
||||||
|
|
||||||
|
state.add_lastday_stats(
|
||||||
|
"warm",
|
||||||
|
TierStats {
|
||||||
|
total_size: 10,
|
||||||
|
num_versions: 1,
|
||||||
|
num_objects: 1,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let stats = state.get_daily_all_tier_stats();
|
||||||
|
let total = stats.get("warm").expect("first sample must create the tier entry").total();
|
||||||
|
assert_eq!(total.total_size, 10, "first sample size must be counted");
|
||||||
|
assert_eq!(total.num_versions, 1, "first sample version must be counted");
|
||||||
|
assert_eq!(total.num_objects, 1, "first sample object must be counted");
|
||||||
|
|
||||||
|
// Later samples must accumulate onto the existing entry rather than
|
||||||
|
// replace it; `LastDayTierStats::add_stats` coverage alone does not
|
||||||
|
// reach this path, because it never goes through the tier map.
|
||||||
|
state.add_lastday_stats(
|
||||||
|
"warm",
|
||||||
|
TierStats {
|
||||||
|
total_size: 20,
|
||||||
|
num_versions: 2,
|
||||||
|
num_objects: 1,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let stats = state.get_daily_all_tier_stats();
|
||||||
|
let total = stats.get("warm").expect("tier entry must survive later samples").total();
|
||||||
|
assert_eq!(total.total_size, 30, "later sample size must accumulate");
|
||||||
|
assert_eq!(total.num_versions, 3, "later sample versions must accumulate");
|
||||||
|
assert_eq!(total.num_objects, 2, "later sample objects must accumulate");
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "current_thread")]
|
#[tokio::test(flavor = "current_thread")]
|
||||||
async fn scanner_transition_state_reports_compensation_pending_buckets() {
|
async fn scanner_transition_state_reports_compensation_pending_buckets() {
|
||||||
let state = TransitionState::new_with_capacity(1);
|
let state = TransitionState::new_with_capacity(1);
|
||||||
|
|||||||
Reference in New Issue
Block a user