Skip to main content

qubit_dcl/double_checked/
executor_ready_builder.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 ******************************************************************************/
10//! Ready builder for [`super::DoubleCheckedLockExecutor`] (tester set, optional
11//! prepare hooks).
12//!
13
14use std::{
15    fmt::Display,
16    marker::PhantomData,
17};
18
19use qubit_function::{
20    ArcRunnable,
21    ArcTester,
22    Runnable,
23};
24
25use super::{
26    CallbackError,
27    ExecutionLogger,
28    double_checked_lock_executor::DoubleCheckedLockExecutor,
29};
30use qubit_lock::Lock;
31
32/// Builder state after the required condition tester has been configured.
33///
34/// This state can configure prepare lifecycle callbacks and build the final
35/// [`DoubleCheckedLockExecutor`].
36///
37/// # Type Parameters
38///
39/// * `L` - The lock type implementing [`Lock<T>`].
40/// * `T` - The data type protected by the lock.
41///
42#[derive(Clone)]
43pub struct ExecutorReadyBuilder<L, T> {
44    /// The lock to store in the executor.
45    pub(in crate::double_checked) lock: L,
46
47    /// Required condition tester.
48    pub(in crate::double_checked) tester: ArcTester,
49
50    /// Logger used by the executor.
51    pub(in crate::double_checked) logger: ExecutionLogger,
52
53    /// Optional action executed after the first check and before locking.
54    pub(in crate::double_checked) prepare_action: Option<ArcRunnable<CallbackError>>,
55
56    /// Optional action executed when prepare must be rolled back.
57    pub(in crate::double_checked) rollback_prepare_action: Option<ArcRunnable<CallbackError>>,
58
59    /// Optional action executed when prepare should be committed.
60    pub(in crate::double_checked) commit_prepare_action: Option<ArcRunnable<CallbackError>>,
61
62    /// Whether panics from tester, callbacks, and task are converted to errors.
63    pub(in crate::double_checked) catch_panics: bool,
64
65    /// Carries the protected data type.
66    pub(in crate::double_checked) _phantom: PhantomData<fn() -> T>,
67}
68
69impl<L, T> ExecutorReadyBuilder<L, T>
70where
71    L: Lock<T>,
72{
73    /// Configures logging when the double-checked condition is not met.
74    ///
75    /// # Parameters
76    ///
77    /// * `level` - Log level used for unmet-condition messages.
78    /// * `message` - Full log message emitted when the condition is not met.
79    ///
80    /// # Returns
81    ///
82    /// This builder with unmet-condition logging configured.
83    #[inline]
84    #[must_use = "assign or chain the returned builder"]
85    pub fn log_unmet_condition(mut self, level: log::Level, message: impl Into<String>) -> Self {
86        self.logger.set_unmet_condition(Some(level), message);
87        self
88    }
89
90    /// Disables logging when the double-checked condition is not met.
91    ///
92    /// # Returns
93    ///
94    /// This builder with unmet-condition logging disabled.
95    #[inline]
96    #[must_use = "assign or chain the returned builder"]
97    pub fn disable_unmet_condition_logging(mut self) -> Self {
98        self.logger.disable_unmet_condition();
99        self
100    }
101
102    /// Configures logging when the prepare action fails.
103    ///
104    /// # Parameters
105    ///
106    /// * `level` - Log level used for prepare failure messages.
107    /// * `message_prefix` - Prefix placed before the prepare failure text.
108    ///
109    /// # Returns
110    ///
111    /// This builder with prepare failure logging configured.
112    #[inline]
113    #[must_use = "assign or chain the returned builder"]
114    pub fn log_prepare_failure(mut self, level: log::Level, message_prefix: impl Into<String>) -> Self {
115        self.logger.set_prepare_failure(Some(level), message_prefix);
116        self
117    }
118
119    /// Disables logging when the prepare action fails.
120    ///
121    /// # Returns
122    ///
123    /// This builder with prepare failure logging disabled.
124    #[inline]
125    #[must_use = "assign or chain the returned builder"]
126    pub fn disable_prepare_failure_logging(mut self) -> Self {
127        self.logger.disable_prepare_failure();
128        self
129    }
130
131    /// Configures logging when the prepare commit action fails.
132    ///
133    /// # Parameters
134    ///
135    /// * `level` - Log level used for prepare-commit failure messages.
136    /// * `message_prefix` - Prefix placed before the prepare-commit failure
137    ///   text.
138    ///
139    /// # Returns
140    ///
141    /// This builder with prepare-commit failure logging configured.
142    #[inline]
143    #[must_use = "assign or chain the returned builder"]
144    pub fn log_prepare_commit_failure(mut self, level: log::Level, message_prefix: impl Into<String>) -> Self {
145        self.logger.set_prepare_commit_failure(Some(level), message_prefix);
146        self
147    }
148
149    /// Disables logging when the prepare commit action fails.
150    ///
151    /// # Returns
152    ///
153    /// This builder with prepare-commit failure logging disabled.
154    #[inline]
155    #[must_use = "assign or chain the returned builder"]
156    pub fn disable_prepare_commit_failure_logging(mut self) -> Self {
157        self.logger.disable_prepare_commit_failure();
158        self
159    }
160
161    /// Configures logging when the prepare rollback action fails.
162    ///
163    /// # Parameters
164    ///
165    /// * `level` - Log level used for prepare-rollback failure messages.
166    /// * `message_prefix` - Prefix placed before the prepare-rollback failure
167    ///   text.
168    ///
169    /// # Returns
170    ///
171    /// This builder with prepare-rollback failure logging configured.
172    #[inline]
173    #[must_use = "assign or chain the returned builder"]
174    pub fn log_prepare_rollback_failure(mut self, level: log::Level, message_prefix: impl Into<String>) -> Self {
175        self.logger.set_prepare_rollback_failure(Some(level), message_prefix);
176        self
177    }
178
179    /// Disables logging when the prepare rollback action fails.
180    ///
181    /// # Returns
182    ///
183    /// This builder with prepare-rollback failure logging disabled.
184    #[inline]
185    #[must_use = "assign or chain the returned builder"]
186    pub fn disable_prepare_rollback_failure_logging(mut self) -> Self {
187        self.logger.disable_prepare_rollback_failure();
188        self
189    }
190
191    /// Sets the prepare action.
192    ///
193    /// The action runs after the first condition check succeeds and before the
194    /// lock is acquired. If it succeeds, the executor will later run either
195    /// rollback or commit according to the final task result.
196    ///
197    /// Errors returned by this action are converted to [`String`] and reported
198    /// by execution methods as [`super::ExecutionResult::Failed`].
199    ///
200    /// # Parameters
201    ///
202    /// * `prepare_action` - The fallible action to run before locking.
203    ///
204    /// # Returns
205    ///
206    /// This builder with prepare configured.
207    ///
208    /// # Errors
209    ///
210    /// This builder method does not return errors. If `prepare_action` later
211    /// returns an error during execution, the execution result becomes
212    /// [`super::ExecutionResult::Failed`] with
213    /// [`super::ExecutorError::PrepareFailed`].
214    #[inline]
215    #[must_use = "assign or chain the returned builder"]
216    pub fn prepare<Rn, E>(mut self, prepare_action: Rn) -> Self
217    where
218        Rn: Runnable<E> + Send + 'static,
219        E: Display,
220    {
221        let mut action = prepare_action;
222        self.prepare_action = Some(ArcRunnable::new(move || {
223            action
224                .run()
225                .map_err(|error| CallbackError::with_callback_type("prepare", error))
226        }));
227        self
228    }
229
230    /// Sets the rollback action for a successfully completed prepare action.
231    ///
232    /// Errors returned by this action are converted to [`String`] and replace
233    /// the original execution result with a prepare-rollback failure.
234    ///
235    /// # Parameters
236    ///
237    /// * `rollback_prepare_action` - The action to run if the second condition
238    ///   check or task execution fails after prepare succeeds.
239    ///
240    /// # Returns
241    ///
242    /// This builder with prepare rollback configured.
243    ///
244    /// # Errors
245    ///
246    /// This builder method does not return errors. If
247    /// `rollback_prepare_action` later returns an error during execution, the
248    /// execution result becomes [`super::ExecutionResult::Failed`] with
249    /// [`super::ExecutorError::PrepareRollbackFailed`].
250    #[inline]
251    #[must_use = "assign or chain the returned builder"]
252    pub fn rollback_prepare<Rn, E>(mut self, rollback_prepare_action: Rn) -> Self
253    where
254        Rn: Runnable<E> + Send + 'static,
255        E: Display,
256    {
257        let mut action = rollback_prepare_action;
258        self.rollback_prepare_action = Some(ArcRunnable::new(move || {
259            action
260                .run()
261                .map_err(|error| CallbackError::with_callback_type("prepare_rollback", error))
262        }));
263        self
264    }
265
266    /// Sets the commit action for a successfully completed prepare action.
267    ///
268    /// Errors returned by this action are converted to [`String`] and replace
269    /// an otherwise successful execution result with a prepare-commit failure.
270    ///
271    /// # Parameters
272    ///
273    /// * `commit_prepare_action` - The action to run if the task succeeds after
274    ///   prepare succeeds.
275    ///
276    /// # Returns
277    ///
278    /// This builder with prepare commit configured.
279    ///
280    /// # Errors
281    ///
282    /// This builder method does not return errors. If `commit_prepare_action`
283    /// later returns an error during execution, the execution result becomes
284    /// [`super::ExecutionResult::Failed`] with
285    /// [`super::ExecutorError::PrepareCommitFailed`].
286    #[inline]
287    #[must_use = "assign or chain the returned builder"]
288    pub fn commit_prepare<Rn, E>(mut self, commit_prepare_action: Rn) -> Self
289    where
290        Rn: Runnable<E> + Send + 'static,
291        E: Display,
292    {
293        let mut action = commit_prepare_action;
294        self.commit_prepare_action = Some(ArcRunnable::new(move || {
295            action
296                .run()
297                .map_err(|error| CallbackError::with_callback_type("prepare_commit", error))
298        }));
299        self
300    }
301
302    /// Enables panic capture for tester, prepare callbacks, and task execution.
303    ///
304    /// When enabled, panic payloads are converted to
305    /// [`super::executor_error::ExecutorError::Panic`] and surfaced through
306    /// [`super::ExecutionResult`].
307    ///
308    /// # Returns
309    ///
310    /// This builder with panic capture enabled.
311    #[inline]
312    #[must_use = "assign or chain the returned builder"]
313    pub fn catch_panics(mut self) -> Self {
314        self.catch_panics = true;
315        self
316    }
317
318    /// Derives a builder with panic capture enabled or disabled for tester,
319    /// prepare callbacks, and task execution.
320    ///
321    /// # Parameters
322    ///
323    /// * `catch_panics` - `true` to capture panics as execution errors, or
324    ///   `false` to let panics unwind.
325    ///
326    /// # Returns
327    ///
328    /// A reconfigured builder with the updated panic-capture setting.
329    #[inline]
330    #[must_use = "assign or chain the returned builder"]
331    pub fn with_panic_capture(mut self, catch_panics: bool) -> Self {
332        self.catch_panics = catch_panics;
333        self
334    }
335
336    /// Disables panic capture for tester, prepare callbacks, and task execution.
337    ///
338    /// # Returns
339    ///
340    /// This builder with panic capture disabled.
341    #[inline]
342    #[must_use = "assign or chain the returned builder"]
343    pub fn disable_catch_panics(mut self) -> Self {
344        self.catch_panics = false;
345        self
346    }
347
348    /// Builds the reusable executor.
349    ///
350    /// # Returns
351    ///
352    /// A [`DoubleCheckedLockExecutor`] containing the configured lock, tester,
353    /// execution logger, and prepare lifecycle callbacks.
354    #[inline]
355    #[must_use = "use the returned executor"]
356    pub fn build(self) -> DoubleCheckedLockExecutor<L, T> {
357        DoubleCheckedLockExecutor::new(self)
358    }
359}