Skip to content

Cache Not Evicting Entries Despite Exceeding max_capacity with Custom Weigher #543

Description

@shohamazon

Hello 🙂
Fist of all, thank you for this amazing project and the hard work you've put on it, really appreciate it! 🌸

I am new to this project, so I might be using it wrong, but, I have an issue where I'm using Moka with a custom weigher to limit cache size in bytes, but entries are not being evicted even when the cache significantly exceeds max_capacity. The cache continues to grow well beyond the configured limit.

I have read about run_pending_tasks() function, but from what I understood, this is just for immediate eviction, and that the evictions are just lazy (might be wrong about this, feel free to correct me).

I do not wont to use run_pending_tasks() on production if possible.

Here is my code for reproduction:

use redis::Value;

#[tokio::test]
async fn test_eviction() {
    let cache: Cache<Vec<u8>, Value> = Cache::builder()
        .max_capacity(2048)  // 2 KB = 2048 bytes
        .weigher(|key: &Vec<u8>, value: &Value| {
            let size = key.len() + match value {
                Value::BulkString(bytes) => bytes.len(),
                _ => 0,
            };
            println!("Weigher: {}", size);
            size as u32
        })
        .eviction_policy(MokaEvictionPolicy::lru())
        .build();

    // Insert 10 entries of ~1084 bytes each (total ~10.8 KB)
    for i in 1..=10 {
        let key = format!("key{}", i).into_bytes();
        let value = Value::BulkString(vec![b'x'; 1024]);  // 1 KB value
        
        cache.insert(key, value);  
        
        println!("After key{}: entry_count={}, weighted_size={}", 
                 i, cache.entry_count(), cache.weighted_size());
    }
    
    tokio::time::sleep(tokio::time::Duration::from_secs(5)).await; // sleep for % sec (!)
    cache.run_pending_tasks();
    
    println!("\nFinal state:");
    println!("  entry_count: {}", cache.entry_count());
    println!("  weighted_size: {}", cache.weighted_size());
    println!("  max_capacity: 2048 bytes");
    
    // Expected: weighted_size <= 2048 (or slightly above)
    // Actual: weighted_size remains high with no eviction
    
    // Check if key1 was evicted
    let key1_exists = cache.get(&b"key1".to_vec()).is_some();
    println!("  key1 exists: {}", key1_exists); // key1 still exists !
}

As you can see above, I am adding some sleep to see if that would help to see any eviction, but it's not working.
Is there a recommended way to trigger eviction deterministically without calling run_pending_tasks() manually?

I would love to understand what I am doing wrong here.

Thank you so much! 🌸

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions