use std::{net::SocketAddr, sync::Arc};
use anyhow::Result;
use bitcoincash::Network;
use prometheus::HistogramVec;
use crate::{
daemon::CookieGetter,
errors::ConnectionError,
metrics::{default_duration_buckets, default_size_buckets, Metrics},
signal::NetworkNotifier,
};
use super::{p2pconnection::P2PConnection, rpcconnection::RPCConnection};
pub struct BitcoindRPCConnectionManager {
addr: SocketAddr,
cookie_getter: Arc<dyn CookieGetter>,
}
impl BitcoindRPCConnectionManager {
pub fn new(addr: SocketAddr, cookie_getter: Arc<dyn CookieGetter>) -> Self {
Self {
addr,
cookie_getter,
}
}
}
impl bb8::ManageConnection for BitcoindRPCConnectionManager {
type Connection = crate::daemon::rpcconnection::RPCConnection;
type Error = crate::errors::ConnectionError;
async fn connect(&self) -> Result<Self::Connection, Self::Error> {
RPCConnection::new(self.addr, self.cookie_getter.clone())
}
async fn is_valid(&self, conn: &mut Self::Connection) -> Result<(), Self::Error> {
match conn.request("ping", &None).await {
Ok(_) => Ok(()),
Err(e) => Err(Self::Error {
msg: format!("ping failed: {e}"),
}),
}
}
fn has_broken(&self, conn: &mut Self::Connection) -> bool {
conn.is_broken()
}
}
pub struct BitcoindP2PConnectionManager {
network: Network,
addr: SocketAddr,
network_notifier: Arc<NetworkNotifier>,
send_duration: Arc<HistogramVec>,
recv_duration: Arc<HistogramVec>,
parse_duration: Arc<HistogramVec>,
recv_size: Arc<HistogramVec>,
}
impl BitcoindP2PConnectionManager {
pub fn new(
network: Network,
addr: SocketAddr,
network_notifier: Arc<NetworkNotifier>,
metrics: &Metrics,
) -> Self {
let send_duration = Arc::new(metrics.histogram_vec(
"rostrum_p2p_send_duration",
"Time spent sending p2p messages (in seconds)",
&["step"],
default_duration_buckets(),
));
let recv_duration = Arc::new(metrics.histogram_vec(
"rostrum_p2p_recv_duration",
"Time spent receiving p2p messages (in seconds)",
&["step"],
default_duration_buckets(),
));
let parse_duration = Arc::new(metrics.histogram_vec(
"rostrum_p2p_parse_duration",
"Time spent parsing p2p messages (in seconds)",
&["step"],
default_duration_buckets(),
));
let recv_size = Arc::new(metrics.histogram_vec(
"rostrum_p2p_recv_size",
"Size of p2p messages read (in bytes)",
&["message"],
default_size_buckets(),
));
Self {
network,
addr,
network_notifier,
send_duration,
recv_duration,
parse_duration,
recv_size,
}
}
}
impl bb8::ManageConnection for BitcoindP2PConnectionManager {
type Connection = crate::daemon::p2pconnection::P2PConnection;
type Error = crate::errors::ConnectionError;
async fn connect(&self) -> Result<Self::Connection, Self::Error> {
P2PConnection::connect(
self.network,
self.addr,
self.network_notifier.clone(),
Arc::clone(&self.send_duration),
Arc::clone(&self.recv_duration),
Arc::clone(&self.parse_duration),
Arc::clone(&self.recv_size),
)
.await
}
async fn is_valid(&self, conn: &mut Self::Connection) -> Result<(), Self::Error> {
match conn.is_broken() {
true => Ok(()),
false => Err(ConnectionError {
msg: "Connection broken".to_string(),
}),
}
}
fn has_broken(&self, conn: &mut Self::Connection) -> bool {
conn.is_broken()
}
}