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}