Unverified Commit 0b64f75a authored by Sebastian Schüpbach's avatar Sebastian Schüpbach
Browse files

add collections and summary routes

parent 859f4fd0
......@@ -27,6 +27,7 @@ use std::time::{Duration, Instant};
pub struct MediaFileCache {
dissemination_copies: HashMap<String, String>,
thumbnails: HashMap<String, String>,
metadata_file_count: HashMap<String, usize>,
base_path: String,
created_on: Instant,
}
......@@ -37,6 +38,7 @@ impl MediaFileCache {
MediaFileCache {
dissemination_copies: HashMap::new(),
thumbnails: HashMap::new(),
metadata_file_count: HashMap::new(),
base_path,
created_on: Instant::now(),
}
......@@ -53,15 +55,34 @@ impl MediaFileCache {
self.dissemination_copies.len()
}
/// Count media files for a collection
pub fn collection_dissemination_copies_size(&self, collection_id: &str) -> usize {
self.dissemination_copies.keys().filter(|k| k.starts_with(collection_id)).count()
}
/// Size of mapping for thumbnails (i.e. the total of cached thumbnails)
pub fn thumbnails_size(&self) -> usize {
self.thumbnails.len()
}
pub fn collection_thumbnails_size(&self, collection_id: &str) -> usize {
self.thumbnails.keys().filter(|k| k.starts_with(collection_id)).count()
}
/// Count metadata files for a collection
pub fn collection_metadata_file_size(&self, collection_id: &str) -> Option<usize> {
self.metadata_file_count.get(collection_id).map(|c| c.to_owned())
}
pub fn get_collections(&self) -> Vec<String> {
self.metadata_file_count.keys().map(|k| k.to_owned()).collect::<Vec<String>>()
}
/// Merges cache with `other`
pub fn merge(&mut self, other: MediaFileCache) {
self.dissemination_copies.extend(other.dissemination_copies);
self.thumbnails.extend(other.thumbnails);
self.metadata_file_count.extend(other.metadata_file_count);
self.created_on = Instant::now();
}
......@@ -71,7 +92,12 @@ impl MediaFileCache {
.file_stem()
.context("Can't extract file stem")?
.to_str()
.context("Can't convert to str")?;
.context("Can't convert file stem to str")?;
let extension = path
.extension()
.context("Can't extract extension")?
.to_str()
.context("Can't convert extension to str")?;
let path = path.to_str().context("Can't read path!")?;
let path_elements = path.split('/').collect::<Vec<&str>>();
let path_size = path_elements.len();
......@@ -95,6 +121,10 @@ impl MediaFileCache {
.context("Path is invalid")?;
self.thumbnails
.insert(format!("{}-{}", collection_id, id.replace(" ", "_")), path.to_owned());
} else if extension == "xml" {
let record_set_id = *path_elements.get(path_size - 2)
.context("Path is invalid")?;
*self.metadata_file_count.entry(record_set_id.to_owned()).or_insert(1) += 1;
}
Ok(())
}
......@@ -118,6 +148,7 @@ impl MediaFileCache {
visit_dirs(Path::new(&self.base_path)).context("Coulnd't scan for files")?;
self.dissemination_copies = temp_cache.dissemination_copies;
self.thumbnails = temp_cache.thumbnails;
self.metadata_file_count = temp_cache.metadata_file_count;
self.created_on = Instant::now();
Ok(())
}
......
......@@ -76,7 +76,7 @@ impl Svc {
impl Service<Request<Body>> for Svc {
type Response = Response<Body>;
type Error = anyhow::Error;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
type Future = Pin<Box<dyn Future<Output=Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
......@@ -129,6 +129,42 @@ impl Service<Request<Body>> for Svc {
internal_server_error()
}
}
"summary" => {
let path_elements = req
.uri()
.path()
.split('/');
// TODO: Use a better approach
if path_elements.clone().count() > 2 {
let collection_id = path_elements.skip(2).take(1).collect::<String>();
if let Ok(l) = self.media_cache.lock() {
if let Some(metadata_count) = l.collection_metadata_file_size(&collection_id) {
let collection_dissemination_copies_size = l.collection_dissemination_copies_size(&collection_id);
let collection_thumbnails_size = l.collection_thumbnails_size(&collection_id);
let body = format!("{{\"metadata_files\": {}, \"dissemination_copies\": {}, \"thumbnails\": {}}}",
metadata_count, collection_dissemination_copies_size, collection_thumbnails_size);
json_response(body)
} else {
not_found()
}
} else {
error!("Couldn't lock cache mutex!");
internal_server_error()
}
} else {
// TODO: Return overall count
bad_request()
}
}
"collections" => {
if let Ok(l) = self.media_cache.lock() {
let body = format!("[\"{}\"]", l.get_collections().join("\",\""));
json_response(body)
} else {
error!("Couldn't lock cache mutex!");
internal_server_error()
}
}
p => {
info!("No route on /{}", p);
bad_request()
......@@ -160,6 +196,15 @@ fn bad_request() -> Result<Response<Body>> {
.context("Can't build response")
}
fn json_response(body: String) -> Result<Response<Body>> {
Response::builder()
.status(StatusCode::OK)
.header("Content-Type", "application/json")
.header("Content-Length", body.as_bytes().len())
.body(body.into())
.context("Can't build response")
}
fn ok() -> Result<Response<Body>> {
Response::builder()
.status(StatusCode::OK)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment