diff --git a/src/beacon/drand.rs b/src/beacon/drand.rs index af229e616a28..47879532d31a 100644 --- a/src/beacon/drand.rs +++ b/src/beacon/drand.rs @@ -242,7 +242,7 @@ impl DrandBeacon { fil_round_time: interval, fil_gen_time: genesis_ts, verified_beacons: SizeTrackingLruCache::new_with_metrics( - "verified_beacons".into(), + "verified_beacons", CACHE_SIZE, ), } diff --git a/src/chain/store/chain_store.rs b/src/chain/store/chain_store.rs index 8554c9c44a24..f9f3294549c6 100644 --- a/src/chain/store/chain_store.rs +++ b/src/chain/store/chain_store.rs @@ -596,7 +596,7 @@ pub struct MessagesInTipsetCache { impl MessagesInTipsetCache { pub fn new(capacity: NonZeroUsize) -> Self { Self { - cache: SizeTrackingLruCache::new_with_metrics("msg_in_tipset".into(), capacity), + cache: SizeTrackingLruCache::new_with_metrics("msg_in_tipset", capacity), } } diff --git a/src/chain/store/index.rs b/src/chain/store/index.rs index 589f079cd60d..bfd5bfe6646a 100644 --- a/src/chain/store/index.rs +++ b/src/chain/store/index.rs @@ -53,8 +53,7 @@ pub enum ResolveNullTipset { impl ChainIndex { pub fn new(db: impl Into) -> Self { let db = db.into(); - let ts_cache = - SizeTrackingLruCache::new_with_metrics("tipset".into(), DEFAULT_TIPSET_CACHE_SIZE); + let ts_cache = SizeTrackingLruCache::new_with_metrics("tipset", DEFAULT_TIPSET_CACHE_SIZE); Self { ts_cache, db, diff --git a/src/chain_sync/bad_block_cache.rs b/src/chain_sync/bad_block_cache.rs index cd4aea139b9d..38f1ec63c752 100644 --- a/src/chain_sync/bad_block_cache.rs +++ b/src/chain_sync/bad_block_cache.rs @@ -37,7 +37,7 @@ impl ShallowClone for BadBlockCache { impl BadBlockCache { pub fn new(cap: NonZeroUsize) -> Self { Self { - cache: SizeTrackingLruCache::new_with_metrics("bad_block".into(), cap), + cache: SizeTrackingLruCache::new_with_metrics("bad_block", cap), } } @@ -81,7 +81,7 @@ impl Default for SeenBlockCache { impl SeenBlockCache { pub fn new(cap: NonZeroUsize) -> Self { Self { - cache: SizeTrackingLruCache::new_with_metrics("seen_gossip_block".into(), cap), + cache: SizeTrackingLruCache::new_with_metrics("seen_gossip_block", cap), } } diff --git a/src/db/blockstore_with_read_cache.rs b/src/db/blockstore_with_read_cache.rs index cd1061257756..df11493ed3f1 100644 --- a/src/db/blockstore_with_read_cache.rs +++ b/src/db/blockstore_with_read_cache.rs @@ -127,7 +127,7 @@ mod tests { records.push((key, record)); } let cache = Arc::new(LruBlockstoreReadCache::new_without_metrics_registry( - "test_blockstore_read_cache".into(), + "test_blockstore_read_cache", CACHE_SIZE.try_into().unwrap(), )); let db = BlockstoreWithReadCache::new( diff --git a/src/db/car/mod.rs b/src/db/car/mod.rs index 2f2293149b36..593942de1f1c 100644 --- a/src/db/car/mod.rs +++ b/src/db/car/mod.rs @@ -84,7 +84,7 @@ impl ZstdFrameCache { ZstdFrameCache { max_size, current_size: Arc::new(AtomicUsize::new(0)), - lru: SizeTrackingLruCache::unbounded_with_metrics("zstd_frame".into()), + lru: SizeTrackingLruCache::unbounded_with_metrics("zstd_frame"), } } diff --git a/src/message_pool/msgpool/msg_pool.rs b/src/message_pool/msgpool/msg_pool.rs index a28e0c057025..7a656d14726b 100644 --- a/src/message_pool/msgpool/msg_pool.rs +++ b/src/message_pool/msgpool/msg_pool.rs @@ -94,11 +94,11 @@ pub(in crate::message_pool) struct Caches { impl Caches { pub(in crate::message_pool) fn new() -> Self { Self { - bls_sig: SizeTrackingLruCache::new_with_metrics("bls_sig".into(), BLS_SIG_CACHE_SIZE), - sig_val: SizeTrackingLruCache::new_with_metrics("sig_val".into(), SIG_VAL_CACHE_SIZE), - key: SizeTrackingLruCache::new_with_metrics("mpool_key".into(), KEY_CACHE_SIZE), + bls_sig: SizeTrackingLruCache::new_with_metrics("bls_sig", BLS_SIG_CACHE_SIZE), + sig_val: SizeTrackingLruCache::new_with_metrics("sig_val", SIG_VAL_CACHE_SIZE), + key: SizeTrackingLruCache::new_with_metrics("mpool_key", KEY_CACHE_SIZE), state_nonce: SizeTrackingLruCache::new_with_metrics( - "state_nonce".into(), + "state_nonce", STATE_NONCE_CACHE_SIZE, ), } diff --git a/src/rpc/methods/chain.rs b/src/rpc/methods/chain.rs index e2ff0f2e91b0..3134395587c9 100644 --- a/src/rpc/methods/chain.rs +++ b/src/rpc/methods/chain.rs @@ -18,9 +18,9 @@ use crate::lotus_json::{HasLotusJson, LotusJson, lotus_json_with_self}; use crate::lotus_json::{assert_all_snapshots, assert_unchanged_via_json}; use crate::message::{ChainMessage, SignedMessage}; use crate::prelude::*; -use crate::rpc::eth::Block as EthBlock; use crate::rpc::eth::{ - EthLog, TxInfo, eth_logs_with_filter, types::ApiHeaders, types::EthFilterSpec, + Block as EthBlock, EthLog, TxInfo, eth_logs_with_filter, types::ApiHeaders, + types::EthFilterSpec, }; use crate::rpc::f3::F3ExportLatestSnapshot; use crate::rpc::types::*; diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index 06c645a928ff..9b5a19dc50b9 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -54,8 +54,8 @@ use crate::shim::gas::GasOutputs; use crate::shim::message::Message; use crate::shim::trace::{CallReturn, ExecutionEvent}; use crate::shim::{clock::ChainEpoch, state_tree::StateTree}; +use crate::state_manager::cache::ForestLruCache; use crate::state_manager::{ExecutedMessage, ExecutedTipset, TipsetState, VMFlush}; -use crate::utils::cache::SizeTrackingLruCache; use crate::utils::db::BlockstoreExt as _; use crate::utils::encoding::from_slice_with_fallback; use crate::utils::get_size::{CidWrapper, big_int_heap_size_helper}; @@ -477,95 +477,125 @@ impl Block { ctx: Ctx, tipset: crate::blocks::Tipset, tx_info: TxInfo, - ) -> Result { - static ETH_BLOCK_CACHE: LazyLock> = + ) -> Result> { + static ETH_BLOCK_HASH_TX_CACHE: LazyLock>> = LazyLock::new(|| { - const DEFAULT_CACHE_SIZE: NonZeroUsize = nonzero!(500usize); - let cache_size = std::env::var("FOREST_ETH_BLOCK_CACHE_SIZE") - .ok() - .and_then(|s| s.parse().ok()) - .unwrap_or(DEFAULT_CACHE_SIZE); - SizeTrackingLruCache::new_with_metrics("eth_block".into(), cache_size) + ForestLruCache::with_size("eth_block_hash_tx", Block::block_cache_size()) }); - let block_cid = tipset.key().cid()?; - let mut block = if let Some(b) = ETH_BLOCK_CACHE.get_cloned(&block_cid.into()) { - b - } else { - let parent_cid = tipset.parents().cid()?; - let block_number = EthInt64(tipset.epoch()); - let block_hash: EthHash = block_cid.into(); + match tx_info { + TxInfo::Full => Self::from_filecoin_tipset_with_full_tx(ctx, tipset).await, + TxInfo::Hash => { + let block_cid = tipset.key().cid()?; + ETH_BLOCK_HASH_TX_CACHE + .get_or_else(&block_cid.into(), async move || { + let block_with_full_tx = + Self::from_filecoin_tipset_with_full_tx(ctx, tipset).await?; + Ok(Arc::new( + Arc::unwrap_or_clone(block_with_full_tx) + .downcast_full_transaction_to_hash(), + )) + }) + .await + } + } + } - let ExecutedTipset { - state_root, - executed_messages, - .. - } = ctx.state_manager.load_executed_tipset(&tipset).await?; - let has_transactions = !executed_messages.is_empty(); - let state_tree = ctx.state_manager.get_state_tree(&state_root)?; - - let mut full_transactions = vec![]; - let mut gas_used = 0; - for ( - i, - ExecutedMessage { - message, receipt, .. - }, - ) in executed_messages.iter().enumerate() - { - let ti = EthUint64(i as u64); - gas_used += receipt.gas_used(); - let mut tx = match message { - ChainMessage::Signed(smsg) => new_eth_tx_from_signed_message( - smsg, - &state_tree, - ctx.chain_config().eth_chain_id, - )?, - ChainMessage::Unsigned(msg) => { - let tx = eth_tx_from_native_message( - msg, + async fn from_filecoin_tipset_with_full_tx( + ctx: Ctx, + tipset: crate::blocks::Tipset, + ) -> Result> { + static ETH_BLOCK_FULL_TX_CACHE: LazyLock>> = + LazyLock::new(|| { + ForestLruCache::with_size("eth_block_full_tx", Block::block_cache_size()) + }); + + let block_cid = tipset.key().cid()?; + ETH_BLOCK_FULL_TX_CACHE + .get_or_else(&block_cid.into(), async move || { + let parent_cid = tipset.parents().cid()?; + let block_number = EthInt64(tipset.epoch()); + let block_hash: EthHash = block_cid.into(); + + let ExecutedTipset { + state_root, + executed_messages, + .. + } = ctx.state_manager.load_executed_tipset(&tipset).await?; + let has_transactions = !executed_messages.is_empty(); + let state_tree = ctx.state_manager.get_state_tree(&state_root)?; + + let mut full_transactions = vec![]; + let mut gas_used = 0; + for ( + i, + ExecutedMessage { + message, receipt, .. + }, + ) in executed_messages.iter().enumerate() + { + let ti = EthUint64(i as u64); + gas_used += receipt.gas_used(); + let mut tx = match message { + ChainMessage::Signed(smsg) => new_eth_tx_from_signed_message( + smsg, &state_tree, ctx.chain_config().eth_chain_id, - )?; - ApiEthTx { - hash: msg.cid().into(), - ..tx + )?, + ChainMessage::Unsigned(msg) => { + let tx = eth_tx_from_native_message( + msg, + &state_tree, + ctx.chain_config().eth_chain_id, + )?; + ApiEthTx { + hash: msg.cid().into(), + ..tx + } } - } - }; - tx.block_hash = block_hash; - tx.block_number = block_number; - tx.transaction_index = ti; - full_transactions.push(tx); - } + }; + tx.block_hash = block_hash; + tx.block_number = block_number; + tx.transaction_index = ti; + full_transactions.push(tx); + } - let b = Block { - hash: block_hash, - number: block_number, - parent_hash: parent_cid.into(), - timestamp: EthUint64(tipset.block_headers().first().timestamp), - base_fee_per_gas: tipset - .block_headers() - .first() - .parent_base_fee - .clone() - .into(), - gas_used: EthUint64(gas_used), - transactions: Transactions::Full(full_transactions), - ..Block::new(has_transactions, tipset.len()) - }; - ETH_BLOCK_CACHE.push(block_cid.into(), b.clone()); - b - }; + Ok(Arc::new(Block { + hash: block_hash, + number: block_number, + parent_hash: parent_cid.into(), + timestamp: EthUint64(tipset.block_headers().first().timestamp), + base_fee_per_gas: tipset + .block_headers() + .first() + .parent_base_fee + .clone() + .into(), + gas_used: EthUint64(gas_used), + transactions: Transactions::Full(full_transactions), + ..Block::new(has_transactions, tipset.len()) + })) + }) + .await + } - if tx_info == TxInfo::Hash - && let Transactions::Full(transactions) = &block.transactions - { - block.transactions = + fn block_cache_size() -> NonZeroUsize { + const DEFAULT_CACHE_SIZE: NonZeroUsize = nonzero!(500usize); + static CACHE_SIZE: std::sync::LazyLock = std::sync::LazyLock::new(|| { + std::env::var("FOREST_ETH_BLOCK_CACHE_SIZE") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(DEFAULT_CACHE_SIZE) + }); + *CACHE_SIZE + } + + fn downcast_full_transaction_to_hash(mut self) -> Self { + if let Transactions::Full(transactions) = &self.transactions { + self.transactions = Transactions::Hash(transactions.iter().map(|tx| tx.hash.to_string()).collect()) } - - Ok(block) + self } } @@ -1396,7 +1426,7 @@ impl RpcMethod<2> for EthGetBlockByHash { const PERMISSION: Permission = Permission::Read; type Params = (EthHash, bool); - type Ok = Block; + type Ok = Arc; async fn handle( ctx: Ctx, @@ -1424,7 +1454,7 @@ impl RpcMethod<2> for EthGetBlockByNumber { Some("Retrieves a block by its number or a special tag."); type Params = (BlockNumberOrPredefined, bool); - type Ok = Block; + type Ok = Arc; async fn handle( ctx: Ctx, diff --git a/src/rpc/methods/eth/types.rs b/src/rpc/methods/eth/types.rs index 4def520deb07..8a96380a81d8 100644 --- a/src/rpc/methods/eth/types.rs +++ b/src/rpc/methods/eth/types.rs @@ -453,7 +453,7 @@ pub struct FilterID(EthHash); lotus_json_with_self!(FilterID); #[derive(Clone, Serialize, Deserialize, PartialEq, Debug)] -pub struct ApiHeaders(#[serde(with = "crate::lotus_json")] pub Block); +pub struct ApiHeaders(#[serde(with = "crate::lotus_json")] pub Arc); lotus_json_with_self!(ApiHeaders); diff --git a/src/rpc/methods/f3.rs b/src/rpc/methods/f3.rs index 174db788d935..38e2c5313ebc 100644 --- a/src/rpc/methods/f3.rs +++ b/src/rpc/methods/f3.rs @@ -172,7 +172,7 @@ impl GetPowerTable { // The RAM overhead on mainnet is ~14MiB const BLOCKSTORE_CACHE_CAP: NonZeroUsize = nonzero!(65536_usize); static BLOCKSTORE_CACHE: LazyLock = LazyLock::new(|| { - LruBlockstoreReadCache::new_with_metrics("get_powertable".into(), BLOCKSTORE_CACHE_CAP) + LruBlockstoreReadCache::new_with_metrics("get_powertable", BLOCKSTORE_CACHE_CAP) }); let db = BlockstoreWithReadCache::new( ctx.db_owned(), diff --git a/src/state_manager/cache.rs b/src/state_manager/cache.rs index 13371a67d5ec..6bf9c6f12521 100644 --- a/src/state_manager/cache.rs +++ b/src/state_manager/cache.rs @@ -1,42 +1,39 @@ // Copyright 2019-2026 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use crate::blocks::TipsetKey; + use crate::prelude::*; use crate::state_manager::DEFAULT_TIPSET_CACHE_SIZE; -use crate::utils::cache::{LruValueConstraints, SizeTrackingLruCache}; +use crate::utils::cache::{LruKeyConstraints, LruValueConstraints, SizeTrackingLruCache}; use ahash::{HashMap, HashMapExt as _}; use parking_lot::RwLock as SyncRwLock; +use std::borrow::Cow; use std::future::Future; use std::num::NonZeroUsize; use tokio::sync::Mutex as TokioMutex; -struct TipsetStateCacheInner { - values: SizeTrackingLruCache, - pending: HashMap>>, +struct ForestLruCacheInner { + values: SizeTrackingLruCache, + pending: HashMap>>, } -impl TipsetStateCacheInner { - pub fn with_size(cache_identifier: &str, cache_size: NonZeroUsize) -> Self { +impl ForestLruCacheInner { + pub fn with_size( + cache_identifier: impl Into>, + cache_size: NonZeroUsize, + ) -> Self { Self { - values: SizeTrackingLruCache::new_with_metrics( - Self::cache_name(cache_identifier).into(), - cache_size, - ), + values: SizeTrackingLruCache::new_with_metrics(cache_identifier, cache_size), pending: HashMap::with_capacity(8), } } - - fn cache_name(cache_identifier: &str) -> String { - format!("tipset_state_{cache_identifier}") - } } /// A generic cache that handles concurrent access and computation for tipset-related data. -pub(crate) struct TipsetStateCache { - cache: Arc>>, +pub(crate) struct ForestLruCache { + cache: Arc>>, } -impl ShallowClone for TipsetStateCache { +impl ShallowClone for ForestLruCache { fn shallow_clone(&self) -> Self { Self { cache: self.cache.shallow_clone(), @@ -49,14 +46,17 @@ enum CacheLookupStatus { Empty(Arc>), } -impl TipsetStateCache { - pub fn new(cache_identifier: &str) -> Self { +impl ForestLruCache { + pub fn new(cache_identifier: impl Into>) -> Self { Self::with_size(cache_identifier, DEFAULT_TIPSET_CACHE_SIZE) } - pub fn with_size(cache_identifier: &str, cache_size: NonZeroUsize) -> Self { + pub fn with_size( + cache_identifier: impl Into>, + cache_size: NonZeroUsize, + ) -> Self { Self { - cache: Arc::new(SyncRwLock::new(TipsetStateCacheInner::with_size( + cache: Arc::new(SyncRwLock::new(ForestLruCacheInner::with_size( cache_identifier, cache_size, ))), @@ -65,8 +65,8 @@ impl TipsetStateCache { fn get_or_insert(&self, get_func: F1, or_insert_func: F2) -> T where - F1: FnOnce(&TipsetStateCacheInner) -> Option, - F2: FnOnce(&mut TipsetStateCacheInner) -> T, + F1: FnOnce(&ForestLruCacheInner) -> Option, + F2: FnOnce(&mut ForestLruCacheInner) -> T, { if let Some(v) = get_func(&self.cache.read()) { v @@ -75,7 +75,7 @@ impl TipsetStateCache { } } - pub async fn get_or_else(&self, key: &TipsetKey, compute: F) -> anyhow::Result + pub async fn get_or_else(&self, key: &K, compute: F) -> anyhow::Result where F: FnOnce() -> Fut, Fut: Future> + Send, @@ -125,21 +125,21 @@ impl TipsetStateCache { } } - pub fn get_map(&self, key: &TipsetKey, mapper: impl Fn(&V) -> T) -> Option { + pub fn get_map(&self, key: &K, mapper: impl Fn(&V) -> T) -> Option { self.cache.read().values.get_map(key, mapper) } - pub fn get(&self, key: &TipsetKey) -> Option { + pub fn get(&self, key: &K) -> Option { self.get_map(key, Clone::clone) } - pub fn insert(&self, key: TipsetKey, value: V) { + pub fn insert(&self, key: K, value: V) { let mut cache = self.cache.write(); cache.pending.retain(|k, _| k != &key); cache.values.push(key, value); } - pub fn remove(&self, key: &TipsetKey) { + pub fn remove(&self, key: &K) { let mut cache = self.cache.write(); cache.pending.retain(|k, _| k != key); cache.values.remove(key); @@ -168,7 +168,7 @@ mod tests { #[tokio::test] async fn test_tipset_cache_basic_functionality() { - let cache: TipsetStateCache = TipsetStateCache::new("test"); + let cache: ForestLruCache = ForestLruCache::new("test"); let key = create_test_tipset_key(1); // Test cache miss and computation @@ -188,7 +188,7 @@ mod tests { #[tokio::test] async fn test_concurrent_same_key_computation() { - let cache: Arc> = Arc::new(TipsetStateCache::new("test")); + let cache: Arc> = Arc::new(ForestLruCache::new("test")); let key = create_test_tipset_key(1); let computation_count = Arc::new(AtomicU8::new(0)); @@ -235,7 +235,7 @@ mod tests { #[tokio::test] async fn test_concurrent_different_keys() { - let cache: Arc> = Arc::new(TipsetStateCache::new("test")); + let cache: Arc> = Arc::new(ForestLruCache::new("test")); let computation_count = Arc::new(AtomicU8::new(0)); // Start tasks that try to compute the different keys diff --git a/src/state_manager/mod.rs b/src/state_manager/mod.rs index ffdaaf37c692..3f8c69d3d718 100644 --- a/src/state_manager/mod.rs +++ b/src/state_manager/mod.rs @@ -6,7 +6,7 @@ mod tests; mod actor_queries; mod address_resolution; -mod cache; +pub mod cache; pub mod chain_rand; pub mod circulating_supply; mod errors; @@ -20,7 +20,7 @@ pub mod utils; pub use self::errors::*; pub use self::state_computation::{apply_block_messages, validate_tipsets}; use crate::beacon::BeaconSchedule; -use crate::blocks::Tipset; +use crate::blocks::{Tipset, TipsetKey}; use crate::chain::{ ChainStore, index::{ChainIndex, ResolveNullTipset}, @@ -48,7 +48,7 @@ use crate::shim::{ state_tree::{ActorState, StateTree}, version::NetworkVersion, }; -use crate::state_manager::cache::TipsetStateCache; +use crate::state_manager::cache::ForestLruCache; use crate::utils::cache::SizeTrackingLruCache; use crate::utils::get_size::{GetSize, vec_heap_size_helper}; use anyhow::Context as _; @@ -167,7 +167,7 @@ pub struct StateManager { /// Chain store cs: ChainStore, /// This is a cache which indexes tipsets to their calculated state output (state root, receipt root). - cache: TipsetStateCache, + cache: ForestLruCache, id_to_deterministic_address_cache: IdToAddressCache, beacon: Arc, engine: Arc, @@ -209,11 +209,11 @@ impl StateManager { Ok(Self { cs, - cache: TipsetStateCache::new("executed_tipset"), // For StateOutput + cache: ForestLruCache::new("tipset_state_executed_tipset"), // For StateOutput beacon, engine, id_to_deterministic_address_cache: SizeTrackingLruCache::new_with_metrics( - "id_to_deterministic_address".into(), + "id_to_deterministic_address", DEFAULT_ID_TO_DETERMINISTIC_ADDRESS_CACHE_SIZE, ), }) diff --git a/src/state_migration/common/mod.rs b/src/state_migration/common/mod.rs index 4c960e65e87b..1daff30e5608 100644 --- a/src/state_migration/common/mod.rs +++ b/src/state_migration/common/mod.rs @@ -31,10 +31,7 @@ pub(in crate::state_migration) struct MigrationCache { impl MigrationCache { pub fn new(size: NonZeroUsize) -> Self { Self { - cache: Arc::new(SizeTrackingLruCache::new_with_metrics( - "migration".into(), - size, - )), + cache: Arc::new(SizeTrackingLruCache::new_with_metrics("migration", size)), } } diff --git a/src/utils/cache/lru.rs b/src/utils/cache/lru.rs index 913bcde4fba8..c5aa8c233813 100644 --- a/src/utils/cache/lru.rs +++ b/src/utils/cache/lru.rs @@ -24,12 +24,12 @@ use prometheus_client::{ use crate::prelude::*; -pub trait KeyConstraints: +pub trait LruKeyConstraints: GetSize + Debug + Send + Sync + Hash + PartialEq + Eq + Clone + 'static { } -impl KeyConstraints for T where +impl LruKeyConstraints for T where T: GetSize + Debug + Send + Sync + Hash + PartialEq + Eq + Clone + 'static { } @@ -41,7 +41,7 @@ impl LruValueConstraints for T where T: GetSize + Debug + Send + Sync + Clone #[derive(Debug)] pub struct SizeTrackingLruCache where - K: KeyConstraints, + K: LruKeyConstraints, V: LruValueConstraints, { cache_id: usize, @@ -51,7 +51,7 @@ where impl ShallowClone for SizeTrackingLruCache where - K: KeyConstraints, + K: LruKeyConstraints, V: LruValueConstraints, { fn shallow_clone(&self) -> Self { @@ -65,19 +65,19 @@ where impl SizeTrackingLruCache where - K: KeyConstraints, + K: LruKeyConstraints, V: LruValueConstraints, { fn register_metrics(&self) { crate::metrics::register_collector(Box::new(self.shallow_clone())); } - fn new_inner(cache_name: Cow<'static, str>, capacity: Option) -> Self { + fn new_inner(cache_name: impl Into>, capacity: Option) -> Self { static ID_GENERATOR: AtomicUsize = AtomicUsize::new(0); Self { cache_id: ID_GENERATOR.fetch_add(1, Ordering::Relaxed), - cache_name, + cache_name: cache_name.into(), #[allow(clippy::disallowed_methods)] cache: Arc::new(RwLock::new( capacity @@ -90,23 +90,26 @@ where } pub fn new_without_metrics_registry( - cache_name: Cow<'static, str>, + cache_name: impl Into>, capacity: NonZeroUsize, ) -> Self { Self::new_inner(cache_name, Some(capacity)) } - pub fn new_with_metrics(cache_name: Cow<'static, str>, capacity: NonZeroUsize) -> Self { + pub fn new_with_metrics( + cache_name: impl Into>, + capacity: NonZeroUsize, + ) -> Self { let c = Self::new_without_metrics_registry(cache_name, capacity); c.register_metrics(); c } - pub fn unbounded_without_metrics_registry(cache_name: Cow<'static, str>) -> Self { + pub fn unbounded_without_metrics_registry(cache_name: impl Into>) -> Self { Self::new_inner(cache_name, None) } - pub fn unbounded_with_metrics(cache_name: Cow<'static, str>) -> Self { + pub fn unbounded_with_metrics(cache_name: impl Into>) -> Self { let c = Self::unbounded_without_metrics_registry(cache_name); c.register_metrics(); c @@ -186,7 +189,7 @@ where impl Collector for SizeTrackingLruCache where - K: KeyConstraints, + K: LruKeyConstraints, V: LruValueConstraints, { fn encode(&self, mut encoder: DescriptorEncoder) -> Result<(), std::fmt::Error> { diff --git a/src/utils/cache/mod.rs b/src/utils/cache/mod.rs index 6394bd6c79dc..a18c29b42898 100644 --- a/src/utils/cache/mod.rs +++ b/src/utils/cache/mod.rs @@ -2,4 +2,4 @@ // SPDX-License-Identifier: Apache-2.0, MIT mod lru; -pub use lru::{LruValueConstraints, SizeTrackingLruCache}; +pub use lru::{LruKeyConstraints, LruValueConstraints, SizeTrackingLruCache};