behavior_actors/discovery/
resolver.rs1use behavior::{
4 Actions, Address, Behavior, BehaviorActed, BehaviorBase, Never, NoBirths, Protocol, Recipient,
5 User,
6};
7use thiserror::Error;
8
9use crate::DeliveryRoute;
10
11pub enum Resolution<K, D: Protocol> {
13 Found {
15 key: K,
17 recipient: Recipient<D>,
19 },
20 Missing {
22 key: K,
24 },
25}
26
27pub enum ResolverMessage<K, Route> {
29 Resolve {
31 key: K,
33 reply_to: Route,
35 },
36}
37
38#[derive(Debug, Error, Clone, PartialEq, Eq)]
40pub enum ResolverConfigError<K> {
41 #[error("resolver definition contains a duplicate key")]
43 DuplicateKey {
44 key: K,
47 },
48}
49
50pub struct Resolver<
63 A: Address,
64 K,
65 D: Protocol<Addr = A>,
66 Route: DeliveryRoute<Protocol: behavior::Protocol<Addr = A, Msg = Resolution<K, D>>>,
67> {
68 bindings: Vec<(K, Recipient<D>)>,
69 marker: core::marker::PhantomData<fn() -> (A, Route)>,
70}
71
72impl<A, K, D, Route> Resolver<A, K, D, Route>
73where
74 A: Address,
75 K: Clone + Eq,
76 D: Protocol<Addr = A>,
77 Route: DeliveryRoute<Protocol: behavior::Protocol<Addr = A, Msg = Resolution<K, D>>>,
78{
79 pub fn from_bindings(bindings: &[(K, Recipient<D>)]) -> Result<Self, ResolverConfigError<K>> {
86 let mut accepted = Vec::with_capacity(bindings.len());
87 for (key, recipient) in bindings {
88 if accepted
89 .iter()
90 .any(|(accepted_key, _): &(K, Recipient<D>)| accepted_key == key)
91 {
92 return Err(ResolverConfigError::DuplicateKey { key: key.clone() });
93 }
94 accepted.push((key.clone(), *recipient));
95 }
96 Ok(Self {
97 bindings: accepted,
98 marker: core::marker::PhantomData,
99 })
100 }
101
102 #[must_use]
104 pub fn bindings(&self) -> &[(K, Recipient<D>)] {
105 &self.bindings
106 }
107}
108
109impl<A, K, D, Route> BehaviorBase for Resolver<A, K, D, Route>
110where
111 A: Address,
112 D: Protocol<Addr = A>,
113 Route: DeliveryRoute<Protocol: behavior::Protocol<Addr = A, Msg = Resolution<K, D>>>,
114{
115 type Base = Self;
116 fn base(&self) -> &Self {
117 self
118 }
119}
120
121impl<A, K, D, Route> behavior::Protocol for Resolver<A, K, D, Route>
122where
123 A: Address,
124 D: Protocol<Addr = A>,
125 Route: DeliveryRoute<Protocol: behavior::Protocol<Addr = A, Msg = Resolution<K, D>>>,
126{
127 type Addr = A;
128 type Msg = ResolverMessage<K, Route>;
129}
130
131impl<A, K, D, Route> Behavior for Resolver<A, K, D, Route>
132where
133 A: Address,
134 K: Clone + Eq,
135 D: Protocol<Addr = A>,
136 Route: DeliveryRoute<Protocol: behavior::Protocol<Addr = A, Msg = Resolution<K, D>>>,
137 Route::Sends: behavior::SendsFor<User<A, ResolverMessage<K, Route>>>,
138{
139 type Protocol = Self;
140 type Event = User<A, behavior::BehaviorMessage<Self>>;
141 type Sends = Route::Sends;
142 type Ph = Never;
143 type Error = Never;
144 type Birth = NoBirths;
145
146 fn transition(&mut self, _: behavior::ActiveTurn, event: Self::Event) -> BehaviorActed<Self> {
147 let ResolverMessage::Resolve { key, reply_to } = event.message;
148 let result = self
149 .bindings
150 .iter()
151 .find(|(bound, _)| bound == &key)
152 .map_or(
153 Resolution::Missing { key: key.clone() },
154 |(_, recipient)| Resolution::Found {
155 key: key.clone(),
156 recipient: *recipient,
157 },
158 );
159 Ok(Actions::send(reply_to.deliver(result)))
160 }
161}
162
163#[cfg(test)]
164mod tests {
165 use super::*;
166 use crate::Activate as _;
167 use behavior::MailAddr;
168 struct Destination;
169 struct Reply;
170 impl behavior::Protocol for Destination {
171 type Addr = MailAddr;
172 type Msg = u8;
173 }
174
175 impl Behavior for Destination {
176 type Protocol = Self;
177 type Event = User<MailAddr, u8>;
178 type Sends = Vec<Never>;
179 type Ph = Never;
180 type Error = Never;
181 type Birth = NoBirths;
182 fn transition(&mut self, _: behavior::ActiveTurn, _: Self::Event) -> BehaviorActed<Self> {
183 Ok(Actions::cont())
184 }
185 }
186 impl behavior::Protocol for Reply {
187 type Addr = MailAddr;
188 type Msg = Resolution<u8, Destination>;
189 }
190
191 impl Behavior for Reply {
192 type Protocol = Self;
193 type Event = User<MailAddr, behavior::BehaviorMessage<Self>>;
194 type Sends = Vec<Never>;
195 type Ph = Never;
196 type Error = Never;
197 type Birth = NoBirths;
198 fn transition(&mut self, _: behavior::ActiveTurn, _: Self::Event) -> BehaviorActed<Self> {
199 Ok(Actions::cont())
200 }
201 }
202 type Subject = Resolver<MailAddr, u8, Destination, Recipient<Reply>>;
203 #[test]
204 fn duplicate_definition_is_rejected_without_consuming_source() {
205 let destination = Recipient::global(MailAddr(1));
206 let source = vec![(1, destination), (1, destination)];
207 assert!(matches!(
208 Subject::from_bindings(&source),
209 Err(ResolverConfigError::DuplicateKey { key: 1 })
210 ));
211 assert_eq!(source.len(), 2);
212 }
213 #[test]
214 fn protocol_reports_found_and_missing_without_mutation_authority() {
215 let destination = Recipient::global(MailAddr(1));
216 let mut s = (Subject::from_bindings(&[(1, destination)]).unwrap())
217 .initialize()
218 .unwrap()
219 .behavior;
220 for key in [1, 2] {
221 let a = s
222 .receive(
223 MailAddr(9),
224 ResolverMessage::Resolve {
225 key,
226 reply_to: Recipient::global(MailAddr(2)),
227 },
228 )
229 .unwrap();
230 assert!(matches!(
231 (&a.sends[0].message, key),
232 (Resolution::Found { .. }, 1) | (Resolution::Missing { .. }, 2)
233 ));
234 }
235 assert_eq!(s.bindings().len(), 1);
236 }
237}