mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-28 16:49:58 -07:00
global: snapshot
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use aide::axum::{ApiRouter, routing::get_with};
|
||||
use axum::{
|
||||
extract::{Path, Query, State},
|
||||
http::HeaderMap,
|
||||
http::{HeaderMap, Uri},
|
||||
response::Redirect,
|
||||
routing::get,
|
||||
};
|
||||
@@ -26,11 +26,12 @@ impl AddressRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/address/{address}",
|
||||
get_with(async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<AddressParam>,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.address(path.address)).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.address(path.address)).await
|
||||
}, |op| op
|
||||
.id("get_address")
|
||||
.addresses_tag()
|
||||
@@ -46,12 +47,13 @@ impl AddressRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/address/{address}/txs",
|
||||
get_with(async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<AddressParam>,
|
||||
Query(params): Query<AddressTxidsParam>,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.address_txids(path.address, params.after_txid, params.limit)).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.address_txids(path.address, params.after_txid, params.limit)).await
|
||||
}, |op| op
|
||||
.id("get_address_txs")
|
||||
.addresses_tag()
|
||||
@@ -67,11 +69,12 @@ impl AddressRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/address/{address}/utxo",
|
||||
get_with(async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<AddressParam>,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.address_utxos(path.address)).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.address_utxos(path.address)).await
|
||||
}, |op| op
|
||||
.id("get_address_utxos")
|
||||
.addresses_tag()
|
||||
@@ -87,12 +90,13 @@ impl AddressRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/address/{address}/txs/mempool",
|
||||
get_with(async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<AddressParam>,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
let hash = state.sync(|q| q.address_mempool_hash(&path.address));
|
||||
state.cached_json(&headers, CacheStrategy::MempoolHash(hash), move |q| q.address_mempool_txids(path.address)).await
|
||||
state.cached_json(&headers, CacheStrategy::MempoolHash(hash), &uri, move |q| q.address_mempool_txids(path.address)).await
|
||||
}, |op| op
|
||||
.id("get_address_mempool_txs")
|
||||
.addresses_tag()
|
||||
@@ -107,12 +111,13 @@ impl AddressRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/address/{address}/txs/chain",
|
||||
get_with(async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<AddressParam>,
|
||||
Query(params): Query<AddressTxidsParam>,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.address_txids(path.address, params.after_txid, 25)).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.address_txids(path.address, params.after_txid, 25)).await
|
||||
}, |op| op
|
||||
.id("get_address_confirmed_txs")
|
||||
.addresses_tag()
|
||||
@@ -128,11 +133,12 @@ impl AddressRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/validate-address/{address}",
|
||||
get_with(async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<ValidateAddressParam>,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Static, move |_q| Ok(AddressValidation::from_address(&path.address))).await
|
||||
state.cached_json(&headers, CacheStrategy::Static, &uri, move |_q| Ok(AddressValidation::from_address(&path.address))).await
|
||||
}, |op| op
|
||||
.id("validate_address")
|
||||
.addresses_tag()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use aide::axum::{ApiRouter, routing::get_with};
|
||||
use axum::{
|
||||
extract::{Path, State},
|
||||
http::HeaderMap,
|
||||
http::{HeaderMap, Uri},
|
||||
};
|
||||
use brk_query::BLOCK_TXS_PAGE_SIZE;
|
||||
use brk_types::{
|
||||
@@ -22,9 +22,9 @@ impl BlockRoutes for ApiRouter<AppState> {
|
||||
self.api_route(
|
||||
"/api/blocks",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
state
|
||||
.cached_json(&headers, CacheStrategy::Height, move |q| q.blocks(None))
|
||||
.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.blocks(None))
|
||||
.await
|
||||
},
|
||||
|op| {
|
||||
@@ -41,10 +41,11 @@ impl BlockRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/block/{hash}",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<BlockHashParam>,
|
||||
State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Static, move |q| q.block(&path.hash)).await
|
||||
state.cached_json(&headers, CacheStrategy::Static, &uri, move |q| q.block(&path.hash)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_block")
|
||||
@@ -64,10 +65,11 @@ impl BlockRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/block/{hash}/status",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<BlockHashParam>,
|
||||
State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.block_status(&path.hash)).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.block_status(&path.hash)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_block_status")
|
||||
@@ -87,10 +89,11 @@ impl BlockRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/block-height/{height}",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<HeightParam>,
|
||||
State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.block_by_height(path.height)).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.block_by_height(path.height)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_block_by_height")
|
||||
@@ -110,10 +113,11 @@ impl BlockRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/blocks/{height}",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<HeightParam>,
|
||||
State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.blocks(Some(path.height))).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.blocks(Some(path.height))).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_blocks_from_height")
|
||||
@@ -132,10 +136,11 @@ impl BlockRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/block/{hash}/txids",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<BlockHashParam>,
|
||||
State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Static, move |q| q.block_txids(&path.hash)).await
|
||||
state.cached_json(&headers, CacheStrategy::Static, &uri, move |q| q.block_txids(&path.hash)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_block_txids")
|
||||
@@ -155,10 +160,11 @@ impl BlockRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/block/{hash}/txs/{start_index}",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<BlockHashStartIndex>,
|
||||
State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Static, move |q| q.block_txs(&path.hash, path.start_index)).await
|
||||
state.cached_json(&headers, CacheStrategy::Static, &uri, move |q| q.block_txs(&path.hash, path.start_index)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_block_txs")
|
||||
@@ -179,10 +185,11 @@ impl BlockRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/block/{hash}/txid/{index}",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<BlockHashTxIndex>,
|
||||
State(state): State<AppState>| {
|
||||
state.cached_text(&headers, CacheStrategy::Static, move |q| q.block_txid_at_index(&path.hash, path.index).map(|t| t.to_string())).await
|
||||
state.cached_text(&headers, CacheStrategy::Static, &uri, move |q| q.block_txid_at_index(&path.hash, path.index).map(|t| t.to_string())).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_block_txid")
|
||||
@@ -202,10 +209,11 @@ impl BlockRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/mining/blocks/timestamp/{timestamp}",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<TimestampParam>,
|
||||
State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.block_by_timestamp(path.timestamp)).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.block_by_timestamp(path.timestamp)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_block_by_timestamp")
|
||||
@@ -223,10 +231,11 @@ impl BlockRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/block/{hash}/raw",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<BlockHashParam>,
|
||||
State(state): State<AppState>| {
|
||||
state.cached_bytes(&headers, CacheStrategy::Static, move |q| q.block_raw(&path.hash)).await
|
||||
state.cached_bytes(&headers, CacheStrategy::Static, &uri, move |q| q.block_raw(&path.hash)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_block_raw")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use aide::axum::{ApiRouter, routing::get_with};
|
||||
use axum::{extract::State, http::HeaderMap, response::Redirect, routing::get};
|
||||
use axum::{extract::State, http::{HeaderMap, Uri}, response::Redirect, routing::get};
|
||||
use brk_types::{Dollars, MempoolBlock, MempoolInfo, RecommendedFees, Txid};
|
||||
|
||||
use crate::extended::TransformResponseExtended;
|
||||
@@ -17,8 +17,8 @@ impl MempoolRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/mempool/info",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, state.mempool_cache(), |q| q.mempool_info()).await
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, state.mempool_cache(), &uri, |q| q.mempool_info()).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_mempool")
|
||||
@@ -33,8 +33,8 @@ impl MempoolRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/mempool/txids",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, state.mempool_cache(), |q| q.mempool_txids()).await
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, state.mempool_cache(), &uri, |q| q.mempool_txids()).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_mempool_txids")
|
||||
@@ -49,8 +49,8 @@ impl MempoolRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/fees/recommended",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, state.mempool_cache(), |q| q.recommended_fees()).await
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, state.mempool_cache(), &uri, |q| q.recommended_fees()).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_recommended_fees")
|
||||
@@ -65,12 +65,8 @@ impl MempoolRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/mempool/price",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
state
|
||||
.server_cached_json(&headers, state.mempool_cache(), "price", |q| {
|
||||
q.live_price()
|
||||
})
|
||||
.await
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, state.mempool_cache(), &uri, |q| q.live_price()).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_live_price")
|
||||
@@ -89,8 +85,8 @@ impl MempoolRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/fees/mempool-blocks",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, state.mempool_cache(), |q| q.mempool_blocks()).await
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, state.mempool_cache(), &uri, |q| q.mempool_blocks()).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_mempool_blocks")
|
||||
|
||||
@@ -48,8 +48,8 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
self.api_route(
|
||||
"/api/metrics",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Static, |q| Ok(q.metrics_catalog().clone())).await
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Static, &uri, |q| Ok(q.metrics_catalog().clone())).await
|
||||
},
|
||||
|op| op
|
||||
.id("get_metrics_tree")
|
||||
@@ -67,10 +67,11 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
"/api/metrics/count",
|
||||
get_with(
|
||||
async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Static, |q| Ok(q.metric_count())).await
|
||||
state.cached_json(&headers, CacheStrategy::Static, &uri, |q| Ok(q.metric_count())).await
|
||||
},
|
||||
|op| op
|
||||
.id("get_metrics_count")
|
||||
@@ -85,10 +86,11 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
"/api/metrics/indexes",
|
||||
get_with(
|
||||
async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Static, |q| Ok(q.indexes().to_vec())).await
|
||||
state.cached_json(&headers, CacheStrategy::Static, &uri, |q| Ok(q.indexes().to_vec())).await
|
||||
},
|
||||
|op| op
|
||||
.id("get_indexes")
|
||||
@@ -105,11 +107,12 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
"/api/metrics/list",
|
||||
get_with(
|
||||
async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
State(state): State<AppState>,
|
||||
Query(pagination): Query<Pagination>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Static, move |q| Ok(q.metrics(pagination))).await
|
||||
state.cached_json(&headers, CacheStrategy::Static, &uri, move |q| Ok(q.metrics(pagination))).await
|
||||
},
|
||||
|op| op
|
||||
.id("list_metrics")
|
||||
@@ -124,12 +127,13 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
"/api/metrics/search/{metric}",
|
||||
get_with(
|
||||
async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
State(state): State<AppState>,
|
||||
Path(path): Path<MetricParam>,
|
||||
Query(query): Query<LimitParam>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Static, move |q| Ok(q.match_metric(&path.metric, query.limit))).await
|
||||
state.cached_json(&headers, CacheStrategy::Static, &uri, move |q| Ok(q.match_metric(&path.metric, query.limit))).await
|
||||
},
|
||||
|op| op
|
||||
.id("search_metrics")
|
||||
@@ -145,11 +149,12 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
"/api/metric/{metric}",
|
||||
get_with(
|
||||
async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
State(state): State<AppState>,
|
||||
Path(path): Path<MetricParam>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Static, move |q| {
|
||||
state.cached_json(&headers, CacheStrategy::Static, &uri, move |q| {
|
||||
if let Some(indexes) = q.metric_to_indexes(path.metric.clone()) {
|
||||
return Ok(indexes.clone())
|
||||
}
|
||||
@@ -296,9 +301,9 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/metrics/cost-basis",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
state
|
||||
.cached_json(&headers, CacheStrategy::Static, |q| q.cost_basis_cohorts())
|
||||
.cached_json(&headers, CacheStrategy::Static, &uri, |q| q.cost_basis_cohorts())
|
||||
.await
|
||||
},
|
||||
|op| {
|
||||
@@ -314,11 +319,12 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/metrics/cost-basis/{cohort}/dates",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(params): Path<CostBasisCohortParam>,
|
||||
State(state): State<AppState>| {
|
||||
state
|
||||
.cached_json(&headers, CacheStrategy::Height, move |q| {
|
||||
.cached_json(&headers, CacheStrategy::Height, &uri, move |q| {
|
||||
q.cost_basis_dates(¶ms.cohort)
|
||||
})
|
||||
.await
|
||||
@@ -337,12 +343,13 @@ impl ApiMetricsRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/metrics/cost-basis/{cohort}/{date}",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
async |uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(params): Path<CostBasisParams>,
|
||||
Query(query): Query<CostBasisQuery>,
|
||||
State(state): State<AppState>| {
|
||||
state
|
||||
.cached_json(&headers, CacheStrategy::Static, move |q| {
|
||||
.cached_json(&headers, CacheStrategy::Static, &uri, move |q| {
|
||||
q.cost_basis_formatted(
|
||||
¶ms.cohort,
|
||||
params.date,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use aide::axum::{ApiRouter, routing::get_with};
|
||||
use axum::{
|
||||
extract::{Path, State},
|
||||
http::HeaderMap,
|
||||
http::{HeaderMap, Uri},
|
||||
response::Redirect,
|
||||
routing::get,
|
||||
};
|
||||
@@ -28,8 +28,8 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/difficulty-adjustment",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, |q| q.difficulty_adjustment()).await
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, |q| q.difficulty_adjustment()).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_difficulty_adjustment")
|
||||
@@ -45,9 +45,9 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/mining/pools",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
// Pool list is static, only changes on code update
|
||||
state.cached_json(&headers, CacheStrategy::Static, |q| Ok(q.all_pools())).await
|
||||
state.cached_json(&headers, CacheStrategy::Static, &uri, |q| Ok(q.all_pools())).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_pools")
|
||||
@@ -63,8 +63,8 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/mining/pools/{time_period}",
|
||||
get_with(
|
||||
async |headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.mining_pools(path.time_period)).await
|
||||
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.mining_pools(path.time_period)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_pool_stats")
|
||||
@@ -80,8 +80,8 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/mining/pool/{slug}",
|
||||
get_with(
|
||||
async |headers: HeaderMap, Path(path): Path<PoolSlugParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.pool_detail(path.slug)).await
|
||||
async |uri: Uri, headers: HeaderMap, Path(path): Path<PoolSlugParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.pool_detail(path.slug)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_pool")
|
||||
@@ -98,8 +98,8 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/mining/hashrate",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, |q| q.hashrate(None)).await
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, |q| q.hashrate(None)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_hashrate")
|
||||
@@ -115,8 +115,8 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/mining/hashrate/{time_period}",
|
||||
get_with(
|
||||
async |headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.hashrate(Some(path.time_period))).await
|
||||
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.hashrate(Some(path.time_period))).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_hashrate_by_period")
|
||||
@@ -132,8 +132,8 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/mining/difficulty-adjustments",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, |q| q.difficulty_adjustments(None)).await
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, |q| q.difficulty_adjustments(None)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_difficulty_adjustments")
|
||||
@@ -149,8 +149,8 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/mining/difficulty-adjustments/{time_period}",
|
||||
get_with(
|
||||
async |headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.difficulty_adjustments(Some(path.time_period))).await
|
||||
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.difficulty_adjustments(Some(path.time_period))).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_difficulty_adjustments_by_period")
|
||||
@@ -166,8 +166,8 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/mining/blocks/fees/{time_period}",
|
||||
get_with(
|
||||
async |headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.block_fees(path.time_period)).await
|
||||
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.block_fees(path.time_period)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_block_fees")
|
||||
@@ -183,8 +183,8 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/mining/blocks/rewards/{time_period}",
|
||||
get_with(
|
||||
async |headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.block_rewards(path.time_period)).await
|
||||
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.block_rewards(path.time_period)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_block_rewards")
|
||||
@@ -218,8 +218,8 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/mining/blocks/sizes-weights/{time_period}",
|
||||
get_with(
|
||||
async |headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.block_sizes_weights(path.time_period)).await
|
||||
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.block_sizes_weights(path.time_period)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_block_sizes_weights")
|
||||
@@ -235,8 +235,8 @@ impl MiningRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/v1/mining/reward-stats/{block_count}",
|
||||
get_with(
|
||||
async |headers: HeaderMap, Path(path): Path<BlockCountParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.reward_stats(path.block_count)).await
|
||||
async |uri: Uri, headers: HeaderMap, Path(path): Path<BlockCountParam>, State(state): State<AppState>| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.reward_stats(path.block_count)).await
|
||||
},
|
||||
|op| {
|
||||
op.id("get_reward_stats")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{borrow::Cow, fs, path};
|
||||
|
||||
use aide::axum::{ApiRouter, routing::get_with};
|
||||
use axum::{extract::State, http::HeaderMap};
|
||||
use axum::{extract::State, http::{HeaderMap, Uri}};
|
||||
use brk_types::{DiskUsage, Health, Height, SyncStatus};
|
||||
use vecdb::GenericStoredVec;
|
||||
|
||||
@@ -18,11 +18,11 @@ impl ServerRoutes for ApiRouter<AppState> {
|
||||
self.api_route(
|
||||
"/api/server/sync",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
let tip_height = state.client.get_last_height();
|
||||
|
||||
state
|
||||
.cached_json(&headers, CacheStrategy::Height, move |q| {
|
||||
.cached_json(&headers, CacheStrategy::Height, &uri, move |q| {
|
||||
let indexed_height = q.height();
|
||||
let tip_height = tip_height?;
|
||||
let blocks_behind = Height::from(tip_height.saturating_sub(*indexed_height));
|
||||
@@ -59,10 +59,10 @@ impl ServerRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/api/server/disk",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
let brk_path = state.data_path.clone();
|
||||
state
|
||||
.cached_json(&headers, CacheStrategy::Height, move |q| {
|
||||
.cached_json(&headers, CacheStrategy::Height, &uri, move |q| {
|
||||
let brk_bytes = dir_size(&brk_path)?;
|
||||
let bitcoin_bytes = dir_size(q.blocks_dir())?;
|
||||
Ok(DiskUsage::new(brk_bytes, bitcoin_bytes))
|
||||
@@ -106,9 +106,9 @@ impl ServerRoutes for ApiRouter<AppState> {
|
||||
.api_route(
|
||||
"/version",
|
||||
get_with(
|
||||
async |headers: HeaderMap, State(state): State<AppState>| {
|
||||
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| {
|
||||
state
|
||||
.cached_json(&headers, CacheStrategy::Static, |_| {
|
||||
.cached_json(&headers, CacheStrategy::Static, &uri, |_| {
|
||||
Ok(env!("CARGO_PKG_VERSION"))
|
||||
})
|
||||
.await
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use aide::axum::{ApiRouter, routing::get_with};
|
||||
use axum::{
|
||||
extract::{Path, State},
|
||||
http::HeaderMap,
|
||||
http::{HeaderMap, Uri},
|
||||
response::Redirect,
|
||||
routing::get,
|
||||
};
|
||||
@@ -24,11 +24,12 @@ impl TxRoutes for ApiRouter<AppState> {
|
||||
"/api/tx/{txid}",
|
||||
get_with(
|
||||
async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(txid): Path<TxidParam>,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.transaction(txid)).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.transaction(txid)).await
|
||||
},
|
||||
|op| op
|
||||
.id("get_tx")
|
||||
@@ -48,11 +49,12 @@ impl TxRoutes for ApiRouter<AppState> {
|
||||
"/api/tx/{txid}/status",
|
||||
get_with(
|
||||
async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(txid): Path<TxidParam>,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.transaction_status(txid)).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.transaction_status(txid)).await
|
||||
},
|
||||
|op| op
|
||||
.id("get_tx_status")
|
||||
@@ -72,11 +74,12 @@ impl TxRoutes for ApiRouter<AppState> {
|
||||
"/api/tx/{txid}/hex",
|
||||
get_with(
|
||||
async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(txid): Path<TxidParam>,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
state.cached_text(&headers, CacheStrategy::Height, move |q| q.transaction_hex(txid)).await
|
||||
state.cached_text(&headers, CacheStrategy::Height, &uri, move |q| q.transaction_hex(txid)).await
|
||||
},
|
||||
|op| op
|
||||
.id("get_tx_hex")
|
||||
@@ -96,12 +99,13 @@ impl TxRoutes for ApiRouter<AppState> {
|
||||
"/api/tx/{txid}/outspend/{vout}",
|
||||
get_with(
|
||||
async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(path): Path<TxidVout>,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
let txid = TxidParam { txid: path.txid };
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.outspend(txid, path.vout)).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.outspend(txid, path.vout)).await
|
||||
},
|
||||
|op| op
|
||||
.id("get_tx_outspend")
|
||||
@@ -121,11 +125,12 @@ impl TxRoutes for ApiRouter<AppState> {
|
||||
"/api/tx/{txid}/outspends",
|
||||
get_with(
|
||||
async |
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
Path(txid): Path<TxidParam>,
|
||||
State(state): State<AppState>
|
||||
| {
|
||||
state.cached_json(&headers, CacheStrategy::Height, move |q| q.outspends(txid)).await
|
||||
state.cached_json(&headers, CacheStrategy::Height, &uri, move |q| q.outspends(txid)).await
|
||||
},
|
||||
|op| op
|
||||
.id("get_tx_outspends")
|
||||
|
||||
@@ -27,10 +27,8 @@ where
|
||||
T: Serialize;
|
||||
fn new_text(value: &str, etag: &str) -> Self;
|
||||
fn new_text_with(status: StatusCode, value: &str, etag: &str) -> Self;
|
||||
fn new_text_cached(value: &str, params: &CacheParams) -> Self;
|
||||
fn new_bytes(value: Vec<u8>, etag: &str) -> Self;
|
||||
fn new_bytes_with(status: StatusCode, value: Vec<u8>, etag: &str) -> Self;
|
||||
fn new_bytes_cached(value: Vec<u8>, params: &CacheParams) -> Self;
|
||||
}
|
||||
|
||||
impl ResponseExtended for Response<Body> {
|
||||
@@ -114,26 +112,4 @@ impl ResponseExtended for Response<Body> {
|
||||
}
|
||||
Self::new_json_cached(value, ¶ms)
|
||||
}
|
||||
|
||||
fn new_text_cached(value: &str, params: &CacheParams) -> Self {
|
||||
let mut response = Response::builder().body(value.to_string().into()).unwrap();
|
||||
let headers = response.headers_mut();
|
||||
headers.insert_content_type_text_plain();
|
||||
headers.insert_cache_control(¶ms.cache_control);
|
||||
if let Some(etag) = ¶ms.etag {
|
||||
headers.insert_etag(etag);
|
||||
}
|
||||
response
|
||||
}
|
||||
|
||||
fn new_bytes_cached(value: Vec<u8>, params: &CacheParams) -> Self {
|
||||
let mut response = Response::builder().body(value.into()).unwrap();
|
||||
let headers = response.headers_mut();
|
||||
headers.insert_content_type_octet_stream();
|
||||
headers.insert_cache_control(¶ms.cache_control);
|
||||
if let Some(etag) = ¶ms.etag {
|
||||
headers.insert_etag(etag);
|
||||
}
|
||||
response
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use std::{path::PathBuf, sync::Arc, time::Instant};
|
||||
use std::{future::Future, path::PathBuf, sync::Arc, time::{Duration, Instant}};
|
||||
|
||||
use derive_more::Deref;
|
||||
|
||||
use axum::{
|
||||
body::{Body, Bytes},
|
||||
http::{HeaderMap, Response},
|
||||
http::{HeaderMap, Response, Uri},
|
||||
};
|
||||
use brk_query::AsyncQuery;
|
||||
use brk_rpc::Client;
|
||||
use jiff::Timestamp;
|
||||
use quick_cache::sync::Cache;
|
||||
use quick_cache::sync::{Cache, GuardResult};
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::{
|
||||
@@ -35,33 +35,12 @@ impl AppState {
|
||||
CacheStrategy::MempoolHash(hash)
|
||||
}
|
||||
|
||||
/// JSON response with caching
|
||||
/// JSON response with HTTP + server-side caching
|
||||
pub async fn cached_json<T, F>(
|
||||
&self,
|
||||
headers: &HeaderMap,
|
||||
strategy: CacheStrategy,
|
||||
f: F,
|
||||
) -> Response<Body>
|
||||
where
|
||||
T: Serialize + Send + 'static,
|
||||
F: FnOnce(&brk_query::Query) -> brk_error::Result<T> + 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::<T>::to_json_response(Err(e), params.etag_str()),
|
||||
}
|
||||
}
|
||||
|
||||
/// JSON response with HTTP caching + server-side cache
|
||||
pub async fn server_cached_json<T, F>(
|
||||
&self,
|
||||
headers: &HeaderMap,
|
||||
strategy: CacheStrategy,
|
||||
cache_prefix: &str,
|
||||
uri: &Uri,
|
||||
f: F,
|
||||
) -> Response<Body>
|
||||
where
|
||||
@@ -73,9 +52,9 @@ impl AppState {
|
||||
return ResponseExtended::new_not_modified();
|
||||
}
|
||||
|
||||
let cache_key = format!("{cache_prefix}-{}", params.etag_str());
|
||||
let full_key = format!("{}-{}", uri, params.etag_str());
|
||||
let result = self
|
||||
.get_or_insert(&cache_key, async move {
|
||||
.get_or_insert(&full_key, async move {
|
||||
let value = self.run(f).await?;
|
||||
Ok(serde_json::to_vec(&value).unwrap().into())
|
||||
})
|
||||
@@ -96,18 +75,95 @@ impl AppState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Text response with HTTP + server-side caching
|
||||
pub async fn cached_text<T, F>(
|
||||
&self,
|
||||
headers: &HeaderMap,
|
||||
strategy: CacheStrategy,
|
||||
uri: &Uri,
|
||||
f: F,
|
||||
) -> Response<Body>
|
||||
where
|
||||
T: AsRef<str> + Send + 'static,
|
||||
F: FnOnce(&brk_query::Query) -> brk_error::Result<T> + Send + 'static,
|
||||
{
|
||||
let params = CacheParams::resolve(&strategy, || self.sync(|q| q.height().into()));
|
||||
if params.matches_etag(headers) {
|
||||
return ResponseExtended::new_not_modified();
|
||||
}
|
||||
|
||||
let full_key = format!("{}-{}", uri, params.etag_str());
|
||||
let result = self
|
||||
.get_or_insert(&full_key, async move {
|
||||
let value = self.run(f).await?;
|
||||
Ok(Bytes::from(value.as_ref().to_owned()))
|
||||
})
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(bytes) => {
|
||||
let mut response = Response::new(Body::from(bytes));
|
||||
let h = response.headers_mut();
|
||||
h.insert_content_type_text_plain();
|
||||
h.insert_cache_control(¶ms.cache_control);
|
||||
if let Some(etag) = ¶ms.etag {
|
||||
h.insert_etag(etag);
|
||||
}
|
||||
response
|
||||
}
|
||||
Err(e) => ResultExtended::<T>::to_text_response(Err(e), params.etag_str()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Binary response with HTTP + server-side caching
|
||||
pub async fn cached_bytes<T, F>(
|
||||
&self,
|
||||
headers: &HeaderMap,
|
||||
strategy: CacheStrategy,
|
||||
uri: &Uri,
|
||||
f: F,
|
||||
) -> Response<Body>
|
||||
where
|
||||
T: Into<Vec<u8>> + Send + 'static,
|
||||
F: FnOnce(&brk_query::Query) -> brk_error::Result<T> + Send + 'static,
|
||||
{
|
||||
let params = CacheParams::resolve(&strategy, || self.sync(|q| q.height().into()));
|
||||
if params.matches_etag(headers) {
|
||||
return ResponseExtended::new_not_modified();
|
||||
}
|
||||
|
||||
let full_key = format!("{}-{}", uri, params.etag_str());
|
||||
let result = self
|
||||
.get_or_insert(&full_key, async move {
|
||||
let value = self.run(f).await?;
|
||||
Ok(Bytes::from(value.into()))
|
||||
})
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(bytes) => {
|
||||
let mut response = Response::new(Body::from(bytes));
|
||||
let h = response.headers_mut();
|
||||
h.insert_content_type_octet_stream();
|
||||
h.insert_cache_control(¶ms.cache_control);
|
||||
if let Some(etag) = ¶ms.etag {
|
||||
h.insert_etag(etag);
|
||||
}
|
||||
response
|
||||
}
|
||||
Err(e) => ResultExtended::<T>::to_bytes_response(Err(e), params.etag_str()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check server-side cache, compute on miss
|
||||
pub async fn get_or_insert(
|
||||
&self,
|
||||
cache_key: &str,
|
||||
compute: impl std::future::Future<Output = brk_error::Result<Bytes>>,
|
||||
compute: impl Future<Output = brk_error::Result<Bytes>>,
|
||||
) -> brk_error::Result<Bytes> {
|
||||
use quick_cache::sync::GuardResult;
|
||||
|
||||
let guard_res = self.cache.get_value_or_guard(
|
||||
cache_key,
|
||||
Some(std::time::Duration::from_millis(50)),
|
||||
);
|
||||
let guard_res = self
|
||||
.cache
|
||||
.get_value_or_guard(cache_key, Some(Duration::from_millis(50)));
|
||||
|
||||
if let GuardResult::Value(bytes) = guard_res {
|
||||
return Ok(bytes);
|
||||
@@ -121,46 +177,4 @@ impl AppState {
|
||||
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
/// Text response with caching
|
||||
pub async fn cached_text<T, F>(
|
||||
&self,
|
||||
headers: &HeaderMap,
|
||||
strategy: CacheStrategy,
|
||||
f: F,
|
||||
) -> Response<Body>
|
||||
where
|
||||
T: AsRef<str> + Send + 'static,
|
||||
F: FnOnce(&brk_query::Query) -> brk_error::Result<T> + 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::<T>::to_text_response(Err(e), params.etag_str()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Binary response with caching
|
||||
pub async fn cached_bytes<T, F>(
|
||||
&self,
|
||||
headers: &HeaderMap,
|
||||
strategy: CacheStrategy,
|
||||
f: F,
|
||||
) -> Response<Body>
|
||||
where
|
||||
T: Into<Vec<u8>> + Send + 'static,
|
||||
F: FnOnce(&brk_query::Query) -> brk_error::Result<T> + 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::<T>::to_bytes_response(Err(e), params.etag_str()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user