use std::{ops::Deref, path::PathBuf, sync::Arc}; use axum::{ body::{Body, Bytes}, http::{HeaderMap, Response}, }; use brk_query::AsyncQuery; use quick_cache::sync::Cache; use serde::Serialize; use crate::{ CacheParams, CacheStrategy, extended::{ResponseExtended, ResultExtended}, }; #[derive(Clone)] pub struct AppState { pub query: AsyncQuery, pub path: Option, pub cache: Arc>, } impl Deref for AppState { type Target = AsyncQuery; fn deref(&self) -> &Self::Target { &self.query } } impl AppState { /// JSON response with caching pub async fn cached_json( &self, headers: &HeaderMap, strategy: CacheStrategy, f: F, ) -> Response where T: Serialize + Send + 'static, F: FnOnce(&brk_query::Query) -> brk_error::Result + Send + 'static, { let params = CacheParams::resolve(&strategy, || self.sync(|q| q.height().into())); if params.matches_etag(headers) { return ResponseExtended::new_not_modified(); } match self.run(f).await { Ok(value) => ResponseExtended::new_json_cached(&value, ¶ms), Err(e) => ResultExtended::::to_json_response(Err(e), params.etag_str()), } } /// Text response with caching pub async fn cached_text( &self, headers: &HeaderMap, strategy: CacheStrategy, f: F, ) -> Response where T: AsRef + Send + 'static, F: FnOnce(&brk_query::Query) -> brk_error::Result + Send + 'static, { let params = CacheParams::resolve(&strategy, || self.sync(|q| q.height().into())); if params.matches_etag(headers) { return ResponseExtended::new_not_modified(); } match self.run(f).await { Ok(value) => ResponseExtended::new_text_cached(value.as_ref(), ¶ms), Err(e) => ResultExtended::::to_text_response(Err(e), params.etag_str()), } } /// Binary response with caching pub async fn cached_bytes( &self, headers: &HeaderMap, strategy: CacheStrategy, f: F, ) -> Response where T: Into> + Send + 'static, F: FnOnce(&brk_query::Query) -> brk_error::Result + Send + 'static, { let params = CacheParams::resolve(&strategy, || self.sync(|q| q.height().into())); if params.matches_etag(headers) { return ResponseExtended::new_not_modified(); } match self.run(f).await { Ok(value) => ResponseExtended::new_bytes_cached(value.into(), ¶ms), Err(e) => ResultExtended::::to_bytes_response(Err(e), params.etag_str()), } } }