hopr_db_sql/
cache.rs

1use moka::future::Cache;
2use moka::Expiry;
3use std::sync::atomic::AtomicU64;
4use std::sync::Arc;
5use std::time::Duration;
6
7use hopr_crypto_types::prelude::*;
8use hopr_db_api::info::{IndexerData, SafeInfo};
9use hopr_internal_types::prelude::*;
10use hopr_primitive_types::prelude::{Address, Balance, U256};
11
12use crate::errors::DbSqlError;
13
14/// Enumerates all singular data that can be cached and
15/// cannot be represented by a key. These values can be cached for long term.
16#[derive(Debug, Clone, PartialEq, strum::EnumDiscriminants)]
17#[strum_discriminants(derive(Hash))]
18pub enum CachedValue {
19    /// Cached [IndexerData].
20    IndexerDataCache(IndexerData),
21    /// Cached [SafeInfo].
22    SafeInfoCache(Option<SafeInfo>),
23}
24
25impl TryFrom<CachedValue> for IndexerData {
26    type Error = DbSqlError;
27
28    fn try_from(value: CachedValue) -> Result<Self, Self::Error> {
29        match value {
30            CachedValue::IndexerDataCache(data) => Ok(data),
31            _ => Err(DbSqlError::DecodingError),
32        }
33    }
34}
35
36impl TryFrom<CachedValue> for Option<SafeInfo> {
37    type Error = DbSqlError;
38
39    fn try_from(value: CachedValue) -> Result<Self, Self::Error> {
40        match value {
41            CachedValue::SafeInfoCache(data) => Ok(data),
42            _ => Err(DbSqlError::DecodingError),
43        }
44    }
45}
46
47struct ExpiryNever;
48
49impl<K, V> Expiry<K, V> for ExpiryNever {
50    fn expire_after_create(&self, _key: &K, _value: &V, _current_time: std::time::Instant) -> Option<Duration> {
51        None
52    }
53}
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
56pub(crate) struct ChannelParties(pub(crate) Address, pub(crate) Address);
57
58/// Contains all caches used by the [crate::db::HoprDb].
59#[derive(Debug, Clone)]
60pub struct HoprDbCaches {
61    pub(crate) single_values: Cache<CachedValueDiscriminants, CachedValue>,
62    pub(crate) unacked_tickets: Cache<HalfKeyChallenge, PendingAcknowledgement>,
63    pub(crate) ticket_index: Cache<Hash, Arc<AtomicU64>>,
64    // key is (channel_id, channel_epoch) to ensure calculation of unrealized value does not
65    // include tickets from other epochs
66    pub(crate) unrealized_value: Cache<(Hash, U256), Balance>,
67    pub(crate) chain_to_offchain: Cache<Address, Option<OffchainPublicKey>>,
68    pub(crate) offchain_to_chain: Cache<OffchainPublicKey, Option<Address>>,
69    pub(crate) src_dst_to_channel: Cache<ChannelParties, Option<ChannelEntry>>,
70}
71
72impl Default for HoprDbCaches {
73    fn default() -> Self {
74        let single_values = Cache::builder().time_to_idle(Duration::from_secs(1800)).build();
75
76        let unacked_tickets = Cache::builder()
77            .time_to_live(Duration::from_secs(30))
78            .max_capacity(1_000_000_000)
79            .build();
80
81        let ticket_index = Cache::builder().expire_after(ExpiryNever).max_capacity(10_000).build();
82
83        let unrealized_value = Cache::builder().expire_after(ExpiryNever).max_capacity(10_000).build();
84
85        let chain_to_offchain = Cache::builder()
86            .time_to_live(Duration::from_secs(600))
87            .max_capacity(100_000)
88            .build();
89
90        let offchain_to_chain = Cache::builder()
91            .time_to_live(Duration::from_secs(600))
92            .max_capacity(100_000)
93            .build();
94
95        let src_dst_to_channel = Cache::builder()
96            .time_to_live(Duration::from_secs(600))
97            .max_capacity(10_000)
98            .build();
99
100        Self {
101            single_values,
102            unacked_tickets,
103            ticket_index,
104            unrealized_value,
105            chain_to_offchain,
106            offchain_to_chain,
107            src_dst_to_channel,
108        }
109    }
110}
111
112impl HoprDbCaches {
113    /// Invalidates all caches.
114    pub fn invalidate_all(&self) {
115        self.single_values.invalidate_all();
116        self.unacked_tickets.invalidate_all();
117        self.unrealized_value.invalidate_all();
118        self.chain_to_offchain.invalidate_all();
119        self.offchain_to_chain.invalidate_all();
120        self.src_dst_to_channel.invalidate_all();
121    }
122}