use std::sync::{Arc, Mutex};
use arc_swap::ArcSwap;
use tokio::task::JoinHandle;
use crate::receipt_store::ReceiptWriterLiveness;
pub(crate) struct ReceiptWriterWatchdogHandle {
verdict: ArcSwap<ReceiptWriterLiveness>,
join: Mutex<Option<JoinHandle<()>>>,
}
impl ReceiptWriterWatchdogHandle {
pub(crate) fn new() -> Self {
Self {
verdict: ArcSwap::from_pointee(ReceiptWriterLiveness::Unknown),
join: Mutex::new(None),
}
}
pub(crate) fn current(&self) -> ReceiptWriterLiveness {
**self.verdict.load()
}
pub(crate) fn publish(&self, verdict: ReceiptWriterLiveness) {
self.verdict.store(Arc::new(verdict));
}
pub(crate) fn set_join_handle(&self, handle: JoinHandle<()>) {
let previous = match self.join.lock() {
Ok(mut join) => join.replace(handle),
Err(poisoned) => poisoned.into_inner().replace(handle),
};
if let Some(previous) = previous {
previous.abort();
}
}
#[cfg(test)]
pub(crate) fn is_running(&self) -> bool {
match self.join.lock() {
Ok(join) => join.is_some(),
Err(poisoned) => poisoned.into_inner().is_some(),
}
}
pub(crate) async fn shutdown(&self) {
let handle = {
let mut join = match self.join.lock() {
Ok(join) => join,
Err(poisoned) => poisoned.into_inner(),
};
join.take()
};
if let Some(handle) = handle {
handle.abort();
let _ = handle.await;
}
}
}