deltachat/events.rs
1//! # Events specification.
2
3use anyhow::Result;
4use tokio::sync::Mutex;
5
6pub(crate) mod chatlist_events;
7mod payload;
8
9pub use self::payload::EventType;
10
11/// Event channel.
12#[derive(Debug, Clone)]
13pub struct Events {
14 /// Unused receiver to prevent the channel from closing.
15 _receiver: async_broadcast::InactiveReceiver<Event>,
16
17 /// Sender side of the event channel.
18 sender: async_broadcast::Sender<Event>,
19}
20
21impl Default for Events {
22 fn default() -> Self {
23 Self::new()
24 }
25}
26
27impl Events {
28 /// Creates a new event channel.
29 pub fn new() -> Self {
30 let (mut sender, _receiver) = async_broadcast::broadcast(1_000);
31
32 // We only keep this receiver around
33 // to prevent the channel from closing.
34 // Deactivating it to prevent it from consuming memory
35 // holding events that are not going to be received.
36 let _receiver = _receiver.deactivate();
37
38 // Remove oldest event on overflow.
39 sender.set_overflow(true);
40
41 Self { _receiver, sender }
42 }
43
44 /// Emits an event into event channel.
45 ///
46 /// If the channel is full, deletes the oldest event first.
47 pub fn emit(&self, event: Event) {
48 self.sender.try_broadcast(event).ok();
49 }
50
51 /// Creates an event emitter.
52 pub fn get_emitter(&self) -> EventEmitter {
53 EventEmitter(Mutex::new(self.sender.new_receiver()))
54 }
55}
56
57/// A receiver of events from a [`Context`].
58///
59/// See [`Context::get_event_emitter`] to create an instance. If multiple instances are
60/// created events emitted by the [`Context`] will only be delivered to one of the
61/// `EventEmitter`s.
62///
63/// [`Context`]: crate::context::Context
64/// [`Context::get_event_emitter`]: crate::context::Context::get_event_emitter
65#[derive(Debug)]
66pub struct EventEmitter(Mutex<async_broadcast::Receiver<Event>>);
67
68impl EventEmitter {
69 /// Async recv of an event. Return `None` if the `Sender` has been dropped.
70 ///
71 /// [`try_recv`]: Self::try_recv
72 pub async fn recv(&self) -> Option<Event> {
73 let mut lock = self.0.lock().await;
74 match lock.recv().await {
75 Err(async_broadcast::RecvError::Overflowed(n)) => Some(Event {
76 id: 0,
77 typ: EventType::EventChannelOverflow { n },
78 }),
79 Err(async_broadcast::RecvError::Closed) => None,
80 Ok(event) => Some(event),
81 }
82 }
83
84 /// Tries to receive an event without blocking.
85 ///
86 /// Returns error if no events are available for reception
87 /// or if receiver mutex is locked by a concurrent call to [`recv`]
88 /// or `try_recv`.
89 ///
90 /// [`recv`]: Self::recv
91 pub fn try_recv(&self) -> Result<Event> {
92 // Using `try_lock` instead of `lock`
93 // to avoid blocking
94 // in case there is a concurrent call to `recv`.
95 let mut lock = self.0.try_lock()?;
96 match lock.try_recv() {
97 Err(async_broadcast::TryRecvError::Overflowed(n)) => {
98 // Some events have been lost,
99 // but the channel is not closed.
100 Ok(Event {
101 id: 0,
102 typ: EventType::EventChannelOverflow { n },
103 })
104 }
105 res @ (Err(async_broadcast::TryRecvError::Empty)
106 | Err(async_broadcast::TryRecvError::Closed)
107 | Ok(_)) => Ok(res?),
108 }
109 }
110}
111
112/// The event emitted by a [`Context`] from an [`EventEmitter`].
113///
114/// Events are documented on the C/FFI API in `deltachat.h` as `DC_EVENT_*` constants. The
115/// context emits them in relation to various operations happening, a lot of these are again
116/// documented in `deltachat.h`.
117///
118/// [`Context`]: crate::context::Context
119#[derive(Debug, Clone, PartialEq, Eq)]
120pub struct Event {
121 /// The ID of the [`Context`] which emitted this event.
122 ///
123 /// This allows using multiple [`Context`]s in a single process as they are identified
124 /// by this ID.
125 ///
126 /// [`Context`]: crate::context::Context
127 pub id: u32,
128 /// The event payload.
129 ///
130 /// These are documented in `deltachat.h` as the `DC_EVENT_*` constants.
131 pub typ: EventType,
132}