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 {}