Skip to main content

qubit_executor/service/
executor_service_builder_error.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use std::io;
11
12use thiserror::Error;
13
14use super::SubmissionError;
15
16/// Error returned when an executor service cannot be built.
17///
18/// This error is shared by executor-service implementations whose construction
19/// may validate worker, queue, timeout, stack, or thread-spawn configuration.
20#[derive(Debug, Error)]
21pub enum ExecutorServiceBuilderError {
22    /// The configured fixed worker count is zero.
23    #[error("executor service pool size must be greater than zero")]
24    ZeroPoolSize,
25
26    /// The configured maximum pool size is zero.
27    #[error("executor service maximum pool size must be greater than zero")]
28    ZeroMaximumPoolSize,
29
30    /// The configured core pool size is greater than the maximum pool size.
31    #[error(
32        "executor service core pool size {core_pool_size} exceeds maximum pool size {maximum_pool_size}"
33    )]
34    CorePoolSizeExceedsMaximum {
35        /// Configured core pool size.
36        core_pool_size: usize,
37
38        /// Configured maximum pool size.
39        maximum_pool_size: usize,
40    },
41
42    /// The configured bounded queue capacity is zero.
43    #[error("executor service queue capacity must be greater than zero")]
44    ZeroQueueCapacity,
45
46    /// The configured worker stack size is zero.
47    #[error("executor service stack size must be greater than zero")]
48    ZeroStackSize,
49
50    /// The configured keep-alive timeout is zero.
51    #[error("executor service keep-alive timeout must be greater than zero")]
52    ZeroKeepAlive,
53
54    /// A worker thread could not be spawned.
55    #[error("failed to spawn executor service worker {}: {source}", format_worker_index(*index))]
56    SpawnWorker {
57        /// Index of the worker that failed to spawn when the builder knows it.
58        index: Option<usize>,
59
60        /// I/O error reported by [`std::thread::Builder::spawn`].
61        source: io::Error,
62    },
63}
64
65impl ExecutorServiceBuilderError {
66    /// Converts a runtime worker-spawn rejection into a build error.
67    ///
68    /// # Parameters
69    ///
70    /// * `error` - Rejection produced while prestarting workers during build.
71    ///
72    /// # Returns
73    ///
74    /// A build error carrying equivalent failure context.
75    pub fn from_submission_error(error: SubmissionError) -> Self {
76        match error {
77            SubmissionError::WorkerSpawnFailed { source } => Self::SpawnWorker {
78                index: None,
79                source: io::Error::new(source.kind(), source.to_string()),
80            },
81            SubmissionError::Shutdown => Self::SpawnWorker {
82                index: None,
83                source: io::Error::other("executor service shut down during prestart"),
84            },
85            SubmissionError::Saturated => Self::SpawnWorker {
86                index: None,
87                source: io::Error::other("executor service saturated during prestart"),
88            },
89        }
90    }
91}
92
93/// Formats an optional worker index for display.
94///
95/// # Parameters
96///
97/// * `index` - Known worker index, if the builder has one.
98///
99/// # Returns
100///
101/// A display fragment for the worker index.
102fn format_worker_index(index: Option<usize>) -> String {
103    index
104        .map(|index| index.to_string())
105        .unwrap_or_else(|| "unknown".to_owned())
106}
107
108impl From<SubmissionError> for ExecutorServiceBuilderError {
109    /// Converts rejected-execution reasons into build-time executor errors.
110    ///
111    /// # Parameters
112    ///
113    /// * `error` - Rejection reason observed during service construction.
114    ///
115    /// # Returns
116    ///
117    /// A build error that preserves equivalent failure context.
118    fn from(error: SubmissionError) -> Self {
119        Self::from_submission_error(error)
120    }
121}