1use std::fmt::Display;
4
5use thiserror::Error;
6use tokio::sync::{mpsc::error::SendError, oneshot::error::RecvError};
7
8#[derive(Error, Debug, Clone)]
10#[non_exhaustive]
11pub enum BatchError<E: Display> {
12 #[error("Unable to send item to the worker for batching: channel closed")]
16 Tx,
17
18 #[error("Error while waiting for batch results: channel closed. {0}")]
22 Rx(#[from] RecvError),
23
24 #[error("Batch item rejected: {0}")]
28 Rejected(RejectionReason),
29
30 #[error("The entire batch failed: {0}")]
32 BatchFailed(#[source] E),
33
34 #[error("Resource acquisition failed: {0}")]
36 ResourceAcquisitionFailed(#[source] E),
37
38 #[error("The batch was cancelled")]
40 Cancelled,
41
42 #[error("The batch processing panicked")]
44 Panic,
45}
46
47#[derive(Debug, Clone, Copy)]
49#[non_exhaustive]
50pub enum RejectionReason {
51 BatchQueueFull(ConcurrencyStatus),
53}
54
55#[derive(Debug, Clone, Copy)]
57#[non_exhaustive]
58pub enum ConcurrencyStatus {
59 Available,
63 MaxedOut,
65}
66
67impl Display for RejectionReason {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 f.write_str(match self {
70 RejectionReason::BatchQueueFull(concurrency) => match concurrency {
71 ConcurrencyStatus::Available => "the batch queue is full",
72 ConcurrencyStatus::MaxedOut => {
73 "the batch queue is full and maximum concurrency reached"
74 }
75 },
76 })
77 }
78}
79
80pub type BatchResult<T, E> = std::result::Result<T, BatchError<E>>;
82
83impl<T, E: Display> From<SendError<T>> for BatchError<E> {
84 fn from(_tx_err: SendError<T>) -> Self {
85 BatchError::Tx
86 }
87}
88
89impl<E> BatchError<E>
90where
91 E: Display,
92{
93 pub fn inner(self) -> BatchResult<E, E> {
95 match self {
96 BatchError::BatchFailed(source) => Ok(source),
97 BatchError::ResourceAcquisitionFailed(source) => Ok(source),
98 _ => Err(self),
99 }
100 }
101}