mempool: general improvements

This commit is contained in:
nym21
2026-04-28 18:46:37 +02:00
parent 66494c081c
commit f1749472e7
95 changed files with 2545 additions and 2670 deletions
+11 -16
View File
@@ -2,8 +2,6 @@ use aide::axum::{ApiRouter, routing::get_with};
use axum::{
extract::{Path, Query, State},
http::{HeaderMap, Uri},
response::Redirect,
routing::get,
};
use brk_types::{AddrStats, AddrValidation, Transaction, Txid, Utxo, Version};
@@ -19,10 +17,7 @@ pub trait AddrRoutes {
impl AddrRoutes for ApiRouter<AppState> {
fn add_addr_routes(self) -> Self {
self
.route("/api/address", get(Redirect::temporary("/api/addresses")))
.route("/api/addresses", get(Redirect::temporary("/api#tag/addresses")))
.api_route(
self.api_route(
"/api/address/{address}",
get_with(async |
uri: Uri,
@@ -31,8 +26,8 @@ impl AddrRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
let strategy = state.addr_cache(Version::ONE, &path.addr, false);
state.cached_json(&headers, strategy, &uri, move |q| q.addr(path.addr)).await
let strategy = state.addr_strategy(Version::ONE, &path.addr, false);
state.respond_json(&headers, strategy, &uri, move |q| q.addr(path.addr)).await
}, |op| op
.id("get_address")
.addrs_tag()
@@ -54,8 +49,8 @@ impl AddrRoutes for ApiRouter<AppState> {
Query(params): Query<AddrTxidsParam>,
State(state): State<AppState>
| {
let strategy = state.addr_cache(Version::ONE, &path.addr, false);
state.cached_json(&headers, strategy, &uri, move |q| q.addr_txs(path.addr, params.after_txid, 50)).await
let strategy = state.addr_strategy(Version::ONE, &path.addr, false);
state.respond_json(&headers, strategy, &uri, move |q| q.addr_txs(path.addr, params.after_txid, 50)).await
}, |op| op
.id("get_address_txs")
.addrs_tag()
@@ -77,8 +72,8 @@ impl AddrRoutes for ApiRouter<AppState> {
Query(params): Query<AddrTxidsParam>,
State(state): State<AppState>
| {
let strategy = state.addr_cache(Version::ONE, &path.addr, true);
state.cached_json(&headers, strategy, &uri, move |q| q.addr_txs(path.addr, params.after_txid, 25)).await
let strategy = state.addr_strategy(Version::ONE, &path.addr, true);
state.respond_json(&headers, strategy, &uri, move |q| q.addr_txs(path.addr, params.after_txid, 25)).await
}, |op| op
.id("get_address_confirmed_txs")
.addrs_tag()
@@ -101,7 +96,7 @@ impl AddrRoutes for ApiRouter<AppState> {
State(state): State<AppState>
| {
let hash = state.sync(|q| q.addr_mempool_hash(&path.addr));
state.cached_json(&headers, CacheStrategy::MempoolHash(hash), &uri, move |q| q.addr_mempool_txids(path.addr)).await
state.respond_json(&headers, CacheStrategy::MempoolHash(hash), &uri, move |q| q.addr_mempool_txids(path.addr)).await
}, |op| op
.id("get_address_mempool_txs")
.addrs_tag()
@@ -123,8 +118,8 @@ impl AddrRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
let strategy = state.addr_cache(Version::ONE, &path.addr, false);
state.cached_json(&headers, strategy, &uri, move |q| q.addr_utxos(path.addr)).await
let strategy = state.addr_strategy(Version::ONE, &path.addr, false);
state.respond_json(&headers, strategy, &uri, move |q| q.addr_utxos(path.addr)).await
}, |op| op
.id("get_address_utxos")
.addrs_tag()
@@ -146,7 +141,7 @@ impl AddrRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, move |_q| Ok(AddrValidation::from_addr(&path.addr))).await
state.respond_json(&headers, CacheStrategy::Deploy, &uri, move |_q| Ok(AddrValidation::from_addr(&path.addr))).await
}, |op| op
.id("validate_address")
.addrs_tag()
+25 -25
View File
@@ -29,8 +29,8 @@ impl BlockRoutes for ApiRouter<AppState> {
headers: HeaderMap,
Path(path): Path<BlockHashParam>,
_: Empty, State(state): State<AppState>| {
let strategy = state.block_cache(Version::ONE, &path.hash);
state.cached_json(&headers, strategy, &uri, move |q| q.block(&path.hash)).await
let strategy = state.block_strategy(Version::ONE, &path.hash);
state.respond_json(&headers, strategy, &uri, move |q| q.block(&path.hash)).await
},
|op| {
op.id("get_block")
@@ -51,8 +51,8 @@ impl BlockRoutes for ApiRouter<AppState> {
"/api/v1/block/{hash}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<BlockHashParam>, _: Empty, State(state): State<AppState>| {
let strategy = state.block_cache(Version::ONE, &path.hash);
state.cached_json(&headers, strategy, &uri, move |q| {
let strategy = state.block_strategy(Version::ONE, &path.hash);
state.respond_json(&headers, strategy, &uri, move |q| {
let height = q.height_by_hash(&path.hash)?;
q.block_by_height_v1(height)
}).await
@@ -74,8 +74,8 @@ impl BlockRoutes for ApiRouter<AppState> {
"/api/block/{hash}/header",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<BlockHashParam>, _: Empty, State(state): State<AppState>| {
let strategy = state.block_cache(Version::ONE, &path.hash);
state.cached_text(&headers, strategy, &uri, move |q| q.block_header_hex(&path.hash)).await
let strategy = state.block_strategy(Version::ONE, &path.hash);
state.respond_text(&headers, strategy, &uri, move |q| q.block_header_hex(&path.hash)).await
},
|op| {
op.id("get_block_header")
@@ -97,7 +97,7 @@ impl BlockRoutes for ApiRouter<AppState> {
headers: HeaderMap,
Path(path): Path<HeightParam>,
_: Empty, State(state): State<AppState>| {
state.cached_text(&headers, state.height_cache(Version::ONE, path.height), &uri, move |q| q.block_hash_by_height(path.height).map(|h| h.to_string())).await
state.respond_text(&headers, state.height_strategy(Version::ONE, path.height), &uri, move |q| q.block_hash_by_height(path.height).map(|h| h.to_string())).await
},
|op| {
op.id("get_block_by_height")
@@ -121,7 +121,7 @@ impl BlockRoutes for ApiRouter<AppState> {
headers: HeaderMap,
Path(path): Path<TimestampParam>,
_: Empty, State(state): State<AppState>| {
state.cached_json(&headers, state.timestamp_cache(Version::ONE, path.timestamp), &uri, move |q| q.block_by_timestamp(path.timestamp)).await
state.respond_json(&headers, state.timestamp_strategy(Version::ONE, path.timestamp), &uri, move |q| q.block_by_timestamp(path.timestamp)).await
},
|op| {
op.id("get_block_by_timestamp")
@@ -143,8 +143,8 @@ impl BlockRoutes for ApiRouter<AppState> {
headers: HeaderMap,
Path(path): Path<BlockHashParam>,
_: Empty, State(state): State<AppState>| {
let strategy = state.block_cache(Version::ONE, &path.hash);
state.cached_bytes(&headers, strategy, &uri, move |q| q.block_raw(&path.hash)).await
let strategy = state.block_strategy(Version::ONE, &path.hash);
state.respond_bytes(&headers, strategy, &uri, move |q| q.block_raw(&path.hash)).await
},
|op| {
op.id("get_block_raw")
@@ -168,7 +168,7 @@ impl BlockRoutes for ApiRouter<AppState> {
headers: HeaderMap,
Path(path): Path<BlockHashParam>,
_: Empty, State(state): State<AppState>| {
state.cached_json(&headers, state.block_status_cache(Version::ONE, &path.hash), &uri, move |q| q.block_status(&path.hash)).await
state.respond_json(&headers, state.block_status_strategy(Version::ONE, &path.hash), &uri, move |q| q.block_status(&path.hash)).await
},
|op| {
op.id("get_block_status")
@@ -189,7 +189,7 @@ impl BlockRoutes for ApiRouter<AppState> {
"/api/blocks/tip/height",
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state.cached_text(&headers, CacheStrategy::Tip, &uri, |q| Ok(q.indexed_height().to_string())).await
state.respond_text(&headers, CacheStrategy::Tip, &uri, |q| Ok(q.indexed_height().to_string())).await
},
|op| {
op.id("get_block_tip_height")
@@ -206,7 +206,7 @@ impl BlockRoutes for ApiRouter<AppState> {
"/api/blocks/tip/hash",
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state.cached_text(&headers, CacheStrategy::Tip, &uri, |q| Ok(q.tip_blockhash().to_string())).await
state.respond_text(&headers, CacheStrategy::Tip, &uri, |q| Ok(q.tip_blockhash().to_string())).await
},
|op| {
op.id("get_block_tip_hash")
@@ -226,8 +226,8 @@ impl BlockRoutes for ApiRouter<AppState> {
headers: HeaderMap,
Path(path): Path<BlockHashTxIndex>,
_: Empty, State(state): State<AppState>| {
let strategy = state.block_cache(Version::ONE, &path.hash);
state.cached_text(&headers, strategy, &uri, move |q| q.block_txid_at_index(&path.hash, path.index).map(|t| t.to_string())).await
let strategy = state.block_strategy(Version::ONE, &path.hash);
state.respond_text(&headers, strategy, &uri, move |q| q.block_txid_at_index(&path.hash, path.index).map(|t| t.to_string())).await
},
|op| {
op.id("get_block_txid")
@@ -251,8 +251,8 @@ impl BlockRoutes for ApiRouter<AppState> {
headers: HeaderMap,
Path(path): Path<BlockHashParam>,
_: Empty, State(state): State<AppState>| {
let strategy = state.block_cache(Version::ONE, &path.hash);
state.cached_json(&headers, strategy, &uri, move |q| q.block_txids(&path.hash)).await
let strategy = state.block_strategy(Version::ONE, &path.hash);
state.respond_json(&headers, strategy, &uri, move |q| q.block_txids(&path.hash)).await
},
|op| {
op.id("get_block_txids")
@@ -276,8 +276,8 @@ impl BlockRoutes for ApiRouter<AppState> {
headers: HeaderMap,
Path(path): Path<BlockHashParam>,
_: Empty, State(state): State<AppState>| {
let strategy = state.block_cache(Version::ONE, &path.hash);
state.cached_json(&headers, strategy, &uri, move |q| q.block_txs(&path.hash, TxIndex::default())).await
let strategy = state.block_strategy(Version::ONE, &path.hash);
state.respond_json(&headers, strategy, &uri, move |q| q.block_txs(&path.hash, TxIndex::default())).await
},
|op| {
op.id("get_block_txs")
@@ -302,8 +302,8 @@ impl BlockRoutes for ApiRouter<AppState> {
headers: HeaderMap,
Path(path): Path<BlockHashStartIndex>,
_: Empty, State(state): State<AppState>| {
let strategy = state.block_cache(Version::ONE, &path.hash);
state.cached_json(&headers, strategy, &uri, move |q| q.block_txs(&path.hash, path.start_index)).await
let strategy = state.block_strategy(Version::ONE, &path.hash);
state.respond_json(&headers, strategy, &uri, move |q| q.block_txs(&path.hash, path.start_index)).await
},
|op| {
op.id("get_block_txs_from_index")
@@ -326,7 +326,7 @@ impl BlockRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.blocks(None))
.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.blocks(None))
.await
},
|op| {
@@ -347,7 +347,7 @@ impl BlockRoutes for ApiRouter<AppState> {
headers: HeaderMap,
Path(path): Path<HeightParam>,
_: Empty, State(state): State<AppState>| {
state.cached_json(&headers, state.height_cache(Version::ONE, path.height), &uri, move |q| q.blocks(Some(path.height))).await
state.respond_json(&headers, state.height_strategy(Version::ONE, path.height), &uri, move |q| q.blocks(Some(path.height))).await
},
|op| {
op.id("get_blocks_from_height")
@@ -368,7 +368,7 @@ impl BlockRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.blocks_v1(None))
.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.blocks_v1(None))
.await
},
|op| {
@@ -389,7 +389,7 @@ impl BlockRoutes for ApiRouter<AppState> {
headers: HeaderMap,
Path(path): Path<HeightParam>,
_: Empty, State(state): State<AppState>| {
state.cached_json(&headers, state.height_cache(Version::ONE, path.height), &uri, move |q| q.blocks_v1(Some(path.height))).await
state.respond_json(&headers, state.height_strategy(Version::ONE, path.height), &uri, move |q| q.blocks_v1(Some(path.height))).await
},
|op| {
op.id("get_blocks_v1_from_height")
+3 -3
View File
@@ -18,7 +18,7 @@ impl FeesRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, state.mempool_cache(), &uri, |q| {
.respond_json(&headers, state.mempool_strategy(), &uri, |q| {
q.mempool_blocks()
})
.await
@@ -39,7 +39,7 @@ impl FeesRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, state.mempool_cache(), &uri, |q| {
.respond_json(&headers, state.mempool_strategy(), &uri, |q| {
q.recommended_fees()
})
.await
@@ -60,7 +60,7 @@ impl FeesRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, state.mempool_cache(), &uri, |q| {
.respond_json(&headers, state.mempool_strategy(), &uri, |q| {
q.recommended_fees()
})
.await
+4 -4
View File
@@ -22,7 +22,7 @@ impl GeneralRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, |q| {
.respond_json(&headers, CacheStrategy::Tip, &uri, |q| {
q.difficulty_adjustment()
})
.await
@@ -43,7 +43,7 @@ impl GeneralRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, state.mempool_cache(), &uri, |q| {
.respond_json(&headers, state.mempool_strategy(), &uri, |q| {
Ok(Prices {
time: Timestamp::now(),
usd: q.live_price()?,
@@ -71,10 +71,10 @@ impl GeneralRoutes for ApiRouter<AppState> {
State(state): State<AppState>| {
let strategy = params
.timestamp
.map(|ts| state.timestamp_cache(Version::ONE, ts))
.map(|ts| state.timestamp_strategy(Version::ONE, ts))
.unwrap_or(CacheStrategy::Tip);
state
.cached_json(&headers, strategy, &uri, move |q| {
.respond_json(&headers, strategy, &uri, move |q| {
q.historical_price(params.timestamp)
})
.await
+4 -4
View File
@@ -18,7 +18,7 @@ impl MempoolRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, state.mempool_cache(), &uri, |q| q.mempool_info())
.respond_json(&headers, state.mempool_strategy(), &uri, |q| q.mempool_info())
.await
},
|op| {
@@ -37,7 +37,7 @@ impl MempoolRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, state.mempool_cache(), &uri, |q| q.mempool_txids())
.respond_json(&headers, state.mempool_strategy(), &uri, |q| q.mempool_txids())
.await
},
|op| {
@@ -56,7 +56,7 @@ impl MempoolRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, state.mempool_cache(), &uri, |q| q.mempool_recent())
.respond_json(&headers, state.mempool_strategy(), &uri, |q| q.mempool_recent())
.await
},
|op| {
@@ -75,7 +75,7 @@ impl MempoolRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, state.mempool_cache(), &uri, |q| q.live_price())
.respond_json(&headers, state.mempool_strategy(), &uri, |q| q.live_price())
.await
},
|op| {
+15 -22
View File
@@ -1,8 +1,5 @@
use std::net::SocketAddr;
use aide::axum::{ApiRouter, routing::get_with};
use axum::{
Extension,
extract::{Path, Query, State},
http::{HeaderMap, Uri},
response::{IntoResponse, Response},
@@ -47,7 +44,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
"/api/metrics",
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.series_catalog().clone())).await
state.respond_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.series_catalog().clone())).await
},
|op| op
.id("get_metrics_tree_deprecated")
@@ -71,7 +68,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.series_count())).await
state.respond_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.series_count())).await
},
|op| op
.id("get_metrics_count_deprecated")
@@ -95,7 +92,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.indexes().to_vec())).await
state.respond_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.indexes().to_vec())).await
},
|op| op
.id("get_indexes_deprecated")
@@ -119,7 +116,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
State(state): State<AppState>,
Query(pagination): Query<Pagination>
| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, move |q| Ok(q.series_list(pagination))).await
state.respond_json(&headers, CacheStrategy::Deploy, &uri, move |q| Ok(q.series_list(pagination))).await
},
|op| op
.id("list_metrics_deprecated")
@@ -143,7 +140,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
State(state): State<AppState>,
Query(query): Query<SearchQuery>
| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, move |q| Ok(q.search_series(&query))).await
state.respond_json(&headers, CacheStrategy::Deploy, &uri, move |q| Ok(q.search_series(&query))).await
},
|op| op
.id("search_metrics_deprecated")
@@ -162,8 +159,8 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
.api_route(
"/api/metrics/bulk",
get_with(
|uri: Uri, headers: HeaderMap, addr: Extension<SocketAddr>, query: Query<SeriesSelection>, state: State<AppState>| async move {
series_legacy::handler(uri, headers, addr, query, state)
|uri: Uri, headers: HeaderMap, query: Query<SeriesSelection>, state: State<AppState>| async move {
series_legacy::handler(uri, headers, query, state)
.await
.into_response()
},
@@ -192,7 +189,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
State(state): State<AppState>,
Path(path): Path<LegacySeriesParam>
| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, move |q| {
state.respond_json(&headers, CacheStrategy::Deploy, &uri, move |q| {
q.series_info(&path.metric).ok_or_else(|| q.series_not_found_error(&path.metric))
}).await
},
@@ -216,13 +213,12 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri,
headers: HeaderMap,
addr: Extension<SocketAddr>,
state: State<AppState>,
Path(path): Path<LegacySeriesWithIndex>,
Query(range): Query<DataRangeFormat>|
-> Response {
let params = SeriesSelection::from((path.index, path.metric, range));
series_legacy::handler(uri, headers, addr, Query(params), state)
series_legacy::handler(uri, headers, Query(params), state)
.await
.into_response()
},
@@ -246,13 +242,12 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri,
headers: HeaderMap,
addr: Extension<SocketAddr>,
state: State<AppState>,
Path(path): Path<LegacySeriesWithIndex>,
Query(range): Query<DataRangeFormat>|
-> Response {
let params = SeriesSelection::from((path.index, path.metric, range));
series_legacy::handler(uri, headers, addr, Query(params), state)
series_legacy::handler(uri, headers, Query(params), state)
.await
.into_response()
},
@@ -280,7 +275,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
State(state): State<AppState>,
Path(path): Path<LegacySeriesWithIndex>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| {
.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| {
q.latest(&path.metric, path.index)
})
.await
@@ -307,7 +302,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
State(state): State<AppState>,
Path(path): Path<LegacySeriesWithIndex>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| {
.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| {
q.len(&path.metric, path.index)
})
.await
@@ -334,7 +329,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
State(state): State<AppState>,
Path(path): Path<LegacySeriesWithIndex>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| {
.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| {
q.version(&path.metric, path.index)
})
.await
@@ -358,7 +353,6 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri,
headers: HeaderMap,
addr: Extension<SocketAddr>,
Path(variant): Path<String>,
Query(range): Query<DataRangeFormat>,
state: State<AppState>|
@@ -379,7 +373,7 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
SeriesList::from(split.collect::<Vec<_>>().join(separator)),
range,
));
series_legacy::handler(uri, headers, addr, Query(params), state)
series_legacy::handler(uri, headers, Query(params), state)
.await
.into_response()
},
@@ -402,12 +396,11 @@ impl ApiMetricsLegacyRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri,
headers: HeaderMap,
addr: Extension<SocketAddr>,
Query(params): Query<SeriesSelectionLegacy>,
state: State<AppState>|
-> Response {
let params: SeriesSelection = params.into();
series_legacy::handler(uri, headers, addr, Query(params), state)
series_legacy::handler(uri, headers, Query(params), state)
.await
.into_response()
},
+18 -24
View File
@@ -2,8 +2,6 @@ use aide::axum::{ApiRouter, routing::get_with};
use axum::{
extract::{Path, State},
http::{HeaderMap, Uri},
response::Redirect,
routing::get,
};
use brk_types::{
BlockFeeRatesEntry, BlockFeesEntry, BlockInfoV1, BlockRewardsEntry, BlockSizesWeights,
@@ -23,16 +21,12 @@ pub trait MiningRoutes {
impl MiningRoutes for ApiRouter<AppState> {
fn add_mining_routes(self) -> Self {
self.route(
"/api/v1/mining",
get(Redirect::temporary("/api#tag/mining")),
)
.api_route(
self.api_route(
"/api/v1/mining/pools",
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
// Pool list is compiled-in, only changes on deploy
state.cached_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.all_pools())).await
state.respond_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.all_pools())).await
},
|op| {
op.id("get_pools")
@@ -49,7 +43,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/pools/{time_period}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.mining_pools(path.time_period)).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.mining_pools(path.time_period)).await
},
|op| {
op.id("get_pool_stats")
@@ -67,7 +61,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/pool/{slug}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<PoolSlugParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.pool_detail(path.slug)).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.pool_detail(path.slug)).await
},
|op| {
op.id("get_pool")
@@ -85,7 +79,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/hashrate/pools",
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, |q| q.pools_hashrate(None)).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, |q| q.pools_hashrate(None)).await
},
|op| {
op.id("get_pools_hashrate")
@@ -102,7 +96,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/hashrate/pools/{time_period}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.pools_hashrate(Some(path.time_period))).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.pools_hashrate(Some(path.time_period))).await
},
|op| {
op.id("get_pools_hashrate_by_period")
@@ -120,7 +114,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/pool/{slug}/hashrate",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<PoolSlugParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.pool_hashrate(path.slug)).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.pool_hashrate(path.slug)).await
},
|op| {
op.id("get_pool_hashrate")
@@ -138,7 +132,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/pool/{slug}/blocks",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<PoolSlugParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.pool_blocks(path.slug, None)).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.pool_blocks(path.slug, None)).await
},
|op| {
op.id("get_pool_blocks")
@@ -156,7 +150,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/pool/{slug}/blocks/{height}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(PoolSlugAndHeightParam {slug, height}): Path<PoolSlugAndHeightParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, state.height_cache(Version::ONE, height), &uri, move |q| q.pool_blocks(slug, Some(height))).await
state.respond_json(&headers, state.height_strategy(Version::ONE, height), &uri, move |q| q.pool_blocks(slug, Some(height))).await
},
|op| {
op.id("get_pool_blocks_from")
@@ -174,7 +168,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/hashrate",
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, |q| q.hashrate(None)).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, |q| q.hashrate(None)).await
},
|op| {
op.id("get_hashrate")
@@ -191,7 +185,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/hashrate/{time_period}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.hashrate(Some(path.time_period))).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.hashrate(Some(path.time_period))).await
},
|op| {
op.id("get_hashrate_by_period")
@@ -209,7 +203,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/difficulty-adjustments",
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, |q| q.difficulty_adjustments(None)).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, |q| q.difficulty_adjustments(None)).await
},
|op| {
op.id("get_difficulty_adjustments")
@@ -226,7 +220,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/difficulty-adjustments/{time_period}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.difficulty_adjustments(Some(path.time_period))).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.difficulty_adjustments(Some(path.time_period))).await
},
|op| {
op.id("get_difficulty_adjustments_by_period")
@@ -244,7 +238,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/reward-stats/{block_count}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<BlockCountParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.reward_stats(path.block_count)).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.reward_stats(path.block_count)).await
},
|op| {
op.id("get_reward_stats")
@@ -262,7 +256,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/blocks/fees/{time_period}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.block_fees(path.time_period)).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.block_fees(path.time_period)).await
},
|op| {
op.id("get_block_fees")
@@ -280,7 +274,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/blocks/rewards/{time_period}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.block_rewards(path.time_period)).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.block_rewards(path.time_period)).await
},
|op| {
op.id("get_block_rewards")
@@ -298,7 +292,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/blocks/fee-rates/{time_period}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.block_fee_rates(path.time_period)).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.block_fee_rates(path.time_period)).await
},
|op| {
op.id("get_block_fee_rates")
@@ -316,7 +310,7 @@ impl MiningRoutes for ApiRouter<AppState> {
"/api/v1/mining/blocks/sizes-weights/{time_period}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(path): Path<TimePeriodParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| q.block_sizes_weights(path.time_period)).await
state.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| q.block_sizes_weights(path.time_period)).await
},
|op| {
op.id("get_block_sizes_weights")
+7 -11
View File
@@ -1,9 +1,4 @@
use std::sync::Arc;
use aide::{
axum::{ApiRouter, routing::get_with},
openapi::OpenApi,
};
use aide::axum::{ApiRouter, routing::get_with};
use axum::{
Extension,
http::HeaderMap,
@@ -63,13 +58,14 @@ impl ApiRoutes for ApiRouter<AppState> {
.add_fees_routes()
.add_mempool_routes()
.add_tx_routes()
.route("/api/server", get(Redirect::temporary("/api#tag/server")))
.api_route(
"/openapi.json",
get_with(
async |headers: HeaderMap,
Extension(api): Extension<Arc<OpenApi>>|
-> Response { Response::static_json(&headers, &*api) },
Extension(api): Extension<OpenApiJson>|
-> Response {
Response::static_json_bytes(&headers, api.bytes())
},
|op| {
op.id("get_openapi")
.server_tag()
@@ -82,9 +78,9 @@ impl ApiRoutes for ApiRouter<AppState> {
"/api.json",
get_with(
async |headers: HeaderMap,
Extension(api): Extension<Arc<ApiJson>>|
Extension(api): Extension<ApiJson>|
-> Response {
Response::static_json(&headers, api.to_json())
Response::static_json_bytes(&headers, api.bytes())
},
|op| {
op.id("get_api")
+7 -6
View File
@@ -1,19 +1,20 @@
use aide::openapi::OpenApi;
use derive_more::Deref;
use axum::body::Bytes;
use serde_json::{Map, Value};
/// Compact OpenAPI spec optimized for LLM consumption.
#[derive(Deref)]
pub struct ApiJson(String);
/// Pre-serialized at startup, served as raw bytes per request.
#[derive(Clone)]
pub struct ApiJson(Bytes);
impl ApiJson {
pub fn new(openapi: &OpenApi) -> Self {
let json = serde_json::to_string(openapi).unwrap();
Self(compact_json(&json))
Self(Bytes::from(compact_json(&json)))
}
pub fn to_json(&self) -> serde_json::Value {
serde_json::from_str(&self.0).unwrap()
pub fn bytes(&self) -> Bytes {
self.0.clone()
}
}
+16
View File
@@ -0,0 +1,16 @@
use aide::openapi::OpenApi;
use axum::body::Bytes;
/// Full OpenAPI spec, pre-serialized at startup and served as raw bytes per request.
#[derive(Clone)]
pub struct OpenApiJson(Bytes);
impl OpenApiJson {
pub fn new(openapi: &OpenApi) -> Self {
Self(Bytes::from(serde_json::to_vec(openapi).unwrap()))
}
pub fn bytes(&self) -> Bytes {
self.0.clone()
}
}
+2
View File
@@ -11,8 +11,10 @@
//
mod compact;
mod full;
pub use compact::ApiJson;
pub use full::OpenApiJson;
use aide::openapi::{Contact, Info, License, OpenApi, Tag};
+17 -27
View File
@@ -4,11 +4,8 @@
//! a formatted body (single + raw + bulk + the legacy module's deprecated
//! handler in `series_legacy.rs`).
use std::net::SocketAddr;
use aide::axum::{ApiRouter, routing::get_with};
use axum::{
Extension,
body::Bytes,
extract::{Path, Query, State},
http::{HeaderMap, Uri},
@@ -31,17 +28,16 @@ use crate::{
/// Shared response pipeline for every series endpoint.
///
/// Resolves the query (which determines the cache key), then delegates to
/// [`AppState::cached_with_params`] for the etag short-circuit, server-side
/// [`AppState::respond_with_params`] for the etag short-circuit, server-side
/// cache lookup, body formatting, and header assembly.
pub(super) async fn serve(
state: AppState,
uri: Uri,
headers: HeaderMap,
addr: SocketAddr,
params: SeriesSelection,
to_bytes: impl FnOnce(&BrkQuery, ResolvedQuery) -> BrkResult<Bytes> + Send + 'static,
) -> Result<Response> {
let max_weight = state.max_weight_for(&addr);
let max_weight = state.max_weight;
let resolved = state.run(move |q| q.resolve(params, max_weight)).await?;
let format = resolved.format();
@@ -54,7 +50,7 @@ pub(super) async fn serve(
);
Ok(state
.cached_with_params(
.respond_with_params(
&headers,
&uri,
cache_params,
@@ -65,7 +61,7 @@ pub(super) async fn serve(
}
Format::JSON => h.insert_content_type_application_json(),
},
move |q, enc| Ok(enc.compress(to_bytes(q, resolved)?)),
move |q| to_bytes(q, resolved),
)
.await)
}
@@ -80,11 +76,10 @@ fn output_to_bytes(out: brk_types::SeriesOutput) -> BrkResult<Bytes> {
async fn data_handler(
uri: Uri,
headers: HeaderMap,
Extension(addr): Extension<SocketAddr>,
Query(params): Query<SeriesSelection>,
State(state): State<AppState>,
) -> Result<Response> {
serve(state, uri, headers, addr, params, |q, r| {
serve(state, uri, headers, params, |q, r| {
output_to_bytes(q.format(r)?)
})
.await
@@ -93,11 +88,10 @@ async fn data_handler(
async fn data_raw_handler(
uri: Uri,
headers: HeaderMap,
Extension(addr): Extension<SocketAddr>,
Query(params): Query<SeriesSelection>,
State(state): State<AppState>,
) -> Result<Response> {
serve(state, uri, headers, addr, params, |q, r| {
serve(state, uri, headers, params, |q, r| {
output_to_bytes(q.format_raw(r)?)
})
.await
@@ -113,7 +107,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
"/api/series",
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.series_catalog().clone())).await
state.respond_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.series_catalog().clone())).await
},
|op| op
.id("get_series_tree")
@@ -136,7 +130,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.series_count())).await
state.respond_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.series_count())).await
},
|op| op
.id("get_series_count")
@@ -156,7 +150,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.indexes().to_vec())).await
state.respond_json(&headers, CacheStrategy::Deploy, &uri, |q| Ok(q.indexes().to_vec())).await
},
|op| op
.id("get_indexes")
@@ -178,7 +172,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
State(state): State<AppState>,
Query(pagination): Query<Pagination>
| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, move |q| Ok(q.series_list(pagination))).await
state.respond_json(&headers, CacheStrategy::Deploy, &uri, move |q| Ok(q.series_list(pagination))).await
},
|op| op
.id("list_series")
@@ -198,7 +192,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
State(state): State<AppState>,
Query(query): Query<SearchQuery>
| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, move |q| Ok(q.search_series(&query))).await
state.respond_json(&headers, CacheStrategy::Deploy, &uri, move |q| Ok(q.search_series(&query))).await
},
|op| op
.id("search_series")
@@ -220,7 +214,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
State(state): State<AppState>,
Path(path): Path<SeriesParam>
| {
state.cached_json(&headers, CacheStrategy::Deploy, &uri, move |q| {
state.respond_json(&headers, CacheStrategy::Deploy, &uri, move |q| {
q.series_info(&path.series).ok_or_else(|| q.series_not_found_error(&path.series))
}).await
},
@@ -242,7 +236,6 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri,
headers: HeaderMap,
addr: Extension<SocketAddr>,
state: State<AppState>,
Path(path): Path<SeriesNameWithIndex>,
Query(range): Query<DataRangeFormat>|
@@ -250,7 +243,6 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
data_handler(
uri,
headers,
addr,
Query(SeriesSelection::from((path.index, path.series, range))),
state,
)
@@ -276,7 +268,6 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri,
headers: HeaderMap,
addr: Extension<SocketAddr>,
state: State<AppState>,
Path(path): Path<SeriesNameWithIndex>,
Query(range): Query<DataRangeFormat>|
@@ -284,7 +275,6 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
data_raw_handler(
uri,
headers,
addr,
Query(SeriesSelection::from((path.index, path.series, range))),
state,
)
@@ -314,7 +304,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
State(state): State<AppState>,
Path(path): Path<SeriesNameWithIndex>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| {
.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| {
q.latest(&path.series, path.index)
})
.await
@@ -340,7 +330,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
State(state): State<AppState>,
Path(path): Path<SeriesNameWithIndex>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| {
.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| {
q.len(&path.series, path.index)
})
.await
@@ -364,7 +354,7 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
State(state): State<AppState>,
Path(path): Path<SeriesNameWithIndex>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| {
.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| {
q.version(&path.series, path.index)
})
.await
@@ -382,8 +372,8 @@ impl ApiSeriesRoutes for ApiRouter<AppState> {
.api_route(
"/api/series/bulk",
get_with(
|uri, headers, addr, query, state| async move {
data_handler(uri, headers, addr, query, state).await.into_response()
|uri, headers, query, state| async move {
data_handler(uri, headers, query, state).await.into_response()
},
|op| op
.id("get_series_bulk")
+6 -8
View File
@@ -5,11 +5,10 @@
//! in legacy mode (registered by metrics endpoints that emit the old format).
//! - `add_series_legacy_routes`: the deprecated `/api/series/cost-basis/*` URLs.
use std::{collections::BTreeMap, net::SocketAddr};
use std::collections::BTreeMap;
use aide::axum::{ApiRouter, routing::get_with};
use axum::{
Extension,
body::Bytes,
extract::{Path, Query, State},
http::{HeaderMap, StatusCode, Uri},
@@ -40,12 +39,11 @@ pub const SUNSET: &str = "2027-01-01T00:00:00Z";
pub async fn handler(
uri: Uri,
headers: HeaderMap,
Extension(addr): Extension<SocketAddr>,
Query(params): Query<SeriesSelection>,
State(state): State<AppState>,
) -> Result<Response> {
let mut response =
super::series::serve(state, uri, headers, addr, params, legacy_bytes).await?;
super::series::serve(state, uri, headers, params, legacy_bytes).await?;
if response.status() == StatusCode::OK {
response.headers_mut().insert_deprecation(SUNSET);
}
@@ -152,7 +150,7 @@ impl ApiSeriesLegacyRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, CacheStrategy::Deploy, &uri, |q| q.urpd_cohorts())
.respond_json(&headers, CacheStrategy::Deploy, &uri, |q| q.urpd_cohorts())
.await
},
|op| {
@@ -179,7 +177,7 @@ impl ApiSeriesLegacyRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| {
.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| {
q.urpd_dates(&params.cohort)
})
.await
@@ -208,9 +206,9 @@ impl ApiSeriesLegacyRoutes for ApiRouter<AppState> {
Path(params): Path<CostBasisParams>,
Query(query): Query<CostBasisQuery>,
State(state): State<AppState>| {
let strategy = state.date_cache(Version::ONE, params.date);
let strategy = state.date_strategy(Version::ONE, params.date);
state
.cached_json(&headers, strategy, &uri, move |q| {
.respond_json(&headers, strategy, &uri, move |q| {
cost_basis_formatted(
q,
&params.cohort,
+16 -6
View File
@@ -4,10 +4,15 @@ use aide::axum::{ApiRouter, routing::get_with};
use axum::{
extract::State,
http::{HeaderMap, Uri},
response::{IntoResponse, Response},
};
use brk_types::{DiskUsage, Health, SyncStatus};
use crate::{CacheStrategy, VERSION, extended::TransformResponseExtended, params::Empty};
use crate::{
CacheStrategy, VERSION,
extended::{HeaderMapExtended, TransformResponseExtended},
params::Empty,
};
use super::AppState;
@@ -20,7 +25,7 @@ impl ServerRoutes for ApiRouter<AppState> {
self.api_route(
"/health",
get_with(
async |_: Empty, State(state): State<AppState>| -> axum::Json<Health> {
async |_: Empty, State(state): State<AppState>| -> Response {
let uptime = state.started_instant.elapsed();
let started_at = state.started_at.to_string();
let sync = state
@@ -33,7 +38,7 @@ impl ServerRoutes for ApiRouter<AppState> {
})
.await
.expect("health sync task panicked");
axum::Json(Health {
let mut response = axum::Json(Health {
status: Cow::Borrowed("healthy"),
service: Cow::Borrowed("brk"),
version: Cow::Borrowed(VERSION),
@@ -42,6 +47,11 @@ impl ServerRoutes for ApiRouter<AppState> {
uptime_seconds: uptime.as_secs(),
sync,
})
.into_response();
let h = response.headers_mut();
h.insert_cache_control("no-store");
h.insert_cdn_cache_control("no-store");
response
},
|op| {
op.id("get_health")
@@ -57,7 +67,7 @@ impl ServerRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, CacheStrategy::Deploy, &uri, |_| {
.respond_json(&headers, CacheStrategy::Deploy, &uri, |_| {
Ok(env!("CARGO_PKG_VERSION"))
})
.await
@@ -77,7 +87,7 @@ impl ServerRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| {
.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| {
let tip_height = q.client().get_last_height()?;
Ok(q.sync_status(tip_height))
})
@@ -102,7 +112,7 @@ impl ServerRoutes for ApiRouter<AppState> {
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
let brk_path = state.data_path.clone();
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| {
.respond_json(&headers, CacheStrategy::Tip, &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))
+12 -12
View File
@@ -28,7 +28,7 @@ impl TxRoutes for ApiRouter<AppState> {
"/api/tx-index/{index}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(param): Path<TxIndexParam>, _: Empty, State(state): State<AppState>| {
state.cached_text(&headers, CacheStrategy::Immutable(Version::ONE), &uri, move |q| q.txid_by_index(param.index).map(|t| t.to_string())).await
state.respond_text(&headers, CacheStrategy::Immutable(Version::ONE), &uri, move |q| q.txid_by_index(param.index).map(|t| t.to_string())).await
},
|op| op
.id("get_tx_by_index")
@@ -46,7 +46,7 @@ impl TxRoutes for ApiRouter<AppState> {
"/api/v1/cpfp/{txid}",
get_with(
async |uri: Uri, headers: HeaderMap, Path(param): Path<TxidParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, state.tx_cache(Version::ONE, &param.txid), &uri, move |q| q.cpfp(&param.txid)).await
state.respond_json(&headers, state.tx_strategy(Version::ONE, &param.txid), &uri, move |q| q.cpfp(&param.txid)).await
},
|op| op
.id("get_cpfp")
@@ -64,7 +64,7 @@ impl TxRoutes for ApiRouter<AppState> {
"/api/v1/tx/{txid}/rbf",
get_with(
async |uri: Uri, headers: HeaderMap, Path(param): Path<TxidParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, state.mempool_cache(), &uri, move |q| q.tx_rbf(&param.txid)).await
state.respond_json(&headers, state.mempool_strategy(), &uri, move |q| q.tx_rbf(&param.txid)).await
},
|op| op
.id("get_tx_rbf")
@@ -88,7 +88,7 @@ impl TxRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
state.cached_json(&headers, state.tx_cache(Version::ONE, &param.txid), &uri, move |q| q.transaction(&param.txid)).await
state.respond_json(&headers, state.tx_strategy(Version::ONE, &param.txid), &uri, move |q| q.transaction(&param.txid)).await
},
|op| op
.id("get_tx")
@@ -114,7 +114,7 @@ impl TxRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
state.cached_text(&headers, state.tx_cache(Version::ONE, &param.txid), &uri, move |q| q.transaction_hex(&param.txid)).await
state.respond_text(&headers, state.tx_strategy(Version::ONE, &param.txid), &uri, move |q| q.transaction_hex(&param.txid)).await
},
|op| op
.id("get_tx_hex")
@@ -134,7 +134,7 @@ impl TxRoutes for ApiRouter<AppState> {
"/api/tx/{txid}/merkleblock-proof",
get_with(
async |uri: Uri, headers: HeaderMap, Path(param): Path<TxidParam>, _: Empty, State(state): State<AppState>| {
state.cached_text(&headers, state.tx_cache(Version::ONE, &param.txid), &uri, move |q| q.merkleblock_proof(&param.txid)).await
state.respond_text(&headers, state.tx_strategy(Version::ONE, &param.txid), &uri, move |q| q.merkleblock_proof(&param.txid)).await
},
|op| op
.id("get_tx_merkleblock_proof")
@@ -152,7 +152,7 @@ impl TxRoutes for ApiRouter<AppState> {
"/api/tx/{txid}/merkle-proof",
get_with(
async |uri: Uri, headers: HeaderMap, Path(param): Path<TxidParam>, _: Empty, State(state): State<AppState>| {
state.cached_json(&headers, state.tx_cache(Version::ONE, &param.txid), &uri, move |q| q.merkle_proof(&param.txid)).await
state.respond_json(&headers, state.tx_strategy(Version::ONE, &param.txid), &uri, move |q| q.merkle_proof(&param.txid)).await
},
|op| op
.id("get_tx_merkle_proof")
@@ -177,7 +177,7 @@ impl TxRoutes for ApiRouter<AppState> {
State(state): State<AppState>
| {
let v = Version::ONE;
state.cached_json_optimistic(&headers, CacheStrategy::Immutable(v), &uri, move |q| {
state.respond_json_optimistic(&headers, CacheStrategy::Immutable(v), &uri, move |q| {
let outspend = q.outspend(&path.txid, path.vout)?;
let strategy = if outspend.is_deeply_spent(q.height()) {
CacheStrategy::Immutable(v)
@@ -212,7 +212,7 @@ impl TxRoutes for ApiRouter<AppState> {
State(state): State<AppState>
| {
let v = Version::ONE;
state.cached_json_optimistic(&headers, CacheStrategy::Immutable(v), &uri, move |q| {
state.respond_json_optimistic(&headers, CacheStrategy::Immutable(v), &uri, move |q| {
let outspends = q.outspends(&param.txid)?;
let height = q.height();
let all_deep = outspends.iter().all(|o| o.is_deeply_spent(height));
@@ -238,7 +238,7 @@ impl TxRoutes for ApiRouter<AppState> {
"/api/tx/{txid}/raw",
get_with(
async |uri: Uri, headers: HeaderMap, Path(param): Path<TxidParam>, _: Empty, State(state): State<AppState>| {
state.cached_bytes(&headers, state.tx_cache(Version::ONE, &param.txid), &uri, move |q| q.transaction_raw(&param.txid)).await
state.respond_bytes(&headers, state.tx_strategy(Version::ONE, &param.txid), &uri, move |q| q.transaction_raw(&param.txid)).await
},
|op| op
.id("get_tx_raw")
@@ -262,7 +262,7 @@ impl TxRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>
| {
state.cached_json(&headers, state.tx_cache(Version::ONE, &param.txid), &uri, move |q| q.transaction_status(&param.txid)).await
state.respond_json(&headers, state.tx_strategy(Version::ONE, &param.txid), &uri, move |q| q.transaction_status(&param.txid)).await
},
|op| op
.id("get_tx_status")
@@ -284,7 +284,7 @@ impl TxRoutes for ApiRouter<AppState> {
async |uri: Uri, headers: HeaderMap, State(state): State<AppState>| -> Result<Response> {
let params = TxidsParam::from_query(uri.query().unwrap_or(""))
.map_err(Error::bad_request)?;
Ok(state.cached_json(&headers, state.mempool_cache(), &uri, move |q| q.transaction_times(&params.txids)).await)
Ok(state.respond_json(&headers, state.mempool_strategy(), &uri, move |q| q.transaction_times(&params.txids)).await)
},
|op| op
.id("get_transaction_times")
+5 -5
View File
@@ -24,7 +24,7 @@ impl ApiUrpdRoutes for ApiRouter<AppState> {
get_with(
async |uri: Uri, headers: HeaderMap, _: Empty, State(state): State<AppState>| {
state
.cached_json(&headers, CacheStrategy::Deploy, &uri, |q| q.urpd_cohorts())
.respond_json(&headers, CacheStrategy::Deploy, &uri, |q| q.urpd_cohorts())
.await
},
|op| {
@@ -50,7 +50,7 @@ impl ApiUrpdRoutes for ApiRouter<AppState> {
_: Empty,
State(state): State<AppState>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| {
.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| {
q.urpd_dates(&params.cohort)
})
.await
@@ -79,7 +79,7 @@ impl ApiUrpdRoutes for ApiRouter<AppState> {
Query(query): Query<UrpdQuery>,
State(state): State<AppState>| {
state
.cached_json(&headers, CacheStrategy::Tip, &uri, move |q| {
.respond_json(&headers, CacheStrategy::Tip, &uri, move |q| {
q.urpd_latest(&params.cohort, query.aggregation)
})
.await
@@ -108,9 +108,9 @@ impl ApiUrpdRoutes for ApiRouter<AppState> {
Path(params): Path<UrpdParams>,
Query(query): Query<UrpdQuery>,
State(state): State<AppState>| {
let strategy = state.date_cache(Version::ONE, params.date);
let strategy = state.date_strategy(Version::ONE, params.date);
state
.cached_json(&headers, strategy, &uri, move |q| {
.respond_json(&headers, strategy, &uri, move |q| {
q.urpd_at(&params.cohort, params.date, query.aggregation)
})
.await