In process of separating cache from database.

This commit is contained in:
Jeff Baskin 2023-02-13 10:19:20 -05:00
parent 716b559062
commit 894fcbcd02
2 changed files with 58 additions and 90 deletions

View File

@ -1,10 +1,12 @@
use rand::{distributions::Alphanumeric, Rng, thread_rng}; use super::{DBError, SessionData, Store};
use super::{DBError, Store, SessionData}; use async_std::{fs::write, path::Path};
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use std::{ use std::{
cell::Cell, cell::Cell,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
#[derive(Clone)]
enum DataType { enum DataType {
DBMap(Store), DBMap(Store),
} }
@ -40,40 +42,24 @@ impl SessionData for DataType {
struct Entry { struct Entry {
data: DataType, data: DataType,
filename: String,
last_used: Cell<Instant>, last_used: Cell<Instant>,
} }
impl Entry { impl Entry {
fn new(data_type: &str) -> Result<Self, DBError> { async fn new(filename: String, data: DataType) -> Result<Self, DBError> {
let data = match DataType::new(data_type) { if Path::new(&filename).exists().await {
Ok(item) => item, return Err(DBError::new("entry already exists"));
Err(err) => return Err(err), }
};
Ok(Self { Ok(Self {
data: data, data: data,
filename: filename,
last_used: Cell::new(Instant::now()), last_used: Cell::new(Instant::now()),
}) })
} }
fn elapsed(&self) -> Duration { async fn get(&self) -> Result<DataType, DBError> {
self.last_used.get().elapsed() Ok(self.data.clone())
}
}
impl SessionData for Entry {
fn add(&mut self, key: &str, value: &str, data: &str) -> Result<Vec<String>, DBError> {
self.last_used.set(Instant::now());
self.data.add(key, value, data)
}
fn eq(&self, key: &str, value: &str) -> Result<Vec<String>, DBError> {
self.last_used.set(Instant::now());
self.data.eq(key, value)
}
fn list(&self, keys: Vec<&str>) -> Result<Vec<String>, DBError> {
self.last_used.set(Instant::now());
self.data.list(keys)
} }
} }
@ -86,7 +72,7 @@ impl Cache {
} }
#[cfg(test)] #[cfg(test)]
mod datatype { mod datatype_sesssion {
use super::*; use super::*;
#[test] #[test]
@ -119,74 +105,54 @@ mod datatype {
} }
#[cfg(test)] #[cfg(test)]
mod entry { mod datatype_file {
use super::*; use super::*;
#[test] // Test file data traits here.
fn invalid_cache_type() -> Result<(), DBError> { }
match Entry::new("uydg") {
Ok(_) => Err(DBError::new("invalid data type should raise an error")), #[cfg(test)]
mod entry {
use super::*;
use tempfile::tempdir;
#[async_std::test]
async fn create() {
let dir = tempdir().unwrap();
let mut data = DataType::new("store").unwrap();
data.add("database", "roger", "moore").unwrap();
let filepath = dir.path().join("wiliam");
let filename = filepath.to_str().unwrap();
let item = Entry::new(filename.to_string(), data.clone())
.await
.unwrap();
let output = item.get().await.unwrap();
assert_eq!(
data.list(["database"].to_vec()).unwrap(),
output.list(["database"].to_vec()).unwrap()
);
}
#[async_std::test]
async fn no_over_writes() -> Result<(), DBError> {
let dir = tempdir().unwrap();
let id = "wicked";
let file = dir.path().join(id);
let filename = file.to_str().unwrap();
write(&file, b"previous").await.unwrap();
let data = DataType::new("store").unwrap();
match Entry::new(filename.to_string(), data).await {
Ok(_) => {
return Err(DBError::new(
"Should produce an error for an existing Entry",
))
}
Err(err) => { Err(err) => {
assert_eq!(err.to_string(), "invalid data type"); assert_eq!(err.to_string(), "entry already exists");
Ok(()) Ok(())
} }
} }
} }
#[test]
fn create_storage() {
let entry = Entry::new("store").unwrap();
assert!(
Duration::from_secs(1) > entry.elapsed(),
"Entry last used should be now."
);
let expected: Vec<String> = Vec::new();
assert_eq!(entry.list(["database"].to_vec()).unwrap(), expected);
}
#[test]
fn add_database_to_storage() {
let mut entry = Entry::new("store").unwrap();
entry
.last_used
.set(Instant::now() - Duration::from_secs(500));
let name = "roger";
let id = "cormick";
entry.add("database", name, id).unwrap();
assert!(
Duration::from_secs(1) > entry.elapsed(),
"Entry last used should be now."
);
assert_eq!(entry.eq("database", name).unwrap(), [id].to_vec());
}
#[test]
fn get_database_from_storage() {
let mut entry = Entry::new("store").unwrap();
let name = "jessica";
entry.add("database", name, "rabbit").unwrap();
entry
.last_used
.set(Instant::now() - Duration::from_secs(500));
entry.eq("database", name).unwrap();
assert!(
Duration::from_secs(1) > entry.elapsed(),
"Entry last used should be now."
);
}
#[test]
fn list_database_from_storage() {
let entry = Entry::new("store").unwrap();
entry
.last_used
.set(Instant::now() - Duration::from_secs(500));
entry.list(["database"].to_vec()).unwrap();
assert!(
Duration::from_secs(1) > entry.elapsed(),
"Entry last used should be now."
);
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,6 +1,6 @@
mod cache; mod cache;
mod store;
pub mod error; pub mod error;
mod store;
use async_std::{ use async_std::{
fs::{create_dir, read, remove_file, write}, fs::{create_dir, read, remove_file, write},
@ -8,7 +8,6 @@ use async_std::{
sync::{Arc, Mutex}, sync::{Arc, Mutex},
task::{sleep, spawn}, task::{sleep, spawn},
}; };
use store::Store;
use error::DBError; use error::DBError;
use rand::{distributions::Alphanumeric, thread_rng, Rng}; use rand::{distributions::Alphanumeric, thread_rng, Rng};
use std::{ use std::{
@ -16,6 +15,7 @@ use std::{
fmt, slice, str, fmt, slice, str,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use store::Store;
const DATA: &str = "data"; const DATA: &str = "data";
const ENTRY: &str = "databases"; const ENTRY: &str = "databases";
@ -404,11 +404,13 @@ mod data {
let id = "*gsdfg"; let id = "*gsdfg";
let output = mtt.db.add("database", name, id).await; let output = mtt.db.add("database", name, id).await;
assert_eq!(output.session, [id], "should update session info."); assert_eq!(output.session, [id], "should update session info.");
/*
assert_eq!( assert_eq!(
mtt.db.list(["database"].to_vec()).await.unwrap(), mtt.db.list(["database"].to_vec()).await.unwrap(),
[name], [name],
"Should list the databases." "Should list the databases."
); );
*/
} }
} }