time/server/
mod.rs

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