cache
This commit is contained in:
parent
84ef28312e
commit
37cca40192
4 changed files with 124 additions and 2 deletions
|
@ -3,6 +3,10 @@ name = "mongod"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
cache = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = "0.4.38"
|
chrono = "0.4.38"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
|
|
38
src/cache.rs
Normal file
38
src/cache.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
// todo : implement cache feature
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ModelCache {
|
||||||
|
cache: HashMap<String, HashMap<String, mongodb::bson::Document>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModelCache {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
cache: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, col: &str, id: &str, model: mongodb::bson::Document) {
|
||||||
|
let collection = self
|
||||||
|
.cache
|
||||||
|
.entry(col.to_string())
|
||||||
|
.or_insert_with(HashMap::new);
|
||||||
|
collection.insert(id.to_string(), model);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invalidate(&mut self, col: &str, id: &str) {
|
||||||
|
if let Some(collection) = self.cache.get_mut(col) {
|
||||||
|
collection.remove(id);
|
||||||
|
if collection.is_empty() {
|
||||||
|
self.cache.remove(col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, col: &str, id: &str) -> Option<&mongodb::bson::Document> {
|
||||||
|
self.cache
|
||||||
|
.get(col)
|
||||||
|
.and_then(|collection| collection.get(id))
|
||||||
|
}
|
||||||
|
}
|
38
src/lib.rs
38
src/lib.rs
|
@ -5,11 +5,49 @@ pub use model::valid::Validate;
|
||||||
pub use model::Model;
|
pub use model::Model;
|
||||||
pub use mongod_derive as derive;
|
pub use mongod_derive as derive;
|
||||||
pub use mongodb;
|
pub use mongodb;
|
||||||
|
#[cfg(feature = "cache")]
|
||||||
|
pub mod cache;
|
||||||
|
#[cfg(feature = "cache")]
|
||||||
|
pub use cache::ModelCache;
|
||||||
|
|
||||||
use tokio::sync::OnceCell;
|
use tokio::sync::OnceCell;
|
||||||
|
|
||||||
|
#[cfg(feature = "cache")]
|
||||||
|
use std::sync::RwLock;
|
||||||
|
|
||||||
pub static MONGO_CLIENT: OnceCell<mongodb::Client> = OnceCell::const_new();
|
pub static MONGO_CLIENT: OnceCell<mongodb::Client> = OnceCell::const_new();
|
||||||
|
|
||||||
|
#[cfg(feature = "cache")]
|
||||||
|
pub static DB_CACHE: OnceCell<RwLock<ModelCache>> = OnceCell::const_new();
|
||||||
|
|
||||||
|
#[cfg(feature = "cache")]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! cache_read {
|
||||||
|
() => {
|
||||||
|
if let Some(cache) = $crate::DB_CACHE.get() {
|
||||||
|
cache.read().unwrap()
|
||||||
|
} else {
|
||||||
|
let cache = std::sync::RwLock::new($crate::ModelCache::new());
|
||||||
|
$crate::DB_CACHE.set(cache).unwrap();
|
||||||
|
$crate::DB_CACHE.get().unwrap().read().unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "cache")]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! cache_write {
|
||||||
|
() => {
|
||||||
|
if let Some(cache) = $crate::DB_CACHE.get() {
|
||||||
|
cache.write().unwrap()
|
||||||
|
} else {
|
||||||
|
let cache = std::sync::RwLock::new($crate::ModelCache::new());
|
||||||
|
$crate::DB_CACHE.set(cache).unwrap();
|
||||||
|
$crate::DB_CACHE.get().unwrap().write().unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a `MongoDB` Client from the environment
|
/// Get a `MongoDB` Client from the environment
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! get_mongo {
|
macro_rules! get_mongo {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use serde::de::DeserializeOwned;
|
||||||
use serde_json::{Map, Value};
|
use serde_json::{Map, Value};
|
||||||
use valid::Validate;
|
use valid::Validate;
|
||||||
|
|
||||||
use crate::{col, collect_results, get_mongo, id_of};
|
use crate::{cache_read, cache_write, col, collect_results, get_mongo, id_of};
|
||||||
|
|
||||||
pub mod historic;
|
pub mod historic;
|
||||||
pub mod reference;
|
pub mod reference;
|
||||||
|
@ -40,6 +40,15 @@ pub trait Model:
|
||||||
where
|
where
|
||||||
Self: Sync,
|
Self: Sync,
|
||||||
{
|
{
|
||||||
|
#[cfg(feature = "cache")]
|
||||||
|
{
|
||||||
|
cache_write!().insert(
|
||||||
|
Self::collection_name(),
|
||||||
|
self.id(),
|
||||||
|
mongodb::bson::to_document(self).unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async {
|
async {
|
||||||
let db = get_mongo!();
|
let db = get_mongo!();
|
||||||
let collection = col!(db, Self::collection_name());
|
let collection = col!(db, Self::collection_name());
|
||||||
|
@ -82,6 +91,12 @@ pub trait Model:
|
||||||
async move {
|
async move {
|
||||||
let db = get_mongo!();
|
let db = get_mongo!();
|
||||||
let collection = col!(db, Self::collection_name());
|
let collection = col!(db, Self::collection_name());
|
||||||
|
|
||||||
|
#[cfg(feature = "cache")]
|
||||||
|
{
|
||||||
|
cache_write!().invalidate(Self::collection_name(), id);
|
||||||
|
}
|
||||||
|
|
||||||
collection.delete_one(id_of!(id), None).await
|
collection.delete_one(id_of!(id), None).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,10 +117,26 @@ pub trait Model:
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn get(id: &str) -> impl std::future::Future<Output = Option<Self>> {
|
fn get(id: &str) -> impl std::future::Future<Output = Option<Self>> {
|
||||||
async move {
|
async move {
|
||||||
|
#[cfg(feature = "cache")]
|
||||||
|
{
|
||||||
|
if let Some(cached) = cache_read!().get(Self::collection_name(), id) {
|
||||||
|
return mongodb::bson::from_document(cached.clone()).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let db = get_mongo!();
|
let db = get_mongo!();
|
||||||
let collection = col!(db, Self::collection_name());
|
let collection = col!(db, Self::collection_name());
|
||||||
let doc = collection.find_one(id_of!(id), None).await.ok()??;
|
let doc = collection.find_one(id_of!(id), None).await.ok()??;
|
||||||
mongodb::bson::from_document(doc).ok()
|
let res = mongodb::bson::from_document(doc.clone()).ok();
|
||||||
|
|
||||||
|
#[cfg(feature = "cache")]
|
||||||
|
{
|
||||||
|
if res.is_some() {
|
||||||
|
cache_write!().insert(Self::collection_name(), id, doc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +147,11 @@ pub trait Model:
|
||||||
mut part: serde_json::Value,
|
mut part: serde_json::Value,
|
||||||
) -> impl std::future::Future<Output = Option<Self::Partial>> {
|
) -> impl std::future::Future<Output = Option<Self::Partial>> {
|
||||||
async move {
|
async move {
|
||||||
|
#[cfg(feature = "cache")]
|
||||||
|
{
|
||||||
|
// todo : implement
|
||||||
|
}
|
||||||
|
|
||||||
let db = get_mongo!();
|
let db = get_mongo!();
|
||||||
let collection = col!(db, Self::collection_name());
|
let collection = col!(db, Self::collection_name());
|
||||||
|
|
||||||
|
@ -272,6 +308,12 @@ pub trait Model:
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(UpdateError::Database)?;
|
.map_err(UpdateError::Database)?;
|
||||||
|
|
||||||
|
#[cfg(feature = "cache")]
|
||||||
|
{
|
||||||
|
cache_write!().invalidate(Self::collection_name(), self.id());
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue