Add caching with LRU cache under mutex
Caches responses of each GET handler in a separate capacity-limited cache (as a custom clone-able `CachedResponse` struct). Subsequent requests will build a `Response` from the cached bytes instead of re-querying the database and re-serializing the JSON. This greatly speeds up the list endpoints and `get_interior_ref_list`. Also caches the api-key-to-id mapping for `Owner`s in order to speed up frequent authentications. Each create handler clears the entire list response cache. Each delete handler also clears the entire list response cache and deletes the cached response for that key. Deleting an owner also deletes their entry in the `owner_ids_by_api_key` cache.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::{Error, Result};
|
||||
use async_trait::async_trait;
|
||||
use chrono::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -50,11 +50,10 @@ impl Model for InteriorRefList {
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
async fn get(db: &PgPool, id: i32) -> Result<Self> {
|
||||
Ok(
|
||||
sqlx::query_as_unchecked!(Self, "SELECT * FROM interior_ref_lists WHERE id = $1", id)
|
||||
.fetch_one(db)
|
||||
.await?,
|
||||
)
|
||||
sqlx::query_as_unchecked!(Self, "SELECT * FROM interior_ref_lists WHERE id = $1", id)
|
||||
.fetch_one(db)
|
||||
.await
|
||||
.map_err(Error::new)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, db))]
|
||||
@@ -95,7 +94,7 @@ impl Model for InteriorRefList {
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
async fn list(db: &PgPool, list_params: ListParams) -> Result<Vec<Self>> {
|
||||
async fn list(db: &PgPool, list_params: &ListParams) -> Result<Vec<Self>> {
|
||||
let result = if let Some(order_by) = list_params.get_order_by() {
|
||||
sqlx::query_as_unchecked!(
|
||||
Self,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use serde::Deserialize;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
|
||||
pub mod interior_ref_list;
|
||||
pub mod model;
|
||||
@@ -11,7 +12,7 @@ pub use model::Model;
|
||||
pub use owner::Owner;
|
||||
pub use shop::Shop;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Deserialize)]
|
||||
pub enum Order {
|
||||
Asc,
|
||||
Desc,
|
||||
@@ -30,7 +31,7 @@ impl fmt::Display for Order {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Deserialize)]
|
||||
pub struct ListParams {
|
||||
limit: Option<i64>,
|
||||
offset: Option<i64>,
|
||||
|
||||
@@ -25,5 +25,5 @@ where
|
||||
async fn get(db: &PgPool, id: i32) -> Result<Self>;
|
||||
async fn save(self, db: &PgPool) -> Result<Self>;
|
||||
async fn delete(db: &PgPool, owner_id: i32, id: i32) -> Result<u64>;
|
||||
async fn list(db: &PgPool, list_params: ListParams) -> Result<Vec<Self>>;
|
||||
async fn list(db: &PgPool, list_params: &ListParams) -> Result<Vec<Self>>;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::{Error, Result};
|
||||
use async_trait::async_trait;
|
||||
use chrono::prelude::*;
|
||||
use ipnetwork::IpNetwork;
|
||||
@@ -34,11 +34,10 @@ impl Model for Owner {
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
async fn get(db: &PgPool, id: i32) -> Result<Self> {
|
||||
Ok(
|
||||
sqlx::query_as!(Self, "SELECT * FROM owners WHERE id = $1", id)
|
||||
.fetch_one(db)
|
||||
.await?,
|
||||
)
|
||||
sqlx::query_as!(Self, "SELECT * FROM owners WHERE id = $1", id)
|
||||
.fetch_one(db)
|
||||
.await
|
||||
.map_err(Error::new)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
@@ -73,7 +72,7 @@ impl Model for Owner {
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
async fn list(db: &PgPool, list_params: ListParams) -> Result<Vec<Self>> {
|
||||
async fn list(db: &PgPool, list_params: &ListParams) -> Result<Vec<Self>> {
|
||||
let result = if let Some(order_by) = list_params.get_order_by() {
|
||||
sqlx::query_as!(
|
||||
Self,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::{Error, Result};
|
||||
use async_trait::async_trait;
|
||||
use chrono::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -35,11 +35,10 @@ impl Model for Shop {
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
async fn get(db: &PgPool, id: i32) -> Result<Self> {
|
||||
Ok(
|
||||
sqlx::query_as!(Self, "SELECT * FROM shops WHERE id = $1", id)
|
||||
.fetch_one(db)
|
||||
.await?,
|
||||
)
|
||||
sqlx::query_as!(Self, "SELECT * FROM shops WHERE id = $1", id)
|
||||
.fetch_one(db)
|
||||
.await
|
||||
.map_err(Error::new)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
@@ -78,7 +77,7 @@ impl Model for Shop {
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(db))]
|
||||
async fn list(db: &PgPool, list_params: ListParams) -> Result<Vec<Self>> {
|
||||
async fn list(db: &PgPool, list_params: &ListParams) -> Result<Vec<Self>> {
|
||||
let result = if let Some(order_by) = list_params.get_order_by() {
|
||||
sqlx::query_as!(
|
||||
Self,
|
||||
|
||||
Reference in New Issue
Block a user