use super::{RawRpcFuture, RawRpcSubscription, RpcClientT};
use std::sync::{
Arc,
atomic::{AtomicUsize, Ordering},
};
#[derive(Clone, Debug)]
pub struct RoundRobinRpcClient<Client> {
inner: Arc<RoundRobinRpcClientInner<Client>>,
}
#[derive(Debug)]
struct RoundRobinRpcClientInner<Client> {
clients: Vec<Client>,
next_index: AtomicUsize,
}
impl<Client: RpcClientT> RoundRobinRpcClient<Client> {
pub fn new(clients: Vec<Client>) -> Self {
assert!(!clients.is_empty(), "At least one client must be provided");
Self {
inner: Arc::new(RoundRobinRpcClientInner {
clients,
next_index: AtomicUsize::new(0),
}),
}
}
fn next_client(&self) -> &Client {
let idx = self.next_index();
&self.inner.clients[idx]
}
fn next_index(&self) -> usize {
self.inner.next_index.fetch_add(1, Ordering::Relaxed) % self.inner.clients.len()
}
}
impl<Client: RpcClientT> RpcClientT for RoundRobinRpcClient<Client> {
fn request_raw<'a>(
&'a self,
method: &'a str,
params: Option<Box<serde_json::value::RawValue>>,
) -> RawRpcFuture<'a, Box<serde_json::value::RawValue>> {
let client = self.next_client();
client.request_raw(method, params)
}
fn subscribe_raw<'a>(
&'a self,
sub: &'a str,
params: Option<Box<serde_json::value::RawValue>>,
unsub: &'a str,
) -> RawRpcFuture<'a, RawRpcSubscription> {
let client = self.next_client();
client.subscribe_raw(sub, params, unsub)
}
}