confitdb 0.1.4

ConfitDB is an experimental, distributed, real-time database, giving full control on conflict resolution.
Documentation
use crate::server_error::ServerError;
use crate::server_status::ServerStatus;
use tokio::sync::oneshot::{channel, Receiver, Sender};

#[derive(Debug)]
pub struct ServerControl {
    shutdown_sender: Option<Sender<String>>,
    ready_receiver: Option<Receiver<Result<(), ServerError>>>,
    done_receiver: Option<Receiver<Result<(), ServerError>>>,
    pub current_status: ServerStatus,
    pub last_error: Result<(), ServerError>,
}

impl ServerControl {
    pub fn new() -> Self {
        ServerControl {
            shutdown_sender: None,
            ready_receiver: None,
            done_receiver: None,
            current_status: ServerStatus::Stopped,
            last_error: Ok({}),
        }
    }

    pub fn get_ready(
        &mut self,
    ) -> Result<
        (
            Receiver<String>,
            Sender<Result<(), ServerError>>,
            Sender<Result<(), ServerError>>,
        ),
        ServerError,
    > {
        match self.current_status {
            ServerStatus::Stopped => {
                let (shutdown_sender, shutdown_receiver) = channel::<String>();
                let (ready_sender, ready_receiver) = channel::<Result<(), ServerError>>();
                let (done_sender, done_receiver) = channel::<Result<(), ServerError>>();
                self.shutdown_sender = Some(shutdown_sender);
                self.ready_receiver = Some(ready_receiver);
                self.done_receiver = Some(done_receiver);
                self.last_error = Ok({});
                self.current_status = ServerStatus::Bootstrapping;
                Ok((shutdown_receiver, ready_sender, done_sender))
            }
            other => Err(ServerError::new(
                format!("invalid status {}", other).as_str(),
            )),
        }
    }

    pub fn stop(&mut self, msg: &str) -> Result<(), ServerError> {
        match self.current_status {
            ServerStatus::Running => {
                self.current_status = ServerStatus::Terminating;
                let ss = self.shutdown_sender.take().unwrap();
                ss.send(msg.to_string()).unwrap();
                Ok(())
            }
            other => Err(ServerError::new(
                format!("invalid status {}", other).as_str(),
            )),
        }
    }

    pub fn update_status(&mut self) {
        match self.current_status {
            ServerStatus::Stopped => {}
            ServerStatus::Bootstrapping => {
                let mut trier = self.ready_receiver.take();
                match &mut trier {
                    Some(tr) => match &tr.try_recv() {
                        Ok(e) => match e {
                            Ok(()) => {
                                self.current_status = ServerStatus::Running;
                            }
                            Err(ref err) => {
                                self.last_error = Err(err.clone());
                                self.current_status = ServerStatus::Stopped;
                            }
                        },
                        Err(_) => (),
                    },
                    None => {}
                }
                self.ready_receiver = trier;
            }
            ServerStatus::Running => {}
            ServerStatus::Terminating => {
                let mut trier = self.done_receiver.take();
                match &mut trier {
                    Some(tr) => match &tr.try_recv() {
                        Ok(e) => {
                            match e {
                                Ok(()) => (),
                                Err(ref err) => {
                                    self.last_error = Err(err.clone());
                                }
                            }
                            self.current_status = ServerStatus::Stopped;
                        }
                        Err(_) => (),
                    },
                    None => {}
                }
                self.done_receiver = trier;
            }
        }
    }
}