server: snapshot

This commit is contained in:
nym21
2025-12-15 16:32:45 +01:00
parent 882a3525af
commit 825a4a77c0
100 changed files with 2677 additions and 3438 deletions

View File

@@ -1,22 +1,11 @@
use std::collections::BTreeMap;
use brk_computer::Computer;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_mempool::Mempool;
use brk_reader::Reader;
use brk_types::{
Address, AddressStats, BlockInfo, BlockStatus, BlockTimestamp, DifficultyAdjustment,
HashrateSummary, Height, Index, IndexInfo, Limit, MempoolBlock, MempoolInfo, Metric,
MetricCount, PoolDetail, PoolInfo, PoolSlug, PoolsSummary, RecommendedFees, TimePeriod,
Timestamp, Transaction, TreeNode, TxOutspend, TxStatus, Txid, TxidPath, Utxo, Vout,
};
use tokio::task::spawn_blocking;
use crate::{
Output, PaginatedIndexParam, PaginatedMetrics, PaginationParam, Params, Query,
vecs::{IndexToVec, MetricToVec, Vecs},
};
use crate::Query;
#[derive(Clone)]
pub struct AsyncQuery(Query);
@@ -31,282 +20,37 @@ impl AsyncQuery {
Self(Query::build(reader, indexer, computer, mempool))
}
/// Run a blocking query operation on a spawn_blocking thread.
/// Use this for I/O-heavy or CPU-intensive operations.
///
/// # Example
/// ```ignore
/// let address_stats = query.run(move |q| q.address(address)).await?;
/// ```
pub async fn run<F, T>(&self, f: F) -> Result<T>
where
F: FnOnce(&Query) -> Result<T> + Send + 'static,
T: Send + 'static,
{
let query = self.0.clone();
spawn_blocking(move || f(&query)).await?
}
/// Run a cheap sync operation directly without spawn_blocking.
/// Use this for simple accessors that don't do I/O.
///
/// # Example
/// ```ignore
/// let height = query.sync(|q| q.height());
/// ```
pub fn sync<F, T>(&self, f: F) -> T
where
F: FnOnce(&Query) -> T,
{
f(&self.0)
}
pub fn inner(&self) -> &Query {
&self.0
}
pub async fn get_height(&self) -> Height {
self.0.get_height()
}
pub async fn get_address(&self, address: Address) -> Result<AddressStats> {
let query = self.0.clone();
spawn_blocking(move || query.get_address(address)).await?
}
pub async fn get_address_txids(
&self,
address: Address,
after_txid: Option<Txid>,
limit: usize,
) -> Result<Vec<Txid>> {
let query = self.0.clone();
spawn_blocking(move || query.get_address_txids(address, after_txid, limit)).await?
}
pub async fn get_address_utxos(&self, address: Address) -> Result<Vec<Utxo>> {
let query = self.0.clone();
spawn_blocking(move || query.get_address_utxos(address)).await?
}
pub async fn get_address_mempool_txids(&self, address: Address) -> Result<Vec<Txid>> {
let query = self.0.clone();
spawn_blocking(move || query.get_address_mempool_txids(address)).await?
}
pub async fn get_transaction(&self, txid: TxidPath) -> Result<Transaction> {
let query = self.0.clone();
spawn_blocking(move || query.get_transaction(txid)).await?
}
pub async fn get_transaction_status(&self, txid: TxidPath) -> Result<TxStatus> {
let query = self.0.clone();
spawn_blocking(move || query.get_transaction_status(txid)).await?
}
pub async fn get_transaction_hex(&self, txid: TxidPath) -> Result<String> {
let query = self.0.clone();
spawn_blocking(move || query.get_transaction_hex(txid)).await?
}
pub async fn get_tx_outspend(&self, txid: TxidPath, vout: Vout) -> Result<TxOutspend> {
let query = self.0.clone();
spawn_blocking(move || query.get_tx_outspend(txid, vout)).await?
}
pub async fn get_tx_outspends(&self, txid: TxidPath) -> Result<Vec<TxOutspend>> {
let query = self.0.clone();
spawn_blocking(move || query.get_tx_outspends(txid)).await?
}
pub async fn get_block(&self, hash: String) -> Result<BlockInfo> {
let query = self.0.clone();
spawn_blocking(move || query.get_block(&hash)).await?
}
pub async fn get_block_by_height(&self, height: Height) -> Result<BlockInfo> {
let query = self.0.clone();
spawn_blocking(move || query.get_block_by_height(height)).await?
}
pub async fn get_block_by_timestamp(&self, timestamp: Timestamp) -> Result<BlockTimestamp> {
self.0.get_block_by_timestamp(timestamp)
}
pub async fn get_block_status(&self, hash: String) -> Result<BlockStatus> {
let query = self.0.clone();
spawn_blocking(move || query.get_block_status(&hash)).await?
}
pub async fn get_blocks(&self, start_height: Option<Height>) -> Result<Vec<BlockInfo>> {
let query = self.0.clone();
spawn_blocking(move || query.get_blocks(start_height)).await?
}
pub async fn get_block_txids(&self, hash: String) -> Result<Vec<Txid>> {
let query = self.0.clone();
spawn_blocking(move || query.get_block_txids(&hash)).await?
}
pub async fn get_block_txs(
&self,
hash: String,
start_index: usize,
) -> Result<Vec<Transaction>> {
let query = self.0.clone();
spawn_blocking(move || query.get_block_txs(&hash, start_index)).await?
}
pub async fn get_block_txid_at_index(&self, hash: String, index: usize) -> Result<Txid> {
self.0.get_block_txid_at_index(&hash, index)
}
pub async fn get_block_raw(&self, hash: String) -> Result<Vec<u8>> {
let query = self.0.clone();
spawn_blocking(move || query.get_block_raw(&hash)).await?
}
pub async fn get_mempool_info(&self) -> Result<MempoolInfo> {
self.0.get_mempool_info()
}
pub async fn get_mempool_txids(&self) -> Result<Vec<Txid>> {
self.0.get_mempool_txids()
}
pub async fn get_recommended_fees(&self) -> Result<RecommendedFees> {
self.0.get_recommended_fees()
}
pub async fn get_mempool_blocks(&self) -> Result<Vec<MempoolBlock>> {
self.0.get_mempool_blocks()
}
pub async fn get_difficulty_adjustment(&self) -> Result<DifficultyAdjustment> {
let query = self.0.clone();
spawn_blocking(move || query.get_difficulty_adjustment()).await?
}
pub async fn get_mining_pools(&self, time_period: TimePeriod) -> Result<PoolsSummary> {
let query = self.0.clone();
spawn_blocking(move || query.get_mining_pools(time_period)).await?
}
pub async fn get_all_pools(&self) -> Result<Vec<PoolInfo>> {
Ok(self.0.get_all_pools())
}
pub async fn get_pool_detail(&self, slug: PoolSlug) -> Result<PoolDetail> {
let query = self.0.clone();
spawn_blocking(move || query.get_pool_detail(slug)).await?
}
pub async fn get_hashrate(&self, time_period: Option<TimePeriod>) -> Result<HashrateSummary> {
let query = self.0.clone();
spawn_blocking(move || query.get_hashrate(time_period)).await?
}
pub async fn get_difficulty_adjustments(
&self,
time_period: Option<TimePeriod>,
) -> Result<Vec<brk_types::DifficultyAdjustmentEntry>> {
let query = self.0.clone();
spawn_blocking(move || query.get_difficulty_adjustments(time_period)).await?
}
pub async fn get_block_fees(
&self,
time_period: TimePeriod,
) -> Result<Vec<brk_types::BlockFeesEntry>> {
let query = self.0.clone();
spawn_blocking(move || query.get_block_fees(time_period)).await?
}
pub async fn get_block_rewards(
&self,
time_period: TimePeriod,
) -> Result<Vec<brk_types::BlockRewardsEntry>> {
let query = self.0.clone();
spawn_blocking(move || query.get_block_rewards(time_period)).await?
}
pub async fn get_block_fee_rates(
&self,
time_period: TimePeriod,
) -> Result<Vec<brk_types::BlockFeeRatesEntry>> {
let query = self.0.clone();
spawn_blocking(move || query.get_block_fee_rates(time_period)).await?
}
pub async fn get_block_sizes_weights(
&self,
time_period: TimePeriod,
) -> Result<brk_types::BlockSizesWeights> {
let query = self.0.clone();
spawn_blocking(move || query.get_block_sizes_weights(time_period)).await?
}
pub async fn get_reward_stats(&self, block_count: usize) -> Result<brk_types::RewardStats> {
let query = self.0.clone();
spawn_blocking(move || query.get_reward_stats(block_count)).await?
}
pub async fn match_metric(&self, metric: Metric, limit: Limit) -> Result<Vec<&'static str>> {
let query = self.0.clone();
spawn_blocking(move || Ok(query.match_metric(&metric, limit))).await?
}
// pub async fn search_metric_with_index(
// &self,
// metric: &str,
// index: Index,
// // params: &Params,
// ) -> Result<Vec<(String, &&dyn AnyExportableVec)>> {
// let query = self.0.clone();
// spawn_blocking(move || query.search_metric_with_index(metric, index)).await?
// }
// pub async fn format(
// &self,
// metrics: Vec<(String, &&dyn AnyExportableVec)>,
// params: &ParamsOpt,
// ) -> Result<Output> {
// let query = self.0.clone();
// spawn_blocking(move || query.format(metrics, params)).await?
// }
pub async fn search_and_format(&self, params: Params) -> Result<Output> {
let query = self.0.clone();
spawn_blocking(move || query.search_and_format(params)).await?
}
pub async fn metric_to_index_to_vec(&self) -> &BTreeMap<&str, IndexToVec<'_>> {
self.0.metric_to_index_to_vec()
}
pub async fn index_to_metric_to_vec(&self) -> &BTreeMap<Index, MetricToVec<'_>> {
self.0.index_to_metric_to_vec()
}
pub async fn metric_count(&self) -> MetricCount {
self.0.metric_count()
}
pub async fn distinct_metric_count(&self) -> usize {
self.0.distinct_metric_count()
}
pub async fn total_metric_count(&self) -> usize {
self.0.total_metric_count()
}
pub async fn get_indexes(&self) -> &[IndexInfo] {
self.0.get_indexes()
}
pub async fn get_metrics(&self, pagination: PaginationParam) -> PaginatedMetrics {
self.0.get_metrics(pagination)
}
pub async fn get_metrics_catalog(&self) -> &TreeNode {
self.0.get_metrics_catalog()
}
pub async fn get_index_to_vecids(&self, paginated_index: PaginatedIndexParam) -> Vec<&str> {
self.0.get_index_to_vecids(paginated_index)
}
pub async fn metric_to_indexes(&self, metric: Metric) -> Option<&Vec<Index>> {
self.0.metric_to_indexes(metric)
}
#[inline]
pub async fn reader(&self) -> &Reader {
self.0.reader()
}
#[inline]
pub async fn indexer(&self) -> &Indexer {
self.0.indexer()
}
#[inline]
pub async fn computer(&self) -> &Computer {
self.0.computer()
}
#[inline]
pub async fn vecs(&self) -> &'static Vecs<'static> {
self.0.vecs()
}
}