use std::sync::{Arc, Mutex};
use chrono::{DateTime, Utc};
use dashmap::DashMap;
use crate::{config_converter::convert_if_needed, Storage};
use crate::{sync_time::synchronized_start, Clock, EventCounterConfig, SingleEventCounter};
use crate::{Error, Result};
pub(crate) struct EventStoreInner {
pub(crate) events: DashMap<String, Arc<Mutex<SingleEventCounter>>>,
pub(crate) storage: Option<Arc<Mutex<Box<dyn Storage>>>>,
pub(crate) formatter: Option<Arc<dyn crate::Formatter>>,
pub(crate) clock: Arc<dyn Clock>,
pub(crate) config: EventCounterConfig,
}
impl EventStoreInner {
pub(crate) fn clock_now(&self) -> DateTime<Utc> {
self.clock.now()
}
pub(crate) fn get_counter_for_record(&self, event_id: &str) -> Arc<Mutex<SingleEventCounter>> {
let preloaded = if !self.events.contains_key(event_id) {
self.load_event_if_needed(event_id).ok().flatten()
} else {
None
};
self.events
.entry(event_id.to_string())
.or_insert_with(|| {
if let Some(counter) = preloaded {
return Arc::new(Mutex::new(counter));
}
Arc::new(Mutex::new(self.create_counter()))
})
.value()
.clone()
}
pub(crate) fn get_counter_for_query(
&self,
event_id: &str,
) -> Option<Arc<Mutex<SingleEventCounter>>> {
if let Some(entry) = self.events.get(event_id) {
return Some(entry.value().clone());
}
if let Ok(Some(counter)) = self.load_event_if_needed(event_id) {
let arc = Arc::new(Mutex::new(counter));
self.events.insert(event_id.to_string(), arc.clone());
return Some(arc);
}
None
}
fn create_counter(&self) -> SingleEventCounter {
let now = self.clock.now();
let starting_instant = synchronized_start(now);
self.config.create_counter(starting_instant)
}
fn load_event_if_needed(&self, event_id: &str) -> Result<Option<SingleEventCounter>> {
if self.events.contains_key(event_id) {
return Ok(None);
}
let storage = match &self.storage {
Some(s) => s,
None => return Ok(None),
};
let storage_guard = storage.lock().unwrap();
let data = match storage_guard.load(event_id)? {
Some(d) => d,
None => return Ok(None),
};
drop(storage_guard);
let formatter = self
.formatter
.as_ref()
.ok_or_else(|| Error::Serialization("No formatter configured".to_string()))?;
let mut counter: SingleEventCounter = formatter.deserialize(&data)?;
let now = self.clock.now();
counter.advance_if_needed(now);
let counter = convert_if_needed(counter, &self.config);
Ok(Some(counter))
}
}