Add latest_interior_ref_list_by_shop_id endpoint

Not sure if this is correct yet, still waiting for rustc to compile...
This commit is contained in:
Tyler Hallada 2020-10-20 01:13:40 -04:00
parent 97a2ac52dc
commit 0dc4247224
6 changed files with 84 additions and 9 deletions

View File

@ -68,12 +68,12 @@ where
Ok(value) Ok(value)
} }
pub async fn delete(&self, key: K) -> Result<Option<V>> { pub async fn delete(&self, key: K) -> Option<V> {
let mut guard = self.lru_mutex.lock().await; let mut guard = self.lru_mutex.lock().await;
let value = guard.pop(&key); let value = guard.pop(&key);
self.log_with_key(&key, "delete"); self.log_with_key(&key, "delete");
Ok(value) value
} }
pub async fn clear(&self) { pub async fn clear(&self) {

View File

@ -20,6 +20,7 @@ pub struct Caches {
pub list_owners: Cache<ListParams, CachedResponse>, pub list_owners: Cache<ListParams, CachedResponse>,
pub list_interior_ref_lists: Cache<ListParams, CachedResponse>, pub list_interior_ref_lists: Cache<ListParams, CachedResponse>,
pub list_merchandise_lists: Cache<ListParams, CachedResponse>, pub list_merchandise_lists: Cache<ListParams, CachedResponse>,
pub latest_interior_ref_list_by_shop_id: Cache<i32, CachedResponse>,
} }
impl Caches { impl Caches {
@ -34,6 +35,10 @@ impl Caches {
list_owners: Cache::new("list_owners", 100), list_owners: Cache::new("list_owners", 100),
list_interior_ref_lists: Cache::new("list_interior_ref_lists", 100), list_interior_ref_lists: Cache::new("list_interior_ref_lists", 100),
list_merchandise_lists: Cache::new("list_merchandise_lists", 100), list_merchandise_lists: Cache::new("list_merchandise_lists", 100),
latest_interior_ref_list_by_shop_id: Cache::new(
"latest_interior_ref_list_by_shop_id",
100,
),
} }
} }
} }

View File

@ -19,7 +19,8 @@ pub fn shops(env: Environment) -> impl Filter<Extract = impl Reply, Error = Reje
.or(delete_shop(env.clone())) .or(delete_shop(env.clone()))
.or(update_shop(env.clone())) .or(update_shop(env.clone()))
.or(create_shop(env.clone())) .or(create_shop(env.clone()))
.or(list_shops(env)), .or(list_shops(env.clone()))
.or(get_latest_interior_ref_list_by_shop_id(env)),
) )
} }
@ -57,6 +58,7 @@ pub fn merchandise_lists(
pub fn get_shop(env: Environment) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { pub fn get_shop(env: Environment) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path::param() warp::path::param()
.and(warp::path::end())
.and(warp::get()) .and(warp::get())
.and(with_env(env)) .and(with_env(env))
.and_then(handlers::get_shop) .and_then(handlers::get_shop)
@ -77,6 +79,7 @@ pub fn delete_shop(
env: Environment, env: Environment,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { ) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path::param() warp::path::param()
.and(warp::path::end())
.and(warp::delete()) .and(warp::delete())
.and(warp::header::optional("api-key")) .and(warp::header::optional("api-key"))
.and(with_env(env)) .and(with_env(env))
@ -106,6 +109,7 @@ pub fn list_shops(
pub fn get_owner(env: Environment) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { pub fn get_owner(env: Environment) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path::param() warp::path::param()
.and(warp::path::end())
.and(warp::get()) .and(warp::get())
.and(with_env(env)) .and(with_env(env))
.and_then(handlers::get_owner) .and_then(handlers::get_owner)
@ -128,6 +132,7 @@ pub fn delete_owner(
env: Environment, env: Environment,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { ) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path::param() warp::path::param()
.and(warp::path::end())
.and(warp::delete()) .and(warp::delete())
.and(warp::header::optional("api-key")) .and(warp::header::optional("api-key"))
.and(with_env(env)) .and(with_env(env))
@ -138,6 +143,7 @@ pub fn update_owner(
env: Environment, env: Environment,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { ) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path::param() warp::path::param()
.and(warp::path::end())
.and(warp::patch()) .and(warp::patch())
.and(json_body::<Owner>()) .and(json_body::<Owner>())
.and(warp::header::optional("api-key")) .and(warp::header::optional("api-key"))
@ -159,6 +165,7 @@ pub fn get_interior_ref_list(
env: Environment, env: Environment,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { ) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path::param() warp::path::param()
.and(warp::path::end())
.and(warp::get()) .and(warp::get())
.and(with_env(env)) .and(with_env(env))
.and_then(handlers::get_interior_ref_list) .and_then(handlers::get_interior_ref_list)
@ -179,6 +186,7 @@ pub fn delete_interior_ref_list(
env: Environment, env: Environment,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { ) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path::param() warp::path::param()
.and(warp::path::end())
.and(warp::delete()) .and(warp::delete())
.and(warp::header::optional("api-key")) .and(warp::header::optional("api-key"))
.and(with_env(env)) .and(with_env(env))
@ -195,10 +203,22 @@ pub fn list_interior_ref_lists(
.and_then(handlers::list_interior_ref_lists) .and_then(handlers::list_interior_ref_lists)
} }
pub fn get_latest_interior_ref_list_by_shop_id(
env: Environment,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path::param()
.and(warp::path("latest_interior_ref_list"))
.and(warp::path::end())
.and(warp::get())
.and(with_env(env))
.and_then(handlers::get_latest_interior_ref_list_by_shop_id)
}
pub fn get_merchandise_list( pub fn get_merchandise_list(
env: Environment, env: Environment,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { ) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path::param() warp::path::param()
.and(warp::path::end())
.and(warp::get()) .and(warp::get())
.and(with_env(env)) .and(with_env(env))
.and_then(handlers::get_merchandise_list) .and_then(handlers::get_merchandise_list)
@ -219,6 +239,7 @@ pub fn delete_merchandise_list(
env: Environment, env: Environment,
) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { ) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone {
warp::path::param() warp::path::param()
.and(warp::path::end())
.and(warp::delete()) .and(warp::delete())
.and(warp::header::optional("api-key")) .and(warp::header::optional("api-key"))
.and(with_env(env)) .and(with_env(env))

View File

@ -7,7 +7,9 @@ use uuid::Uuid;
use warp::reply::{json, with_header, with_status}; use warp::reply::{json, with_header, with_status};
use warp::{Rejection, Reply}; use warp::{Rejection, Reply};
use super::models::{InteriorRefList, ListParams, Model, UpdateableModel, Owner, Shop, MerchandiseList}; use super::models::{
InteriorRefList, ListParams, MerchandiseList, Model, Owner, Shop, UpdateableModel,
};
use super::problem::{reject_anyhow, unauthorized_no_api_key, unauthorized_no_owner}; use super::problem::{reject_anyhow, unauthorized_no_api_key, unauthorized_no_owner};
use super::Environment; use super::Environment;
@ -137,6 +139,10 @@ pub async fn delete_shop(
.await .await
.map_err(reject_anyhow)?; .map_err(reject_anyhow)?;
env.caches.list_shops.clear().await; env.caches.list_shops.clear().await;
env.caches
.latest_interior_ref_list_by_shop_id
.delete(id)
.await;
Ok(StatusCode::NO_CONTENT) Ok(StatusCode::NO_CONTENT)
} }
@ -247,13 +253,11 @@ pub async fn delete_owner(
env.caches env.caches
.owner_ids_by_api_key .owner_ids_by_api_key
.delete(api_key.expect("api-key has been validated during authenticate")) .delete(api_key.expect("api-key has been validated during authenticate"))
.await .await;
.map_err(reject_anyhow)?;
env.caches.list_owners.clear().await; env.caches.list_owners.clear().await;
Ok(StatusCode::NO_CONTENT) Ok(StatusCode::NO_CONTENT)
} }
// TODO: probably need a way to get by shop id instead
pub async fn get_interior_ref_list(id: i32, env: Environment) -> Result<impl Reply, Rejection> { pub async fn get_interior_ref_list(id: i32, env: Environment) -> Result<impl Reply, Rejection> {
env.caches env.caches
.interior_ref_list .interior_ref_list
@ -302,6 +306,10 @@ pub async fn create_interior_ref_list(
let reply = with_header(reply, "Location", url.as_str()); let reply = with_header(reply, "Location", url.as_str());
let reply = with_status(reply, StatusCode::CREATED); let reply = with_status(reply, StatusCode::CREATED);
env.caches.list_interior_ref_lists.clear().await; env.caches.list_interior_ref_lists.clear().await;
env.caches
.latest_interior_ref_list_by_shop_id
.delete(saved_interior_ref_list.shop_id)
.await;
Ok(reply) Ok(reply)
} }
@ -311,6 +319,9 @@ pub async fn delete_interior_ref_list(
env: Environment, env: Environment,
) -> Result<impl Reply, Rejection> { ) -> Result<impl Reply, Rejection> {
let owner_id = authenticate(&env, api_key).await.map_err(reject_anyhow)?; let owner_id = authenticate(&env, api_key).await.map_err(reject_anyhow)?;
let interior_ref_list = InteriorRefList::get(&env.db, id)
.await
.map_err(reject_anyhow)?;
InteriorRefList::delete(&env.db, owner_id, id) InteriorRefList::delete(&env.db, owner_id, id)
.await .await
.map_err(reject_anyhow)?; .map_err(reject_anyhow)?;
@ -320,9 +331,29 @@ pub async fn delete_interior_ref_list(
.await .await
.map_err(reject_anyhow)?; .map_err(reject_anyhow)?;
env.caches.list_interior_ref_lists.clear().await; env.caches.list_interior_ref_lists.clear().await;
env.caches
.latest_interior_ref_list_by_shop_id
.delete(interior_ref_list.shop_id)
.await;
Ok(StatusCode::NO_CONTENT) Ok(StatusCode::NO_CONTENT)
} }
pub async fn get_latest_interior_ref_list_by_shop_id(
shop_id: i32,
env: Environment,
) -> Result<impl Reply, Rejection> {
env.caches
.latest_interior_ref_list_by_shop_id
.get_response(shop_id, || async {
let interior_ref_list =
InteriorRefList::get_latest_by_shop_id(&env.db, shop_id).await?;
let reply = json(&interior_ref_list);
let reply = with_status(reply, StatusCode::OK);
Ok(reply)
})
.await
}
// TODO: probably need a way to get by shop id instead // TODO: probably need a way to get by shop id instead
pub async fn get_merchandise_list(id: i32, env: Environment) -> Result<impl Reply, Rejection> { pub async fn get_merchandise_list(id: i32, env: Environment) -> Result<impl Reply, Rejection> {
env.caches env.caches

View File

@ -125,3 +125,21 @@ impl Model for InteriorRefList {
Ok(result) Ok(result)
} }
} }
impl InteriorRefList {
#[instrument(level = "debug", skip(db))]
pub async fn get_latest_by_shop_id(db: &PgPool, shop_id: i32) -> Result<Self> {
sqlx::query_as_unchecked!(
Self,
"SELECT interior_ref_lists.* FROM interior_ref_lists
INNER JOIN shops ON (interior_ref_lists.shop_id = shops.id)
WHERE shops.id = $1
ORDER BY interior_ref_lists.created_at DESC
LIMIT 1",
shop_id,
)
.fetch_one(db)
.await
.map_err(Error::new)
}
}

View File

@ -7,6 +7,7 @@ use tracing::instrument;
use super::ListParams; use super::ListParams;
use super::{Model, UpdateableModel}; use super::{Model, UpdateableModel};
use crate::models::InteriorRefList;
use crate::problem::forbidden_permission; use crate::problem::forbidden_permission;
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
@ -103,7 +104,6 @@ impl Model for Shop {
} }
} }
#[async_trait] #[async_trait]
impl UpdateableModel for Shop { impl UpdateableModel for Shop {
#[instrument(level = "debug", skip(self, db))] #[instrument(level = "debug", skip(self, db))]