Skip to content

Commit

Permalink
implement caching
Browse files Browse the repository at this point in the history
  • Loading branch information
henrikskog committed Jul 12, 2024
1 parent 279edc8 commit f636e90
Show file tree
Hide file tree
Showing 6 changed files with 329 additions and 45 deletions.
143 changes: 130 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ dirs = "5.0.1"
humansize = "2.1.3"
itertools = "0.13.0"
itsuki = "0.2.0"
moka = { version = "0.12.8", features = ["sync"] }
once_cell = "1.19.0"
open = "5.2.0"
ratatui = { version = "0.27.0", features = ["unstable-widget-ref"] }
serde = { version = "1.0.204", features = ["derive"] }
serde_json = "=1.0.1"
syntect = { version = "5.2.0", default-features = false, features = [
"default-fancy",
] }
Expand Down
87 changes: 87 additions & 0 deletions src/cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use moka::sync::Cache;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::fs::File;
use std::fs::OpenOptions;
use std::io::Read;
use std::io::{self, Write};
use std::num::NonZeroUsize;

#[derive(Serialize, Deserialize)]
struct CacheEntry<T> {
key: String,
value: T,
}

pub struct SyncMokaCache<T> {
pub cache: Cache<String, T>,
pub file_path: String,
}

impl<T> fmt::Debug for SyncMokaCache<T>
where
T: fmt::Debug + Clone + Send + Sync + 'static, // Added 'static bound
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SyncMokaCache")
.field("file_path", &self.file_path)
.field("cache", &self.cache.iter().collect::<Vec<_>>())
.finish()
}
}

impl<T> SyncMokaCache<T>
where
T: Serialize + for<'de> Deserialize<'de> + Clone + Send + Sync + 'static,
{
pub fn new(size: NonZeroUsize, file_path: String) -> io::Result<Self>
where
T: for<'de> Deserialize<'de>,
{
println!("Initializing cache with size: {} at {}", size, file_path);
let cache = Cache::builder().max_capacity(size.get() as u64).build();

if let Ok(mut file) = File::open(&file_path) {
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let entries: Vec<CacheEntry<T>> = serde_json::from_str(&contents)?;
for entry in entries {
cache.insert(entry.key, entry.value);
}
}

Ok(SyncMokaCache { cache, file_path })
}

pub fn put(&self, key: String, value: T) -> io::Result<()> {
self.cache.insert(key.clone(), value);
self.sync_to_file()?;
Ok(())
}

pub fn get(&self, key: &str) -> Option<T> {
self.cache.get(key)
}

fn sync_to_file(&self) -> io::Result<()> {
let temp_file_path = format!("{}.tmp", self.file_path);
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(&temp_file_path)?;
let entries: Vec<CacheEntry<T>> = self
.cache
.iter()
.map(|(k, v)| CacheEntry {
key: k.to_string(),
value: v.clone(),
})
.collect();

let json = serde_json::to_string(&entries)?;
file.write_all(json.as_bytes())?;
std::fs::rename(temp_file_path, &self.file_path)?;
Ok(())
}
}
Loading

0 comments on commit f636e90

Please sign in to comment.