1
1
use {
2
+ super :: State ,
2
3
crate :: aggregate:: {
3
4
wormhole_merkle:: WormholeMerkleState ,
4
5
AccumulatorMessages ,
@@ -96,79 +97,42 @@ pub enum MessageStateFilter {
96
97
Only ( MessageType ) ,
97
98
}
98
99
99
- pub struct Cache {
100
- /// Accumulator messages cache
101
- ///
102
- /// We do not write to this cache much, so we can use a simple RwLock instead of a DashMap.
103
- accumulator_messages_cache : Arc < RwLock < BTreeMap < Slot , AccumulatorMessages > > > ,
104
-
105
- /// Wormhole merkle state cache
106
- ///
107
- /// We do not write to this cache much, so we can use a simple RwLock instead of a DashMap.
108
- wormhole_merkle_state_cache : Arc < RwLock < BTreeMap < Slot , WormholeMerkleState > > > ,
100
+ /// A Cache of AccumulatorMessage by slot. We do not write to this cache much, so we can use a simple RwLock instead of a DashMap.
101
+ type AccumulatorMessagesCache = Arc < RwLock < BTreeMap < Slot , AccumulatorMessages > > > ;
109
102
110
- message_cache : Arc < RwLock < HashMap < MessageStateKey , BTreeMap < MessageStateTime , MessageState > > > > ,
111
- cache_size : u64 ,
112
- }
113
-
114
- async fn retrieve_message_state (
115
- cache : & Cache ,
116
- key : MessageStateKey ,
117
- request_time : RequestTime ,
118
- ) -> Option < MessageState > {
119
- match cache. message_cache . read ( ) . await . get ( & key) {
120
- Some ( key_cache) => {
121
- match request_time {
122
- RequestTime :: Latest => key_cache. last_key_value ( ) . map ( |( _, v) | v) . cloned ( ) ,
123
- RequestTime :: FirstAfter ( time) => {
124
- // If the requested time is before the first element in the vector, we are
125
- // not sure that the first element is the closest one.
126
- if let Some ( ( _, oldest_record_value) ) = key_cache. first_key_value ( ) {
127
- if time < oldest_record_value. time ( ) . publish_time {
128
- return None ;
129
- }
130
- }
103
+ /// A Cache of WormholeMerkleState by slot. We do not write to this cache much, so we can use a simple RwLock instead of a DashMap.
104
+ type WormholeMerkleStateCache = Arc < RwLock < BTreeMap < Slot , WormholeMerkleState > > > ;
131
105
132
- let lookup_time = MessageStateTime {
133
- publish_time : time,
134
- slot : 0 ,
135
- } ;
106
+ /// A Cache of `Time<->MessageState` by feed id.
107
+ type MessageCache = Arc < RwLock < HashMap < MessageStateKey , BTreeMap < MessageStateTime , MessageState > > > > ;
136
108
137
- // Get the first element that is greater than or equal to the lookup time.
138
- key_cache
139
- . lower_bound ( Bound :: Included ( & lookup_time) )
140
- . peek_next ( )
141
- . map ( |( _, v) | v)
142
- . cloned ( )
143
- }
144
- RequestTime :: AtSlot ( slot) => {
145
- // Get the state with slot equal to the lookup slot.
146
- key_cache
147
- . iter ( )
148
- . rev ( ) // Usually the slot lies at the end of the map
149
- . find ( |( k, _) | k. slot == slot)
150
- . map ( |( _, v) | v)
151
- . cloned ( )
152
- }
153
- }
154
- }
155
- None => None ,
156
- }
109
+ /// A collection of caches for various program state.
110
+ pub struct CacheState {
111
+ accumulator_messages_cache : AccumulatorMessagesCache ,
112
+ wormhole_merkle_state_cache : WormholeMerkleStateCache ,
113
+ message_cache : MessageCache ,
114
+ cache_size : u64 ,
157
115
}
158
116
159
- impl Cache {
160
- pub fn new ( cache_size : u64 ) -> Self {
117
+ impl CacheState {
118
+ pub fn new ( size : u64 ) -> Self {
161
119
Self {
162
- message_cache : Arc :: new ( RwLock :: new ( HashMap :: new ( ) ) ) ,
163
- accumulator_messages_cache : Arc :: new ( RwLock :: new ( BTreeMap :: new ( ) ) ) ,
120
+ accumulator_messages_cache : Arc :: new ( RwLock :: new ( BTreeMap :: new ( ) ) ) ,
164
121
wormhole_merkle_state_cache : Arc :: new ( RwLock :: new ( BTreeMap :: new ( ) ) ) ,
165
- cache_size,
122
+ message_cache : Arc :: new ( RwLock :: new ( HashMap :: new ( ) ) ) ,
123
+ cache_size : size,
166
124
}
167
125
}
168
126
}
169
127
170
- #[ async_trait:: async_trait]
171
- pub trait AggregateCache {
128
+ /// Allow downcasting State into CacheState for functions that depend on the `Cache` service.
129
+ impl < ' a > From < & ' a State > for & ' a CacheState {
130
+ fn from ( state : & ' a State ) -> & ' a CacheState {
131
+ & state. cache
132
+ }
133
+ }
134
+
135
+ pub trait Cache {
172
136
async fn message_state_keys ( & self ) -> Vec < MessageStateKey > ;
173
137
async fn store_message_states ( & self , message_states : Vec < MessageState > ) -> Result < ( ) > ;
174
138
async fn prune_removed_keys ( & self , current_keys : HashSet < MessageStateKey > ) ;
@@ -190,10 +154,13 @@ pub trait AggregateCache {
190
154
async fn fetch_wormhole_merkle_state ( & self , slot : Slot ) -> Result < Option < WormholeMerkleState > > ;
191
155
}
192
156
193
- #[ async_trait:: async_trait]
194
- impl AggregateCache for crate :: state:: State {
157
+ impl < T > Cache for T
158
+ where
159
+ for < ' a > & ' a T : Into < & ' a CacheState > ,
160
+ T : Sync ,
161
+ {
195
162
async fn message_state_keys ( & self ) -> Vec < MessageStateKey > {
196
- self . cache
163
+ self . into ( )
197
164
. message_cache
198
165
. read ( )
199
166
. await
@@ -203,7 +170,7 @@ impl AggregateCache for crate::state::State {
203
170
}
204
171
205
172
async fn store_message_states ( & self , message_states : Vec < MessageState > ) -> Result < ( ) > {
206
- let mut message_cache = self . cache . message_cache . write ( ) . await ;
173
+ let mut message_cache = self . into ( ) . message_cache . write ( ) . await ;
207
174
208
175
for message_state in message_states {
209
176
let key = message_state. key ( ) ;
@@ -212,7 +179,7 @@ impl AggregateCache for crate::state::State {
212
179
cache. insert ( time, message_state) ;
213
180
214
181
// Remove the earliest message states if the cache size is exceeded
215
- while cache. len ( ) > self . cache . cache_size as usize {
182
+ while cache. len ( ) > self . into ( ) . cache_size as usize {
216
183
cache. pop_first ( ) ;
217
184
}
218
185
}
@@ -227,7 +194,7 @@ impl AggregateCache for crate::state::State {
227
194
/// lose the cache for that key and cannot retrieve it for historical
228
195
/// price queries.
229
196
async fn prune_removed_keys ( & self , current_keys : HashSet < MessageStateKey > ) {
230
- let mut message_cache = self . cache . message_cache . write ( ) . await ;
197
+ let mut message_cache = self . into ( ) . message_cache . write ( ) . await ;
231
198
232
199
// Sometimes, some keys are removed from the accumulator. We track which keys are not
233
200
// present in the message states and remove them from the cache.
@@ -262,7 +229,7 @@ impl AggregateCache for crate::state::State {
262
229
feed_id : id,
263
230
type_ : message_type,
264
231
} ;
265
- retrieve_message_state ( & self . cache , key, request_time. clone ( ) )
232
+ retrieve_message_state ( self . into ( ) , key, request_time. clone ( ) )
266
233
} )
267
234
} ) )
268
235
. await
@@ -275,60 +242,95 @@ impl AggregateCache for crate::state::State {
275
242
& self ,
276
243
accumulator_messages : AccumulatorMessages ,
277
244
) -> Result < ( ) > {
278
- let mut cache = self . cache . accumulator_messages_cache . write ( ) . await ;
245
+ let mut cache = self . into ( ) . accumulator_messages_cache . write ( ) . await ;
279
246
cache. insert ( accumulator_messages. slot , accumulator_messages) ;
280
- while cache. len ( ) > self . cache . cache_size as usize {
247
+ while cache. len ( ) > self . into ( ) . cache_size as usize {
281
248
cache. pop_first ( ) ;
282
249
}
283
250
Ok ( ( ) )
284
251
}
285
252
286
253
async fn fetch_accumulator_messages ( & self , slot : Slot ) -> Result < Option < AccumulatorMessages > > {
287
- let cache = self . cache . accumulator_messages_cache . read ( ) . await ;
254
+ let cache = self . into ( ) . accumulator_messages_cache . read ( ) . await ;
288
255
Ok ( cache. get ( & slot) . cloned ( ) )
289
256
}
290
257
291
258
async fn store_wormhole_merkle_state (
292
259
& self ,
293
260
wormhole_merkle_state : WormholeMerkleState ,
294
261
) -> Result < ( ) > {
295
- let mut cache = self . cache . wormhole_merkle_state_cache . write ( ) . await ;
262
+ let mut cache = self . into ( ) . wormhole_merkle_state_cache . write ( ) . await ;
296
263
cache. insert ( wormhole_merkle_state. root . slot , wormhole_merkle_state) ;
297
- while cache. len ( ) > self . cache . cache_size as usize {
264
+ while cache. len ( ) > self . into ( ) . cache_size as usize {
298
265
cache. pop_first ( ) ;
299
266
}
300
267
Ok ( ( ) )
301
268
}
302
269
303
270
async fn fetch_wormhole_merkle_state ( & self , slot : Slot ) -> Result < Option < WormholeMerkleState > > {
304
- let cache = self . cache . wormhole_merkle_state_cache . read ( ) . await ;
271
+ let cache = self . into ( ) . wormhole_merkle_state_cache . read ( ) . await ;
305
272
Ok ( cache. get ( & slot) . cloned ( ) )
306
273
}
307
274
}
308
275
276
+ async fn retrieve_message_state (
277
+ cache : & CacheState ,
278
+ key : MessageStateKey ,
279
+ request_time : RequestTime ,
280
+ ) -> Option < MessageState > {
281
+ match cache. message_cache . read ( ) . await . get ( & key) {
282
+ Some ( key_cache) => {
283
+ match request_time {
284
+ RequestTime :: Latest => key_cache. last_key_value ( ) . map ( |( _, v) | v) . cloned ( ) ,
285
+ RequestTime :: FirstAfter ( time) => {
286
+ // If the requested time is before the first element in the vector, we are
287
+ // not sure that the first element is the closest one.
288
+ if let Some ( ( _, oldest_record_value) ) = key_cache. first_key_value ( ) {
289
+ if time < oldest_record_value. time ( ) . publish_time {
290
+ return None ;
291
+ }
292
+ }
293
+
294
+ let lookup_time = MessageStateTime {
295
+ publish_time : time,
296
+ slot : 0 ,
297
+ } ;
298
+
299
+ // Get the first element that is greater than or equal to the lookup time.
300
+ key_cache
301
+ . lower_bound ( Bound :: Included ( & lookup_time) )
302
+ . peek_next ( )
303
+ . map ( |( _, v) | v)
304
+ . cloned ( )
305
+ }
306
+ RequestTime :: AtSlot ( slot) => {
307
+ // Get the state with slot equal to the lookup slot.
308
+ key_cache
309
+ . iter ( )
310
+ . rev ( ) // Usually the slot lies at the end of the map
311
+ . find ( |( k, _) | k. slot == slot)
312
+ . map ( |( _, v) | v)
313
+ . cloned ( )
314
+ }
315
+ }
316
+ }
317
+ None => None ,
318
+ }
319
+ }
320
+
309
321
#[ cfg( test) ]
310
322
mod test {
311
323
use {
312
324
super :: * ,
313
325
crate :: {
314
- aggregate:: {
315
- wormhole_merkle:: {
316
- WormholeMerkleMessageProof ,
317
- WormholeMerkleState ,
318
- } ,
319
- AccumulatorMessages ,
320
- ProofSet ,
321
- } ,
326
+ aggregate:: wormhole_merkle:: WormholeMerkleMessageProof ,
322
327
state:: test:: setup_state,
323
328
} ,
324
329
pyth_sdk:: UnixTimestamp ,
325
330
pythnet_sdk:: {
326
331
accumulators:: merkle:: MerklePath ,
327
332
hashers:: keccak256_160:: Keccak160 ,
328
- messages:: {
329
- Message ,
330
- PriceFeedMessage ,
331
- } ,
333
+ messages:: PriceFeedMessage ,
332
334
wire:: v1:: WormholeMerkleRoot ,
333
335
} ,
334
336
} ;
@@ -369,7 +371,7 @@ mod test {
369
371
slot : Slot ,
370
372
) -> MessageState
371
373
where
372
- S : AggregateCache ,
374
+ S : Cache ,
373
375
{
374
376
let message_state = create_dummy_price_feed_message_state ( feed_id, publish_time, slot) ;
375
377
state
0 commit comments