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