Browse Source

add file cache object

master
Schneider 4 years ago
parent
commit
71827e157d
Signed by: schneider GPG Key ID: 3F50B02A50039F3B
  1. 92
      src/cache.rs
  2. 1
      src/main.rs
  3. 9
      src/template.rs

92
src/cache.rs

@ -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)
}
}

1
src/main.rs

@ -38,6 +38,7 @@ use structopt::{clap, StructOpt};
// Local imports
mod app;
mod cache;
mod gitignore;
mod helpers;
mod template;

9
src/template.rs

@ -1,5 +1,6 @@
//! This module contains structs for working with the github templates
use directories::ProjectDirs;
use log::{debug, trace};
use reqwest::blocking::Client;
use reqwest::header::{ACCEPT, CONTENT_TYPE, USER_AGENT};
@ -115,8 +116,12 @@ impl GithubTemplates {
/// Returns the path of the file cache
fn cache_path() -> PathBuf {
let proj = directories::ProjectDirs::from("org", "webschneider", env!("CARGO_PKG_NAME"));
let mut cache: PathBuf = crate::helpers::cache_dir();
let proj = ProjectDirs::from("org", "webschneider", env!("CARGO_PKG_NAME"));
let mut cache: PathBuf = match proj {
Some(p) => p.cache_dir().into(),
None => PathBuf::from("/tmp"),
};
cache.push("templates.json");
debug!("Using cache path for templates: {}", cache.to_str().unwrap_or("err"));
cache

Loading…
Cancel
Save