@@ -49,6 +49,7 @@ use std::{
49
49
time:: { Duration , Instant } ,
50
50
} ;
51
51
use substrate_rpc_client:: { rpc_params, BatchRequestBuilder , ChainApi , ClientT , StateApi } ;
52
+ use tokio_retry:: { strategy:: FixedInterval , Retry } ;
52
53
53
54
type KeyValue = ( StorageKey , StorageData ) ;
54
55
type TopKeyValues = Vec < KeyValue > ;
@@ -317,8 +318,10 @@ where
317
318
const BATCH_SIZE_INCREASE_FACTOR : f32 = 1.10 ;
318
319
const BATCH_SIZE_DECREASE_FACTOR : f32 = 0.50 ;
319
320
const INITIAL_BATCH_SIZE : usize = 5000 ;
320
- // NOTE: increasing this value does not seem to impact speed all that much.
321
+ // nodes by default will not return more than 1000 keys per request
321
322
const DEFAULT_KEY_DOWNLOAD_PAGE : u32 = 1000 ;
323
+ const KEYS_PAGE_MAX_RETRIES : usize = 12 ;
324
+ const KEYS_PAGE_RETRY_INTERVAL : Duration = Duration :: from_secs ( 5 ) ;
322
325
323
326
async fn rpc_get_storage (
324
327
& self ,
@@ -345,6 +348,22 @@ where
345
348
} )
346
349
}
347
350
351
+ async fn get_keys_single_page (
352
+ & self ,
353
+ prefix : Option < StorageKey > ,
354
+ start_key : Option < StorageKey > ,
355
+ at : B :: Hash ,
356
+ ) -> Result < Vec < StorageKey > , & ' static str > {
357
+ self . as_online ( )
358
+ . rpc_client ( )
359
+ . storage_keys_paged ( prefix, Self :: DEFAULT_KEY_DOWNLOAD_PAGE , start_key, Some ( at) )
360
+ . await
361
+ . map_err ( |e| {
362
+ error ! ( target: LOG_TARGET , "Error = {:?}" , e) ;
363
+ "rpc get_keys failed"
364
+ } )
365
+ }
366
+
348
367
/// Get all the keys at `prefix` at `hash` using the paged, safe RPC methods.
349
368
async fn rpc_get_keys_paged (
350
369
& self ,
@@ -354,20 +373,13 @@ where
354
373
let mut last_key: Option < StorageKey > = None ;
355
374
let mut all_keys: Vec < StorageKey > = vec ! [ ] ;
356
375
let keys = loop {
357
- let page = self
358
- . as_online ( )
359
- . rpc_client ( )
360
- . storage_keys_paged (
361
- Some ( prefix. clone ( ) ) ,
362
- Self :: DEFAULT_KEY_DOWNLOAD_PAGE ,
363
- last_key. clone ( ) ,
364
- Some ( at) ,
365
- )
366
- . await
367
- . map_err ( |e| {
368
- error ! ( target: LOG_TARGET , "Error = {:?}" , e) ;
369
- "rpc get_keys failed"
370
- } ) ?;
376
+ // This loop can hit the node with very rapid requests, occasionally causing it to
377
+ // error out in CI (https://github.com/paritytech/substrate/issues/14129), so we retry.
378
+ let retry_strategy = FixedInterval :: new ( Self :: KEYS_PAGE_RETRY_INTERVAL )
379
+ . take ( Self :: KEYS_PAGE_MAX_RETRIES ) ;
380
+ let get_page_closure =
381
+ || self . get_keys_single_page ( Some ( prefix. clone ( ) ) , last_key. clone ( ) , at) ;
382
+ let page = Retry :: spawn ( retry_strategy, get_page_closure) . await ?;
371
383
let page_len = page. len ( ) ;
372
384
373
385
all_keys. extend ( page) ;
@@ -385,7 +397,7 @@ where
385
397
HexDisplay :: from( new_last_key)
386
398
) ;
387
399
last_key = Some ( new_last_key. clone ( ) ) ;
388
- }
400
+ } ;
389
401
} ;
390
402
391
403
Ok ( keys)
0 commit comments