crb_agent/message/
event.rs

1use crate::address::{Address, Envelope, MessageFor};
2use crate::agent::Agent;
3use crate::context::Context;
4use anyhow::{Error, Result, anyhow};
5use async_trait::async_trait;
6use crb_core::Tag;
7use crb_send::Recipient;
8
9pub trait EventExt<E: TheEvent> {
10    fn event(&self, event: E) -> Result<()>;
11}
12
13impl<A, E> EventExt<E> for Address<A>
14where
15    A: OnEvent<E>,
16    E: TheEvent,
17{
18    fn event(&self, event: E) -> Result<()> {
19        Address::event(self, event)
20    }
21}
22
23impl<A, E> EventExt<E> for Context<A>
24where
25    A: OnEvent<E>,
26    E: TheEvent,
27{
28    fn event(&self, event: E) -> Result<()> {
29        self.address().event(event)
30    }
31}
32
33pub trait TheEvent: Send + 'static {}
34
35impl<T> TheEvent for T where Self: Send + 'static {}
36
37impl<A: Agent> Address<A> {
38    pub fn event<E>(&self, event: E) -> Result<()>
39    where
40        A: OnEvent<E>,
41        E: TheEvent,
42    {
43        self.send(Event::new(event))
44    }
45
46    pub fn event_tagged<E, T>(&self, event: E, tag: T) -> Result<()>
47    where
48        A: OnEvent<E, T>,
49        E: TheEvent,
50        T: Tag,
51    {
52        self.send(Event::new_tagged(event, tag))
53    }
54
55    pub fn recipient<E>(&self) -> Recipient<E>
56    where
57        A: OnEvent<E>,
58        E: TheEvent,
59    {
60        Recipient::new(self.clone()).reform(Event::new)
61    }
62
63    pub fn recipient_tagged<E, T>(&self, tag: T) -> Recipient<E>
64    where
65        A: OnEvent<E, T>,
66        E: TheEvent,
67        T: Tag + Sync + Clone,
68    {
69        Recipient::new(self.clone()).reform(move |event| Event::new_tagged(event, tag.clone()))
70    }
71}
72
73impl<A: Agent> Context<A> {
74    pub fn event<E>(&self, event: E) -> Result<()>
75    where
76        A: OnEvent<E>,
77        E: TheEvent,
78    {
79        self.address().event(event)
80    }
81
82    pub fn event_tagged<E, T>(&self, event: E, tag: T) -> Result<()>
83    where
84        A: OnEvent<E, T>,
85        E: TheEvent,
86        T: Tag,
87    {
88        self.address().event_tagged(event, tag)
89    }
90
91    pub fn recipient<E>(&self) -> Recipient<E>
92    where
93        A: OnEvent<E>,
94        E: TheEvent,
95    {
96        self.address().recipient()
97    }
98
99    pub fn recipient_tagged<E, T>(&self, tag: T) -> Recipient<E>
100    where
101        A: OnEvent<E, T>,
102        E: TheEvent,
103        T: Tag + Sync + Clone,
104    {
105        self.address().recipient_tagged(tag)
106    }
107}
108
109/// Do not introduce tags: use event wrapper instead.
110#[async_trait]
111pub trait OnEvent<E: TheEvent, T: Tag = ()>: Agent {
112    // TODO: Add when RFC 192 will be implemented (associated types defaults)
113    // type Error: Into<Error> + Send + 'static;
114
115    async fn handle_tagged(&mut self, event: E, _tag: T, ctx: &mut Context<Self>) -> Result<()> {
116        self.handle(event, ctx).await
117    }
118
119    async fn handle(&mut self, _event: E, _ctx: &mut Context<Self>) -> Result<()> {
120        Err(anyhow!("The handle method in not implemented."))
121    }
122
123    async fn fallback(&mut self, err: Error, _ctx: &mut Context<Self>) -> Result<()> {
124        Err(err)
125    }
126}
127
128pub struct Event<E, T = ()> {
129    event: E,
130    tag: T,
131}
132
133impl<E> Event<E> {
134    pub fn new(event: E) -> Self {
135        Self { event, tag: () }
136    }
137
138    pub fn envelope<A>(event: E) -> Envelope<A>
139    where
140        A: OnEvent<E>,
141        E: TheEvent,
142    {
143        Self::new(event).into_envelope::<A>()
144    }
145}
146
147impl<E, T> Event<E, T> {
148    pub fn new_tagged(event: E, tag: T) -> Self {
149        Self { event, tag }
150    }
151}
152
153impl<E, T> Event<E, T>
154where
155    E: TheEvent,
156    T: Tag,
157{
158    pub fn into_envelope<A>(self) -> Envelope<A>
159    where
160        A: OnEvent<E, T>,
161    {
162        Box::new(self)
163    }
164}
165
166#[async_trait]
167impl<A, E, T> MessageFor<A> for Event<E, T>
168where
169    A: OnEvent<E, T>,
170    E: TheEvent,
171    T: Tag,
172{
173    async fn handle(self: Box<Self>, agent: &mut A, ctx: &mut Context<A>) -> Result<()> {
174        if let Err(err) = agent.handle_tagged(self.event, self.tag, ctx).await {
175            agent.fallback(err, ctx).await
176        } else {
177            Ok(())
178        }
179    }
180}