From 9a50e301cb149d25603767617fc41078e833bf58 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 30 Mar 2023 18:51:56 +0000 Subject: [PATCH] Avoid connection-per-RPC-call again by caching connections In general, only one request will be in flight at a time in `lightning-block-sync`. Ideally we'd only have one connection, but without using the `futures` mutex type. Here we solve this narrowly for the one-request-at-a-time case by caching the connection and takeing the connection out of the cache while we work on it. --- lightning-block-sync/src/rest.rs | 11 ++++++++--- lightning-block-sync/src/rpc.rs | 12 ++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/lightning-block-sync/src/rest.rs b/lightning-block-sync/src/rest.rs index c2926b7a..43008930 100644 --- a/lightning-block-sync/src/rest.rs +++ b/lightning-block-sync/src/rest.rs @@ -9,10 +9,12 @@ use bitcoin::hashes::hex::ToHex; use std::convert::TryFrom; use std::convert::TryInto; +use std::sync::Mutex; /// A simple REST client for requesting resources using HTTP `GET`. pub struct RestClient { endpoint: HttpEndpoint, + client: Mutex>, } impl RestClient { @@ -20,7 +22,7 @@ impl RestClient { /// /// The endpoint should contain the REST path component (e.g., http://127.0.0.1:8332/rest). pub fn new(endpoint: HttpEndpoint) -> std::io::Result { - Ok(Self { endpoint }) + Ok(Self { endpoint, client: Mutex::new(None) }) } /// Requests a resource encoded in `F` format and interpreted as type `T`. @@ -28,8 +30,11 @@ impl RestClient { where F: TryFrom, Error = std::io::Error> + TryInto { let host = format!("{}:{}", self.endpoint.host(), self.endpoint.port()); let uri = format!("{}/{}", self.endpoint.path().trim_end_matches("/"), resource_path); - let mut client = HttpClient::connect(&self.endpoint)?; - client.get::(&uri, &host).await?.try_into() + let mut client = if let Some(client) = self.client.lock().unwrap().take() { client } + else { HttpClient::connect(&self.endpoint)? }; + let res = client.get::(&uri, &host).await?.try_into(); + *self.client.lock().unwrap() = Some(client); + res } } diff --git a/lightning-block-sync/src/rpc.rs b/lightning-block-sync/src/rpc.rs index 521d94f3..4c4706cb 100644 --- a/lightning-block-sync/src/rpc.rs +++ b/lightning-block-sync/src/rpc.rs @@ -7,6 +7,8 @@ use crate::http::{HttpClient, HttpEndpoint, HttpError, JsonResponse}; use bitcoin::hash_types::BlockHash; use bitcoin::hashes::hex::ToHex; +use std::sync::Mutex; + use serde_json; use std::convert::TryFrom; @@ -39,6 +41,7 @@ impl Error for RpcError {} pub struct RpcClient { basic_auth: String, endpoint: HttpEndpoint, + client: Mutex>, id: AtomicUsize, } @@ -50,6 +53,7 @@ impl RpcClient { Ok(Self { basic_auth: "Basic ".to_string() + credentials, endpoint, + client: Mutex::new(None), id: AtomicUsize::new(0), }) } @@ -68,8 +72,12 @@ impl RpcClient { "id": &self.id.fetch_add(1, Ordering::AcqRel).to_string() }); - let mut client = HttpClient::connect(&self.endpoint)?; - let mut response = match client.post::(&uri, &host, &self.basic_auth, content).await { + let mut client = if let Some(client) = self.client.lock().unwrap().take() { client } + else { HttpClient::connect(&self.endpoint)? }; + let http_response = client.post::(&uri, &host, &self.basic_auth, content).await; + *self.client.lock().unwrap() = Some(client); + + let mut response = match http_response { Ok(JsonResponse(response)) => response, Err(e) if e.kind() == std::io::ErrorKind::Other => { match e.get_ref().unwrap().downcast_ref::() { -- 2.30.2