### Insert or get entries: or_insert family (Rust) Source: https://docs.rs/moka/latest/src/moka/sync/entry_selector Demonstrates using EntrySelector to insert or get entries in a Moka Cache. Includes examples for or_insert (fixed default), or_insert_with (closure default), or_insert_with_if (conditional replacement), and or_optionally_insert_with (optional insertion). These methods return Entry handles, let you check freshness, and guarantee only one evaluation of the init closure across concurrent calls for the same key. ```rust use moka::sync::Cache; let cache: Cache = Cache::new(100); let key = "key1".to_string(); let entry = cache.entry(key.clone()).or_insert(3); assert!(entry.is_fresh()); assert_eq!(entry.key(), &key); assert_eq!(entry.into_value(), 3); let entry = cache.entry(key).or_insert(6); // Not fresh because the value was already in the cache. assert!(!entry.is_fresh()); assert_eq!(entry.into_value(), 3); ``` ```rust use moka::sync::Cache; let cache: Cache = Cache::new(100); let key = "key1".to_string(); let entry = cache .entry(key.clone()) .or_insert_with(|| "value1".to_string()); assert!(entry.is_fresh()); assert_eq!(entry.key(), &key); assert_eq!(entry.into_value(), "value1"); let entry = cache .entry(key) .or_insert_with(|| "value2".to_string()); // Not fresh because the value was already in the cache. assert!(!entry.is_fresh()); assert_eq!(entry.into_value(), "value1"); ``` ```rust pub fn or_insert_with_if( self, init: impl FnOnce() -> V, replace_if: impl FnMut(&V) -> bool, ) -> Entry { let key = Arc::new(self.owned_key); self.cache .get_or_insert_with_hash_and_fun(key, self.hash, init, Some(replace_if), true) } ``` ```rust use moka::sync::Cache; let cache: Cache = Cache::new(100); let key = "key1".to_string(); let none_entry = cache .entry(key.clone()) .or_optionally_insert_with(|| None); assert!(none_entry.is_none()); let some_entry = cache .entry(key.clone()) .or_optionally_insert_with(|| Some(3)); assert!(some_entry.is_some()); let entry = some_entry.unwrap(); assert!(entry.is_fresh()); assert_eq!(entry.key(), &key); assert_eq!(entry.into_value(), 3); let some_entry = cache .entry(key) .or_optionally_insert_with(|| Some(6)); let entry = some_entry.unwrap(); // Not fresh because the value was already in the cache. assert!(!entry.is_fresh()); assert_eq!(entry.into_value(), 3); ``` -------------------------------- ### Example: Increment or Remove Counter (Rust) Source: https://docs.rs/moka/latest/src/moka/sync/entry_selector Demonstrates how to use `and_compute_with` to conditionally increment a counter or remove it if it reaches a certain threshold. The example shows inserting a new value, incrementing an existing value, and removing an entry. ```rust use moka::{ sync::Cache, ops::compute::{CompResult, Op}, }; let cache: Cache = Cache::new(100); let key = "key1".to_string(); /// Increment a cached `u64` counter. If the counter is greater than or /// equal to 2, remove it. fn inclement_or_remove_counter( cache: &Cache, key: &str, ) -> CompResult { cache .entry(key.to_string()) .and_compute_with(|maybe_entry| { if let Some(entry) = maybe_entry { let counter = entry.into_value(); if counter < 2 { Op::Put(counter.saturating_add(1)) // Update } else { Op::Remove } } else { Op::Put(1) // Insert } }) } // This should insert a new counter value 1 to the cache, and return the // value with the kind of the operation performed. let result = inclement_or_remove_counter(&cache, &key); let CompResult::Inserted(entry) = result else { panic!("`Inserted` should be returned: {result:?}"); }; assert_eq!(entry.into_value(), 1); // This should increment the cached counter value by 1. ``` -------------------------------- ### Moka Cache Configuration Example (Rust) Source: https://docs.rs/moka/latest/src/moka/future/builder Demonstrates how to configure a Moka Cache with specific capacity and expiration settings using the `Cache::builder()` method. It shows setting maximum capacity, time-to-live, and time-to-idle durations. This example requires the 'future' feature and the 'tokio' and 'futures' crates. ```rust use moka::future::Cache; use std::time::Duration; #[tokio::main] async fn main() { let cache = Cache::builder() // Max 10,000 entries .max_capacity(10_000) // Time to live (TTL): 30 minutes .time_to_live(Duration::from_secs(30 * 60)) // Time to idle (TTI): 5 minutes .time_to_idle(Duration::from_secs( 5 * 60)) // Create the cache. .build(); // This entry will expire after 5 minutes (TTI) if there is no get(). cache.insert(0, "zero").await; // This get() will extend the entry life for another 5 minutes. cache.get(&0); // Even though we keep calling get(), the entry will expire // after 30 minutes (TTL) from the insert(). } ``` -------------------------------- ### Rust Cache::or_try_insert_with Example Source: https://docs.rs/moka/latest/src/moka/sync/entry_selector Demonstrates the usage of `Cache::or_try_insert_with` to conditionally insert values into a cache, handling potential errors. It showcases both error and successful insertion scenarios. ```Rust /// let cache: Cache = Cache::new(100); /// let key = "key1".to_string(); /// /// let error_entry = cache /// .entry_by_ref(&key) /// .or_try_insert_with(|| Err("error")); /// assert!(error_entry.is_err()); /// /// let ok_entry = cache /// .entry_by_ref(&key) /// .or_try_insert_with(|| Ok::(3)); /// assert!(ok_entry.is_ok()); /// let entry = ok_entry.unwrap(); /// assert!(entry.is_fresh()); /// assert_eq!(entry.key(), &key); /// assert_eq!(entry.into_value(), 3); /// /// let ok_entry = cache /// .entry_by_ref(&key) /// .or_try_insert_with(|| Ok::(6)); /// let entry = ok_entry.unwrap(); /// // Not fresh because the value was already in the cache. /// assert!(!entry.is_fresh()); /// assert_eq!(entry.into_value(), 3); /// ``` ``` -------------------------------- ### Create New CacheBuilder with Capacity in Rust Source: https://docs.rs/moka/latest/src/moka/sync/builder Shows how to initialize a CacheBuilder with a specific maximum capacity. This is the starting point for configuring a new cache instance with custom settings. ```rust pub fn new(max_capacity: u64) -> Self { Self { max_capacity: Some(max_capacity), ..Default::default() } } ``` -------------------------------- ### Build basic cache with policies Source: https://docs.rs/moka/latest/src/moka/sync/builder Example showing how to build caches with different configurations. Demonstrates creating a simple cache and one with TTL and TTI policies. Shows how to verify policy settings via the cache policy API. ```rust #[test] fn build_cache() { // Cache let cache = CacheBuilder::new(100).build(); let policy = cache.policy(); assert_eq!(policy.max_capacity(), Some(100)); assert_eq!(policy.time_to_live(), None); assert_eq!(policy.time_to_idle(), None); assert_eq!(policy.num_segments(), 1); cache.insert('a', "Alice"); assert_eq!(cache.get(&'a'), Some("Alice")); let cache = CacheBuilder::new(100) .time_to_live(Duration::from_secs(45 * 60)) .time_to_idle(Duration::from_secs(15 * 60)) .build(); let config = cache.policy(); assert_eq!(config.max_capacity(), Some(100)); assert_eq!(config.time_to_live(), Some(Duration::from_secs(45 * 60))); assert_eq!(config.time_to_idle(), Some(Duration::from_secs(15 * 60))); assert_eq!(config.num_segments(), 1); cache.insert('a', "Alice"); assert_eq!(cache.get(&'a'), Some("Alice")); } ``` -------------------------------- ### String Replacement in Rust Source: https://docs.rs/moka/latest/moka/sync/type This example demonstrates how to replace a portion of a string using the `replace_range` method. It shows how to find the index of a specific character and then replace the substring before that character. ```Rust let mut s = String::from("α is alpha, β is beta"); let beta_offset = s.find('β').unwrap_or(s.len()); // Replace the range up until the β from the string s.replace_range(..beta_offset, "Α is capital alpha; "); assert_eq!(s, "Α is capital alpha; β is beta") ``` -------------------------------- ### Building Cache with Custom Hasher (Rust) Source: https://docs.rs/moka/latest/src/moka/future/builder Illustrates how to build a Moka Cache with a custom hasher, such as the AHash hasher. This allows for potentially improved hashing performance. The example requires the 'ahash' crate in addition to Moka and Tokio. ```rust // Cargo.toml // [dependencies] // ahash = "0.8" // moka = { version = ..., features = ["future"] } // tokio = { version = "1", features = ["rt-multi-thread", "macros" ] } use moka::future::Cache; #[tokio::main] async fn main() { // Example usage with a custom hasher would follow here, // typically involving `Cache::builder_with_hasher(my_hasher).build()` // or similar, depending on the specific builder API. // For brevity, this snippet focuses on the import and context. } ``` -------------------------------- ### Build Cache with Expiration Policies in Rust Source: https://docs.rs/moka/latest/src/moka/sync/builder Demonstrates how to configure a Cache instance with max capacity, time-to-live (TTL), and time-to-idle (TTI) expiration policies. The example shows insertion and access patterns that affect entry expiration. ```rust use moka::sync::Cache; use std::time::Duration; let cache = Cache::builder() // Max 10,000 entries .max_capacity(10_000) // Time to live (TTL): 30 minutes .time_to_live(Duration::from_secs(30 * 60)) // Time to idle (TTI): 5 minutes .time_to_idle(Duration::from_secs( 5 * 60)) // Create the cache. .build(); // This entry will expire after 5 minutes (TTI) if there is no get(). cache.insert(0, "zero"); // This get() will extend the entry life for another 5 minutes. cache.get(&0); // Even though we keep calling get(), the entry will expire // after 30 minutes (TTL) from the insert(). ``` -------------------------------- ### Rust: or_insert Cache Operation Source: https://docs.rs/moka/latest/moka/future/struct Demonstrates the `or_insert` function, which retrieves an entry or inserts a new one with the provided default value if it doesn't exist. The example verifies the entry's freshness and value after the operation. ```rust // Cargo.toml // // [dependencies] // moka = { version = "0.12", features = ["future" ] } // tokio = { version = "1", features = ["rt-multi-thread", "macros" ] } use moka::future::Cache; #[tokio::main] async fn main() { let cache: Cache = Cache::new(100); let key = "key1".to_string(); let entry = cache.entry(key.clone()).or_insert(3).await; assert!(entry.is_fresh()); assert_eq!(entry.key(), &key); assert_eq!(entry.into_value(), 3); let entry = cache.entry(key).or_insert(6).await; // Not fresh because the value was already in the cache. assert!(!entry.is_fresh()); assert_eq!(entry.into_value(), 3); } ``` -------------------------------- ### Rust: or_default Cache Operation Source: https://docs.rs/moka/latest/moka/future/struct Illustrates the `or_default` function, which retrieves an entry or inserts a new one with a default value if it doesn't exist. The example demonstrates how the cache is updated and whether the entry is fresh after the operation. ```rust // Cargo.toml // // [dependencies] // moka = { version = "0.12", features = ["future" ] } // tokio = { version = "1", features = ["rt-multi-thread", "macros" ] } use moka::future::Cache; #[tokio::main] async fn main() { let cache: Cache> = Cache::new(100); let key = "key1".to_string(); let entry = cache.entry(key.clone()).or_default().await; assert!(entry.is_fresh()); assert_eq!(entry.key(), &key); assert_eq!(entry.into_value(), None); let entry = cache.entry(key).or_default().await; // Not fresh because the value was already in the cache. assert!(!entry.is_fresh()); } ``` -------------------------------- ### Example of using and_upsert_with with Moka cache in Rust Source: https://docs.rs/moka/latest/src/moka/future/entry_selector Demonstrates how to perform an upsert operation on a Moka future cache using the and_upsert_with method. The example shows both insertion and update paths with a closure that returns an immediately ready future, and validates the results. Requires Tokio runtime and the moka crate with the "future" feature enabled. ```rust // Cargo.toml // // [dependencies] // moka = { version = "0.12.8", features = ["future"] } // tokio = { version = "1", features = ["rt-multi-thread", "macros" ] } use moka::future::Cache; #[tokio::main] async fn main() { let cache: Cache = Cache::new(100); let key = "key1".to_string(); let entry = cache .entry(key.clone()) .and_upsert_with(|maybe_entry| { let counter = if let Some(entry) = maybe_entry { entry.into_value().saturating_add(1) // Update } else { 1 // Insert }; // Return a Future that is resolved to `counter` immediately. std::future::ready(counter) }) .await; // It was not an update. assert!(!entry.is_old_value_replaced()); assert_eq!(entry.key(), &key); assert_eq!(entry.into_value(), 1); let entry = cache .entry(key.clone()) .and_upsert_with(|maybe_entry| { let counter = if let Some(entry) = maybe_entry { entry.into_value().saturating_add(1) } else { 1 }; std::future::ready(counter) }) .await; // It was an update. assert!(entry.is_old_value_replaced()); assert_eq!(entry.key(), &key); assert_eq!(entry.into_value(), 2); } ``` -------------------------------- ### String to Boxed String Conversion in Rust Source: https://docs.rs/moka/latest/moka/sync/type This example shows how to convert a `String` into a `Box`. It utilizes the `into_boxed_str` method, which discards excess capacity before performing the conversion. ```Rust let s = String::from("hello"); let b = s.into_boxed_str(); ``` -------------------------------- ### String Concatenation in Rust Source: https://docs.rs/moka/latest/moka/sync/type This example demonstrates string concatenation using the `+` operator for `String`s and `&str` slices, highlighting the difference between taking the first string by value and borrowing the second. It also shows how to use `clone()` to keep the first string valid after concatenation. ```Rust let a = String::from("hello"); let b = String::from(" world"); let c = a + &b; // `a` is moved and can no longer be used here. ``` ```Rust let a = String::from("hello"); let b = String::from(" world"); let c = a.clone() + &b; // `a` is still valid here. ``` ```Rust let a = "hello"; let b = " world"; let c = a.to_string() + b; ``` -------------------------------- ### Counter Increment and Removal Pattern - Rust Source: https://docs.rs/moka/latest/src/moka/sync/entry_selector Example usage pattern showing how to implement atomic counter operations using compute operations. Demonstrates incrementing existing counters, removing counters when they reach zero, and inserting new counters. Shows proper handling of all compute result variants. ```rust /// let result = inclement_or_remove_counter(&cache, &key); /// let CompResult::ReplacedWith(entry) = result else { /// panic!("`ReplacedWith` should be returned: {result:?}"); /// }; /// assert_eq!(entry.into_value(), 2); /// /// // This should remove the cached counter from the cache, and returns the /// // _removed_ value. /// let result = inclement_or_remove_counter(&cache, &key); /// let CompResult::Removed(entry) = result else { /// panic!("`Removed` should be returned: {result:?}"); /// }; /// assert_eq!(entry.into_value(), 2); /// /// // The key should no longer exist. /// assert!(!cache.contains_key(&key)); /// /// // This should start over; insert a new counter value 1 to the cache. /// let result = inclement_or_remove_counter(&cache, &key); /// let CompResult::Inserted(entry) = result else { /// panic!("`Inserted` should be returned: {result:?}"); /// }; /// assert_eq!(entry.into_value(), 1); ``` -------------------------------- ### HashMap Growth Test in Rust Source: https://docs.rs/moka/latest/src/moka/cht/segment This test checks the HashMap's ability to grow its capacity dynamically during insertions, ensuring integrity throughout. It starts with low capacity and inserts up to MAX_VALUE elements, verifying each insertion and retrieval. Similar to the insertion test, it uses insert_entry_and and get methods; no specific inputs/outputs beyond the loop iterations; may encounter allocation issues on resource-constrained environments like emulators. ```Rust #[test] fn growth() { const MAX_VALUE: i32 = 512; let map = HashMap::with_capacity(0); for i in 0..MAX_VALUE { assert_eq!(map.insert_entry_and(i, map.hash(&i), i, |_, v| *v), None); assert!(!map.is_empty()); assert_eq!(map.len(), (i + 1) as usize); for j in 0..=i { let hash = map.hash(&j); assert_eq!(map.get(hash, |&k| k == j), Some(j)); assert_eq!(map.insert_entry_and(j, hash, j, |_, v| *v), Some(j)); } for l in i + 1..MAX_VALUE { assert_eq!(map.get(map.hash(&l), |&k| k == l), None); } } run_deferred(); } ``` -------------------------------- ### Create and configure cache with CacheBuilder (Rust) Source: https://docs.rs/moka/latest/src/moka/sync/builder Initializes a cache with specified capacity, segments, TTL, TTI, and eviction listener. Demonstrates policy assertions and basic insert/get operations. ```rust let cache = CacheBuilder::new(100).segments(15).build(); let policy = cache.policy(); assert_eq!(policy.max_capacity(), Some(100)); assert!(policy.time_to_live().is_none()); assert!(policy.time_to_idle().is_none()); assert_eq!(policy.num_segments(), 16_usize.next_power_of_two()); cache.insert('b', "Bob"); assert_eq!(cache.get(&'b'), Some("Bob")); ``` ```rust let listener = move |_key, _value, _cause| (); let builder = CacheBuilder::new(400) .time_to_live(Duration::from_secs(45 * 60)) .time_to_idle(Duration::from_secs(15 * 60)) .eviction_listener(listener) .name("tracked_sessions") .segments(24); assert!(builder.eviction_listener.is_some()); let cache = builder.build(); let policy = cache.policy(); assert_eq!(policy.max_capacity(), Some(400)); assert_eq!(policy.time_to_live(), Some(Duration::from_secs(45 * 60))); assert_eq!(policy.time_to_idle(), Some(Duration::from_secs(15 * 60))); assert_eq!(policy.num_segments(), 24_usize.next_power_of_two()); assert_eq!(cache.name(), Some("tracked_sessions")); cache.insert('b', "Bob"); assert_eq!(cache.get(&'b'), Some("Bob")); ``` -------------------------------- ### Deprecated get or insert with closure in Rust Source: https://docs.rs/moka/latest/src/moka/sync/segment Deprecated method for getting a value from cache or inserting the result of a closure. Replaced by get_with method. Marks as deprecated since version 0.8.0. ```rust #[deprecated(since = "0.8.0", note = "Replaced with `get_with`")] pub fn get_or_insert_with(&self, key: K, init: impl FnOnce() -> V) -> V { self.get_with(key, init) } ``` -------------------------------- ### Deprecated try get or insert with closure in Rust Source: https://docs.rs/moka/latest/src/moka/sync/segment Deprecated method for attempting to get a value from cache or inserting the result of a fallible closure. Replaced by try_get_with method. Marks as deprecated since version 0.8.0. ```rust #[deprecated(since = "0.8.0", note = "Replaced with `try_get_with`")] pub fn get_or_try_insert_with(&self, key: K, init: F) -> Result> where F: FnOnce() -> Result, E: Send + Sync + 'static, { self.try_get_with(key, init) } ``` -------------------------------- ### Cache iteration example in Rust Source: https://docs.rs/moka/latest/src/moka/sync/segment Example demonstrating how to use the cache iterator to retrieve key-value pairs. Shows creation of a SegmentedCache, insertion of a value, and iteration over entries. The iterator returns entries as (Arc, V) tuples where V is a clone of the stored value. ```rust use moka::sync::SegmentedCache; let cache = SegmentedCache::new(100, 4); cache.insert("Julia", 14); let mut iter = cache.iter(); let (k, v) = iter.next().unwrap(); // (Arc, V) assert_eq!(*k, "Julia"); assert_eq!(v, 14); assert!(iter.next().is_none()); ``` -------------------------------- ### Moka Cache Builder - Basic Configuration and Usage Source: https://docs.rs/moka/latest/src/moka/future/builder Demonstrates basic cache configuration using the Moka cache builder pattern. Shows how to create a cache with max capacity and custom hasher, along with async insertion operations. The cache type must include the hasher type parameter when using custom hashers. ```rust /// async fn main() { /// // The type of this cache is: Cache /// let cache = Cache::builder() /// .max_capacity(100) /// .build_with_hasher(ahash::RandomState::default()); /// cache.insert(1, "one".to_string()).await; /// } /// ``` /// Here is a good example: /// ```rust /// # use moka::future::Cache; /// # #[tokio::main] /// # async fn main() { /// # let cache = Cache::builder() /// # .build_with_hasher(ahash::RandomState::default()); /// struct Good { /// // Specifying the type in Cache format. /// cache: Cache, /// } /// // Storing the cache from above example. This should compile. /// Good { cache }; /// # } /// ``` ``` -------------------------------- ### Build and test cache with various configurations Source: https://docs.rs/moka/latest/src/moka/future/builder Demonstrates building a cache with different configurations, including capacity, TTL, and TTI. The tests validate that the cache behaves correctly with these settings and panic appropriately when configured with durations longer than 1000 years. ```rust #[tokio::test] async fn build_cache() { let cache = CacheBuilder::new(100).build(); let policy = cache.policy(); assert_eq!(policy.max_capacity(), Some(100)); assert_eq!(policy.time_to_live(), None); assert_eq!(policy.time_to_idle(), None); assert_eq!(policy.num_segments(), 1); cache.insert('a', "Alice").await; assert_eq!(cache.get(&'a').await, Some("Alice")); let cache = CacheBuilder::new(100) .time_to_live(Duration::from_secs(45 * 60)) .time_to_idle(Duration::from_secs(15 * 60)) .build(); let policy = cache.policy(); assert_eq!(policy.max_capacity(), Some(100)); assert_eq!(policy.time_to_live(), Some(Duration::from_secs(45 * 60))); assert_eq!(policy.time_to_idle(), Some(Duration::from_secs(15 * 60))); assert_eq!(policy.num_segments(), 1); cache.insert('a', "Alice").await; assert_eq!(cache.get(&'a').await, Some("Alice")); } #[tokio::test] #[should_panic(expected = "time_to_live is longer than 1000 years")] async fn build_cache_too_long_ttl() { let thousand_years_secs: u64 = 1000 * 365 * 24 * 3600; let builder: CacheBuilder = CacheBuilder::new(100); let duration = Duration::from_secs(thousand_years_secs); builder .time_to_live(duration + Duration::from_secs(1)) .build(); } #[tokio::test] #[should_panic(expected = "time_to_idle is longer than 1000 years")] async fn build_cache_too_long_tti() { let thousand_years_secs: u64 = 1000 * 365 * 24 * 3600; let builder: CacheBuilder = CacheBuilder::new(100); let duration = Duration::from_secs(thousand_years_secs); builder .time_to_idle(duration + Duration::from_secs(1)) .build(); } ``` -------------------------------- ### Rust String As Mut Vec Source: https://docs.rs/moka/latest/moka/sync/type Shows how to get a mutable reference to the contents of a String as a Vec. ```Rust const unsafe fn as_mut_vec(&mut self) -> &mut Vec ⓘ ``` -------------------------------- ### Rust: Get Timer Node Source: https://docs.rs/moka/latest/src/moka/common/concurrent Retrieves the timer node associated with this entry, if any. This is used for time-based operations, such as cache expiration or periodic updates. ```rust pub(crate) fn timer_node(&self) -> Option> { self.nodes.lock().timer_node } ``` -------------------------------- ### Get Key Value With Entry Handler Source: https://docs.rs/moka/latest/src/moka/future/base_cache Retrieves a key-value pair and applies a function to the entry if it exists. Uses hash-based lookup for efficiency. ```rust fn get_key_value_and(&self, key: &Q, hash: u64, with_entry: F) -> Option where Q: Equivalent + Hash + ?Sized, ``` -------------------------------- ### Kani proof for ensure capacity method Source: https://docs.rs/moka/latest/src/moka/common/frequency_sketch Formal verification proof using Kani to ensure the ensure_capacity method doesn't panic for any possible input capacity. Tests arbitrary capacity values using Kani's any() function for symbolic execution. ```rust #[kani::proof] fn verify_ensure_capacity() { // Check for arbitrary capacities. let capacity = kani::any(); let mut sketch = FrequencySketch::default(); sketch.ensure_capacity(capacity); } ``` -------------------------------- ### Get or insert with closure in Rust Source: https://docs.rs/moka/latest/src/moka/sync/segment Retrieves a value from cache or inserts the result of a closure, ensuring thread-safe operation for concurrent calls on the same key. Uses hashing for cache selection. ```rust pub fn get_with(&self, key: K, init: impl FnOnce() -> V) -> V { let hash = self.inner.hash(&key); let key = Arc::new(key); let replace_if = None as Option bool>; self.inner .select(hash) .get_or_insert_with_hash_and_fun(key, hash, init, replace_if, false) .into_value() } ``` -------------------------------- ### Async Cache Insertion with Moka (Rust) Source: https://docs.rs/moka/latest/moka/future/struct Demonstrates how to use Moka's asynchronous `Cache` to insert values, handling both successful insertions and potential errors. It shows the use of `entry().or_try_insert_with()` with async closures and checks the state of the inserted entry. ```rust // Cargo.toml // // [dependencies] // moka = { version = "0.12", features = ["future"] } // tokio = { version = "1", features = ["rt-multi-thread", "macros" ] } use moka::future::Cache; #[tokio::main] async fn main() { let cache: Cache = Cache::new(100); let key = "key1".to_string(); // Example of an insert that returns an error let error_entry = cache .entry(key.clone()) .or_try_insert_with(async { Err("error") }) .await; assert!(error_entry.is_err()); // Example of a successful insert let ok_entry = cache .entry(key.clone()) .or_try_insert_with(async { Ok::(3) }) .await; assert!(ok_entry.is_ok()); let entry = ok_entry.unwrap(); assert!(entry.is_fresh()); assert_eq!(entry.key(), &key); assert_eq!(entry.into_value(), 3); // Example of accessing an existing key; it won't be fresh let ok_entry = cache .entry(key) .or_try_insert_with(async { Ok::(6) }) .await; let entry = ok_entry.unwrap(); // Not fresh because the value was already in the cache. assert!(!entry.is_fresh()); assert_eq!(entry.into_value(), 3); } ``` -------------------------------- ### Get cache entry by reference in Rust Source: https://docs.rs/moka/latest/src/moka/sync/segment Retrieves a cache entry by reference, using a hash of the key for selection. Requires the key to implement Equivalent, ToOwned, and Hash traits. ```rust pub fn entry_by_ref<'a, Q>(&'a self, key: &'a Q) -> RefKeyEntrySelector<'a, K, Q, V, S> where Q: Equivalent + ToOwned + Hash + ?Sized, { let hash = self.inner.hash(key); let cache = self.inner.select(hash); RefKeyEntrySelector::new(key, hash, cache) } ``` -------------------------------- ### Rust String Reserve Source: https://docs.rs/moka/latest/moka/sync/type Demonstrates how to use the `reserve` method to pre-allocate memory for a String, followed by checks on the capacity. It also shows usage of `shrink_to` to reduce allocated capacity. ```Rust let mut s = String::from("foo"); s.reserve(100); assert!(s.capacity() >= 100); s.shrink_to(10); assert!(s.capacity() >= 10); s.shrink_to(0); assert!(s.capacity() >= 3); ``` -------------------------------- ### Kani proof for frequency method bounds Source: https://docs.rs/moka/latest/src/moka/common/frequency_sketch Formal verification proof ensuring that the frequency method always returns values within expected bounds (0-15). Tests multiple predetermined capacities with arbitrary hash values. ```rust #[kani::proof] fn verify_frequency() { // Check for some selected capacities. for capacity in CAPACITIES { let mut sketch = FrequencySketch::default(); sketch.ensure_capacity(*capacity); // Check for arbitrary hashes. let hash = kani::any(); let frequency = sketch.frequency(hash); assert!(frequency <= 15); } } ``` -------------------------------- ### Get Key Lock Source: https://docs.rs/moka/latest/src/moka/future/base_cache Retrieves a key lock from the key locks map if available. This function is used internally to manage concurrent access to specific keys. ```rust self.key_locks.as_ref().map(|kls| kls.key_lock(key)) ``` -------------------------------- ### Admit Candidate Based on Eviction Policy (TinyLFU) Source: https://docs.rs/moka/latest/src/moka/future/base_cache Implements the admission logic for the TinyLFU eviction policy. It creates an `EntrySizeAndFrequency` candidate and uses a static `admit` method to determine if the candidate can be admitted, potentially returning victim keys that need to be evicted. ```rust 1667 let admission_result = match &self.eviction_policy { 1668 EvictionPolicyConfig::TinyLfu => { 1669 let mut candidate = EntrySizeAndFrequency::new(new_weight); 1670 candidate.add_frequency(freq, kh.hash); 1671 Self::admit(&candidate, &self.cache, deqs, freq) 1672 } 1673 EvictionPolicyConfig::Lru => AdmissionResult::Admitted { 1674 victim_keys: SmallVec::default(), 1675 }, 1676 }; ``` -------------------------------- ### Rust: Get Write Order Queue Node Source: https://docs.rs/moka/latest/src/moka/common/concurrent Retrieves the node associated with the write order queue for this entry, if it exists. This is used for managing entries based on their write sequence. ```rust pub(crate) fn write_order_q_node(&self) -> Option> { self.nodes.lock().write_order_q_node } ``` -------------------------------- ### Rust: Get Policy Weight Source: https://docs.rs/moka/latest/src/moka/common/concurrent Retrieves the policy-specific weight of a `ValueEntry`. This weight is used by cache eviction algorithms (like LRU or LFU) to prioritize which entries to keep or discard. ```rust pub(crate) fn policy_weight(&self) -> u32 { self.info.policy_weight() } ``` -------------------------------- ### Rust: or_optionally_insert_with Source: https://docs.rs/moka/latest/src/moka/sync/entry_selector This method retrieves an entry from the cache. If the entry doesn't exist, it calls the provided closure to create it and inserts it into the cache. It handles potential errors from the closure and returns an `Option>`. ```Rust pub fn or_optionally_insert_with( self, init: impl FnOnce() -> Option, ) -> Option> { let key = Arc::new(self.owned_key); self.cache .get_or_optionally_insert_with_hash_and_fun(key, self.hash, init, true) } ``` -------------------------------- ### Configure Cache Segments in Rust Source: https://docs.rs/moka/latest/src/moka/sync/builder Demonstrates how to set the number of segments for a SegmentedCache. Includes a panic check to ensure at least one segment is specified. ```rust pub fn segments( self, num_segments: usize, ) -> CacheBuilder> { assert!(num_segments != 0); CacheBuilder { name: self.name, max_capacity: self.max_capacity, initial_capacity: self.initial_capacity, num_segments: Some(num_segments), weigher: self.weigher, eviction_policy: self.eviction_policy, eviction_listener: self.eviction_listener, expiration_policy: self.expiration_policy, housekeeper_config: self.housekeeper_config, invalidator_enabled: self.invalidator_enabled, clock: self.clock, cache_type: PhantomData, } } ``` -------------------------------- ### Convert Cow<'a, str> to String (Rust) Source: https://docs.rs/moka/latest/moka/sync/type This code demonstrates converting a clone-on-write string (`Cow<'a, str>`) to an owned `String`. If the input is borrowed, the string will be cloned to create the `String`. ```Rust // If the string is not owned... let cow: Cow<'_, str> = Cow::Borrowed("eggplant"); // It will allocate on the heap and copy the string. let owned: String = String::from(cow); assert_eq!(&owned[..], "eggplant") ``` -------------------------------- ### Rust String Remove Matches Source: https://docs.rs/moka/latest/moka/sync/type Shows how to remove all occurrences of a pattern from a String using the `remove_matches` method (nightly feature). Includes examples of both a simple and overlapping pattern. ```Rust #![feature(string_remove_matches)] let mut s = String::from("Trees are not green, the sky is not blue."); s.remove_matches("not "); assert_eq!("Trees are green, the sky is blue.", s); ``` ```Rust #![feature(string_remove_matches)] let mut s = String::from("banana"); s.remove_matches("ana"); assert_eq!("bna", s); ``` -------------------------------- ### Optionally insert entry using or_optionally_insert_with (Rust) Source: https://docs.rs/moka/latest/src/moka/sync/entry_selector Attempts to insert a value into the cache using an init closure that returns an Option. If the closure returns Some, the entry is added; if None, no insertion occurs. Returns an Option indicating success. ```Rust pub fn or_optionally_insert_with( self, init: impl FnOnce() -> Option, ) -> Option> { self.cache .get_or_optionally_insert_with_hash_by_ref_and_fun(self.ref_key, self.hash, init, true) } ``` -------------------------------- ### Rust: or_try_insert_with Source: https://docs.rs/moka/latest/src/moka/sync/entry_selector Similar to `or_optionally_insert_with`, this method attempts to retrieve an entry. If it doesn't exist, it executes a closure that returns a `Result`. If the result is successful (Ok), the entry is inserted. If it's an error (Err), no entry is inserted, and the error is returned. ```Rust pub fn or_try_insert_with(self, init: F) -> Result, Arc> where F: FnOnce() -> Result, E: Send + Sync + 'static, { let key = Arc::new(self.owned_key); self.cache .get_or_try_insert_with_hash_and_fun(key, self.hash, init, true) } ``` -------------------------------- ### Get or insert by reference with closure in Rust Source: https://docs.rs/moka/latest/src/moka/sync/segment Similar to get_with but accepts a reference to the key instead of an owned value. Clones the key if needed for cache insertion. Uses hashing for cache selection. ```rust pub fn get_with_by_ref(&self, key: &Q, init: impl FnOnce() -> V) -> V where Q: Equivalent + ToOwned + Hash + ?Sized, { let hash = self.inner.hash(key); let replace_if = None as Option bool>; self.inner .select(hash) .get_or_insert_with_hash_by_ref_and_fun(key, hash, init, replace_if, false) .into_value() } ``` -------------------------------- ### Rust String: Get Capacity Source: https://docs.rs/moka/latest/moka/sync/type Retrieves the current capacity of a String in bytes. This indicates the amount of space allocated for the string's contents, not necessarily the amount of data currently stored. ```Rust let s = String::with_capacity(10); assert!(s.capacity() >= 10); ``` -------------------------------- ### Implement try_init_or_read method Source: https://docs.rs/moka/latest/src/moka/sync/value_initializer Core method for concurrent value initialization with retry logic. Handles cache lookup, value initialization, error handling, and panic recovery with configurable retry limit. ```rust pub(crate) fn try_init_or_read( &self, key: &Arc, type_id: TypeId, mut get: impl FnMut() -> Option, init: impl FnOnce() -> O, mut insert: impl FnMut(V), post_init: fn(O) -> Result, ) -> InitResult where E: Send + Sync + 'static, { use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; use InitResult::{InitErr, ReadExisting}; const MAX_RETRIES: usize = 200; let mut retries = 0; let (w_key, w_hash) = self.waiter_key_hash(key, type_id); let waiter = MiniArc::new(RwLock::new(WaiterValue::Computing)); let mut lock = waiter.write(); loop { let Some(existing_waiter) = self.try_insert_waiter(w_key.clone(), w_hash, &waiter) else { // Inserted. break; }; // Somebody else's waiter already exists, so wait for its result to become available. let waiter_result = existing_waiter.read(); match &*waiter_result { WaiterValue::Ready(Ok(value)) => return ReadExisting(value.clone()), WaiterValue::Ready(Err(e)) => return InitErr(Arc::clone(e).downcast().unwrap()), // Somebody else's init closure has been panicked. WaiterValue::InitClosurePanicked => { retries += 1; assert!( retries < MAX_RETRIES, "Too many retries. Tried to read the return value from the `init` \ closure but failed {retries} times. Maybe the `init` kept panicking?" ); // Retry from the beginning. continue; } // Unexpected state. s @ (WaiterValue::Computing | WaiterValue::ReadyNone) => panic!( "Got unexpected state `{s:?}` after resolving `init` future. \ This might be a bug in Moka" ), } } ``` -------------------------------- ### Conditional get or insert with closure in Rust Source: https://docs.rs/moka/latest/src/moka/sync/segment Retrieves a value from cache or conditionally inserts based on a replace_if closure. The closure determines whether to replace an existing value. Uses hashing for cache selection. ```rust pub fn get_with_if( &self, key: K, init: impl FnOnce() -> V, replace_if: impl FnMut(&V) -> bool, ) -> V { let hash = self.inner.hash(&key); let key = Arc::new(key); self.inner .select(hash) .get_or_insert_with_hash_and_fun(key, hash, init, Some(replace_if), false) .into_value() } ``` -------------------------------- ### Rust: Get Access Order Queue Node Source: https://docs.rs/moka/latest/src/moka/common/concurrent Retrieves the node associated with the access order queue for this entry, if it exists. This allows for manipulation or inspection of the entry's position in the access recency tracking. ```rust pub(crate) fn access_order_q_node(&self) -> Option> { self.nodes.lock().access_order_q_node } ``` -------------------------------- ### Entry Struct Source: https://docs.rs/moka/latest/moka/struct Documentation for the `Entry` struct, which represents a snapshot of a single entry in the cache. It allows for accessing and manipulating cached data. ```APIDOC ## Struct Entry ### Description A snapshot of a single entry in the cache. `Entry` is constructed from the methods like `or_insert` on the struct returned by cache’s `entry` or `entry_by_ref` methods. `Entry` holds the cached key and value at the time it was constructed. It also carries extra information about the entry; `is_fresh` method returns `true` if the value was not cached and was freshly computed. ### Method Struct Definition ### Endpoint `pub struct Entry { /* private fields */ } ### Parameters None ### Request Example N/A ### Response #### Success Response (N/A) - N/A #### Response Example N/A ## Implementations ### impl Entry #### pub fn key(&self) -> &K Returns a reference to the wrapped key. #### pub fn value(&self) -> &V Returns a reference to the wrapped value. Note that the returned reference is _not_ pointing to the original value in the cache. Instead, it is pointing to the cloned value in this `Entry`. #### pub fn into_value(self) -> V Consumes this `Entry`, returning the wrapped value. Note that the returned value is a clone of the original value in the cache. It was cloned when this `Entry` was constructed. #### pub fn is_fresh(&self) -> bool Returns `true` if the value in this `Entry` was not cached and was freshly computed. #### pub fn is_old_value_replaced(&self) -> bool Returns `true` if an old value existed in the cache and was replaced by the value in this `Entry`. Note that the new value can be the same as the old value. This method still returns `true` in that case. ``` -------------------------------- ### Kani proof for index calculation safety Source: https://docs.rs/moka/latest/src/moka/common/frequency_sketch Formal verification proof ensuring that the index_of method works correctly for any capacity and hash combination. Uses Kani's symbolic execution to test arbitrary inputs. ```rust #[kani::proof] fn verify_index_of() { // Check for arbitrary capacities. let capacity = kani::any(); let mut sketch = FrequencySketch::default(); sketch.ensure_capacity(capacity); ``` -------------------------------- ### Optional get or insert with closure in Rust Source: https://docs.rs/moka/latest/src/moka/sync/segment Retrieves a value from cache or optionally inserts based on closure returning Some(value). Returns None if closure returns None. Ensures thread-safe operation for concurrent calls. ```rust pub fn optionally_get_with(&self, key: K, init: F) -> Option where F: FnOnce() -> Option, { let hash = self.inner.hash(&key); let key = Arc::new(key); self.inner .select(hash) .get_or_optionally_insert_with_hash_and_fun(key, hash, init, false) .map(Entry::into_value) } ``` -------------------------------- ### Utility Functions for Capacity and Parallelism in Rust Source: https://docs.rs/moka/latest/src/moka/common Provides helper functions: sketch_capacity converts max capacity to a u32 sketch size (min 128, max u32::MAX), and available_parallelism detects CPU cores for testing. No external dependencies beyond std; used for cache sizing and concurrency. ```Rust // Ensures the value fits in a range of `128u32..=u32::MAX`. pub(crate) fn sketch_capacity(max_capacity: u64) -> u32 { max_capacity.try_into().unwrap_or(u32::MAX).max(128) } #[cfg(test)] pub(crate) fn available_parallelism() -> usize { use std::{num::NonZeroUsize, thread::available_parallelism}; available_parallelism().map(NonZeroUsize::get).unwrap_or(1) } ```