farmfe_core 2.1.0

Core types and data structures for farm.
use std::sync::Arc;

use dashmap::DashMap;
use rayon::iter::{IntoParallelIterator, ParallelIterator};

use crate::{
  cache::{
    store::{constant::CacheStoreTrait, CacheStoreKey},
    CacheContext,
    // cache_store::{CacheStore, CacheStoreKey},
    // resource_cache::resource_memory_store::ArchivedCachedResourcePot,
  },
  deserialize, serialize, HashMap,
};

use super::resource_memory_store::{CachedResourcePot, ResourceMemoryStore};

/// In memory store for Resource Pot
pub struct ResourcePotMemoryStore {
  /// low level cache store
  store: Box<dyn CacheStoreTrait>,
  /// resource pot id -> Cached Resource Pot
  cached_resources: DashMap<String, CachedResourcePot>,
}

impl ResourcePotMemoryStore {
  pub fn new(context: Arc<CacheContext>) -> Self {
    let store = context.store_factory.create_cache_store("resource");

    Self {
      store,
      cached_resources: DashMap::new(),
    }
  }

  pub fn is_cache_changed(&self, name: String, hash: String) -> bool {
    self
      .store
      .is_cache_changed(&CacheStoreKey { name, key: hash })
  }
}

impl ResourceMemoryStore for ResourcePotMemoryStore {
  fn has_cache(&self, name: &str) -> bool {
    if self.cached_resources.contains_key(name) {
      return true;
    }

    self.store.has_cache(name)
  }

  fn set_cache(&self, name: &str, resource: CachedResourcePot) {
    self.cached_resources.insert(name.to_string(), resource);
  }

  fn get_cache(&self, name: &str) -> Option<CachedResourcePot> {
    if let Some((_, resource)) = self.cached_resources.remove(name) {
      return Some(resource);
    }

    if let Some(cache) = self.store.read_cache_ref(name) {
      let resource = deserialize!(&cache.value(), CachedResourcePot);
      return Some(resource);
    }

    None
  }

  fn write_cache(&self) {
    let mut cache_map = HashMap::default();

    for entry in self.cached_resources.iter() {
      let store_key = CacheStoreKey {
        name: entry.key().clone(),
        key: entry.value().hash.clone(),
      };

      if self.store.is_cache_changed(&store_key) {
        cache_map.insert(store_key, entry);
      }
    }

    let cache_map = cache_map
      .into_par_iter()
      .map(|(store_key, resource)| (store_key, serialize!(resource.value())))
      .collect::<HashMap<_, _>>();

    self.store.write_cache(cache_map);
  }
}