moka/
notification.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//! Common data types for notifications.

pub(crate) mod notifier;

use std::sync::Arc;

pub(crate) type EvictionListener<K, V> =
    Arc<dyn Fn(Arc<K>, V, RemovalCause) + Send + Sync + 'static>;

pub(crate) type EvictionListenerRef<'a, K, V> =
    &'a Arc<dyn Fn(Arc<K>, V, RemovalCause) + Send + Sync + 'static>;

// NOTE: Currently, dropping the cache will drop all entries without sending
// notifications. Calling `invalidate_all` method of the cache will trigger
// the notifications, but currently there is no way to know when all entries
// have been invalidated and their notifications have been sent.

/// Configuration for an eviction listener of a cache.
///
/// Currently only setting the [`DeliveryMode`][delivery-mode] is supported.
///
/// [delivery-mode]: ./enum.DeliveryMode.html
#[derive(Clone, Debug, Default)]
pub struct Configuration {
    mode: DeliveryMode,
}

impl Configuration {
    pub fn builder() -> ConfigurationBuilder {
        ConfigurationBuilder::default()
    }

    pub fn delivery_mode(&self) -> DeliveryMode {
        self.mode
    }
}

/// Builds a [`Configuration`][conf] with some configuration knobs.
///
/// Currently only setting the [`DeliveryMode`][delivery-mode] is supported.
///
/// [conf]: ./struct.Configuration.html
/// [delivery-mode]: ./enum.DeliveryMode.html
#[derive(Default)]
pub struct ConfigurationBuilder {
    mode: DeliveryMode,
}

impl ConfigurationBuilder {
    pub fn build(self) -> Configuration {
        Configuration { mode: self.mode }
    }

    pub fn delivery_mode(self, mode: DeliveryMode) -> Self {
        Self { mode }
    }
}

/// Specifies how and when an eviction notification should be delivered to an
/// eviction listener.
///
/// For more details, see [the document][delivery-mode-doc] of `sync::Cache`.
///
/// [delivery-mode-doc]: ../sync/struct.Cache.html#delivery-modes-for-eviction-listener
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum DeliveryMode {
    /// With this mode, a notification should be delivered to the listener
    /// immediately after an entry was evicted. It also guarantees that eviction
    /// notifications and cache write operations such and `insert`, `get_with` and
    /// `invalidate` for a given cache key are ordered by the time when they
    /// occurred.
    ///
    /// To guarantee the order, cache maintains key-level lock, which will reduce
    /// concurrent write performance.
    ///
    /// Use this mode when the order is more import than the write performance.
    Immediate,
    /// With this mode, a notification will be delivered to the listener some time
    /// after an entry was evicted. Therefore, it does not preserve the order of
    /// eviction notifications and write operations.
    ///
    /// On the other hand, cache does not maintain key-level lock, so there will be
    /// no overhead on write performance.
    ///
    /// Use this mode when write performance is more important than preserving the
    /// order of eviction notifications and write operations.
    Queued,
}

impl Default for DeliveryMode {
    fn default() -> Self {
        Self::Immediate
    }
}

/// Indicates the reason why a cached entry was removed.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RemovalCause {
    /// The entry's expiration timestamp has passed.
    Expired,
    /// The entry was manually removed by the user.
    Explicit,
    /// The entry itself was not actually removed, but its value was replaced by
    /// the user.
    Replaced,
    /// The entry was evicted due to size constraints.
    Size,
}

impl RemovalCause {
    pub fn was_evicted(&self) -> bool {
        matches!(self, Self::Expired | Self::Size)
    }
}

#[cfg(all(test, feature = "sync"))]
pub(crate) mod macros {

    macro_rules! assert_with_mode {
        ($cond:expr, $delivery_mode:ident) => {
            assert!(
                $cond,
                "assertion failed. (delivery mode: {:?})",
                $delivery_mode
            )
        };
    }

    macro_rules! assert_eq_with_mode {
        ($left:expr, $right:expr, $delivery_mode:ident) => {
            assert_eq!($left, $right, "(delivery mode: {:?})", $delivery_mode)
        };
    }

    pub(crate) use {assert_eq_with_mode, assert_with_mode};
}