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

89 lines
2.6 KiB
Rust

use mediarepo_core::bincode;
use mediarepo_core::error::RepoResult;
use mediarepo_logic::dao::job::JobDao;
use mediarepo_logic::dto::UpsertJobStateDto;
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use tokio::sync::RwLock;
#[derive(Debug)]
pub struct StateData {
job_id: i64,
inner: Arc<RwLock<HashMap<String, Vec<u8>>>>,
changed_keys: Arc<RwLock<HashSet<String>>>,
}
impl StateData {
pub fn job_id(&self) -> i64 {
self.job_id
}
/// Loads the state from the database
pub async fn load(job_dao: JobDao, job_id: i64) -> RepoResult<Self> {
let states = job_dao.states_for_job_id(job_id).await?;
let states_map = states
.into_iter()
.map(|s| (s.key().to_owned(), s.into_value()))
.collect::<HashMap<String, Vec<u8>>>();
Ok(Self {
job_id,
inner: Arc::new(RwLock::new(states_map)),
changed_keys: Default::default(),
})
}
/// Returns the deserialized copy of a state object from the inner map
pub async fn entry<S: AsRef<str>, T: DeserializeOwned>(&self, key: S) -> RepoResult<Option<T>> {
let entries = self.inner.read().await;
let entry = entries.get(key.as_ref());
if let Some(bytes) = entry {
let value = bincode::deserialize(bytes)?;
Ok(Some(value))
} else {
Ok(None)
}
}
/// Stores an entry in inner map
pub async fn store_entry<T: Serialize>(&self, key: String, value: &T) -> RepoResult<()> {
let entry_bytes = bincode::serialize(value)?;
let mut entries = self.inner.write().await;
entries.insert(key.clone(), entry_bytes);
let mut changed_entries = self.changed_keys.write().await;
changed_entries.insert(key);
Ok(())
}
/// Returns a list of all changed state objects as an upsert list
pub async fn changed_states(&self) -> Vec<UpsertJobStateDto> {
let mut upsert_list = Vec::new();
{
let changed_keys = self.changed_keys.read().await;
let entries = self.inner.read().await;
for key in &*changed_keys {
if let Some(value) = entries.get(key) {
upsert_list.push(UpsertJobStateDto {
job_id: self.job_id,
key: key.to_owned(),
value: value.clone(),
});
}
}
}
{
let mut changed_keys = self.changed_keys.write().await;
changed_keys.clear();
}
upsert_list
}
}