1
1
use std:: {
2
2
collections:: { HashSet , VecDeque } ,
3
- sync:: Arc ,
3
+ sync:: { Arc , Mutex } ,
4
4
} ;
5
5
6
6
use bitcoin:: { BlockHash , consensus:: Encodable } ;
@@ -90,9 +90,10 @@ pub struct GetSuccessorsHandler<Network: BlockchainNetwork> {
90
90
blockchain_manager_tx : Sender < BlockchainManagerRequest > ,
91
91
network : Network ,
92
92
metrics : GetSuccessorMetrics ,
93
+ pruning_task_handle : Mutex < Option < tokio:: task:: JoinHandle < ( ) > > > ,
93
94
}
94
95
95
- impl < Network : BlockchainNetwork > GetSuccessorsHandler < Network > {
96
+ impl < Network : BlockchainNetwork + Send + Sync > GetSuccessorsHandler < Network > {
96
97
/// Creates a GetSuccessorsHandler to be used to access the blockchain state
97
98
/// inside of the adapter when a `GetSuccessorsRequest` is received.
98
99
pub fn new (
@@ -106,6 +107,7 @@ impl<Network: BlockchainNetwork> GetSuccessorsHandler<Network> {
106
107
blockchain_manager_tx,
107
108
network,
108
109
metrics : GetSuccessorMetrics :: new ( metrics_registry) ,
110
+ pruning_task_handle : Mutex :: new ( None ) ,
109
111
}
110
112
}
111
113
@@ -123,6 +125,21 @@ impl<Network: BlockchainNetwork> GetSuccessorsHandler<Network> {
123
125
. processed_block_hashes
124
126
. observe ( request. processed_block_hashes . len ( ) as f64 ) ;
125
127
128
+ // Spawn persist-to-disk task without waiting for it to finish, and make sure there
129
+ // is only one task running at a time.
130
+ let cache = self . state . header_cache . clone ( ) ;
131
+ let mut handle = self . pruning_task_handle . lock ( ) . unwrap ( ) ;
132
+ let is_finished = handle
133
+ . as_ref ( )
134
+ . map ( |handle| handle. is_finished ( ) )
135
+ . unwrap_or ( true ) ;
136
+ if is_finished {
137
+ * handle = Some ( tokio:: task:: spawn_blocking ( move || {
138
+ // Error is ignored, since it is a background task
139
+ let _ = cache. persist_and_prune_headers_below_anchor ( request. anchor ) ;
140
+ } ) ) ;
141
+ }
142
+
126
143
let ( blocks, next, obsolete_blocks) = {
127
144
let anchor_height = self
128
145
. state
@@ -312,6 +329,7 @@ mod test {
312
329
use super :: * ;
313
330
314
331
use bitcoin:: { Block , consensus:: Decodable } ;
332
+ use ic_logger:: no_op_logger;
315
333
use ic_metrics:: MetricsRegistry ;
316
334
use tokio:: sync:: mpsc:: channel;
317
335
@@ -323,12 +341,18 @@ mod test {
323
341
Block :: consensus_decode ( & mut ( * serialized_block) . as_slice ( ) ) . unwrap ( )
324
342
}
325
343
344
+ fn new_blockchain_state < Network : BlockchainNetwork > (
345
+ network : Network ,
346
+ ) -> BlockchainState < Network > {
347
+ BlockchainState :: new ( network, None , & MetricsRegistry :: default ( ) , no_op_logger ( ) )
348
+ }
349
+
326
350
/// This tests ensures that `BlockchainManager::get_successors(...)` will return relevant blocks
327
351
/// with the next headers of many forks and enqueue missing block hashes.
328
352
#[ tokio:: test]
329
353
async fn test_get_successors ( ) {
330
354
let network = bitcoin:: Network :: Regtest ;
331
- let blockchain_state = BlockchainState :: new ( network, & MetricsRegistry :: default ( ) ) ;
355
+ let blockchain_state = new_blockchain_state ( network) ;
332
356
let genesis = blockchain_state. genesis ( ) ;
333
357
let genesis_hash = genesis. block_hash ( ) ;
334
358
let ( blockchain_manager_tx, _blockchain_manager_rx) = channel ( 10 ) ;
@@ -440,7 +464,7 @@ mod test {
440
464
#[ tokio:: test]
441
465
async fn test_get_successors_wait_header_sync_regtest ( ) {
442
466
let network = bitcoin:: Network :: Regtest ;
443
- let blockchain_state = BlockchainState :: new ( network, & MetricsRegistry :: default ( ) ) ;
467
+ let blockchain_state = new_blockchain_state ( network) ;
444
468
let genesis = blockchain_state. genesis ( ) ;
445
469
let genesis_hash = genesis. block_hash ( ) ;
446
470
let ( blockchain_manager_tx, _blockchain_manager_rx) = channel ( 10 ) ;
@@ -490,7 +514,7 @@ mod test {
490
514
#[ tokio:: test]
491
515
async fn test_get_successors_multiple_blocks ( ) {
492
516
let network = bitcoin:: Network :: Regtest ;
493
- let blockchain_state = BlockchainState :: new ( network, & MetricsRegistry :: default ( ) ) ;
517
+ let blockchain_state = new_blockchain_state ( network) ;
494
518
let genesis = blockchain_state. genesis ( ) ;
495
519
let genesis_hash = genesis. block_hash ( ) ;
496
520
let ( blockchain_manager_tx, _blockchain_manager_rx) = channel ( 10 ) ;
@@ -564,7 +588,7 @@ mod test {
564
588
#[ tokio:: test]
565
589
async fn test_get_successors_max_num_blocks ( ) {
566
590
let network = bitcoin:: Network :: Regtest ;
567
- let blockchain_state = BlockchainState :: new ( network, & MetricsRegistry :: default ( ) ) ;
591
+ let blockchain_state = new_blockchain_state ( network) ;
568
592
let genesis = blockchain_state. genesis ( ) ;
569
593
let genesis_hash = genesis. block_hash ( ) ;
570
594
let ( blockchain_manager_tx, _blockchain_manager_rx) = channel ( 10 ) ;
@@ -600,7 +624,7 @@ mod test {
600
624
#[ tokio:: test]
601
625
async fn test_get_successors_multiple_blocks_out_of_order ( ) {
602
626
let network = bitcoin:: Network :: Regtest ;
603
- let blockchain_state = BlockchainState :: new ( network, & MetricsRegistry :: default ( ) ) ;
627
+ let blockchain_state = new_blockchain_state ( network) ;
604
628
let genesis = blockchain_state. genesis ( ) ;
605
629
let genesis_hash = genesis. block_hash ( ) ;
606
630
let ( blockchain_manager_tx, _blockchain_manager_rx) = channel ( 10 ) ;
@@ -694,7 +718,7 @@ mod test {
694
718
#[ tokio:: test]
695
719
async fn test_get_successors_large_block ( ) {
696
720
let network = bitcoin:: Network :: Regtest ;
697
- let blockchain_state = BlockchainState :: new ( network, & MetricsRegistry :: default ( ) ) ;
721
+ let blockchain_state = new_blockchain_state ( network) ;
698
722
let genesis = blockchain_state. genesis ( ) ;
699
723
let genesis_hash = genesis. block_hash ( ) ;
700
724
let ( blockchain_manager_tx, _blockchain_manager_rx) = channel ( 10 ) ;
@@ -760,7 +784,7 @@ mod test {
760
784
#[ tokio:: test]
761
785
async fn test_get_successors_many_blocks_until_size_cap_is_met ( ) {
762
786
let network = bitcoin:: Network :: Regtest ;
763
- let blockchain_state = BlockchainState :: new ( network, & MetricsRegistry :: default ( ) ) ;
787
+ let blockchain_state = new_blockchain_state ( network) ;
764
788
let genesis = blockchain_state. genesis ( ) ;
765
789
let genesis_hash = genesis. block_hash ( ) ;
766
790
let ( blockchain_manager_tx, _blockchain_manager_rx) = channel ( 10 ) ;
0 commit comments