-
Notifications
You must be signed in to change notification settings - Fork 221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add sync rpc client pool to wallet connectivity #3199
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -27,11 +27,12 @@ use futures::{ | |||||
SinkExt, | ||||||
}; | ||||||
use tari_comms::{peer_manager::NodeId, protocol::rpc::RpcClientLease}; | ||||||
use tari_core::base_node::rpc; | ||||||
use tari_core::base_node::{rpc::BaseNodeWalletRpcClient, sync::rpc::BaseNodeSyncRpcClient}; | ||||||
use tokio::sync::watch; | ||||||
|
||||||
pub enum WalletConnectivityRequest { | ||||||
ObtainBaseNodeWalletRpcClient(oneshot::Sender<RpcClientLease<rpc::BaseNodeWalletRpcClient>>), | ||||||
ObtainBaseNodeWalletRpcClient(oneshot::Sender<RpcClientLease<BaseNodeWalletRpcClient>>), | ||||||
ObtainBaseNodeSyncRpcClient(oneshot::Sender<RpcClientLease<BaseNodeSyncRpcClient>>), | ||||||
SetBaseNode(NodeId), | ||||||
} | ||||||
|
||||||
|
@@ -68,7 +69,7 @@ impl WalletConnectivityHandle { | |||||
/// node/nodes. It will be block until this is happens. The ONLY other time it will return is if the node is | ||||||
/// shutting down, where it will return None. Use this function whenever no work can be done without a | ||||||
/// BaseNodeWalletRpcClient RPC session. | ||||||
pub async fn obtain_base_node_rpc_client(&mut self) -> Option<RpcClientLease<rpc::BaseNodeWalletRpcClient>> { | ||||||
pub async fn obtain_base_node_wallet_rpc_client(&mut self) -> Option<RpcClientLease<BaseNodeWalletRpcClient>> { | ||||||
let (reply_tx, reply_rx) = oneshot::channel(); | ||||||
// Under what conditions do the (1) mpsc channel and (2) oneshot channel error? | ||||||
// (1) when the receiver has been dropped | ||||||
|
@@ -85,6 +86,22 @@ impl WalletConnectivityHandle { | |||||
reply_rx.await.ok() | ||||||
} | ||||||
|
||||||
/// Obtain a BaseNodeSyncRpcClient. | ||||||
/// | ||||||
/// This can be relied on to obtain a pooled BaseNodeSyncRpcClient rpc session from a currently selected base | ||||||
/// node/nodes. It will be block until this is happens. The ONLY other time it will return is if the node is | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
/// shutting down, where it will return None. Use this function whenever no work can be done without a | ||||||
/// BaseNodeSyncRpcClient RPC session. | ||||||
pub async fn obtain_base_node_sync_rpc_client(&mut self) -> Option<RpcClientLease<BaseNodeSyncRpcClient>> { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where will this be used in the wallet? Is it for |
||||||
let (reply_tx, reply_rx) = oneshot::channel(); | ||||||
self.sender | ||||||
.send(WalletConnectivityRequest::ObtainBaseNodeSyncRpcClient(reply_tx)) | ||||||
.await | ||||||
.ok()?; | ||||||
|
||||||
reply_rx.await.ok() | ||||||
} | ||||||
|
||||||
pub async fn get_connectivity_status(&mut self) -> OnlineStatus { | ||||||
self.online_status_rx.recv().await.unwrap_or(OnlineStatus::Offline) | ||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,7 +36,7 @@ use tari_comms::{ | |
peer_manager::NodeId, | ||
protocol::rpc::{RpcClientLease, RpcClientPool}, | ||
}; | ||
use tari_core::base_node::rpc; | ||
use tari_core::base_node::{rpc::BaseNodeWalletRpcClient, sync::rpc::BaseNodeSyncRpcClient}; | ||
use tokio::time; | ||
|
||
const LOG_TARGET: &str = "wallet::connectivity"; | ||
|
@@ -54,9 +54,14 @@ pub struct WalletConnectivityService { | |
request_stream: Fuse<mpsc::Receiver<WalletConnectivityRequest>>, | ||
connectivity: ConnectivityRequester, | ||
base_node_watch: Watch<Option<NodeId>>, | ||
base_node_wallet_rpc_client_pool: Option<RpcClientPool<rpc::BaseNodeWalletRpcClient>>, | ||
pools: Option<ClientPoolContainer>, | ||
online_status_watch: Watch<OnlineStatus>, | ||
pending_base_node_rpc_requests: Vec<oneshot::Sender<RpcClientLease<rpc::BaseNodeWalletRpcClient>>>, | ||
pending_requests: Vec<ReplyOneshot>, | ||
} | ||
|
||
struct ClientPoolContainer { | ||
pub base_node_wallet_rpc_client: RpcClientPool<BaseNodeWalletRpcClient>, | ||
pub base_node_sync_rpc_client: RpcClientPool<BaseNodeSyncRpcClient>, | ||
} | ||
|
||
impl WalletConnectivityService { | ||
|
@@ -72,8 +77,8 @@ impl WalletConnectivityService { | |
request_stream: request_stream.fuse(), | ||
connectivity, | ||
base_node_watch, | ||
base_node_wallet_rpc_client_pool: None, | ||
pending_base_node_rpc_requests: Vec::new(), | ||
pools: None, | ||
pending_requests: Vec::new(), | ||
online_status_watch, | ||
} | ||
} | ||
|
@@ -100,7 +105,10 @@ impl WalletConnectivityService { | |
use WalletConnectivityRequest::*; | ||
match request { | ||
ObtainBaseNodeWalletRpcClient(reply) => { | ||
self.handle_get_base_node_wallet_rpc_client(reply).await; | ||
self.handle_pool_request(reply.into()).await; | ||
}, | ||
ObtainBaseNodeSyncRpcClient(reply) => { | ||
self.handle_pool_request(reply.into()).await; | ||
}, | ||
|
||
SetBaseNode(peer) => { | ||
|
@@ -109,12 +117,20 @@ impl WalletConnectivityService { | |
} | ||
} | ||
|
||
async fn handle_pool_request(&mut self, reply: ReplyOneshot) { | ||
use ReplyOneshot::*; | ||
match reply { | ||
WalletRpc(tx) => self.handle_get_base_node_wallet_rpc_client(tx).await, | ||
SyncRpc(tx) => self.handle_get_base_node_sync_rpc_client(tx).await, | ||
} | ||
} | ||
|
||
async fn handle_get_base_node_wallet_rpc_client( | ||
&mut self, | ||
reply: oneshot::Sender<RpcClientLease<rpc::BaseNodeWalletRpcClient>>, | ||
reply: oneshot::Sender<RpcClientLease<BaseNodeWalletRpcClient>>, | ||
) { | ||
match self.base_node_wallet_rpc_client_pool { | ||
Some(ref pool) => match pool.get().await { | ||
match self.pools { | ||
Some(ref pools) => match pools.base_node_wallet_rpc_client.get().await { | ||
Ok(client) => { | ||
let _ = reply.send(client); | ||
}, | ||
|
@@ -124,16 +140,47 @@ impl WalletConnectivityService { | |
"Base node connection failed: {}. Reconnecting...", e | ||
); | ||
self.trigger_reconnect(); | ||
self.pending_base_node_rpc_requests.push(reply); | ||
self.pending_requests.push(reply.into()); | ||
}, | ||
}, | ||
None => { | ||
self.pending_base_node_rpc_requests.push(reply); | ||
self.pending_requests.push(reply.into()); | ||
if self.base_node_watch.borrow().is_none() { | ||
warn!( | ||
target: LOG_TARGET, | ||
"{} requests are waiting for base node to be set", | ||
self.pending_base_node_rpc_requests.len() | ||
self.pending_requests.len() | ||
); | ||
} | ||
}, | ||
} | ||
} | ||
|
||
async fn handle_get_base_node_sync_rpc_client( | ||
&mut self, | ||
reply: oneshot::Sender<RpcClientLease<BaseNodeSyncRpcClient>>, | ||
) { | ||
match self.pools { | ||
Some(ref pools) => match pools.base_node_sync_rpc_client.get().await { | ||
Ok(client) => { | ||
let _ = reply.send(client); | ||
}, | ||
Err(e) => { | ||
warn!( | ||
target: LOG_TARGET, | ||
"Base node connection failed: {}. Reconnecting...", e | ||
); | ||
self.trigger_reconnect(); | ||
self.pending_requests.push(reply.into()); | ||
}, | ||
}, | ||
None => { | ||
self.pending_requests.push(reply.into()); | ||
if self.base_node_watch.borrow().is_none() { | ||
warn!( | ||
target: LOG_TARGET, | ||
"{} requests are waiting for base node to be set", | ||
self.pending_requests.len() | ||
); | ||
} | ||
}, | ||
|
@@ -151,12 +198,12 @@ impl WalletConnectivityService { | |
} | ||
|
||
fn set_base_node_peer(&mut self, peer: NodeId) { | ||
self.base_node_wallet_rpc_client_pool = None; | ||
self.pools = None; | ||
self.base_node_watch.broadcast(Some(peer)); | ||
} | ||
|
||
async fn setup_base_node_connection(&mut self, peer: NodeId) { | ||
self.base_node_wallet_rpc_client_pool = None; | ||
self.pools = None; | ||
loop { | ||
debug!( | ||
target: LOG_TARGET, | ||
|
@@ -194,8 +241,10 @@ impl WalletConnectivityService { | |
"Successfully established peer connection to base node {}", | ||
conn.peer_node_id() | ||
); | ||
let pool = conn.create_rpc_client_pool(self.config.base_node_rpc_pool_size); | ||
self.base_node_wallet_rpc_client_pool = Some(pool); | ||
self.pools = Some(ClientPoolContainer { | ||
base_node_sync_rpc_client: conn.create_rpc_client_pool(self.config.base_node_rpc_pool_size), | ||
base_node_wallet_rpc_client: conn.create_rpc_client_pool(self.config.base_node_rpc_pool_size), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
}); | ||
self.notify_pending_requests().await?; | ||
debug!( | ||
target: LOG_TARGET, | ||
|
@@ -206,14 +255,40 @@ impl WalletConnectivityService { | |
} | ||
|
||
async fn notify_pending_requests(&mut self) -> Result<(), WalletConnectivityError> { | ||
let current_pending = mem::take(&mut self.pending_base_node_rpc_requests); | ||
let current_pending = mem::take(&mut self.pending_requests); | ||
for reply in current_pending { | ||
if reply.is_canceled() { | ||
continue; | ||
} | ||
|
||
self.handle_get_base_node_wallet_rpc_client(reply).await; | ||
self.handle_pool_request(reply).await; | ||
} | ||
Ok(()) | ||
} | ||
} | ||
|
||
enum ReplyOneshot { | ||
WalletRpc(oneshot::Sender<RpcClientLease<BaseNodeWalletRpcClient>>), | ||
SyncRpc(oneshot::Sender<RpcClientLease<BaseNodeSyncRpcClient>>), | ||
} | ||
|
||
impl ReplyOneshot { | ||
pub fn is_canceled(&self) -> bool { | ||
use ReplyOneshot::*; | ||
match self { | ||
WalletRpc(tx) => tx.is_canceled(), | ||
SyncRpc(tx) => tx.is_canceled(), | ||
} | ||
} | ||
} | ||
|
||
impl From<oneshot::Sender<RpcClientLease<BaseNodeWalletRpcClient>>> for ReplyOneshot { | ||
fn from(tx: oneshot::Sender<RpcClientLease<BaseNodeWalletRpcClient>>) -> Self { | ||
ReplyOneshot::WalletRpc(tx) | ||
} | ||
} | ||
impl From<oneshot::Sender<RpcClientLease<BaseNodeSyncRpcClient>>> for ReplyOneshot { | ||
fn from(tx: oneshot::Sender<RpcClientLease<BaseNodeSyncRpcClient>>) -> Self { | ||
ReplyOneshot::SyncRpc(tx) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.