use crate::static_def::DATABASE;
use crate::time::timestamp;
use anyhow::*;
use aqueue::Actor;
use log::*;
use std::collections::HashMap;
use super::ConfigValue;
const CONFIG_VALUE_OUT_TIME: i64 = 5 * 600000000i64;
#[derive(Default)]
pub struct ConfigValueCache {
config_value: HashMap<String, ConfigValue>,
}
pub enum ConfigValueType {
I64(i64),
F64(f64),
String(String),
}
pub trait DBConfigValue: Send + Sync {
fn load_config_value(value: &ConfigValue) -> Option<Self>
where
Self: Sized;
fn modify_config_value(self, value: &mut ConfigValue);
}
impl DBConfigValue for String {
#[inline]
fn load_config_value(value: &ConfigValue) -> Option<Self> {
value.value_varchar.clone()
}
#[inline]
fn modify_config_value(self, value: &mut ConfigValue) {
value.value_varchar = Some(self)
}
}
impl DBConfigValue for i64 {
#[inline]
fn load_config_value(value: &ConfigValue) -> Option<Self> {
value.value_bigint
}
#[inline]
fn modify_config_value(self, value: &mut ConfigValue) {
value.value_bigint = Some(self)
}
}
impl DBConfigValue for f64 {
#[inline]
fn load_config_value(value: &ConfigValue) -> Option<Self> {
value.value_double
}
#[inline]
fn modify_config_value(self, value: &mut ConfigValue) {
value.value_double = Some(self)
}
}
impl ConfigValueCache {
#[inline]
pub fn new() -> Self {
Self::default()
}
#[inline]
async fn load_config_value<T: DBConfigValue>(&mut self, key: &str) -> Result<Option<T>> {
let value = DATABASE.load_config_value(key).await?;
if let Some(mut value) = value {
value.create_time = timestamp();
let ret = T::load_config_value(&value);
self.config_value.insert(value.key.clone(), value);
Ok(ret)
} else {
warn!("not found config key:{}", key);
Ok(None)
}
}
#[inline]
async fn read_config_value<T: DBConfigValue>(&mut self, key: &str) -> Result<Option<T>> {
if let Some(value) = self.config_value.get(key) {
if value.create_time + CONFIG_VALUE_OUT_TIME > timestamp() {
return Ok(T::load_config_value(value));
}
}
self.load_config_value(key).await
}
}
pub trait IConfigValue {
async fn get_config_value<T: DBConfigValue + 'static>(&self, key: &str) -> Result<Option<T>>;
}
impl IConfigValue for Actor<ConfigValueCache> {
#[inline]
async fn get_config_value<T: DBConfigValue + 'static>(&self, key: &str) -> Result<Option<T>> {
self.inner_call(|inner| async move { inner.get_mut().read_config_value::<T>(key).await })
.await
}
}