11use async_trait:: async_trait;
2- use mithril_common:: entities:: { Epoch , StakeDistribution } ;
3- use mithril_common:: signable_builder:: StakeDistributionRetriever ;
4- use mithril_common:: StdResult ;
5- use tokio:: sync:: RwLock ;
6-
7- use super :: { adapter:: StoreAdapter , StorePruner } ;
8-
9- type Adapter = Box < dyn StoreAdapter < Key = Epoch , Record = StakeDistribution > > ;
2+ use mithril_common:: {
3+ entities:: { Epoch , StakeDistribution } ,
4+ StdResult ,
5+ } ;
106
117/// Represent a way to store the stake of mithril party members.
128#[ async_trait]
@@ -21,184 +17,3 @@ pub trait StakeStorer: Sync + Send {
2117 /// Get the stakes of all party at a given `epoch`.
2218 async fn get_stakes ( & self , epoch : Epoch ) -> StdResult < Option < StakeDistribution > > ;
2319}
24-
25- /// A [StakeStorer] that use a [StoreAdapter] to store data.
26- pub struct StakeStore {
27- adapter : RwLock < Adapter > ,
28- retention_limit : Option < usize > ,
29- }
30-
31- impl StakeStore {
32- /// StakeStore factory
33- pub fn new ( adapter : Adapter , retention_limit : Option < usize > ) -> Self {
34- Self {
35- adapter : RwLock :: new ( adapter) ,
36- retention_limit,
37- }
38- }
39- }
40-
41- #[ async_trait]
42- impl StorePruner for StakeStore {
43- type Key = Epoch ;
44- type Record = StakeDistribution ;
45-
46- fn get_adapter (
47- & self ,
48- ) -> & RwLock < Box < dyn StoreAdapter < Key = Self :: Key , Record = Self :: Record > > > {
49- & self . adapter
50- }
51-
52- fn get_max_records ( & self ) -> Option < usize > {
53- self . retention_limit
54- }
55- }
56-
57- #[ async_trait]
58- impl StakeStorer for StakeStore {
59- async fn save_stakes (
60- & self ,
61- epoch : Epoch ,
62- stakes : StakeDistribution ,
63- ) -> StdResult < Option < StakeDistribution > > {
64- let signers = {
65- let mut adapter = self . adapter . write ( ) . await ;
66- let signers = adapter. get_record ( & epoch) . await ?;
67- adapter. store_record ( & epoch, & stakes) . await ?;
68-
69- signers
70- } ;
71- // it is important the adapter gets out of the scope to free the write lock it holds.
72- // Otherwise the method below will hang forever waiting for the lock.
73- self . prune ( ) . await ?;
74-
75- Ok ( signers)
76- }
77-
78- async fn get_stakes ( & self , epoch : Epoch ) -> StdResult < Option < StakeDistribution > > {
79- Ok ( self . adapter . read ( ) . await . get_record ( & epoch) . await ?)
80- }
81- }
82-
83- #[ async_trait]
84- impl StakeDistributionRetriever for StakeStore {
85- async fn retrieve ( & self , epoch : Epoch ) -> StdResult < Option < StakeDistribution > > {
86- let stake_distribution = self . get_stakes ( epoch) . await ?;
87-
88- Ok ( stake_distribution)
89- }
90- }
91-
92- #[ cfg( test) ]
93- mod tests {
94- use super :: super :: adapter:: MemoryAdapter ;
95- use super :: * ;
96-
97- fn init_store (
98- nb_epoch : u64 ,
99- signers_per_epoch : u64 ,
100- retention_limit : Option < usize > ,
101- ) -> StakeStore {
102- let mut values: Vec < ( Epoch , StakeDistribution ) > = Vec :: new ( ) ;
103-
104- for epoch in 1 ..=nb_epoch {
105- let mut signers: StakeDistribution = StakeDistribution :: new ( ) ;
106-
107- for party_idx in 1 ..=signers_per_epoch {
108- let party_id = format ! ( "{party_idx}" ) ;
109- signers. insert ( party_id. clone ( ) , 100 * party_idx + 1 ) ;
110- }
111- values. push ( ( Epoch ( epoch) , signers) ) ;
112- }
113-
114- let values = if !values. is_empty ( ) {
115- Some ( values)
116- } else {
117- None
118- } ;
119- let adapter: MemoryAdapter < Epoch , StakeDistribution > = MemoryAdapter :: new ( values) . unwrap ( ) ;
120- StakeStore :: new ( Box :: new ( adapter) , retention_limit)
121- }
122-
123- #[ tokio:: test]
124- async fn save_key_in_empty_store ( ) {
125- let store = init_store ( 0 , 0 , None ) ;
126- let res = store
127- . save_stakes ( Epoch ( 1 ) , StakeDistribution :: from ( [ ( "1" . to_string ( ) , 123 ) ] ) )
128- . await
129- . expect ( "Test adapter should not fail." ) ;
130-
131- assert ! ( res. is_none( ) ) ;
132- }
133-
134- #[ tokio:: test]
135- async fn update_signer_in_store ( ) {
136- let store = init_store ( 1 , 1 , None ) ;
137- let res = store
138- . save_stakes ( Epoch ( 1 ) , StakeDistribution :: from ( [ ( "1" . to_string ( ) , 123 ) ] ) )
139- . await
140- . expect ( "Test adapter should not fail." ) ;
141-
142- assert_eq ! (
143- StakeDistribution :: from( [ ( "1" . to_string( ) , 101 ) ] ) ,
144- res. expect( "the result should not be empty" ) ,
145- ) ;
146- }
147-
148- #[ tokio:: test]
149- async fn get_stakes_for_empty_epoch ( ) {
150- let store = init_store ( 2 , 1 , None ) ;
151- let res = store
152- . get_stakes ( Epoch ( 0 ) )
153- . await
154- . expect ( "Test adapter should not fail." ) ;
155-
156- assert ! ( res. is_none( ) ) ;
157- }
158-
159- #[ tokio:: test]
160- async fn get_stakes_for_existing_epoch ( ) {
161- let store = init_store ( 2 , 2 , None ) ;
162- let res = store
163- . get_stakes ( Epoch ( 1 ) )
164- . await
165- . expect ( "Test adapter should not fail." ) ;
166-
167- assert ! ( res. is_some( ) ) ;
168- assert_eq ! ( 2 , res. expect( "Query result should not be empty." ) . len( ) ) ;
169- }
170-
171- #[ tokio:: test]
172- async fn check_retention_limit ( ) {
173- let store = init_store ( 2 , 2 , Some ( 2 ) ) ;
174- let _res = store
175- . save_stakes ( Epoch ( 3 ) , StakeDistribution :: from ( [ ( "1" . to_string ( ) , 123 ) ] ) )
176- . await
177- . unwrap ( ) ;
178- assert ! ( store. get_stakes( Epoch ( 1 ) ) . await . unwrap( ) . is_none( ) ) ;
179- }
180-
181- #[ tokio:: test]
182- async fn retrieve_with_no_stakes_returns_none ( ) {
183- let store = init_store ( 0 , 0 , None ) ;
184-
185- let result = store. retrieve ( Epoch ( 1 ) ) . await . unwrap ( ) ;
186-
187- assert ! ( result. is_none( ) ) ;
188- }
189-
190- #[ tokio:: test]
191- async fn retrieve_returns_stake_distribution ( ) {
192- let stake_distribution_to_retrieve =
193- StakeDistribution :: from ( [ ( "pool-123" . to_string ( ) , 123 ) ] ) ;
194- let store = init_store ( 0 , 0 , None ) ;
195- store
196- . save_stakes ( Epoch ( 1 ) , stake_distribution_to_retrieve. clone ( ) )
197- . await
198- . unwrap ( ) ;
199-
200- let stake_distribution = store. retrieve ( Epoch ( 1 ) ) . await . unwrap ( ) ;
201-
202- assert_eq ! ( stake_distribution, Some ( stake_distribution_to_retrieve) ) ;
203- }
204- }
0 commit comments