mod v1;
mod v2;
mod v3;
use crate::{
config::Config,
persistence::{
PersistentStorage,
error::{PersistenceError, PersistenceResult},
},
server::CloneableWbApi,
worterbuch::Worterbuch,
};
use serde::{Deserialize, Serialize};
use serde_json::json;
use sha2::{Digest, Sha256};
use std::path::{Path, PathBuf};
use tokio::{
fs::{self, File, remove_file},
io::{AsyncReadExt, AsyncWriteExt},
select,
};
use tokio_graceful_shutdown::{SubsystemBuilder, SubsystemHandle};
use tracing::{debug, info, instrument, warn};
use worterbuch_common::{GraveGoods, Key, LastWill, ValueEntry};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
struct GraveGoodsLastWill {
grave_goods: GraveGoods,
last_will: LastWill,
}
pub(crate) async fn periodic(
worterbuch: CloneableWbApi,
config: Config,
subsys: &mut SubsystemHandle,
) -> PersistenceResult<()> {
v3::periodic(worterbuch, config, subsys).await
}
pub(crate) async fn synchronous(
worterbuch: &mut Worterbuch,
config: &Config,
) -> PersistenceResult<()> {
v3::synchronous(worterbuch, config).await
}
#[instrument(skip(config), err)]
pub(crate) async fn load(config: &Config) -> PersistenceResult<Worterbuch> {
info!("Trying to load v3 persistence file …");
match v3::load(config).await {
Ok(wb) => Ok(wb),
Err(e) => {
warn!("Could not load persistence file: {e}");
info!("Trying to load v2 persistence file …");
match v2::load(config).await {
Ok(wb) => Ok(wb),
Err(e) => {
warn!("Could not load persistence file: {e}");
info!("Trying to load v1 persistence file …");
v1::load(config).await
}
}
}
}
}
#[derive(PartialEq)]
pub struct PersistentJsonStorage {
config: Config,
}
impl PersistentJsonStorage {
pub fn new(
subsys: &SubsystemHandle,
config: Config,
api: CloneableWbApi,
flush_periodically: bool,
) -> Self {
info!("Using JSON file persistence.");
if flush_periodically {
let config_pers = config.clone();
subsys.start(SubsystemBuilder::new(
"json-persistence",
async |subsys: &mut SubsystemHandle| periodic(api, config_pers, subsys).await,
));
}
Self { config }
}
}
impl PersistentStorage for PersistentJsonStorage {
async fn update_value(&self, _: &Key, _: &ValueEntry) -> PersistenceResult<()> {
Ok(())
}
async fn delete_value(&self, _: &Key) -> PersistenceResult<()> {
Ok(())
}
async fn flush(&mut self, worterbuch: &mut Worterbuch) -> PersistenceResult<()> {
synchronous(worterbuch, &self.config).await
}
async fn load(&self, _: &Config) -> PersistenceResult<Worterbuch> {
load(&self.config).await
}
async fn clear(&self) -> PersistenceResult<()> {
Ok(())
}
}