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