You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
genmarkov/src/state.rs

138 lines
2.7 KiB

//! State
use super::*;
use tokio::{
sync::{
watch,
},
};
use config::Config;
use msg::Initialiser;
#[derive(Debug)]
pub struct ShutdownError;
impl error::Error for ShutdownError{}
impl fmt::Display for ShutdownError
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "shutdown signal caught")
}
}
#[derive(Debug, Clone)]
pub struct State
{
config: Arc<Config>, //to avoid cloning config
exclude: Arc<(sanitise::filter::Filter, sanitise::filter::Filter)>,
chain: Arc<RwLock<Chain<String>>>,
save: Arc<Notify>,
begin: Initialiser,
shutdown: Arc<watch::Sender<bool>>,
shutdown_recv: watch::Receiver<bool>,
}
impl State
{
/// Consume this `state` into its initialiser
pub fn into_initialiser(self) -> Initialiser
{
self.begin
}
/// Allow the saver task to start work
pub fn init(self) -> Result<(), msg::InitError>
{
self.begin.set()
}
/// Has `init` been called?
pub fn is_init(&self) -> bool
{
self.begin.is_set()
}
/// A future that completes either when `init` is called, or `shutdown`.
pub async fn on_init(&mut self) -> Result<(), ShutdownError>
{
if self.has_shutdown() {
return Err(ShutdownError);
}
let mut begin = self.begin.clone();
tokio::select!{ //fuck
Ok(()) = begin.wait() => Ok(()),
_ = self.on_shutdown() => {
debug!("on_init(): shutdown received");
Err(ShutdownError)
}
else => Err(ShutdownError)
}
}
pub fn inbound_filter(&self) -> &sanitise::filter::Filter
{
&self.exclude.0
}
pub fn outbound_filter(&self) -> &sanitise::filter::Filter
{
&self.exclude.1
}
pub fn new(config: Config, chain: Arc<RwLock<Chain<String>>>, save: Arc<Notify>) -> Self
{
let (shutdown, shutdown_recv) = watch::channel(false);
Self {
exclude: Arc::new((config.filter.get_inbound_filter(),
config.filter.get_outbound_filter())),
config: Arc::new(config),
chain,
save,
begin: Initialiser::new(),
shutdown: Arc::new(shutdown),
shutdown_recv,
}
}
pub fn config(&self) -> &Config
{
self.config.as_ref()
}
pub fn notify_save(&self)
{
self.save.notify();
}
pub fn chain(&self) -> &RwLock<Chain<String>>
{
&self.chain.as_ref()
}
pub fn when(&self) -> &Arc<Notify>
{
&self.save
}
pub fn shutdown(self)
{
self.shutdown.broadcast(true).expect("Failed to communicate shutdown");
self.save.notify();
}
pub fn has_shutdown(&self) -> bool
{
*self.shutdown_recv.borrow()
}
pub async fn on_shutdown(&mut self)
{
if !self.has_shutdown() {
while let Some(false) = self.shutdown_recv.recv().await {
}
}
}
}