Skip to content

Commit

Permalink
feat(nodejs): Silently stop background syncing when Wallet is dropped
Browse files Browse the repository at this point in the history
  • Loading branch information
marc2332 committed Dec 18, 2023
1 parent 8951f4c commit 62e2f2f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 9 deletions.
42 changes: 34 additions & 8 deletions bindings/nodejs/src/wallet.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use std::sync::Arc;
use std::{sync::Arc, ops::{Deref, DerefMut}};

use iota_sdk_bindings_core::{
call_wallet_method as rust_call_wallet_method,
Expand All @@ -16,26 +16,52 @@ use crate::{
build_js_error, client::ClientMethodHandler, destroyed_err, secret_manager::SecretManagerMethodHandler, NodejsError,
};

pub type WalletMethodHandler = Arc<RwLock<Option<Wallet>>>;
pub struct WalletMethodHandlerInner(Option<Wallet>);

impl Drop for WalletMethodHandlerInner {
fn drop(&mut self) {
log::debug!("drop WalletMethodHandlerInner");
// Request to stop the background syncing silently if this wallet hasn't been destroyed yet
if let Some(wallet) = self.0.take() {
wallet.request_stop_background_syncing();
}
}
}

impl Deref for WalletMethodHandlerInner {
type Target = Option<Wallet>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for WalletMethodHandlerInner {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

pub type WalletMethodHandler = Arc<RwLock<WalletMethodHandlerInner>>;

#[napi(js_name = "createWallet")]
pub async fn create_wallet(options: String) -> Result<External<WalletMethodHandler>> {
let wallet_options = serde_json::from_str::<WalletOptions>(&options).map_err(NodejsError::new)?;
let wallet = wallet_options.build().await.map_err(NodejsError::new)?;

Ok(External::new(Arc::new(RwLock::new(Some(wallet)))))
Ok(External::new(Arc::new(RwLock::new(WalletMethodHandlerInner(Some(wallet))))))
}

#[napi(js_name = "destroyWallet")]
pub async fn destroy_wallet(wallet: External<WalletMethodHandler>) {
*wallet.as_ref().write().await = None;
**wallet.as_ref().write().await = None;
}

#[napi(js_name = "callWalletMethod")]
pub async fn call_wallet_method(wallet: External<WalletMethodHandler>, method: String) -> Result<String> {
let method = serde_json::from_str::<WalletMethod>(&method).map_err(NodejsError::new)?;

match &*wallet.as_ref().read().await {
match &**wallet.as_ref().read().await {
Some(wallet) => {
let response = rust_call_wallet_method(&wallet, method).await;
match response {
Expand All @@ -58,7 +84,7 @@ pub async fn listen_wallet(
validated_event_types.push(WalletEventType::try_from(event_type).map_err(NodejsError::new)?);
}

match &*wallet.as_ref().read().await {
match &**wallet.as_ref().read().await {
Some(wallet) => {
wallet
.listen(validated_event_types, move |event_data| {
Expand All @@ -78,7 +104,7 @@ pub async fn listen_wallet(

#[napi(js_name = "getClient")]
pub async fn get_client(wallet: External<WalletMethodHandler>) -> Result<External<ClientMethodHandler>> {
if let Some(wallet) = &*wallet.as_ref().read().await {
if let Some(wallet) = &**wallet.as_ref().read().await {
Ok(External::new(Arc::new(RwLock::new(Some(wallet.client().clone())))))
} else {
Err(destroyed_err("Wallet"))
Expand All @@ -87,7 +113,7 @@ pub async fn get_client(wallet: External<WalletMethodHandler>) -> Result<Externa

#[napi(js_name = "getSecretManager")]
pub async fn get_secret_manager(wallet: External<WalletMethodHandler>) -> Result<External<SecretManagerMethodHandler>> {
if let Some(wallet) = &*wallet.as_ref().read().await {
if let Some(wallet) = &**wallet.as_ref().read().await {
Ok(External::new(wallet.get_secret_manager().clone()))
} else {
Err(destroyed_err("Wallet"))
Expand Down
8 changes: 7 additions & 1 deletion sdk/src/wallet/core/operations/background_syncing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ where
Ok(())
}

/// Request to stop the background syncing of the wallet
pub fn request_stop_background_syncing(&self) {
log::debug!("[request_stop_background_syncing]");
self.background_syncing_status.store(2, Ordering::Relaxed);
}

/// Stop the background syncing of the wallet
pub async fn stop_background_syncing(&self) -> crate::wallet::Result<()> {
log::debug!("[stop_background_syncing]");
Expand All @@ -80,7 +86,7 @@ where
return Ok(());
}
// send stop request
self.background_syncing_status.store(2, Ordering::Relaxed);
self.request_stop_background_syncing();
// wait until it stopped
while self.background_syncing_status.load(Ordering::Relaxed) != 0 {
#[cfg(target_family = "wasm")]
Expand Down

0 comments on commit 62e2f2f

Please sign in to comment.