Skip to main content

breez_sdk_spark/
connection_manager.rs

1//! Shareable transports for cross-SDK-instance connection reuse.
2
3use std::sync::Arc;
4
5use platform_utils::{HttpClient, create_http_client};
6use spark_wallet::{
7    BalancedConnectionManager, ConnectionManager as InnerConnectionManager,
8    DefaultConnectionManager,
9};
10
11use crate::default_user_agent;
12
13/// A shared HTTP transport for SSP GraphQL traffic.
14///
15/// All SDK instances that are built with the same `SspConnectionManager` send
16/// SSP requests over the same pooled `reqwest::Client`. This means each
17/// process opens at most one TCP+TLS+HTTP/2 connection to the SSP regardless
18/// of how many wallets are loaded — useful for multi-tenant servers running
19/// many SDK instances.
20///
21/// # Caveats
22///
23/// - The user-agent of the first SDK to construct this manager is reused for
24///   all subsequent instances. This is rarely a problem since SDK instances
25///   in one process typically share a build version.
26/// - Connections close when the last `Arc<SspConnectionManager>` is dropped.
27///   `BreezSdk::disconnect` does not close them.
28#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
29pub struct SspConnectionManager {
30    pub(crate) client: Arc<dyn HttpClient>,
31}
32
33/// Construct a new shared SSP connection manager.
34///
35/// Pass the returned `Arc<SspConnectionManager>` to
36/// [`SdkBuilder::with_ssp_connection_manager`](crate::SdkBuilder::with_ssp_connection_manager)
37/// when building each SDK instance that should share the underlying HTTP
38/// connection pool.
39#[cfg_attr(feature = "uniffi", uniffi::export)]
40pub fn new_ssp_connection_manager(user_agent: Option<String>) -> Arc<SspConnectionManager> {
41    let user_agent = user_agent.unwrap_or_else(default_user_agent);
42    Arc::new(SspConnectionManager {
43        client: create_http_client(Some(&user_agent)),
44    })
45}
46
47/// A shareable manager for gRPC connections to the Spark operators.
48///
49/// Construct one via [`new_connection_manager`] and pass the same `Arc` to
50/// multiple [`SdkBuilder`](crate::SdkBuilder)s via
51/// [`SdkBuilder::with_connection_manager`](crate::SdkBuilder::with_connection_manager).
52/// Connections close when the last `Arc<ConnectionManager>` is dropped;
53/// [`BreezSdk::disconnect`](crate::BreezSdk::disconnect) does not affect them.
54///
55/// All SDK instances sharing a `ConnectionManager` must be configured for the
56/// same network and operator pool. The TLS settings and user agent of the
57/// first SDK to connect to a given operator are reused for everyone afterwards.
58#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
59pub struct ConnectionManager {
60    pub(crate) inner: Arc<dyn InnerConnectionManager>,
61}
62
63/// Creates a new shareable [`ConnectionManager`].
64///
65/// `connections_per_operator` controls per-operator connection pooling:
66/// `None` keeps a single connection per operator (suitable for almost every
67/// deployment); `Some(n)` opens `n` connections per operator and balances
68/// requests across them.
69#[cfg_attr(feature = "uniffi", uniffi::export)]
70#[must_use]
71pub fn new_connection_manager(connections_per_operator: Option<u32>) -> Arc<ConnectionManager> {
72    let inner: Arc<dyn InnerConnectionManager> = match connections_per_operator {
73        Some(n) if n > 1 => Arc::new(BalancedConnectionManager::new(n)),
74        _ => Arc::new(DefaultConnectionManager::new()),
75    };
76    Arc::new(ConnectionManager { inner })
77}