Skip to content

Commit

Permalink
feat(hide): implement 'hidden' datastore
Browse files Browse the repository at this point in the history
  • Loading branch information
RouHim committed Nov 1, 2022
1 parent 3374cb8 commit 5e0e12a
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 54 deletions.
90 changes: 50 additions & 40 deletions src/integration_test_resources_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ use assertor::{assert_that, EqualityAssertion, VecAssertion};
use chrono::{Local, NaiveDateTime};
use evmap::{ReadHandle, WriteHandle};
use rand::Rng;
use test::TestRequest;

use crate::geo_location::GeoLocation;
use crate::resource_reader::RemoteResource;
use crate::{kv_store, resource_endpoint, resource_reader, scheduler, utils, ResourceReader};
use crate::{
kv_store, resource_endpoint, resource_reader, resource_store, scheduler, utils, ResourceReader,
};

const TEST_JPEG_EXIF_URL: &str =
"https://raw.githubusercontent.com/ianare/exif-samples/master/jpg/gps/DSCN0010.jpg";
Expand Down Expand Up @@ -52,7 +55,7 @@ async fn test_get_all_resources() {
// WHEN requesting all resources
let response: Vec<String> = test::call_and_read_body_json(
&app_server,
test::TestRequest::get().uri("/api/resources").to_request(),
TestRequest::get().uri("/api/resources").to_request(),
)
.await;

Expand Down Expand Up @@ -92,9 +95,7 @@ async fn test_this_week_in_past_resources() {
// WHEN requesting of this week in past resources
let response: Vec<String> = test::call_and_read_body_json(
&app_server,
test::TestRequest::get()
.uri("/api/resources/week")
.to_request(),
TestRequest::get().uri("/api/resources/week").to_request(),
)
.await;

Expand Down Expand Up @@ -125,9 +126,7 @@ async fn test_get_random_resources() {
// WHEN requesting a random resource
let response: String = test::call_and_read_body_json(
&app_server,
test::TestRequest::get()
.uri("/api/resources/random")
.to_request(),
TestRequest::get().uri("/api/resources/random").to_request(),
)
.await;

Expand Down Expand Up @@ -159,7 +158,7 @@ async fn test_get_resource_by_id_and_resolution() {
// WHEN requesting a random resource
let response = test::call_and_read_body(
&app_server,
test::TestRequest::get()
TestRequest::get()
.uri(format!("/api/resources/{test_image_1_id}/10/10").as_str())
.to_request(),
)
Expand Down Expand Up @@ -194,7 +193,7 @@ async fn test_get_resource_metadata_by_id() {
// WHEN requesting a random resource
let response: RemoteResource = test::call_and_read_body_json(
&app_server,
test::TestRequest::get()
TestRequest::get()
.uri(format!("/api/resources/{test_image_1_id}/metadata").as_str())
.to_request(),
)
Expand Down Expand Up @@ -246,7 +245,7 @@ async fn test_get_resource_description_by_id() {
let response = String::from_utf8(
test::call_and_read_body(
&app_server,
test::TestRequest::get()
TestRequest::get()
.uri(format!("/api/resources/{test_image_1_id}/description").as_str())
.to_request(),
)
Expand All @@ -263,7 +262,7 @@ async fn test_get_resource_description_by_id() {
}

#[actix_web::test]
async fn hide_resource() {
async fn get_hidden_resources() {
// GIVEN is a folder structure with two assets and another file type
let base_test_dir = create_temp_folder().await;
let test_image_1_id = utils::md5(
Expand All @@ -276,16 +275,6 @@ async fn hide_resource() {
.await
.as_str(),
);
let _test_image_2_id = utils::md5(
create_test_image(
&base_test_dir,
"sub1",
"test_image_2.jpg",
TEST_JPEG_EXIF_URL,
)
.await
.as_str(),
);

// AND a running this-week-in-past instance
let (kv_reader, kv_writer) = evmap::new::<String, String>();
Expand All @@ -297,27 +286,31 @@ async fn hide_resource() {
))
.await;

// WHEN hiding a resource
let _: Vec<String> = test::call_and_read_body_json(
// AND this image is hidden
let _ = test::call_and_read_body(
&app_server,
test::TestRequest::post()
TestRequest::post()
.uri(format!("/api/resources/hide/{test_image_1_id}").as_str())
.to_request(),
)
.await;

// WHEN receiving all hidden resources
let response: Vec<String> = test::call_and_read_body_json(
&app_server,
TestRequest::get().uri("/api/resources/hide").to_request(),
)
.await;

// THEN then one image should be hidden
// assert_that!(response).contains_exactly(vec![
// utils::md5(test_image_1.as_str()),
// utils::md5(test_image_2.as_str()),
// ]);
assert_that!(response).contains_exactly(vec![test_image_1_id]);

// cleanup
cleanup(&base_test_dir).await;
}

#[actix_web::test]
async fn get_all_hidden_resources() {
async fn get_hidden_resources_when_set_visible_again() {
// GIVEN is a folder structure with two assets and another file type
let base_test_dir = create_temp_folder().await;
let test_image_1_id = utils::md5(
Expand All @@ -342,9 +335,18 @@ async fn get_all_hidden_resources() {
.await;

// AND this image is hidden
let _: Vec<String> = test::call_and_read_body_json(
let _ = test::call_and_read_body(
&app_server,
TestRequest::post()
.uri(format!("/api/resources/hide/{test_image_1_id}").as_str())
.to_request(),
)
.await;

// AND this image is set to visible again
let _ = test::call_and_read_body(
&app_server,
test::TestRequest::post()
TestRequest::delete()
.uri(format!("/api/resources/hide/{test_image_1_id}").as_str())
.to_request(),
)
Expand All @@ -353,14 +355,12 @@ async fn get_all_hidden_resources() {
// WHEN receiving all hidden resources
let response: Vec<String> = test::call_and_read_body_json(
&app_server,
test::TestRequest::get()
.uri("/api/resources/hide".to_string().as_str())
.to_request(),
TestRequest::get().uri("/api/resources/hide").to_request(),
)
.await;

// THEN then one image should be hidden
assert_that!(response).contains_exactly(vec![test_image_1_id]);
// THEN then no image should be hidden
assert_that!(response).contains_exactly(vec![]);

// cleanup
cleanup(&base_test_dir).await;
Expand All @@ -382,7 +382,9 @@ fn build_app(
scheduler::init();
scheduler::fetch_resources(resource_reader.clone(), kv_writer_mutex.clone());
let geo_location_cache = kv_store::new();
let resource_store = resource_store::initialize();
App::new()
.app_data(web::Data::new(resource_store))
.app_data(web::Data::new(kv_reader))
.app_data(web::Data::new(resource_reader))
.app_data(web::Data::new(kv_writer_mutex))
Expand All @@ -394,7 +396,10 @@ fn build_app(
.service(resource_endpoint::random_resource)
.service(resource_endpoint::get_resource_by_id_and_resolution)
.service(resource_endpoint::get_resource_metadata_by_id)
.service(resource_endpoint::get_resource_metadata_description_by_id),
.service(resource_endpoint::get_resource_metadata_description_by_id)
.service(resource_endpoint::get_all_hidden_resources)
.service(resource_endpoint::set_resource_hidden)
.service(resource_endpoint::delete_resource_hidden),
)
}

Expand Down Expand Up @@ -450,9 +455,14 @@ async fn create_temp_folder() -> PathBuf {
fs::create_dir_all(&test_dir).unwrap();

// set cache folder to test dir
let cache_dir = format!("/tmp/cache/{}/{}", &random_string, TEST_FOLDER_NAME);
env::set_var("CACHE_DIR", &cache_dir);
let cache_dir = test_dir.join("cache");
let data_dir = test_dir.join("data");

env::set_var("CACHE_DIR", &cache_dir.as_path().to_str().unwrap());
env::set_var("DATA_FOLDER", &data_dir.as_path().to_str().unwrap());

fs::create_dir_all(&cache_dir).unwrap();
fs::create_dir_all(&data_dir).unwrap();

test_dir
}
16 changes: 12 additions & 4 deletions src/resource_endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,22 @@ pub async fn get_resource_metadata_description_by_id(
}

#[post("/hide/{resource_id}")]
pub async fn set_resource_hidden(resources_id: web::Path<String>) -> HttpResponse {
println!("Hiding resource {resources_id}");
pub async fn set_resource_hidden(
resources_id: web::Path<String>,
resource_store: web::Data<ResourceStore>,
) -> HttpResponse {
resource_store.get_ref().add_hidden(resources_id.as_str());
HttpResponse::Ok().finish()
}

#[delete("/hide/{resource_id}")]
pub async fn delete_resource_hidden(resources_id: web::Path<String>) -> HttpResponse {
println!("make resource {resources_id} visible again");
pub async fn delete_resource_hidden(
resources_id: web::Path<String>,
resource_store: web::Data<ResourceStore>,
) -> HttpResponse {
resource_store
.get_ref()
.remove_hidden(resources_id.as_str());
HttpResponse::Ok().finish()
}

Expand Down
39 changes: 29 additions & 10 deletions src/resource_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ use std::env;
use std::path::PathBuf;

use r2d2::Pool;
use r2d2_sqlite::rusqlite::OpenFlags;
use r2d2_sqlite::SqliteConnectionManager;

#[derive(Clone)]
pub struct ResourceStore {
pool: Pool<SqliteConnectionManager>,
connection_pool: Pool<SqliteConnectionManager>,
}

impl ResourceStore {
pub fn get_all_hidden(&self) -> Vec<String> {
let connection = self.pool.get().unwrap();
let connection = self.connection_pool.get().unwrap();
let mut stmt = connection.prepare("SELECT id FROM hidden").unwrap();
let mut rows = stmt.query([]).unwrap();
let mut ids: Vec<String> = Vec::new();
Expand All @@ -20,23 +21,41 @@ impl ResourceStore {
}
ids
}

pub fn add_hidden(&self, resource_key: &str) {
let connection = self.connection_pool.get().unwrap();
let mut stmt = connection
.prepare("INSERT OR IGNORE INTO hidden(id) VALUES(?)")
.unwrap();
stmt.execute([resource_key]).unwrap();
}

pub fn remove_hidden(&self, resource_key: &str) {
let connection = self.connection_pool.get().unwrap();
let mut stmt = connection
.prepare("DELETE FROM hidden WHERE ID = ?")
.unwrap();
stmt.execute([resource_key]).unwrap();
}
}

pub fn initialize() -> ResourceStore {
let database_path = env::var("DATA_FOLDER").unwrap_or_else(|_| "./data".to_string());
let resources_path = PathBuf::from(database_path).join("resources.db");
let manager = SqliteConnectionManager::file(resources_path);
let pool = r2d2::Pool::new(manager).unwrap();
let manager = SqliteConnectionManager::file(resources_path).with_flags(OpenFlags::default());
let connection_pool = Pool::new(manager).expect("Pool creation failed");

create_table_hidden(&connection_pool);

ResourceStore { connection_pool }
}

fn create_table_hidden(pool: &Pool<SqliteConnectionManager>) {
pool.get()
.unwrap()
.execute(
"CREATE TABLE IF NOT EXISTS hidden (
id VARCHAR(128) PRIMARY KEY,
)",
(), // empty list of parameters.
"CREATE TABLE IF NOT EXISTS hidden (id TEXT PRIMARY KEY);",
(),
)
.expect("table creation of 'hidden' failed");

ResourceStore { pool }
}

0 comments on commit 5e0e12a

Please sign in to comment.