maiko/actor_builder.rs
1use std::sync::Arc;
2
3use tokio::sync::mpsc::Receiver;
4
5use crate::{
6 Actor, ActorConfig, ActorId, Context, Envelope, Event, Result, Subscribe, Supervisor, Topic,
7 internal::Subscription,
8};
9
10/// Builder for registering an actor with custom configuration.
11///
12/// Returned by [`Supervisor::build_actor`]. Use this when you need to override
13/// per-actor settings such as channel capacity or when you want to separate
14/// actor construction from topic subscription.
15///
16/// Defaults to no topic subscriptions and channel capacity inherited from the
17/// global [`SupervisorConfig`](crate::SupervisorConfig).
18///
19/// # Examples
20///
21/// ```rust,ignore
22/// // Custom channel capacity for a slow consumer
23/// sup.build_actor("writer", |ctx| Writer::new(ctx))
24/// .topics(&[Topic::Data])
25/// .channel_capacity(512)
26/// .build()?;
27///
28/// // Replace the entire actor config
29/// sup.build_actor("fast", |ctx| Fast::new(ctx))
30/// .topics(Subscribe::all())
31/// .config(my_config)
32/// .build()?;
33/// ```
34///
35/// [`Supervisor::build_actor`]: crate::Supervisor::build_actor
36#[must_use = "actor is not registered until .build() is called"]
37pub struct ActorBuilder<'a, E: Event, T: Topic<E>, A: Actor<Event = E>> {
38 supervisor: &'a mut Supervisor<E, T>,
39 actor: A,
40 ctx: Context<A::Event>,
41 config: ActorConfig,
42 topics: Subscription<T>,
43 receiver: Receiver<Arc<Envelope<E>>>,
44}
45
46impl<'a, E: Event, T: Topic<E>, A: Actor<Event = E>> ActorBuilder<'a, E, T, A> {
47 pub(crate) fn new(
48 supervisor: &'a mut Supervisor<E, T>,
49 actor: A,
50 ctx: Context<A::Event>,
51 receiver: Receiver<Arc<Envelope<E>>>,
52 ) -> Self {
53 let config = ActorConfig::new(supervisor.config());
54 Self {
55 supervisor,
56 ctx,
57 actor,
58 config,
59 topics: Subscription::None,
60 receiver,
61 }
62 }
63
64 /// Set the topics this actor subscribes to.
65 ///
66 /// Accepts anything that converts to [`Subscribe`]: a topic slice,
67 /// [`Subscribe::all()`], or [`Subscribe::none()`].
68 pub fn topics<S>(mut self, topics: S) -> Self
69 where
70 S: Into<Subscribe<E, T>>,
71 {
72 self.topics = topics.into().0;
73 self
74 }
75
76 /// Replace the entire [`ActorConfig`] for this actor.
77 pub fn config<C>(mut self, config: C) -> Self
78 where
79 C: Into<ActorConfig>,
80 {
81 self.config = config.into();
82 self
83 }
84
85 /// Transform the current [`ActorConfig`] with a closure.
86 ///
87 /// Unlike [`config()`](Self::config) which replaces the entire config,
88 /// this preserves inherited defaults and lets you tweak individual fields.
89 ///
90 /// ```rust,ignore
91 /// sup.build_actor("consumer", |ctx| Consumer::new(ctx))
92 /// .topics(&[Topic::Data])
93 /// .channel_capacity(256)
94 /// .with_config(|c| c.with_max_events_per_tick(64))
95 /// .build()?;
96 /// ```
97 pub fn with_config<F>(mut self, f: F) -> Self
98 where
99 F: FnOnce(ActorConfig) -> ActorConfig,
100 {
101 self.config = f(self.config);
102 self
103 }
104
105 /// Set the actor's mailbox channel capacity.
106 ///
107 /// Shorthand for modifying the channel capacity without replacing the
108 /// full config. See [`ActorConfig::with_channel_capacity`].
109 pub fn channel_capacity(mut self, capacity: usize) -> Self {
110 self.config = self.config.with_channel_capacity(capacity);
111 self
112 }
113
114 /// Register the actor with the supervisor and return its [`ActorId`].
115 ///
116 /// # Errors
117 ///
118 /// Returns [`Error::DuplicateActorName`](crate::Error::DuplicateActorName)
119 /// if an actor with the same name is already registered.
120 pub fn build(self) -> Result<ActorId> {
121 self.supervisor.register_actor(
122 self.ctx,
123 self.actor,
124 self.topics,
125 self.config,
126 self.receiver,
127 )
128 }
129}