2021-04-14 19:11:00 -07:00
|
|
|
//! Low memory caching stuff
|
|
|
|
|
2021-04-19 19:01:32 -07:00
|
|
|
use std::{path::PathBuf, sync::Arc};
|
2021-04-14 19:11:00 -07:00
|
|
|
|
|
|
|
use async_trait::async_trait;
|
|
|
|
use lru::LruCache;
|
2021-04-19 19:01:32 -07:00
|
|
|
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender};
|
|
|
|
use tokio::sync::RwLock;
|
2021-04-14 19:11:00 -07:00
|
|
|
|
2021-04-18 14:06:40 -07:00
|
|
|
use super::{BoxedImageStream, Cache, CacheError, CacheKey, CacheStream, ImageMetadata};
|
2021-04-14 19:11:00 -07:00
|
|
|
|
|
|
|
pub struct LowMemCache {
|
2021-04-18 14:06:40 -07:00
|
|
|
on_disk: LruCache<CacheKey, ImageMetadata>,
|
2021-04-14 19:11:00 -07:00
|
|
|
disk_path: PathBuf,
|
2021-04-14 20:44:13 -07:00
|
|
|
disk_max_size: u64,
|
|
|
|
disk_cur_size: u64,
|
2021-04-19 19:01:32 -07:00
|
|
|
master_sender: UnboundedSender<u64>,
|
2021-04-14 19:11:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl LowMemCache {
|
2021-04-19 19:01:32 -07:00
|
|
|
pub fn new(disk_max_size: u64, disk_path: PathBuf) -> Arc<RwLock<Box<dyn Cache>>> {
|
|
|
|
let (tx, mut rx) = unbounded_channel();
|
|
|
|
let new_self: Arc<RwLock<Box<dyn Cache>>> = Arc::new(RwLock::new(Box::new(Self {
|
2021-04-14 19:11:00 -07:00
|
|
|
on_disk: LruCache::unbounded(),
|
|
|
|
disk_path,
|
|
|
|
disk_max_size,
|
|
|
|
disk_cur_size: 0,
|
2021-04-19 19:01:32 -07:00
|
|
|
master_sender: tx,
|
|
|
|
})));
|
|
|
|
|
|
|
|
let new_self_0 = Arc::clone(&new_self);
|
|
|
|
tokio::spawn(async move {
|
|
|
|
loop {
|
|
|
|
let new_size = match rx.recv().await {
|
|
|
|
Some(v) => v,
|
|
|
|
None => break,
|
|
|
|
};
|
|
|
|
|
|
|
|
new_self_0.write().await.increase_usage(new_size).await;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
new_self.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn prune(&mut self) {
|
|
|
|
todo!()
|
2021-04-14 19:11:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
impl Cache for LowMemCache {
|
2021-04-18 14:06:40 -07:00
|
|
|
async fn get(
|
|
|
|
&mut self,
|
|
|
|
key: &CacheKey,
|
|
|
|
) -> Option<Result<(CacheStream, &ImageMetadata), CacheError>> {
|
2021-04-18 14:25:28 -07:00
|
|
|
let metadata = self.on_disk.get(key)?;
|
|
|
|
let path = self.disk_path.clone().join(PathBuf::from(key.clone()));
|
2021-04-18 20:06:18 -07:00
|
|
|
super::fs::read_file(&path)
|
|
|
|
.await
|
|
|
|
.map(|res| res.map(|stream| (stream, metadata)).map_err(Into::into))
|
2021-04-14 19:11:00 -07:00
|
|
|
}
|
|
|
|
|
2021-04-18 14:06:40 -07:00
|
|
|
async fn put(
|
2021-04-17 20:19:27 -07:00
|
|
|
&mut self,
|
|
|
|
key: CacheKey,
|
2021-04-18 14:06:40 -07:00
|
|
|
image: BoxedImageStream,
|
|
|
|
metadata: ImageMetadata,
|
|
|
|
) -> Result<(CacheStream, &ImageMetadata), CacheError> {
|
|
|
|
let path = self.disk_path.clone().join(PathBuf::from(key.clone()));
|
|
|
|
self.on_disk.put(key.clone(), metadata);
|
2021-04-19 19:01:32 -07:00
|
|
|
super::fs::write_file(&path, image, self.master_sender.clone())
|
2021-04-18 14:06:40 -07:00
|
|
|
.await
|
|
|
|
.map(move |stream| (stream, self.on_disk.get(&key).unwrap()))
|
|
|
|
.map_err(Into::into)
|
2021-04-14 19:11:00 -07:00
|
|
|
}
|
2021-04-18 14:38:33 -07:00
|
|
|
|
2021-04-19 19:01:32 -07:00
|
|
|
async fn increase_usage(&mut self, amt: u64) {
|
|
|
|
self.disk_cur_size += amt;
|
|
|
|
if self.disk_cur_size > self.disk_max_size {
|
|
|
|
self.prune().await;
|
|
|
|
}
|
2021-04-18 14:38:33 -07:00
|
|
|
}
|
2021-04-14 19:11:00 -07:00
|
|
|
}
|