Schneider
5 years ago
3 changed files with 100 additions and 2 deletions
@ -0,0 +1,92 @@ |
|||
use crate::errors::*;
|
|||
use core::time::Duration;
|
|||
use log::{debug, trace};
|
|||
use serde::Serialize;
|
|||
use std::fs::File as FsFile;
|
|||
use std::io::{BufReader, BufWriter};
|
|||
use std::path::PathBuf;
|
|||
use std::time::SystemTime;
|
|||
|
|||
pub trait Cache {
|
|||
fn set<S>(&self, key: &str, data: S) -> Result<()>
|
|||
where S: Serialize;
|
|||
fn get<D>(&self, key: &str) -> Result<Vec<D>>
|
|||
where D: serde::de::DeserializeOwned;
|
|||
fn exists(&self, key: &str) -> bool;
|
|||
}
|
|||
|
|||
/// A File cache
|
|||
pub struct File {
|
|||
/// The root path to the files
|
|||
root: PathBuf,
|
|||
/// Time to live for items
|
|||
ttl: Duration,
|
|||
}
|
|||
|
|||
impl File {
|
|||
/// Create a new File cache
|
|||
///
|
|||
/// The cached objects will be stored in the provided root folder.
|
|||
/// The folder will be created, if it does not yet exist.
|
|||
///
|
|||
/// ## Errors
|
|||
/// The function returns an `Err` if the creation of the folders fails
|
|||
pub fn new(root: &PathBuf, ttl: Duration) -> Result<Self> {
|
|||
if !root.exists() {
|
|||
std::fs::create_dir_all(root)
|
|||
.chain_err(|| "Error while creating dirs for file cache")?;
|
|||
}
|
|||
Ok(Self { root: root.clone(), ttl })
|
|||
}
|
|||
}
|
|||
|
|||
impl Cache for File {
|
|||
fn exists(&self, key: &str) -> bool {
|
|||
trace!("Check existence of {} in file cache", key);
|
|||
let mut path = self.root.clone();
|
|||
path.push(key);
|
|||
if !path.exists() {
|
|||
return false;
|
|||
}
|
|||
|
|||
let modified: SystemTime = path
|
|||
.metadata()
|
|||
.map(|meta| meta.modified().unwrap_or(SystemTime::UNIX_EPOCH))
|
|||
.unwrap_or(SystemTime::UNIX_EPOCH);
|
|||
|
|||
if modified.elapsed().unwrap_or(Duration::from_secs(u64::max_value())) > self.ttl {
|
|||
debug!("Cache file is too older (> days), won't be used");
|
|||
return false;
|
|||
}
|
|||
|
|||
true
|
|||
}
|
|||
|
|||
fn set<S>(&self, key: &str, data: S) -> Result<()>
|
|||
where S: serde::Serialize {
|
|||
let mut path: PathBuf = self.root.clone();
|
|||
path.push(key);
|
|||
trace!("Serializing data to cache file {}", path.to_string_lossy());
|
|||
let cache =
|
|||
FsFile::create(path).chain_err(|| "Error while creating file cache to write")?;
|
|||
let writer = BufWriter::new(cache);
|
|||
serde_json::to_writer(writer, &data)
|
|||
.chain_err(|| "Error while serialzing templates to file cache")?;
|
|||
debug!("Serialization of data completed");
|
|||
Ok(())
|
|||
}
|
|||
|
|||
fn get<D>(&self, key: &str) -> Result<Vec<D>>
|
|||
where D: serde::de::DeserializeOwned {
|
|||
let mut path = self.root.clone();
|
|||
path.push(key);
|
|||
debug!("Retrieving {} from file cache", key);
|
|||
let f = FsFile::open(path)
|
|||
.chain_err(|| format!("Error while opening cache file for key {}", key))?;
|
|||
let reader = BufReader::new(f);
|
|||
let obj: Vec<D> = serde_json::from_reader(reader)
|
|||
.chain_err(|| "Error while reading templates from file cache")?;
|
|||
debug!("Deserialized {} templates from file cache", obj.len());
|
|||
Ok(obj)
|
|||
}
|
|||
}
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue