1
- use chrono:: NaiveDateTime ;
2
- use mithril_common:: entities:: Beacon ;
3
- use mithril_common:: entities:: Epoch ;
4
1
use mithril_common:: StdError ;
5
2
6
- use mithril_common:: sqlite:: Provider ;
7
- use mithril_common:: sqlite:: SourceAlias ;
8
3
use mithril_common:: {
9
- entities:: SignedEntityType ,
4
+ entities:: { Beacon , Epoch , SignedEntityType } ,
10
5
sqlite:: { HydrationError , Projection , SqLiteEntity , WhereCondition } ,
6
+ sqlite:: { Provider , SourceAlias } ,
11
7
} ;
8
+
9
+ use chrono:: NaiveDateTime ;
12
10
use sqlite:: Row ;
13
11
use sqlite:: { Connection , Value } ;
12
+
13
+ use std:: sync:: Arc ;
14
+
15
+ use tokio:: sync:: Mutex ;
14
16
use uuid:: Uuid ;
15
17
16
18
type StdResult < T > = Result < T , StdError > ;
@@ -20,6 +22,7 @@ type StdResult<T> = Result<T, StdError>;
20
22
/// An open message is a message open for signatures. Every signer may send a
21
23
/// single signature for this message from which a multi signature will be
22
24
/// generated if possible.
25
+ #[ allow( dead_code) ]
23
26
pub struct OpenMessage {
24
27
/// OpenMessage unique identifier
25
28
open_message_id : Uuid ,
@@ -53,9 +56,9 @@ impl SqLiteEntity for OpenMessage {
53
56
) )
54
57
} ) ?;
55
58
let message = row. get :: < String , _ > ( 4 ) ;
56
- let epoch_settings_id = row. get :: < i64 , _ > ( 1 ) ;
57
- let epoch_val = u64:: try_from ( epoch_settings_id )
58
- . map_err ( |e| panic ! ( "Integer field open_message.epoch_settings_id (value={epoch_settings_id }) is incompatible with u64 Epoch representation. Error = {e}" ) ) ?;
59
+ let epoch_setting_id = row. get :: < i64 , _ > ( 1 ) ;
60
+ let epoch_val = u64:: try_from ( epoch_setting_id )
61
+ . map_err ( |e| panic ! ( "Integer field open_message.epoch_setting_id (value={epoch_setting_id }) is incompatible with u64 Epoch representation. Error = {e}" ) ) ?;
59
62
60
63
let signed_entity_type_id = usize:: try_from ( row. get :: < i64 , _ > ( 3 ) ) . map_err ( |e| {
61
64
panic ! (
@@ -94,10 +97,14 @@ impl SqLiteEntity for OpenMessage {
94
97
95
98
fn get_projection ( ) -> Projection {
96
99
Projection :: from ( & [
97
- ( "open_message_id" , "{:open_message:}.open_message_id" , "int" ) ,
98
100
(
99
- "epoch_settings_id" ,
100
- "{:open_message:}.epoch_settings_id" ,
101
+ "open_message_id" ,
102
+ "{:open_message:}.open_message_id" ,
103
+ "text" ,
104
+ ) ,
105
+ (
106
+ "epoch_setting_id" ,
107
+ "{:open_message:}.epoch_setting_id" ,
101
108
"int" ,
102
109
) ,
103
110
( "beacon" , "{:open_message:}.beacon" , "text" ) ,
@@ -123,7 +130,7 @@ impl<'client> OpenMessageProvider<'client> {
123
130
124
131
fn get_epoch_condition ( & self , epoch : Epoch ) -> WhereCondition {
125
132
WhereCondition :: new (
126
- "epoch_settings_id = ?*" ,
133
+ "epoch_setting_id = ?*" ,
127
134
vec ! [ Value :: Integer ( epoch. 0 as i64 ) ] ,
128
135
)
129
136
}
@@ -138,6 +145,8 @@ impl<'client> OpenMessageProvider<'client> {
138
145
)
139
146
}
140
147
148
+ // Useful in test and probably in the future.
149
+ #[ allow( dead_code) ]
141
150
fn get_open_message_id_condition ( & self , open_message_id : & str ) -> WhereCondition {
142
151
WhereCondition :: new (
143
152
"open_message_id = ?*" ,
@@ -176,7 +185,7 @@ impl<'client> InsertOpenMessageProvider<'client> {
176
185
signed_entity_type : & SignedEntityType ,
177
186
message : & str ,
178
187
) -> StdResult < WhereCondition > {
179
- let expression = "(open_message_id, epoch_settings_id , beacon, signed_entity_type_id, message) values (?*, ?*, ?*, ?*, ?*)" ;
188
+ let expression = "(open_message_id, epoch_setting_id , beacon, signed_entity_type_id, message) values (?*, ?*, ?*, ?*, ?*)" ;
180
189
let parameters = vec ! [
181
190
Value :: String ( Uuid :: new_v4( ) . to_string( ) ) ,
182
191
Value :: Integer ( epoch. 0 as i64 ) ,
@@ -215,7 +224,7 @@ impl<'client> DeleteOpenMessageProvider<'client> {
215
224
216
225
fn get_epoch_condition ( & self , epoch : Epoch ) -> WhereCondition {
217
226
WhereCondition :: new (
218
- "epoch_settings_id = ?*" ,
227
+ "epoch_setting_id = ?*" ,
219
228
vec ! [ Value :: Integer ( epoch. 0 as i64 ) ] ,
220
229
)
221
230
}
@@ -236,18 +245,28 @@ impl<'client> Provider<'client> for DeleteOpenMessageProvider<'client> {
236
245
}
237
246
}
238
247
239
- pub struct OpenMessageRepository < ' client > {
240
- connection : & ' client Connection ,
248
+ /// ## Open message repository
249
+ ///
250
+ /// This is a business oriented layer to perform actions on the database through
251
+ /// providers.
252
+ pub struct OpenMessageRepository {
253
+ connection : Arc < Mutex < Connection > > ,
241
254
}
242
255
243
- impl < ' client > OpenMessageRepository < ' client > {
256
+ impl OpenMessageRepository {
257
+ /// Instanciate service
258
+ pub fn new ( connection : Arc < Mutex < Connection > > ) -> Self {
259
+ Self { connection }
260
+ }
261
+
244
262
/// Return the latest [OpenMessage] for the given Epoch and [SignedEntityType].
245
- pub fn get_open_message (
263
+ pub async fn get_open_message (
246
264
& self ,
247
265
epoch : Epoch ,
248
266
signed_entity_type : & SignedEntityType ,
249
267
) -> StdResult < Option < OpenMessage > > {
250
- let provider = OpenMessageProvider :: new ( self . connection ) ;
268
+ let lock = self . connection . lock ( ) . await ;
269
+ let provider = OpenMessageProvider :: new ( & lock) ;
251
270
let filters = provider
252
271
. get_epoch_condition ( epoch)
253
272
. and_where ( provider. get_signed_entity_type_condition ( signed_entity_type) ) ;
@@ -257,14 +276,15 @@ impl<'client> OpenMessageRepository<'client> {
257
276
}
258
277
259
278
/// Create a new [OpenMessage] in the database.
260
- pub fn create_open_message (
279
+ pub async fn create_open_message (
261
280
& self ,
262
281
epoch : Epoch ,
263
282
beacon : & Beacon ,
264
283
signed_entity_type : & SignedEntityType ,
265
284
message : & str ,
266
285
) -> StdResult < OpenMessage > {
267
- let provider = InsertOpenMessageProvider :: new ( self . connection ) ;
286
+ let lock = self . connection . lock ( ) . await ;
287
+ let provider = InsertOpenMessageProvider :: new ( & lock) ;
268
288
let filters = provider. get_insert_condition ( epoch, beacon, signed_entity_type, message) ?;
269
289
let mut cursor = provider. find ( filters) ?;
270
290
@@ -274,19 +294,23 @@ impl<'client> OpenMessageRepository<'client> {
274
294
}
275
295
276
296
/// Remove all the [OpenMessage] for the given Epoch in the database.
277
- pub fn clean_epoch ( & self , epoch : Epoch ) -> StdResult < ( ) > {
278
- let provider = DeleteOpenMessageProvider :: new ( self . connection ) ;
297
+ /// It returns the number of messages removed.
298
+ pub async fn clean_epoch ( & self , epoch : Epoch ) -> StdResult < usize > {
299
+ let lock = self . connection . lock ( ) . await ;
300
+ let provider = DeleteOpenMessageProvider :: new ( & lock) ;
279
301
let filters = provider. get_epoch_condition ( epoch) ;
280
- let _ = provider. find ( filters) ?;
302
+ let cursor = provider. find ( filters) ?;
281
303
282
- Ok ( ( ) )
304
+ Ok ( cursor . count ( ) )
283
305
}
284
306
}
285
307
286
308
#[ cfg( test) ]
287
309
mod tests {
288
310
use mithril_common:: sqlite:: SourceAlias ;
289
311
312
+ use crate :: { dependency_injection:: DependenciesBuilder , Configuration } ;
313
+
290
314
use super :: * ;
291
315
292
316
#[ test]
@@ -295,7 +319,7 @@ mod tests {
295
319
let aliases = SourceAlias :: new ( & [ ( "{:open_message:}" , "open_message" ) ] ) ;
296
320
297
321
assert_eq ! (
298
- "open_message.open_message_id as open_message_id, open_message.epoch_settings_id as epoch_settings_id , open_message.beacon as beacon, open_message.signed_entity_type_id as signed_entity_type_id, open_message.message as message, open_message.created_at as created_at" . to_string( ) ,
322
+ "open_message.open_message_id as open_message_id, open_message.epoch_setting_id as epoch_setting_id , open_message.beacon as beacon, open_message.signed_entity_type_id as signed_entity_type_id, open_message.message as message, open_message.created_at as created_at" . to_string( ) ,
299
323
projection. expand( aliases)
300
324
)
301
325
}
@@ -306,7 +330,7 @@ mod tests {
306
330
let provider = OpenMessageProvider :: new ( & connection) ;
307
331
let ( expr, params) = provider. get_epoch_condition ( Epoch ( 12 ) ) . expand ( ) ;
308
332
309
- assert_eq ! ( "epoch_settings_id = ?1" . to_string( ) , expr) ;
333
+ assert_eq ! ( "epoch_setting_id = ?1" . to_string( ) , expr) ;
310
334
assert_eq ! ( vec![ Value :: Integer ( 12 ) ] , params, ) ;
311
335
}
312
336
@@ -353,7 +377,7 @@ mod tests {
353
377
. unwrap ( )
354
378
. expand ( ) ;
355
379
356
- assert_eq ! ( "(open_message_id, epoch_settings_id , beacon, signed_entity_type_id, message) values (?1, ?2, ?3, ?4, ?5)" . to_string( ) , expr) ;
380
+ assert_eq ! ( "(open_message_id, epoch_setting_id , beacon, signed_entity_type_id, message) values (?1, ?2, ?3, ?4, ?5)" . to_string( ) , expr) ;
357
381
assert_eq ! ( Value :: Integer ( 12 ) , params[ 1 ] ) ;
358
382
assert_eq ! (
359
383
Value :: String ( r#"{"network":"","epoch":0,"immutable_file_number":0}"# . to_string( ) ) ,
@@ -369,7 +393,87 @@ mod tests {
369
393
let provider = DeleteOpenMessageProvider :: new ( & connection) ;
370
394
let ( expr, params) = provider. get_epoch_condition ( Epoch ( 12 ) ) . expand ( ) ;
371
395
372
- assert_eq ! ( "epoch_settings_id = ?1" . to_string( ) , expr) ;
396
+ assert_eq ! ( "epoch_setting_id = ?1" . to_string( ) , expr) ;
373
397
assert_eq ! ( vec![ Value :: Integer ( 12 ) ] , params, ) ;
374
398
}
399
+
400
+ async fn get_connection ( ) -> Arc < Mutex < Connection > > {
401
+ let config = Configuration :: new_sample ( ) ;
402
+ let mut builder = DependenciesBuilder :: new ( config) ;
403
+ let connection = builder. get_sqlite_connection ( ) . await . unwrap ( ) ;
404
+ {
405
+ let lock = connection. lock ( ) . await ;
406
+ lock. execute ( r#"insert into epoch_setting(epoch_setting_id, protocol_parameters) values (1, '{"k": 100, "m": 5, "phi": 0.65 }');"# ) . unwrap ( ) ;
407
+ }
408
+
409
+ connection
410
+ }
411
+
412
+ #[ tokio:: test]
413
+ async fn repository_create_open_message ( ) {
414
+ let connection = get_connection ( ) . await ;
415
+ let repository = OpenMessageRepository :: new ( connection. clone ( ) ) ;
416
+ let open_message = repository
417
+ . create_open_message (
418
+ Epoch ( 1 ) ,
419
+ & Beacon :: default ( ) ,
420
+ & SignedEntityType :: CardanoImmutableFilesFull ,
421
+ "this is a message" ,
422
+ )
423
+ . await
424
+ . unwrap ( ) ;
425
+
426
+ assert_eq ! ( Epoch ( 1 ) , open_message. epoch) ;
427
+ assert_eq ! ( "this is a message" . to_string( ) , open_message. message) ;
428
+ assert_eq ! (
429
+ SignedEntityType :: CardanoImmutableFilesFull ,
430
+ open_message. signed_entity_type
431
+ ) ;
432
+
433
+ let message = {
434
+ let lock = connection. lock ( ) . await ;
435
+ let provider = OpenMessageProvider :: new ( & lock) ;
436
+ let mut cursor = provider
437
+ . find ( WhereCondition :: new (
438
+ "open_message_id = ?*" ,
439
+ vec ! [ Value :: String ( open_message. open_message_id. to_string( ) ) ] ,
440
+ ) )
441
+ . unwrap ( ) ;
442
+
443
+ cursor. next ( ) . expect ( & format ! (
444
+ "OpenMessage ID='{}' should exist in the database." ,
445
+ open_message. open_message_id. to_string( )
446
+ ) )
447
+ } ;
448
+
449
+ assert_eq ! ( open_message. message, message. message) ;
450
+ assert_eq ! ( open_message. epoch, message. epoch) ;
451
+ }
452
+
453
+ #[ tokio:: test]
454
+ async fn repository_clean_open_message ( ) {
455
+ let connection = get_connection ( ) . await ;
456
+ let repository = OpenMessageRepository :: new ( connection. clone ( ) ) ;
457
+ let _ = repository
458
+ . create_open_message (
459
+ Epoch ( 1 ) ,
460
+ & Beacon :: default ( ) ,
461
+ & SignedEntityType :: CardanoImmutableFilesFull ,
462
+ "this is a message" ,
463
+ )
464
+ . await
465
+ . unwrap ( ) ;
466
+ let _ = repository
467
+ . create_open_message (
468
+ Epoch ( 1 ) ,
469
+ & Beacon :: default ( ) ,
470
+ & SignedEntityType :: MithrilStakeDistribution ,
471
+ "this is a stake distribution" ,
472
+ )
473
+ . await
474
+ . unwrap ( ) ;
475
+ let count = repository. clean_epoch ( Epoch ( 1 ) ) . await . unwrap ( ) ;
476
+
477
+ assert_eq ! ( 2 , count) ;
478
+ }
375
479
}
0 commit comments