Fix the processing sucesfull counter not being atomic

This commit is contained in:
Arnaud_Cayrol 2026-02-14 16:28:33 +01:00
parent e814731ec2
commit 746f3b3109
4 changed files with 27 additions and 2 deletions

View file

@ -84,8 +84,8 @@
.reduce((sum, [_, val]) => sum + (typeof val === 'number' ? val : 0), 0) .reduce((sum, [_, val]) => sum + (typeof val === 'number' ? val : 0), 0)
); );
// Calculate kept (successful) count: completed - skipped // Kept count from backend (tracked atomically alongside skip stats)
let keptCount = $derived(Math.max(0, displayCompleted - skipTotal)); let keptCount = $derived(displaySkipStats.kept || 0);
// Dynamically build skip reasons from whatever the backend sends // Dynamically build skip reasons from whatever the backend sends
// Filter to only show non-zero counts, exclude the 'total' field // Filter to only show non-zero counts, exclude the 'total' field

View file

@ -206,6 +206,7 @@ pub async fn process_single_asset(
}; };
} }
skip_stats.increment_kept();
AssetProcessResult::Success { asset_id } AssetProcessResult::Success { asset_id }
} }
PipelineResult::Skipped { PipelineResult::Skipped {

View file

@ -18,6 +18,8 @@ pub struct SkipStatsResponse {
pub counts: HashMap<String, u32>, pub counts: HashMap<String, u32>,
/// Total number of skipped images. /// Total number of skipped images.
pub total: u32, pub total: u32,
/// Number of images kept (passed all filters).
pub kept: u32,
} }
impl From<&SkipStats> for SkipStatsResponse { impl From<&SkipStats> for SkipStatsResponse {
@ -25,6 +27,7 @@ impl From<&SkipStats> for SkipStatsResponse {
Self { Self {
counts: stats.counts().clone(), counts: stats.counts().clone(),
total: stats.total(), total: stats.total(),
kept: stats.kept(),
} }
} }
} }

View file

@ -56,6 +56,8 @@ impl std::fmt::Display for JobStatus {
pub struct SkipStats { pub struct SkipStats {
/// Map of skip reason ID to count. /// Map of skip reason ID to count.
counts: HashMap<String, u32>, counts: HashMap<String, u32>,
/// Number of images kept (passed all filters).
kept: u32,
} }
impl SkipStats { impl SkipStats {
@ -79,6 +81,16 @@ impl SkipStats {
&self.counts &self.counts
} }
/// Number of images kept (passed all filters).
pub fn kept(&self) -> u32 {
self.kept
}
/// Set the kept count.
pub fn set_kept(&mut self, count: u32) {
self.kept = count;
}
/// Total number of skipped images. /// Total number of skipped images.
pub fn total(&self) -> u32 { pub fn total(&self) -> u32 {
self.counts.values().sum() self.counts.values().sum()
@ -94,6 +106,8 @@ pub struct AtomicSkipStats {
/// Map of skip reason to atomic counter. /// Map of skip reason to atomic counter.
/// Uses std::sync::RwLock for synchronous access (required for HashMap mutations). /// Uses std::sync::RwLock for synchronous access (required for HashMap mutations).
counts: StdRwLock<HashMap<String, Arc<AtomicU32>>>, counts: StdRwLock<HashMap<String, Arc<AtomicU32>>>,
/// Number of images kept (passed all filters).
kept: AtomicU32,
} }
impl AtomicSkipStats { impl AtomicSkipStats {
@ -102,6 +116,11 @@ impl AtomicSkipStats {
Self::default() Self::default()
} }
/// Increment the kept counter. Returns the new count.
pub fn increment_kept(&self) -> u32 {
self.kept.fetch_add(1, Ordering::SeqCst) + 1
}
/// Increment a counter for the given reason string. /// Increment a counter for the given reason string.
/// ///
/// If the reason doesn't exist yet, it's created with an initial count of 1. /// If the reason doesn't exist yet, it's created with an initial count of 1.
@ -136,6 +155,7 @@ impl AtomicSkipStats {
for (reason, counter) in counts.iter() { for (reason, counter) in counts.iter() {
stats.set(reason.clone(), counter.load(Ordering::SeqCst)); stats.set(reason.clone(), counter.load(Ordering::SeqCst));
} }
stats.set_kept(self.kept.load(Ordering::SeqCst));
stats stats
} }
@ -143,6 +163,7 @@ impl AtomicSkipStats {
pub fn reset(&self) { pub fn reset(&self) {
let mut counts = self.counts.write().unwrap(); let mut counts = self.counts.write().unwrap();
counts.clear(); counts.clear();
self.kept.store(0, Ordering::SeqCst);
} }
} }