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}