2022-03-09 18:33:05 -08:00
|
|
|
//! Simple client that connects to a given UDP port with the QUIC protocol and provides
|
|
|
|
//! an interface for sending transactions which is restricted by the server's flow control.
|
|
|
|
|
|
|
|
use {
|
2022-04-12 20:04:40 -07:00
|
|
|
crate::{
|
2022-05-19 12:29:27 -07:00
|
|
|
connection_cache::ConnectionCacheStats,
|
2022-06-10 09:25:24 -07:00
|
|
|
nonblocking::quic_client::{QuicClient, QuicLazyInitializedEndpoint},
|
2022-04-12 20:04:40 -07:00
|
|
|
tpu_connection::{ClientStats, TpuConnection},
|
|
|
|
},
|
2022-04-12 07:15:59 -07:00
|
|
|
lazy_static::lazy_static,
|
|
|
|
log::*,
|
2022-06-10 09:25:24 -07:00
|
|
|
solana_sdk::transport::Result as TransportResult,
|
2022-06-01 16:20:11 -07:00
|
|
|
std::{net::SocketAddr, sync::Arc},
|
2022-03-09 18:33:05 -08:00
|
|
|
tokio::runtime::Runtime,
|
|
|
|
};
|
|
|
|
|
2022-04-12 07:15:59 -07:00
|
|
|
lazy_static! {
|
|
|
|
static ref RUNTIME: Runtime = tokio::runtime::Builder::new_multi_thread()
|
|
|
|
.enable_all()
|
|
|
|
.build()
|
|
|
|
.unwrap();
|
|
|
|
}
|
2022-03-09 18:33:05 -08:00
|
|
|
|
|
|
|
pub struct QuicTpuConnection {
|
|
|
|
client: Arc<QuicClient>,
|
2022-05-19 12:29:27 -07:00
|
|
|
connection_stats: Arc<ConnectionCacheStats>,
|
2022-03-09 18:33:05 -08:00
|
|
|
}
|
|
|
|
|
2022-04-12 20:04:40 -07:00
|
|
|
impl QuicTpuConnection {
|
|
|
|
pub fn base_stats(&self) -> Arc<ClientStats> {
|
2022-06-01 16:20:11 -07:00
|
|
|
self.client.stats()
|
2022-04-12 20:04:40 -07:00
|
|
|
}
|
|
|
|
|
2022-06-10 09:25:24 -07:00
|
|
|
pub fn new(
|
|
|
|
endpoint: Arc<QuicLazyInitializedEndpoint>,
|
|
|
|
tpu_addr: SocketAddr,
|
|
|
|
connection_stats: Arc<ConnectionCacheStats>,
|
|
|
|
) -> Self {
|
|
|
|
let client = Arc::new(QuicClient::new(endpoint, tpu_addr));
|
2022-03-09 18:33:05 -08:00
|
|
|
|
2022-05-19 12:29:27 -07:00
|
|
|
Self {
|
|
|
|
client,
|
|
|
|
connection_stats,
|
|
|
|
}
|
2022-03-09 18:33:05 -08:00
|
|
|
}
|
2022-05-26 08:21:16 -07:00
|
|
|
}
|
2022-03-09 18:33:05 -08:00
|
|
|
|
2022-05-26 08:21:16 -07:00
|
|
|
impl TpuConnection for QuicTpuConnection {
|
2022-03-09 18:33:05 -08:00
|
|
|
fn tpu_addr(&self) -> &SocketAddr {
|
2022-06-01 16:20:11 -07:00
|
|
|
self.client.tpu_addr()
|
2022-03-09 18:33:05 -08:00
|
|
|
}
|
|
|
|
|
2022-05-26 08:21:16 -07:00
|
|
|
fn send_wire_transaction_batch<T>(&self, buffers: &[T]) -> TransportResult<()>
|
2022-03-24 08:40:26 -07:00
|
|
|
where
|
|
|
|
T: AsRef<[u8]>,
|
|
|
|
{
|
2022-05-26 08:21:16 -07:00
|
|
|
let stats = ClientStats::default();
|
|
|
|
let len = buffers.len();
|
2022-04-12 07:15:59 -07:00
|
|
|
let _guard = RUNTIME.enter();
|
2022-05-19 12:29:27 -07:00
|
|
|
let send_batch = self
|
|
|
|
.client
|
2022-05-26 08:21:16 -07:00
|
|
|
.send_batch(buffers, &stats, self.connection_stats.clone());
|
|
|
|
let res = RUNTIME.block_on(send_batch);
|
|
|
|
self.connection_stats
|
|
|
|
.add_client_stats(&stats, len, res.is_ok());
|
|
|
|
res?;
|
2022-04-12 07:15:59 -07:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-05-26 08:21:16 -07:00
|
|
|
fn send_wire_transaction_async(&self, wire_transaction: Vec<u8>) -> TransportResult<()> {
|
|
|
|
let stats = Arc::new(ClientStats::default());
|
2022-04-12 07:15:59 -07:00
|
|
|
let _guard = RUNTIME.enter();
|
|
|
|
let client = self.client.clone();
|
2022-05-19 12:29:27 -07:00
|
|
|
let connection_stats = self.connection_stats.clone();
|
2022-04-14 19:20:34 -07:00
|
|
|
//drop and detach the task
|
2022-04-12 07:15:59 -07:00
|
|
|
let _ = RUNTIME.spawn(async move {
|
2022-05-26 08:21:16 -07:00
|
|
|
let send_buffer =
|
|
|
|
client.send_buffer(wire_transaction, &stats, connection_stats.clone());
|
2022-04-12 07:15:59 -07:00
|
|
|
if let Err(e) = send_buffer.await {
|
2022-06-10 09:25:24 -07:00
|
|
|
warn!(
|
|
|
|
"Failed to send transaction async to {}, error: {:?} ",
|
|
|
|
client.tpu_addr(),
|
|
|
|
e
|
|
|
|
);
|
2022-04-14 19:20:34 -07:00
|
|
|
datapoint_warn!("send-wire-async", ("failure", 1, i64),);
|
2022-05-26 08:21:16 -07:00
|
|
|
connection_stats.add_client_stats(&stats, 1, false);
|
|
|
|
} else {
|
|
|
|
connection_stats.add_client_stats(&stats, 1, true);
|
2022-04-14 19:20:34 -07:00
|
|
|
}
|
|
|
|
});
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-05-26 08:21:16 -07:00
|
|
|
fn send_wire_transaction_batch_async(&self, buffers: Vec<Vec<u8>>) -> TransportResult<()> {
|
|
|
|
let stats = Arc::new(ClientStats::default());
|
2022-04-14 19:20:34 -07:00
|
|
|
let _guard = RUNTIME.enter();
|
|
|
|
let client = self.client.clone();
|
2022-05-19 12:29:27 -07:00
|
|
|
let connection_stats = self.connection_stats.clone();
|
2022-05-26 08:21:16 -07:00
|
|
|
let len = buffers.len();
|
2022-04-14 19:20:34 -07:00
|
|
|
//drop and detach the task
|
|
|
|
let _ = RUNTIME.spawn(async move {
|
2022-05-26 08:21:16 -07:00
|
|
|
let send_batch = client.send_batch(&buffers, &stats, connection_stats.clone());
|
2022-04-14 19:20:34 -07:00
|
|
|
if let Err(e) = send_batch.await {
|
|
|
|
warn!("Failed to send transaction batch async to {:?}", e);
|
|
|
|
datapoint_warn!("send-wire-batch-async", ("failure", 1, i64),);
|
2022-05-26 08:21:16 -07:00
|
|
|
connection_stats.add_client_stats(&stats, len, false);
|
|
|
|
} else {
|
|
|
|
connection_stats.add_client_stats(&stats, len, true);
|
2022-04-12 07:15:59 -07:00
|
|
|
}
|
|
|
|
});
|
2022-03-09 18:33:05 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|