Skip to main content

arcly_stream/engine/
builder.rs

1//! The engine builder — replaces `ApplicationRegistry::from_config`.
2
3use super::{AppSpec, Engine, EngineConfig};
4use crate::auth::{AllowAll, StreamAuthenticator};
5use crate::observe::{NoopObserver, Observer};
6use std::sync::Arc;
7
8/// Fluent builder for an [`Engine`]. Takes plain owned specs instead of a
9/// deserialized config schema, so consumers never adopt `stream-center`'s TOML.
10///
11/// ```
12/// use arcly_stream::prelude::*;
13///
14/// let engine = Engine::builder()
15///     .max_publishers(1_000)
16///     .application(AppSpec::new("live").broadcast_capacity(8192))
17///     .build();
18/// assert_eq!(engine.list_apps().len(), 1);
19/// ```
20pub struct EngineBuilder {
21    config: EngineConfig,
22    apps: Vec<AppSpec>,
23    observer: Option<Arc<dyn Observer>>,
24    authenticator: Option<Arc<dyn StreamAuthenticator>>,
25}
26
27impl EngineBuilder {
28    /// A fresh builder with default config, no apps, and permit-all auth.
29    pub fn new() -> Self {
30        Self {
31            config: EngineConfig::default(),
32            apps: Vec::new(),
33            observer: None,
34            authenticator: None,
35        }
36    }
37
38    /// Set the hard cap on concurrent publishing streams.
39    pub fn max_publishers(mut self, n: usize) -> Self {
40        self.config.max_publishers = n;
41        self
42    }
43
44    /// Replace the whole engine config.
45    pub fn config(mut self, config: EngineConfig) -> Self {
46        self.config = config;
47        self
48    }
49
50    /// Register an application.
51    pub fn application(mut self, app: AppSpec) -> Self {
52        self.apps.push(app);
53        self
54    }
55
56    /// Register many applications at once.
57    pub fn applications(mut self, apps: impl IntoIterator<Item = AppSpec>) -> Self {
58        self.apps.extend(apps);
59        self
60    }
61
62    /// Install a telemetry observer. Defaults to [`NoopObserver`] if unset.
63    pub fn observer<O: Observer>(mut self, observer: O) -> Self {
64        self.observer = Some(Arc::new(observer));
65        self
66    }
67
68    /// Install a pre-shared observer (when the host already holds an `Arc`).
69    pub fn observer_arc(mut self, observer: Arc<dyn Observer>) -> Self {
70        self.observer = Some(observer);
71        self
72    }
73
74    /// Install a stream authenticator. Defaults to [`AllowAll`] if unset.
75    pub fn authenticator<A: StreamAuthenticator>(mut self, auth: A) -> Self {
76        self.authenticator = Some(Arc::new(auth));
77        self
78    }
79
80    /// Install a pre-shared authenticator (when the host already holds an `Arc`).
81    pub fn authenticator_arc(mut self, auth: Arc<dyn StreamAuthenticator>) -> Self {
82        self.authenticator = Some(auth);
83        self
84    }
85
86    /// Set the idle timeout after which frame-less streams are reaped.
87    pub fn idle_timeout(mut self, timeout: std::time::Duration) -> Self {
88        self.config.idle_timeout = Some(timeout);
89        self
90    }
91
92    /// Build the engine.
93    pub fn build(self) -> Arc<Engine> {
94        let observer = self.observer.unwrap_or_else(|| Arc::new(NoopObserver));
95        let authenticator = self.authenticator.unwrap_or_else(|| Arc::new(AllowAll));
96        Engine::from_parts(self.config, self.apps, observer, authenticator)
97    }
98}
99
100impl Default for EngineBuilder {
101    fn default() -> Self {
102        Self::new()
103    }
104}