-
Notifications
You must be signed in to change notification settings - Fork 358
/
Copy pathcache.rs
131 lines (116 loc) · 3.57 KB
/
cache.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
use core::fmt::Formatter;
use std::fmt;
use std::time::Duration;
use moka::sync::Cache as MokaCache;
use ibc::core::ics02_client::client_state::AnyClientState;
use ibc::core::ics02_client::height::Height;
use ibc::core::ics03_connection::connection::ConnectionEnd;
use ibc::core::ics04_channel::channel::ChannelEnd;
use ibc::core::ics24_host::identifier::{ClientId, ConnectionId, PortChannelId};
const CHANNEL_CACHE_TTL: Duration = Duration::from_secs(60);
const CONNECTION_CACHE_TTL: Duration = Duration::from_secs(10 * 60);
const CLIENT_STATE_CACHE_TTL: Duration = Duration::from_millis(500);
const LATEST_HEIGHT_CACHE_TTL: Duration = Duration::from_millis(200);
#[derive(Clone)]
pub struct Cache {
channels: MokaCache<PortChannelId, ChannelEnd>,
connections: MokaCache<ConnectionId, ConnectionEnd>,
client_states: MokaCache<ClientId, AnyClientState>,
latest_height: MokaCache<(), Height>,
}
impl Default for Cache {
fn default() -> Self {
Self::new()
}
}
impl Cache {
pub fn new() -> Cache {
let channels = MokaCache::builder().time_to_live(CHANNEL_CACHE_TTL).build();
let connections = MokaCache::builder()
.time_to_live(CONNECTION_CACHE_TTL)
.build();
let client_states = MokaCache::builder()
.time_to_live(CLIENT_STATE_CACHE_TTL)
.build();
let latest_height = MokaCache::builder()
.time_to_live(LATEST_HEIGHT_CACHE_TTL)
.build();
Cache {
channels,
connections,
client_states,
latest_height,
}
}
pub fn get_or_try_insert_channel_with<F, E>(
&self,
id: &PortChannelId,
f: F,
) -> Result<ChannelEnd, E>
where
F: FnOnce() -> Result<ChannelEnd, E>,
{
if let Some(chan) = self.channels.get(id) {
// If cache hit, return it.
Ok(chan)
} else {
// Only cache a channel end if the channel is open.
let chan = f()?;
if chan.state().is_open() {
self.channels.insert(id.clone(), chan.clone());
}
Ok(chan)
}
}
pub fn get_or_try_insert_connection_with<F, E>(
&self,
id: &ConnectionId,
f: F,
) -> Result<ConnectionEnd, E>
where
F: FnOnce() -> Result<ConnectionEnd, E>,
{
if let Some(conn) = self.connections.get(id) {
Ok(conn)
} else {
let conn = f()?;
if conn.state().is_open() {
self.connections.insert(id.clone(), conn.clone());
}
Ok(conn)
}
}
pub fn get_or_try_insert_client_state_with<F, E>(
&self,
id: &ClientId,
f: F,
) -> Result<AnyClientState, E>
where
F: FnOnce() -> Result<AnyClientState, E>,
{
if let Some(state) = self.client_states.get(id) {
Ok(state)
} else {
let state = f()?;
self.client_states.insert(id.clone(), state.clone());
Ok(state)
}
}
pub fn get_or_try_update_latest_height_with<F, E>(&self, f: F) -> Result<Height, E>
where
F: FnOnce() -> Result<Height, E>,
{
if let Some(height) = self.latest_height.get(&()) {
Ok(height)
} else {
let height = f()?;
self.latest_height.insert((), height);
Ok(height)
}
}
}
impl fmt::Debug for Cache {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Cache").finish_non_exhaustive()
}
}