Skip to main content

qubit_progress/error/
metric_error.rs

1// =============================================================================
2//    Copyright (c) 2025 - 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Errors returned by live metric transitions.
9// qubit-style: allow source-test-pair
10
11use std::{
12    error::Error,
13    fmt,
14};
15
16use crate::OperationLifecycle;
17
18/// Failure while reading or mutating one stateful metric.
19#[derive(Clone, Debug, Eq, PartialEq)]
20pub enum MetricError {
21    /// The enclosing operation is freezing or already closed.
22    OperationNotOpen {
23        /// Stable metric ID.
24        metric_id: String,
25        /// Lifecycle state that rejected the transition.
26        state: OperationLifecycle,
27    },
28    /// A completion delta attempted to consume more active work than exists.
29    InsufficientActive {
30        /// Stable metric ID.
31        metric_id: String,
32        /// Total terminal work requested by the delta.
33        requested: u64,
34        /// Active work available at the linearization point.
35        available: u64,
36    },
37    /// A transition would exceed the configured total.
38    TotalExceeded {
39        /// Stable metric ID.
40        metric_id: String,
41        /// Configured total.
42        total: u64,
43        /// Attempted occupied count.
44        attempted: u64,
45    },
46    /// Metric arithmetic overflowed.
47    CountOverflow {
48        /// Stable metric ID.
49        metric_id: String,
50    },
51}
52
53impl fmt::Display for MetricError {
54    /// Formats the metric transition failure.
55    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
56        match self {
57            Self::OperationNotOpen { metric_id, state } => write!(
58                formatter,
59                "metric {metric_id:?} is not open because operation is {state:?}"
60            ),
61            Self::InsufficientActive {
62                metric_id,
63                requested,
64                available,
65            } => write!(
66                formatter,
67                "metric {metric_id:?} cannot complete {requested} work items because only {available} are active"
68            ),
69            Self::TotalExceeded {
70                metric_id,
71                total,
72                attempted,
73            } => write!(
74                formatter,
75                "metric {metric_id:?} would occupy {attempted} work items above total {total}"
76            ),
77            Self::CountOverflow { metric_id } => {
78                write!(formatter, "counts for metric {metric_id:?} overflowed")
79            }
80        }
81    }
82}
83
84impl Error for MetricError {}