qubit_batch/process/batch_process_result.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use std::{
11 fmt,
12 time::Duration,
13};
14
15use crate::BatchProcessResultBuilder;
16
17/// Structured result produced by a batch processor.
18///
19/// The result distinguishes completed input items from successfully processed
20/// items because some processors can report a success count, such as affected
21/// database rows, that differs from the number of input items whose chunk
22/// returned.
23///
24/// ```rust
25/// use std::time::Duration;
26///
27/// use qubit_batch::BatchProcessResultBuilder;
28///
29/// let result = BatchProcessResultBuilder::builder(3)
30/// .completed_count(3)
31/// .processed_count(3)
32/// .chunk_count(1)
33/// .elapsed(Duration::ZERO)
34/// .build()
35/// .expect("process result counters should be consistent");
36///
37/// assert!(result.is_success());
38/// assert_eq!(result.item_count(), 3);
39/// assert_eq!(result.chunk_count(), 1);
40/// ```
41#[derive(Debug, Clone, PartialEq, Eq)]
42pub struct BatchProcessResult {
43 /// Declared item count for the batch.
44 item_count: usize,
45 /// Number of input items whose processing reached a terminal outcome.
46 completed_count: usize,
47 /// Number of items reported as successfully processed.
48 processed_count: usize,
49 /// Number of chunks submitted by the processor.
50 chunk_count: usize,
51 /// Total monotonic elapsed duration.
52 elapsed: Duration,
53}
54
55impl BatchProcessResult {
56 /// Starts building a batch process result.
57 ///
58 /// # Parameters
59 ///
60 /// * `item_count` - Declared item count for the batch.
61 ///
62 /// # Returns
63 ///
64 /// A result builder initialized with zero counters and zero elapsed time.
65 #[inline]
66 pub const fn builder(item_count: usize) -> BatchProcessResultBuilder {
67 BatchProcessResultBuilder::builder(item_count)
68 }
69
70 /// Creates a new batch process result from a validated builder.
71 ///
72 /// # Parameters
73 ///
74 /// * `builder` - Validated process result builder carrying all result
75 /// fields.
76 ///
77 /// # Returns
78 ///
79 /// A fully populated batch process result.
80 #[inline]
81 pub(crate) const fn new(builder: BatchProcessResultBuilder) -> Self {
82 Self {
83 item_count: builder.item_count,
84 completed_count: builder.completed_count,
85 processed_count: builder.processed_count,
86 chunk_count: builder.chunk_count,
87 elapsed: builder.elapsed,
88 }
89 }
90
91 /// Returns the declared item count.
92 ///
93 /// # Returns
94 ///
95 /// The expected number of input items.
96 #[inline]
97 pub const fn item_count(&self) -> usize {
98 self.item_count
99 }
100
101 /// Returns how many input items reached a terminal outcome.
102 ///
103 /// # Returns
104 ///
105 /// The number of completed input items.
106 #[inline]
107 pub const fn completed_count(&self) -> usize {
108 self.completed_count
109 }
110
111 /// Returns how many items were reported as successfully processed.
112 ///
113 /// # Returns
114 ///
115 /// The processor-reported success count.
116 #[inline]
117 pub const fn processed_count(&self) -> usize {
118 self.processed_count
119 }
120
121 /// Returns the number of chunks submitted by the processor.
122 ///
123 /// # Returns
124 ///
125 /// The submitted chunk count.
126 #[inline]
127 pub const fn chunk_count(&self) -> usize {
128 self.chunk_count
129 }
130
131 /// Returns the total monotonic elapsed duration.
132 ///
133 /// # Returns
134 ///
135 /// The elapsed duration for this batch processing attempt.
136 #[inline]
137 pub const fn elapsed(&self) -> Duration {
138 self.elapsed
139 }
140
141 /// Returns whether all declared items were processed successfully.
142 ///
143 /// # Returns
144 ///
145 /// `true` when every declared item completed and was reported as processed.
146 #[inline]
147 pub const fn is_success(&self) -> bool {
148 self.completed_count == self.item_count && self.processed_count == self.item_count
149 }
150}
151
152impl fmt::Display for BatchProcessResult {
153 /// Formats a concise summary of this batch process result.
154 ///
155 /// # Parameters
156 ///
157 /// * `f` - Formatter receiving the summary text.
158 ///
159 /// # Returns
160 ///
161 /// The formatter result.
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 write!(
164 f,
165 "processed {}/{} items in {} chunks ({:?})",
166 self.processed_count, self.item_count, self.chunk_count, self.elapsed
167 )
168 }
169}