time/server/
mod.rs

1//! # Server
2//!
3//! This module contains everything related to servers. The server
4//! runs the timer, accepts connections from clients and sends
5//! responses. It accepts connections using server binders. A server
6//! should have at least one binder, otherwise it stops by itself.
7//!
8//!
9
10#[cfg(feature = "tcp-binder")]
11pub mod tcp;
12
13use async_trait::async_trait;
14use log::{debug, trace};
15use std::{
16    fmt::Debug,
17    future::Future,
18    io::{Error, ErrorKind, Result},
19    ops::{Deref, DerefMut},
20    sync::Arc,
21    time::Duration,
22};
23use tokio::{sync::Mutex, task, time};
24
25use crate::{
26    handler::{self, Handler},
27    request::{Request, RequestReader},
28    response::{Response, ResponseWriter},
29    timer::{ThreadSafeTimer, TimerConfig, TimerCycle, TimerEvent, TimerLoop},
30};
31
32/// The server state enum.
33///
34/// Enumeration of all the possible states of a server.
35#[derive(Clone, Debug, Default, Eq, PartialEq)]
36pub enum ServerState {
37    /// The server is in running mode, which blocks the main process.
38    Running,
39
40    /// The server received the order to stop.
41    Stopping,
42
43    /// The server is stopped and will free the main process.
44    #[default]
45    Stopped,
46}
47
48/// The server configuration.
49pub struct ServerConfig {
50    /// The server state changed handler.
51    handler: Arc<Handler<ServerEvent>>,
52
53    /// The binders list the server should use when starting up.
54    binders: Vec<Box<dyn ServerBind>>,
55}
56
57impl Default for ServerConfig {
58    fn default() -> Self {
59        Self {
60            handler: handler::default(),
61            binders: Vec::new(),
62        }
63    }
64}
65
66/// The server state changed event.
67#[derive(Clone, Debug, Eq, PartialEq)]
68pub enum ServerEvent {
69    /// The server just started.
70    Started,
71
72    /// The server is stopping.
73    Stopping,
74
75    /// The server has stopped.
76    Stopped,
77}
78
79/// Thread safe version of the server state.
80#[derive(Clone, Debug, Default)]
81pub struct ThreadSafeState(Arc<Mutex<ServerState>>);
82
83impl ThreadSafeState {
84    /// Create a new server thread safe state using defaults.
85    pub fn new() -> Self {
86        Self::default()
87    }
88
89    /// Change the inner server state with the given one.
90    async fn set(&self, next_state: ServerState) {
91        let mut state = self.lock().await;
92        *state = next_state;
93    }
94
95    /// Change the inner server state to running.
96    pub async fn set_running(&self) {
97        self.set(ServerState::Running).await
98    }
99
100    /// Change the inner server state to stopping.
101    pub async fn set_stopping(&self) {
102        self.set(ServerState::Stopping).await
103    }
104
105    /// Change the inner server state to stopped.
106    pub async fn set_stopped(&self) {
107        self.set(ServerState::Stopped).await
108    }
109}
110
111impl Deref for ThreadSafeState {
112    type Target = Arc<Mutex<ServerState>>;
113
114    fn deref(&self) -> &Self::Target {
115        &self.0
116    }
117}
118
119impl DerefMut for ThreadSafeState {
120    fn deref_mut(&mut self) -> &mut Self::Target {
121        &mut self.0
122    }
123}
124
125/// The server bind trait.
126///
127/// Server binders must implement this trait.
128#[async_trait]
129pub trait ServerBind: Debug + Send + Sync {
130    /// Describe how the server should bind to accept connections from
131    /// clients.
132    async fn bind(&self, timer: ThreadSafeTimer) -> Result<()>;
133}
134
135/// The server stream trait.
136///
137/// Describes how a request should be parsed and handled.
138#[async_trait]
139pub trait ServerStream: RequestReader + ResponseWriter {
140    /// Read the request, process it then write the response.
141    async fn handle(&mut self, timer: ThreadSafeTimer) -> Result<()> {
142        let req = self.read().await?;
143        let res = match req {
144            Request::Start => {
145                debug!("starting timer");
146                timer.start().await?;
147                Response::Ok
148            }
149            Request::Get => {
150                debug!("getting timer");
151                let timer = timer.get().await;
152                trace!("{timer:#?}");
153                Response::Timer(timer)
154            }
155            Request::Set(duration) => {
156                debug!("setting timer");
157                timer.set(duration).await?;
158                Response::Ok
159            }
160            Request::Pause => {
161                debug!("pausing timer");
162                timer.pause().await?;
163                Response::Ok
164            }
165            Request::Resume => {
166                debug!("resuming timer");
167                timer.resume().await?;
168                Response::Ok
169            }
170            Request::Stop => {
171                debug!("stopping timer");
172                timer.stop().await?;
173                Response::Ok
174            }
175        };
176        self.write(res).await?;
177        Ok(())
178    }
179}
180
181impl<T: RequestReader + ResponseWriter> ServerStream for T {}
182
183/// The server struct.
184#[derive(Default)]
185pub struct Server {
186    /// The server configuration.
187    config: ServerConfig,
188
189    /// The current server state.
190    state: ThreadSafeState,
191
192    /// The current server timer.
193    timer: ThreadSafeTimer,
194}
195
196impl Server {
197    /// Start the server by running the timer in a dedicated thread as
198    /// well as all the binders in dedicated threads.
199    ///
200    /// The main thread is then blocked by the given `wait` closure.
201    pub async fn bind_with<F: Future<Output = Result<()>>>(
202        self,
203        wait: impl FnOnce() -> F + Send + Sync + 'static,
204    ) -> Result<()> {
205        debug!("starting server");
206
207        let handler = &self.config.handler;
208        let fire_event = |event: ServerEvent| async move {
209            debug!("firing server event {event:?}");
210            if let Err(err) = handler(event.clone()).await {
211                debug!("error while firing server event, skipping it");
212                debug!("{err:?}");
213            }
214        };
215
216        self.state.set_running().await;
217        fire_event(ServerEvent::Started).await;
218
219        // the tick represents the timer running in a separated thread
220        let state = self.state.clone();
221        let timer = self.timer.clone();
222        let tick = task::spawn(async move {
223            loop {
224                let mut state = state.lock().await;
225                match *state {
226                    ServerState::Stopping => {
227                        *state = ServerState::Stopped;
228                        break;
229                    }
230                    ServerState::Stopped => {
231                        break;
232                    }
233                    ServerState::Running => {
234                        timer.update().await;
235                    }
236                };
237                drop(state);
238
239                time::sleep(Duration::from_secs(1)).await;
240            }
241        });
242
243        // start all binders in dedicated threads in order not to
244        // block the main thread
245        for binder in self.config.binders {
246            let timer = self.timer.clone();
247            task::spawn(async move {
248                debug!("binding {binder:?}");
249                if let Err(err) = binder.bind(timer).await {
250                    debug!("error while binding, skipping it");
251                    debug!("{err:?}");
252                }
253            });
254        }
255
256        debug!("main loop started");
257        wait().await?;
258        debug!("main loop stopped");
259
260        self.state.set_stopping().await;
261        fire_event(ServerEvent::Stopping).await;
262
263        // wait for the timer thread to stop before exiting
264        tick.await
265            .map_err(|_| Error::new(ErrorKind::Other, "cannot wait for timer thread"))?;
266        fire_event(ServerEvent::Stopped).await;
267
268        Ok(())
269    }
270
271    /// Wrapper around [`Server::bind_with`] where the `wait` closure
272    /// sleeps every second in an infinite loop.
273    pub async fn bind(self) -> Result<()> {
274        self.bind_with(|| async {
275            loop {
276                time::sleep(Duration::from_secs(1)).await;
277            }
278        })
279        .await
280    }
281}
282
283/// The server builder.
284///
285/// Convenient builder to help building a final [`Server`].
286#[derive(Default)]
287pub struct ServerBuilder {
288    /// The server configuration.
289    server_config: ServerConfig,
290
291    /// The timer configuration.
292    timer_config: TimerConfig,
293}
294
295impl ServerBuilder {
296    /// Create a new server builder using defaults.
297    pub fn new() -> Self {
298        Self::default()
299    }
300
301    /// Set the server configuration.
302    pub fn with_server_config(mut self, config: ServerConfig) -> Self {
303        self.server_config = config;
304        self
305    }
306
307    /// Set the timer configuration.
308    pub fn with_timer_config(mut self, config: TimerConfig) -> Self {
309        self.timer_config = config;
310        self
311    }
312
313    /// Configure the timer to follow the Pomodoro time management
314    /// method, which alternates 25 min of work and 5 min of breaks 4
315    /// times, then ends with a long break of 15 min.
316    ///
317    /// See <https://en.wikipedia.org/wiki/Pomodoro_Technique>.
318    pub fn with_pomodoro_config(mut self) -> Self {
319        let work = TimerCycle::new("Work", 25 * 60);
320        let short_break = TimerCycle::new("Short break", 5 * 60);
321        let long_break = TimerCycle::new("Long break", 15 * 60);
322
323        *self.timer_config.cycles = vec![
324            work.clone(),
325            short_break.clone(),
326            work.clone(),
327            short_break.clone(),
328            work.clone(),
329            short_break.clone(),
330            work.clone(),
331            short_break.clone(),
332            long_break,
333        ];
334        self
335    }
336
337    /// Configure the timer to follow the 52/17 time management
338    /// method, which alternates 52 min of work and 17 min of resting.
339    ///
340    /// See <https://en.wikipedia.org/wiki/52/17_rule>.
341    pub fn with_52_17_config(mut self) -> Self {
342        let work = TimerCycle::new("Work", 52 * 60);
343        let rest = TimerCycle::new("Rest", 17 * 60);
344
345        *self.timer_config.cycles = vec![work, rest];
346        self
347    }
348
349    /// Set the server handler.
350    pub fn with_server_handler<F: Future<Output = Result<()>> + Send + 'static>(
351        mut self,
352        handler: impl Fn(ServerEvent) -> F + Send + Sync + 'static,
353    ) -> Self {
354        self.server_config.handler = Arc::new(move |evt| Box::pin(handler(evt)));
355        self
356    }
357
358    /// Push the given server binder.
359    pub fn with_binder(mut self, binder: Box<dyn ServerBind>) -> Self {
360        self.server_config.binders.push(binder);
361        self
362    }
363
364    /// Set the timer handler.
365    pub fn with_timer_handler<F: Future<Output = Result<()>> + Send + 'static>(
366        mut self,
367        handler: impl Fn(TimerEvent) -> F + Sync + Send + 'static,
368    ) -> Self {
369        self.timer_config.handler = Arc::new(move |evt| Box::pin(handler(evt)));
370        self
371    }
372
373    /// Push the given timer cycle.
374    pub fn with_cycle<C>(mut self, cycle: C) -> Self
375    where
376        C: Into<TimerCycle>,
377    {
378        self.timer_config.cycles.push(cycle.into());
379        self
380    }
381
382    /// Set the timer cycles.
383    pub fn with_cycles<C, I>(mut self, cycles: I) -> Self
384    where
385        C: Into<TimerCycle>,
386        I: IntoIterator<Item = C>,
387    {
388        for cycle in cycles {
389            self.timer_config.cycles.push(cycle.into());
390        }
391        self
392    }
393
394    /// Set the timer cycles count.
395    pub fn with_cycles_count(mut self, count: impl Into<TimerLoop>) -> Self {
396        self.timer_config.cycles_count = count.into();
397        self
398    }
399
400    /// Build the final server.
401    pub fn build(self) -> Result<Server> {
402        Ok(Server {
403            config: self.server_config,
404            state: ThreadSafeState::new(),
405            timer: ThreadSafeTimer::new(self.timer_config)?,
406        })
407    }
408}