Skip to content

Commit

Permalink
Make storage_page_size for the LegacyBackend configurable (#1458)
Browse files Browse the repository at this point in the history
  • Loading branch information
jsdw authored Feb 29, 2024
1 parent 3ffccb0 commit ddd0865
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 13 deletions.
58 changes: 49 additions & 9 deletions subxt/src/backend/legacy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> {
storage_page_size: u32,
_marker: std::marker::PhantomData<T>,
}

impl<T: Config> Default for LegacyBackendBuilder<T> {
fn default() -> Self {
Self::new()
}
}

impl<T: Config> LegacyBackendBuilder<T> {
/// 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<T> {
LegacyBackend {
storage_page_size: self.storage_page_size,
methods: LegacyRpcMethods::new(client),
}
}
}

/// The legacy backend.
#[derive(Debug, Clone)]
pub struct LegacyBackend<T> {
storage_page_size: u32,
methods: LegacyRpcMethods<T>,
}

impl<T: Config> LegacyBackend<T> {
/// 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<T> {
LegacyBackendBuilder::new()
}
}

Expand Down Expand Up @@ -74,6 +112,7 @@ impl<T: Config + Send + Sync + 'static> Backend<T> for LegacyBackend<T> {
let keys = StorageFetchDescendantKeysStream {
at,
key,
storage_page_size: self.storage_page_size,
methods: self.methods.clone(),
done: Default::default(),
keys_fut: Default::default(),
Expand Down Expand Up @@ -104,6 +143,7 @@ impl<T: Config + Send + Sync + 'static> Backend<T> for LegacyBackend<T> {
let keys_stream = StorageFetchDescendantKeysStream {
at,
key,
storage_page_size: self.storage_page_size,
methods: self.methods.clone(),
done: Default::default(),
keys_fut: Default::default(),
Expand Down Expand Up @@ -332,16 +372,15 @@ 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)]
pub struct StorageFetchDescendantKeysStream<T: Config> {
methods: LegacyRpcMethods<T>,
key: Vec<u8>,
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<Vec<u8>>,
// Keys, future and cached:
Expand Down Expand Up @@ -392,12 +431,13 @@ impl<T: Config> Stream for StorageFetchDescendantKeysStream<T> {
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),
)
Expand Down
6 changes: 3 additions & 3 deletions subxt/src/client/online_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl<T: Config> OnlineClient<T> {
/// Allows insecure URLs without SSL encryption, e.g. (http:// and ws:// URLs).
pub async fn from_insecure_url(url: impl AsRef<str>) -> Result<OnlineClient<T>, 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
}
}
Expand All @@ -85,7 +85,7 @@ impl<T: Config> OnlineClient<T> {
/// 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<OnlineClient<T>, Error> {
let backend = Arc::new(LegacyBackend::new(rpc_client));
let backend = Arc::new(LegacyBackend::builder().build(rpc_client));
OnlineClient::from_backend(backend).await
}

Expand All @@ -108,7 +108,7 @@ impl<T: Config> OnlineClient<T> {
metadata: impl Into<Metadata>,
rpc_client: RpcClient,
) -> Result<OnlineClient<T>, 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)
}

Expand Down
2 changes: 1 addition & 1 deletion testing/integration-tests/src/utils/node_proc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ async fn build_rpc_client(ws_url: &str) -> Result<rpc::RpcClient, String> {
async fn build_legacy_client<T: Config>(
rpc_client: rpc::RpcClient,
) -> Result<OnlineClient<T>, 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}"))?;
Expand Down

0 comments on commit ddd0865

Please sign in to comment.