use std::sync::Arc;
use tokio::sync::Mutex;
use crate::server::database::PvDatabase;
use super::manager::update_status_pvs;
use super::save_set::SaveSet;
pub(super) enum Tick<W> {
Unchanged(W),
Changed(W),
}
pub(super) struct ChangeWatermark<W> {
state: W,
set: Arc<SaveSet>,
lock: Arc<Mutex<()>>,
db: Arc<PvDatabase>,
status_prefix: Option<String>,
}
impl<W> ChangeWatermark<W> {
pub(super) fn new(
state: W,
set: Arc<SaveSet>,
lock: Arc<Mutex<()>>,
db: Arc<PvDatabase>,
status_prefix: Option<String>,
) -> Self {
Self {
state,
set,
lock,
db,
status_prefix,
}
}
pub(super) fn state(&self) -> &W {
&self.state
}
pub(super) fn set(&self) -> &SaveSet {
&self.set
}
pub(super) fn db(&self) -> &PvDatabase {
&self.db
}
pub(super) async fn advance(&mut self, tick: Tick<W>) {
let candidate = match tick {
Tick::Unchanged(next) => {
self.state = next;
return;
}
Tick::Changed(next) => next,
};
let _guard = self.lock.lock().await;
let result = self.set.save_once(&self.db).await;
if let Some(ref prefix) = self.status_prefix {
update_status_pvs(&self.db, prefix, &self.set, &result).await;
}
if result.is_ok() {
self.state = candidate;
}
}
}