From 7f5ba946461ae31d3febdb520cbf53a9d448b187 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Thu, 29 Feb 2024 12:30:21 +0000 Subject: [PATCH] Make storage_page_size for the LegacyBackend configurable --- subxt/src/backend/legacy/mod.rs | 58 ++++++++++++++++--- subxt/src/client/online_client.rs | 6 +- .../integration-tests/src/utils/node_proc.rs | 2 +- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/subxt/src/backend/legacy/mod.rs b/subxt/src/backend/legacy/mod.rs index cffb3f4475..7649da1592 100644 --- a/subxt/src/backend/legacy/mod.rs +++ b/subxt/src/backend/legacy/mod.rs @@ -22,18 +22,56 @@ use std::task::{Context, Poll}; // Expose the RPC methods. pub use rpc_methods::LegacyRpcMethods; +/// Configure and build an [`LegacyBackend`]. +pub struct LegacyBackendBuilder { + storage_page_size: u32, + _marker: std::marker::PhantomData, +} + +impl Default for LegacyBackendBuilder { + fn default() -> Self { + Self::new() + } +} + +impl LegacyBackendBuilder { + /// Create a new [`LegacyBackendBuilder`]. + pub fn new() -> Self { + Self { + storage_page_size: 64, + _marker: std::marker::PhantomData, + } + } + + /// Iterating over storage entries using the [`LegacyBackend`] requires + /// fetching entries in batches. This configures the number of entries that + /// we'll try to obtain in each batch (default: 64). + pub fn storage_page_size(mut self, storage_page_size: u32) -> Self { + self.storage_page_size = storage_page_size; + self + } + + /// Given an [`RpcClient`] to use to make requests, this returns a [`LegacyBackend`], + /// which implements the [`Backend`] trait. + pub fn build(self, client: RpcClient) -> LegacyBackend { + LegacyBackend { + storage_page_size: self.storage_page_size, + methods: LegacyRpcMethods::new(client), + } + } +} + /// The legacy backend. #[derive(Debug, Clone)] pub struct LegacyBackend { + storage_page_size: u32, methods: LegacyRpcMethods, } impl LegacyBackend { - /// Instantiate a new backend which uses the legacy API methods. - pub fn new(client: RpcClient) -> Self { - Self { - methods: LegacyRpcMethods::new(client), - } + /// Configure and construct an [`LegacyBackend`]. + pub fn builder() -> LegacyBackendBuilder { + LegacyBackendBuilder::new() } } @@ -74,6 +112,7 @@ impl Backend for LegacyBackend { let keys = StorageFetchDescendantKeysStream { at, key, + storage_page_size: self.storage_page_size, methods: self.methods.clone(), done: Default::default(), keys_fut: Default::default(), @@ -104,6 +143,7 @@ impl Backend for LegacyBackend { let keys_stream = StorageFetchDescendantKeysStream { at, key, + storage_page_size: self.storage_page_size, methods: self.methods.clone(), done: Default::default(), keys_fut: Default::default(), @@ -332,9 +372,6 @@ where }) } -/// How many keys/values to fetch at once. -const STORAGE_PAGE_SIZE: u32 = 32; - /// This provides a stream of values given some prefix `key`. It /// internally manages pagination and such. #[allow(clippy::type_complexity)] @@ -342,6 +379,8 @@ pub struct StorageFetchDescendantKeysStream { methods: LegacyRpcMethods, key: Vec, at: T::Hash, + // How many entries to ask for each time. + storage_page_size: u32, // What key do we start paginating from? None = from the beginning. pagination_start_key: Option>, // Keys, future and cached: @@ -392,12 +431,13 @@ impl Stream for StorageFetchDescendantKeysStream { let methods = this.methods.clone(); let key = this.key.clone(); let at = this.at; + let storage_page_size = this.storage_page_size; let pagination_start_key = this.pagination_start_key.take(); let keys_fut = async move { methods .state_get_keys_paged( &key, - STORAGE_PAGE_SIZE, + storage_page_size, pagination_start_key.as_deref(), Some(at), ) diff --git a/subxt/src/client/online_client.rs b/subxt/src/client/online_client.rs index f4e2f8c723..77718caa7f 100644 --- a/subxt/src/client/online_client.rs +++ b/subxt/src/client/online_client.rs @@ -76,7 +76,7 @@ impl OnlineClient { /// Allows insecure URLs without SSL encryption, e.g. (http:// and ws:// URLs). pub async fn from_insecure_url(url: impl AsRef) -> Result, Error> { let client = RpcClient::from_insecure_url(url).await?; - let backend = LegacyBackend::new(client); + let backend = LegacyBackend::builder().build(client); OnlineClient::from_backend(Arc::new(backend)).await } } @@ -85,7 +85,7 @@ impl OnlineClient { /// Construct a new [`OnlineClient`] by providing an [`RpcClient`] to drive the connection. /// This will use the current default [`Backend`], which may change in future releases. pub async fn from_rpc_client(rpc_client: RpcClient) -> Result, Error> { - let backend = Arc::new(LegacyBackend::new(rpc_client)); + let backend = Arc::new(LegacyBackend::builder().build(rpc_client)); OnlineClient::from_backend(backend).await } @@ -108,7 +108,7 @@ impl OnlineClient { metadata: impl Into, rpc_client: RpcClient, ) -> Result, Error> { - let backend = Arc::new(LegacyBackend::new(rpc_client)); + let backend = Arc::new(LegacyBackend::builder().build(rpc_client)); OnlineClient::from_backend_with(genesis_hash, runtime_version, metadata, backend) } diff --git a/testing/integration-tests/src/utils/node_proc.rs b/testing/integration-tests/src/utils/node_proc.rs index d3ac752fec..65a27012bc 100644 --- a/testing/integration-tests/src/utils/node_proc.rs +++ b/testing/integration-tests/src/utils/node_proc.rs @@ -201,7 +201,7 @@ async fn build_rpc_client(ws_url: &str) -> Result { async fn build_legacy_client( rpc_client: rpc::RpcClient, ) -> Result, String> { - let backend = legacy::LegacyBackend::new(rpc_client); + let backend = legacy::LegacyBackend::builder().build(rpc_client); let client = OnlineClient::from_backend(Arc::new(backend)) .await .map_err(|e| format!("Cannot construct OnlineClient from backend: {e}"))?;