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("executor service core pool size {core_pool_size} exceeds maximum pool size {maximum_pool_size}")]
32    CorePoolSizeExceedsMaximum {
33        /// Configured core pool size.
34        core_pool_size: usize,
35
36        /// Configured maximum pool size.
37        maximum_pool_size: usize,
38    },
39
40    /// The configured bounded queue capacity is zero.
41    #[error("executor service queue capacity must be greater than zero")]
42    ZeroQueueCapacity,
43
44    /// The configured worker stack size is zero.
45    #[error("executor service stack size must be greater than zero")]
46    ZeroStackSize,
47
48    /// The configured keep-alive timeout is zero.
49    #[error("executor service keep-alive timeout must be greater than zero")]
50    ZeroKeepAlive,
51
52    /// A worker thread could not be spawned.
53    #[error("failed to spawn executor service worker {}: {source}", format_worker_index(*index))]
54    SpawnWorker {
55        /// Index of the worker that failed to spawn when the builder knows it.
56        index: Option<usize>,
57
58        /// I/O error reported by [`std::thread::Builder::spawn`].
59        source: io::Error,
60    },
61}
62
63impl ExecutorServiceBuilderError {
64    /// Converts a runtime worker-spawn rejection into a build error.
65    ///
66    /// # Parameters
67    ///
68    /// * `error` - Rejection produced while prestarting workers during build.
69    ///
70    /// # Returns
71    ///
72    /// A build error carrying equivalent failure context.
73    pub fn from_submission_error(error: SubmissionError) -> Self {
74        match error {
75            SubmissionError::WorkerSpawnFailed { source } => Self::SpawnWorker {
76                index: None,
77                source: io::Error::new(source.kind(), source.to_string()),
78            },
79            SubmissionError::Shutdown => Self::SpawnWorker {
80                index: None,
81                source: io::Error::other("executor service shut down during prestart"),
82            },
83            SubmissionError::Saturated => Self::SpawnWorker {
84                index: None,
85                source: io::Error::other("executor service saturated during prestart"),
86            },
87        }
88    }
89}
90
91/// Formats an optional worker index for display.
92///
93/// # Parameters
94///
95/// * `index` - Known worker index, if the builder has one.
96///
97/// # Returns
98///
99/// A display fragment for the worker index.
100fn format_worker_index(index: Option<usize>) -> String {
101    index
102        .map(|index| index.to_string())
103        .unwrap_or_else(|| "unknown".to_owned())
104}
105
106impl From<SubmissionError> for ExecutorServiceBuilderError {
107    /// Converts rejected-execution reasons into build-time executor errors.
108    ///
109    /// # Parameters
110    ///
111    /// * `error` - Rejection reason observed during service construction.
112    ///
113    /// # Returns
114    ///
115    /// A build error that preserves equivalent failure context.
116    fn from(error: SubmissionError) -> Self {
117        Self::from_submission_error(error)
118    }
119}