Skip to content

Commit

Permalink
feat: Add requesting storage persistence for more quota (#318)
Browse files Browse the repository at this point in the history
  • Loading branch information
fl0rek authored Jul 5, 2024
1 parent 24b8bc4 commit 9866347
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 4 deletions.
1 change: 1 addition & 0 deletions node-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ web-sys = { version = "0.3.69", features = [
"Navigator",
"SharedWorker",
"SharedWorkerGlobalScope",
"StorageManager",
"Worker",
"WorkerGlobalScope",
"WorkerOptions",
Expand Down
27 changes: 25 additions & 2 deletions node-wasm/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! Error type and utilities.
use std::fmt::Display;
use std::fmt::{self, Display};

use serde::{Deserialize, Serialize};
use wasm_bindgen::convert::IntoWasmAbi;
use wasm_bindgen::describe::WasmDescribe;
use wasm_bindgen::JsValue;
use wasm_bindgen::{JsCast, JsValue};

/// Alias for a `Result` with the error type [`Error`].
pub type Result<T, E = Error> = std::result::Result<T, E>;
Expand Down Expand Up @@ -50,6 +50,29 @@ impl Error {
}
}

impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
let Some(error) = self.0.dyn_ref::<js_sys::Error>() else {
return write!(f, "{:?}", self.0.as_string());
};

write!(f, "{} ({})", error.name(), error.message())?;

let mut cause = error.cause();
loop {
if let Some(error) = cause.dyn_ref::<js_sys::Error>() {
write!(f, "\n{} ({})", error.name(), error.message())?;
cause = error.cause();
} else {
write!(f, "\n{:?}", cause.as_string())?;
break;
}
}

Ok(())
}
}

// Similar to https://github.com/rustwasm/wasm-bindgen/blob/9b37613bbab0cd71f55dcc782d59dd00c1d4d200/src/describe.rs#L218-L222
//
// This is needed to impl IntoWasmAbi.
Expand Down
7 changes: 6 additions & 1 deletion node-wasm/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use libp2p::identity::Keypair;
use libp2p::multiaddr::Protocol;
use serde::{Deserialize, Serialize};
use serde_wasm_bindgen::to_value;
use tracing::error;
use wasm_bindgen::prelude::*;
use web_sys::BroadcastChannel;

Expand All @@ -14,7 +15,7 @@ use lumina_node::node::NodeConfig;
use lumina_node::store::IndexedDbStore;

use crate::error::{Context, Result};
use crate::utils::{is_chrome, js_value_from_display, Network};
use crate::utils::{is_chrome, js_value_from_display, request_storage_persistence, Network};
use crate::worker::commands::{CheckableResponseExt, NodeCommand, SingleHeaderQuery};
use crate::worker::{AnyWorker, WorkerClient};
use crate::wrapper::libp2p::NetworkInfoSnapshot;
Expand Down Expand Up @@ -89,6 +90,10 @@ impl NodeDriver {
worker_script_url: &str,
worker_type: Option<NodeWorkerKind>,
) -> Result<NodeDriver> {
if let Err(e) = request_storage_persistence().await {
error!("Error requesting storage persistence: {e}");
}

// For chrome we default to running in a dedicated Worker because:
// 1. Chrome Android does not support SharedWorkers at all
// 2. On desktop Chrome, restarting Lumina's worker causes all network connections to fail.
Expand Down
29 changes: 29 additions & 0 deletions node-wasm/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use lumina_node::network;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use tracing::{info, warn};
use tracing_subscriber::filter::LevelFilter;
use tracing_subscriber::fmt::format::Pretty;
use tracing_subscriber::fmt::time::UtcTime;
Expand Down Expand Up @@ -150,6 +151,34 @@ where
}
}

/// Request persistent storage from user for us, which has side effect of increasing the quota we
/// have. This function doesn't `await` on JavaScript promise, as that would block until user
/// either allows or blocks our request in a prompt (and we cannot do much with the result anyway).
pub(crate) async fn request_storage_persistence() -> Result<(), Error> {
let fullfiled = Closure::once(move |granted: JsValue| {
if granted.is_truthy() {
info!("Storage persistence acquired: {:?}", granted);
} else {
warn!("User rejected storage persistance request")
}
});
let rejected = Closure::once(move |_ev: JsValue| {
warn!("Error during persistant storage request");
});

// don't drop the promise, we'll log the result and hope the user clicked the right button
let _promise = get_navigator()?
.storage()
.persist()?
.then2(&fullfiled, &rejected);

// stop rust from dropping them
fullfiled.forget();
rejected.forget();

Ok(())
}

const CHROME_USER_AGENT_DETECTION_STR: &str = "Chrome/";

// Currently, there's an issue with SharedWorkers on Chrome where restarting Lumina's worker
Expand Down
2 changes: 1 addition & 1 deletion node-wasm/src/worker/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ impl AnyWorker {

fn setup_on_error_callback(&self) -> Closure<dyn Fn(MessageEvent)> {
let onerror = Closure::new(|ev: MessageEvent| {
error!("received error from Worker: {:?}", ev.to_string());
error!("received error from Worker: {:?}", ev);
});
match self {
AnyWorker::SharedWorker(worker) => {
Expand Down

0 comments on commit 9866347

Please sign in to comment.