Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for eviction listener #145

Merged
merged 38 commits into from
Jul 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
3f28855
Support notification on eviction
tatsuya6502 May 30, 2022
aecfef1
Support notification on eviction
tatsuya6502 May 30, 2022
b4e0171
Fix a Clippy warning
tatsuya6502 May 31, 2022
1727b78
Support notification on eviction
tatsuya6502 May 31, 2022
31d6874
Support notification on eviction
tatsuya6502 May 31, 2022
14ba86a
Support notification on eviction
tatsuya6502 May 31, 2022
7fa072b
Support notification on eviction
tatsuya6502 May 31, 2022
fa991fa
Support notification on eviction
tatsuya6502 May 31, 2022
ea67182
Support notification on eviction
tatsuya6502 Jun 1, 2022
5b3aa78
Support notification on eviction
tatsuya6502 Jun 1, 2022
d8567c9
Support notification on eviction
tatsuya6502 Jun 12, 2022
8adca0f
Support notification on eviction
tatsuya6502 Jun 12, 2022
b39d669
Support notification on eviction
tatsuya6502 Jun 13, 2022
59ca134
Raise the minimal version of Triomphe crate from v0.1 to v0.1.3
tatsuya6502 Jun 14, 2022
090844e
Support notification on eviction
tatsuya6502 Jun 14, 2022
5e3a3cd
Merge branch 'next' into eviction-listener
tatsuya6502 Jun 18, 2022
1462700
Support notification on eviction
tatsuya6502 Jun 20, 2022
fac2a00
Support notification on eviction
tatsuya6502 Jun 20, 2022
e8f75ac
Support notification on eviction
tatsuya6502 Jun 21, 2022
6cf464a
Support notification on eviction
tatsuya6502 Jun 21, 2022
9b65faa
Support notification on eviction
tatsuya6502 Jun 21, 2022
b49f5e9
Support notification on eviction
tatsuya6502 Jun 26, 2022
81d36ff
Bump the version to v0.9.0
tatsuya6502 Jun 26, 2022
8ec7c2b
Support notification on eviction
tatsuya6502 Jun 26, 2022
a6fbf2a
Support notification on eviction
tatsuya6502 Jun 26, 2022
3b40d96
Support notification on eviction
tatsuya6502 Jun 28, 2022
f02d9c6
Merge branch 'next' into eviction-listener
tatsuya6502 Jun 28, 2022
e49f0fe
Merge branch 'next' into eviction-listener
tatsuya6502 Jul 2, 2022
b97f622
Support notification on eviction
tatsuya6502 Jul 2, 2022
cf758d5
Fix Clippy warning
tatsuya6502 Jul 2, 2022
b206dbc
Support notification on eviction
tatsuya6502 Jul 3, 2022
e207c38
Support notification on eviction
tatsuya6502 Jul 3, 2022
5e0b978
Support notification on eviction
tatsuya6502 Jul 4, 2022
6a5b974
Support notification on eviction
tatsuya6502 Jul 4, 2022
823f7e3
Support notification on eviction
tatsuya6502 Jul 4, 2022
fc8d7ee
Support notification on eviction
tatsuya6502 Jul 4, 2022
2aff444
Support notification on eviction
tatsuya6502 Jul 4, 2022
317b0ab
Support notification on eviction
tatsuya6502 Jul 4, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"rust-analyzer.cargo.features": ["future", "dash", "unstable-debug-counters"],
"rust-analyzer.cargo.features": ["future", "dash", "logging", "unstable-debug-counters"],
"rust-analyzer.server.extraEnv": {
"CARGO_TARGET_DIR": "target/ra"
},
"editor.rulers": [85],
"cSpell.words": [
"aarch",
"actix",
Expand Down
8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "moka"
version = "0.8.6"
version = "0.9.0"
edition = "2018"
rust-version = "1.51"

Expand Down Expand Up @@ -58,7 +58,7 @@ tagptr = "0.2"

# Opt-out serde and stable_deref_trait features
# https://github.com/Manishearth/triomphe/pull/5
triomphe = { version = "0.1", default-features = false }
triomphe = { version = "0.1.3", default-features = false }

# Optional dependencies (enabled by default)
quanta = { version = "0.10.0", optional = true }
Expand All @@ -83,11 +83,13 @@ log = { version = "0.4", optional = true }

[dev-dependencies]
actix-rt = { version = "2.7", default-features = false }
anyhow = "1.0"
async-std = { version = "1.11", features = ["attributes"] }
env_logger = "0.9"
getrandom = "0.2"
reqwest = "0.11.11"
skeptic = "0.13"
tokio = { version = "1.19", features = ["rt-multi-thread", "macros", "sync", "time" ] }
tokio = { version = "1.19", features = ["fs", "macros", "rt-multi-thread", "sync", "time" ] }

[target.'cfg(trybuild)'.dev-dependencies]
trybuild = "1.0"
Expand Down
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ algorithm to determine which entries to evict when the capacity is exceeded.
- Supports expiration policies:
- Time to live
- Time to idle
- Supports eviction listener, a callback function that will be called when an entry
is removed from the cache.


[tiny-lfu]: https://github.com/moka-rs/moka/wiki#admission-and-eviction-policies

Expand Down Expand Up @@ -528,20 +531,23 @@ $ cargo +nightly -Z unstable-options --config 'build.rustdocflags="--cfg docsrs"
## Road Map

- [x] `async` optimized caches. (`v0.2.0`)
- [x] Size-aware eviction. (`v0.7.0` via
[#24](https://github.com/moka-rs/moka/pull/24))
- [X] API stabilization. (Smaller core cache API, shorter names for frequently
used methods) (`v0.8.0` via [#105](https://github.com/moka-rs/moka/pull/105))
- [x] Size-aware eviction. (`v0.7.0` via [#24][gh-pull-024])
- [x] API stabilization. (Smaller core cache API, shorter names for frequently
used methods) (`v0.8.0` via [#105][gh-pull-105])
- e.g.
- `get_or_insert_with(K, F)` → `get_with(K, F)`
- `get_or_try_insert_with(K, F)` → `try_get_with(K, F)`
- `blocking_insert(K, V)` → `blocking().insert(K, V)`
- `time_to_live()` → `policy().time_to_live()`
- [ ] Notifications on eviction, etc.
- [x] Notifications on eviction. (`v0.9.0` via [#145][gh-pull-145])
- [ ] Cache statistics. (Hit rate, etc.)
- [ ] Upgrade TinyLFU to Window-TinyLFU. ([details][tiny-lfu])
- [ ] The variable (per-entry) expiration, using a hierarchical timer wheel.

[gh-pull-024]: https://github.com/moka-rs/moka/pull/24
[gh-pull-105]: https://github.com/moka-rs/moka/pull/105
[gh-pull-145]: https://github.com/moka-rs/moka/pull/145


## About the Name

Expand Down
8 changes: 4 additions & 4 deletions src/cht/segment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ impl<K, V, S> HashMap<K, V, S> {
}
}

pub(crate) fn actual_num_segments(&self) -> usize {
self.segments.len()
}

/// Returns the number of elements in the map.
///
/// # Safety
Expand Down Expand Up @@ -560,10 +564,6 @@ impl<K: Hash + Eq, V, S: BuildHasher> HashMap<K, V, S> {
{
bucket::hash(&self.build_hasher, key)
}

pub(crate) fn actual_num_segments(&self) -> usize {
self.segments.len()
}
}

impl<K, V, S> Drop for HashMap<K, V, S> {
Expand Down
4 changes: 4 additions & 0 deletions src/common/concurrent/thread_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub(crate) enum PoolName {
Housekeeper,
#[cfg(any(feature = "sync", feature = "future"))]
Invalidator,
#[cfg(any(feature = "sync", feature = "future"))]
RemovalNotifier,
}

impl PoolName {
Expand All @@ -19,6 +21,8 @@ impl PoolName {
PoolName::Housekeeper => "moka-housekeeper-{}",
#[cfg(any(feature = "sync", feature = "future"))]
PoolName::Invalidator => "moka-invalidator-{}",
#[cfg(any(feature = "sync", feature = "future"))]
PoolName::RemovalNotifier => "moka-notifier-{}",
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/common/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// The error type for the functionalities around
/// [`Cache#invalidate_entries_if`][invalidate-if] method.
/// [`Cache::invalidate_entries_if`][invalidate-if] method.
///
/// [invalidate-if]: ./sync/struct.Cache.html#method.invalidate_entries_if
#[derive(thiserror::Error, Debug)]
Expand Down
2 changes: 1 addition & 1 deletion src/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub use {
};

/// The type of the unique ID to identify a predicate used by
/// [`Cache#invalidate_entries_if`][invalidate-if] method.
/// [`Cache::invalidate_entries_if`][invalidate-if] method.
///
/// A `PredicateId` is a `String` of UUID (version 4).
///
Expand Down
59 changes: 56 additions & 3 deletions src/future/builder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use super::Cache;
use crate::common::{builder_utils, concurrent::Weigher};
use crate::{
common::{builder_utils, concurrent::Weigher},
notification::{self, DeliveryMode, EvictionListener, RemovalCause},
};

use std::{
collections::hash_map::RandomState,
Expand All @@ -13,7 +16,7 @@ use std::{
///
/// [cache-struct]: ./struct.Cache.html
///
/// # Examples
/// # Example: Expirations
///
/// ```rust
/// // Cargo.toml
Expand Down Expand Up @@ -51,9 +54,12 @@ use std::{
///
#[must_use]
pub struct CacheBuilder<K, V, C> {
name: Option<String>,
max_capacity: Option<u64>,
initial_capacity: Option<usize>,
weigher: Option<Weigher<K, V>>,
eviction_listener: Option<EvictionListener<K, V>>,
eviction_listener_conf: Option<notification::Configuration>,
time_to_live: Option<Duration>,
time_to_idle: Option<Duration>,
invalidator_enabled: bool,
Expand All @@ -67,9 +73,12 @@ where
{
fn default() -> Self {
Self {
name: None,
max_capacity: None,
initial_capacity: None,
weigher: None,
eviction_listener: None,
eviction_listener_conf: None,
time_to_live: None,
time_to_idle: None,
invalidator_enabled: false,
Expand Down Expand Up @@ -103,10 +112,13 @@ where
let build_hasher = RandomState::default();
builder_utils::ensure_expirations_or_panic(self.time_to_live, self.time_to_idle);
Cache::with_everything(
self.name,
self.max_capacity,
self.initial_capacity,
build_hasher,
self.weigher,
self.eviction_listener,
self.eviction_listener_conf,
self.time_to_live,
self.time_to_idle,
self.invalidator_enabled,
Expand All @@ -126,10 +138,13 @@ where
{
builder_utils::ensure_expirations_or_panic(self.time_to_live, self.time_to_idle);
Cache::with_everything(
self.name,
self.max_capacity,
self.initial_capacity,
hasher,
self.weigher,
self.eviction_listener,
self.eviction_listener_conf,
self.time_to_live,
self.time_to_idle,
self.invalidator_enabled,
Expand All @@ -138,6 +153,15 @@ where
}

impl<K, V, C> CacheBuilder<K, V, C> {
/// Sets the name of the cache. Currently the name is used for identification
/// only in logging messages.
pub fn name(self, name: &str) -> Self {
Self {
name: Some(name.to_string()),
..self
}
}

/// Sets the max capacity of the cache.
pub fn max_capacity(self, max_capacity: u64) -> Self {
Self {
Expand All @@ -154,7 +178,7 @@ impl<K, V, C> CacheBuilder<K, V, C> {
}
}

/// Sets the weigher closure of the cache.
/// Sets the weigher closure to the cache.
///
/// The closure should take `&K` and `&V` as the arguments and returns a `u32`
/// representing the relative size of the entry.
Expand All @@ -165,6 +189,35 @@ impl<K, V, C> CacheBuilder<K, V, C> {
}
}

/// Sets the eviction listener closure to the cache.
///
/// The closure should take `Arc<K>`, `V` and [`RemovalCause`][removal-cause] as
/// the arguments. The [queued delivery mode][queued-mode] is used for the
/// listener.
///
/// # Panics
///
/// It is very important to make the listener closure not to panic. Otherwise,
/// the cache will stop calling the listener after a panic. This is an intended
/// behavior because the cache cannot know whether is is memory safe or not to
/// call the panicked lister again.
///
/// [removal-cause]: ../notification/enum.RemovalCause.html
/// [queued-mode]: ../notification/enum.DeliveryMode.html#variant.Queued
pub fn eviction_listener_with_queued_delivery_mode(
self,
listener: impl Fn(Arc<K>, V, RemovalCause) + Send + Sync + 'static,
) -> Self {
let conf = notification::Configuration::builder()
.delivery_mode(DeliveryMode::Queued)
.build();
Self {
eviction_listener: Some(Arc::new(listener)),
eviction_listener_conf: Some(conf),
..self
}
}

/// Sets the time to live of the cache.
///
/// A cached entry will be expired after the specified duration past from
Expand Down
Loading