Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 2c3b923

Browse files
authored
remote-externalities: retry for get_keys (#14167)
* retry get keys request * remove redundant clone * remove redundant at
1 parent b938a72 commit 2c3b923

File tree

3 files changed

+42
-17
lines changed

3 files changed

+42
-17
lines changed

Cargo.lock

+13-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

utils/frame/remote-externalities/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ futures = "0.3"
2626
async-recursion = "1.0.4"
2727
indicatif = "0.17.3"
2828
spinners = "4.1.0"
29+
tokio-retry = "0.3.0"
2930

3031
[dev-dependencies]
3132
frame-support = { version = "4.0.0-dev", path = "../../../frame/support" }

utils/frame/remote-externalities/src/lib.rs

+28-16
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ use std::{
4949
time::{Duration, Instant},
5050
};
5151
use substrate_rpc_client::{rpc_params, BatchRequestBuilder, ChainApi, ClientT, StateApi};
52+
use tokio_retry::{strategy::FixedInterval, Retry};
5253

5354
type KeyValue = (StorageKey, StorageData);
5455
type TopKeyValues = Vec<KeyValue>;
@@ -317,8 +318,10 @@ where
317318
const BATCH_SIZE_INCREASE_FACTOR: f32 = 1.10;
318319
const BATCH_SIZE_DECREASE_FACTOR: f32 = 0.50;
319320
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
321322
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);
322325

323326
async fn rpc_get_storage(
324327
&self,
@@ -345,6 +348,22 @@ where
345348
})
346349
}
347350

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+
348367
/// Get all the keys at `prefix` at `hash` using the paged, safe RPC methods.
349368
async fn rpc_get_keys_paged(
350369
&self,
@@ -354,20 +373,13 @@ where
354373
let mut last_key: Option<StorageKey> = None;
355374
let mut all_keys: Vec<StorageKey> = vec![];
356375
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?;
371383
let page_len = page.len();
372384

373385
all_keys.extend(page);
@@ -385,7 +397,7 @@ where
385397
HexDisplay::from(new_last_key)
386398
);
387399
last_key = Some(new_last_key.clone());
388-
}
400+
};
389401
};
390402

391403
Ok(keys)

0 commit comments

Comments
 (0)