Skip to main content

aion/runtime/
config.rs

1//! Builder-supplied scheduler configuration for the embedded runtime.
2
3use std::time::Duration;
4
5/// Configuration used when constructing the embedded BEAM runtime.
6#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
7pub struct RuntimeConfig {
8    /// Optional scheduler thread count supplied by the engine builder.
9    ///
10    /// `None` is passed through to beamr so the embedded runtime applies its own
11    /// runtime-aware default.
12    pub thread_count: Option<usize>,
13
14    /// Bounded readiness and retry policy for live signal mailbox delivery.
15    pub signal_delivery: SignalDeliveryConfig,
16
17    /// Whether the durable-outbox fan-out dispatch path is enabled.
18    pub outbox_enabled: bool,
19}
20
21/// Bounded signal delivery retry policy supplied by engine configuration.
22#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub struct SignalDeliveryConfig {
24    /// Maximum time to wait for a just-spawned process body to materialize.
25    pub ready_timeout: Duration,
26
27    /// Maximum number of mailbox enqueue attempts after the ready gate.
28    pub max_enqueue_attempts: u32,
29
30    /// Initial sleep between failed enqueue attempts.
31    pub initial_backoff: Duration,
32
33    /// Upper bound for exponential backoff between enqueue attempts.
34    pub max_backoff: Duration,
35}
36
37impl Default for SignalDeliveryConfig {
38    fn default() -> Self {
39        Self::new(
40            Duration::from_millis(50),
41            8,
42            Duration::from_millis(1),
43            Duration::from_millis(8),
44        )
45    }
46}
47
48impl SignalDeliveryConfig {
49    /// Create an explicit signal delivery policy.
50    #[must_use]
51    pub const fn new(
52        ready_timeout: Duration,
53        max_enqueue_attempts: u32,
54        initial_backoff: Duration,
55        max_backoff: Duration,
56    ) -> Self {
57        Self {
58            ready_timeout,
59            max_enqueue_attempts,
60            initial_backoff,
61            max_backoff,
62        }
63    }
64
65    /// Bound for draining the single cleanup worker after every registered
66    /// process has been force-unblocked.
67    ///
68    /// A zero process-readiness bound is valid for refusal tests, but is not a
69    /// useful thread-shutdown observation window. Use at least the standard
70    /// readiness window and scale it by every job the worker can own (one
71    /// running plus the bounded queue) rather than imposing an unrelated
72    /// timeout constant.
73    pub(crate) fn cleanup_shutdown_timeout(self) -> Duration {
74        self.ready_timeout
75            .max(Self::default().ready_timeout)
76            .saturating_mul(self.max_enqueue_attempts.max(1).saturating_add(1))
77    }
78}
79
80impl RuntimeConfig {
81    /// Create runtime configuration from the builder-supplied scheduler count.
82    #[must_use]
83    pub fn new(thread_count: Option<usize>) -> Self {
84        Self {
85            thread_count,
86            signal_delivery: SignalDeliveryConfig::default(),
87            outbox_enabled: false,
88        }
89    }
90
91    /// Override the signal delivery retry policy.
92    #[must_use]
93    pub const fn with_signal_delivery(mut self, signal_delivery: SignalDeliveryConfig) -> Self {
94        self.signal_delivery = signal_delivery;
95        self
96    }
97
98    /// Override whether the durable-outbox fan-out dispatch path is enabled.
99    #[must_use]
100    pub const fn with_outbox_enabled(mut self, enabled: bool) -> Self {
101        self.outbox_enabled = enabled;
102        self
103    }
104}