From 5cfe2801506f5cae717d3089eef5f87d4b7f4dcb Mon Sep 17 00:00:00 2001 From: Yiannis Marangos Date: Mon, 16 Dec 2024 18:50:14 +0200 Subject: [PATCH] feat(node-wasm): Add more configuration options in `NodeConfig` (#487) --- node-wasm/src/client.rs | 76 ++++++++++++++++++++++++++++++----------- node-wasm/src/worker.rs | 10 ++++-- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/node-wasm/src/client.rs b/node-wasm/src/client.rs index b0e8e16f..3f9ceaae 100644 --- a/node-wasm/src/client.rs +++ b/node-wasm/src/client.rs @@ -2,6 +2,7 @@ use std::time::Duration; +use blockstore::EitherBlockstore; use js_sys::Array; use serde::{Deserialize, Serialize}; use serde_wasm_bindgen::to_value; @@ -9,10 +10,10 @@ use tracing::{debug, error}; use wasm_bindgen::prelude::*; use web_sys::BroadcastChannel; -use lumina_node::blockstore::IndexedDbBlockstore; +use lumina_node::blockstore::{InMemoryBlockstore, IndexedDbBlockstore}; use lumina_node::network; -use lumina_node::node::NodeBuilder; -use lumina_node::store::IndexedDbStore; +use lumina_node::node::{NodeBuilder, MIN_PRUNING_DELAY, MIN_SAMPLING_WINDOW}; +use lumina_node::store::{EitherStore, InMemoryStore, IndexedDbStore}; use crate::commands::{CheckableResponseExt, NodeCommand, SingleHeaderQuery}; use crate::error::{Context, Result}; @@ -21,6 +22,7 @@ use crate::utils::{ is_safari, js_value_from_display, request_storage_persistence, resolve_dnsaddr_multiaddress, timeout, Network, }; +use crate::worker::{WasmBlockstore, WasmStore}; use crate::wrapper::libp2p::NetworkInfoSnapshot; use crate::wrapper::node::{PeerTrackerInfoSnapshot, SyncingInfoSnapshot}; @@ -33,9 +35,29 @@ pub struct WasmNodeConfig { /// A list of bootstrap peers to connect to. #[wasm_bindgen(getter_with_clone)] pub bootnodes: Vec, - /// Sampling window size, defines maximum age of headers considered for syncing and sampling. - /// Headers older than sampling window by more than an hour are eligible for pruning. + /// Whether to store data in persistent memory or not. + /// + /// **Default value:** true + pub use_persistent_memory: bool, + /// Sampling window defines maximum age of a block considered for syncing and sampling. + /// + /// If this is not set, then default value will apply: + /// + /// * If `use_persistent_memory == true`, default value is 30 days. + /// * If `use_persistent_memory == false`, default value is 60 seconds. + /// + /// The minimum value that can be set is 60 seconds. pub custom_sampling_window_secs: Option, + /// Pruning delay defines how much time the pruner should wait after sampling window in + /// order to prune the block. + /// + /// If this is not set, then default value will apply: + /// + /// * If `use_persistent_memory == true`, default value is 1 hour. + /// * If `use_persistent_memory == false`, default value is 60 seconds. + /// + /// The minimum value that can be set is 60 seconds. + pub custom_pruning_delay_secs: Option, } /// `NodeClient` is responsible for steering [`NodeWorker`] by sending it commands and receiving @@ -382,28 +404,37 @@ impl WasmNodeConfig { WasmNodeConfig { network, bootnodes, + use_persistent_memory: true, custom_sampling_window_secs: None, + custom_pruning_delay_secs: None, } } - pub(crate) async fn into_node_builder( - self, - ) -> Result> { + pub(crate) async fn into_node_builder(self) -> Result> { let network = network::Network::from(self.network); let network_id = network.id(); - let store = IndexedDbStore::new(network_id) - .await - .context("Failed to open the store")?; - let blockstore = IndexedDbBlockstore::new(&format!("{network_id}-blockstore")) - .await - .context("Failed to open the blockstore")?; + let mut builder = if self.use_persistent_memory { + let store = IndexedDbStore::new(network_id) + .await + .context("Failed to open the store")?; + let blockstore = IndexedDbBlockstore::new(&format!("{network_id}-blockstore")) + .await + .context("Failed to open the blockstore")?; + + NodeBuilder::new() + .store(EitherStore::Right(store)) + .blockstore(EitherBlockstore::Right(blockstore)) + } else { + NodeBuilder::new() + .store(EitherStore::Left(InMemoryStore::new())) + .blockstore(EitherBlockstore::Left(InMemoryBlockstore::new())) + // In-memory stores are memory hungry, so we lower sampling and pruining window. + .sampling_window(MIN_SAMPLING_WINDOW) + .pruning_delay(MIN_PRUNING_DELAY) + }; - let mut builder = NodeBuilder::new() - .store(store) - .blockstore(blockstore) - .network(network) - .sync_batch_size(128); + builder = builder.network(network).sync_batch_size(128); let mut bootnodes = Vec::with_capacity(self.bootnodes.len()); @@ -422,6 +453,11 @@ impl WasmNodeConfig { builder = builder.sampling_window(dur); } + if let Some(secs) = self.custom_pruning_delay_secs { + let dur = Duration::from_secs(secs.into()); + builder = builder.pruning_delay(dur); + } + Ok(builder) } } @@ -513,7 +549,9 @@ mod tests { .start(&WasmNodeConfig { network: Network::Private, bootnodes, + use_persistent_memory: false, custom_sampling_window_secs: None, + custom_pruning_delay_secs: None, }) .await .unwrap(); diff --git a/node-wasm/src/worker.rs b/node-wasm/src/worker.rs index 2b988a76..a9c10029 100644 --- a/node-wasm/src/worker.rs +++ b/node-wasm/src/worker.rs @@ -1,5 +1,6 @@ use std::fmt::Debug; +use blockstore::EitherBlockstore; use js_sys::Array; use libp2p::{Multiaddr, PeerId}; use serde::{Deserialize, Serialize}; @@ -11,10 +12,10 @@ use wasm_bindgen::prelude::*; use wasm_bindgen_futures::spawn_local; use web_sys::BroadcastChannel; -use lumina_node::blockstore::IndexedDbBlockstore; +use lumina_node::blockstore::{InMemoryBlockstore, IndexedDbBlockstore}; use lumina_node::events::{EventSubscriber, NodeEventInfo}; use lumina_node::node::{Node, SyncingInfo}; -use lumina_node::store::{IndexedDbStore, SamplingMetadata}; +use lumina_node::store::{EitherStore, InMemoryStore, IndexedDbStore, SamplingMetadata}; use crate::client::WasmNodeConfig; use crate::commands::{NodeCommand, SingleHeaderQuery, WorkerResponse}; @@ -23,6 +24,9 @@ use crate::ports::{ClientMessage, WorkerServer}; use crate::utils::random_id; use crate::wrapper::libp2p::NetworkInfoSnapshot; +pub(crate) type WasmBlockstore = EitherBlockstore; +pub(crate) type WasmStore = EitherStore; + #[derive(Debug, Serialize, Deserialize, Error)] pub enum WorkerError { /// Worker is initialised, but the node has not been started yet. Use [`NodeDriver::start`]. @@ -53,7 +57,7 @@ pub struct NodeWorker { } struct NodeWorkerInstance { - node: Node, + node: Node, events_channel_name: String, }