@@ -222,6 +222,40 @@ pub trait CookieGetter: Send + Sync {
222222 fn get ( & self ) -> Result < Vec < u8 > > ;
223223}
224224
225+ #[ derive( Clone ) ]
226+ struct ConnectionConfig {
227+ addr : SocketAddr ,
228+ fallback : Option < SocketAddr > ,
229+ cookie_getter : Arc < dyn CookieGetter > ,
230+ signal : Waiter ,
231+ max_age : Option < Duration > ,
232+ }
233+
234+ impl ConnectionConfig {
235+ fn connect ( & self ) -> Result < Connection > {
236+ Connection :: new (
237+ self . addr ,
238+ self . fallback ,
239+ Arc :: clone ( & self . cookie_getter ) ,
240+ self . signal . clone ( ) ,
241+ self . max_age ,
242+ )
243+ }
244+
245+ fn connect_once ( & self ) -> Result < Connection > {
246+ let ( conn, active_addr) = tcp_connect_once ( self . addr , self . fallback ) ?;
247+ Connection :: from_stream (
248+ conn,
249+ active_addr,
250+ self . addr ,
251+ self . fallback ,
252+ Arc :: clone ( & self . cookie_getter ) ,
253+ self . signal . clone ( ) ,
254+ None , // a one-shot connection never needs proactive recycling
255+ )
256+ }
257+ }
258+
225259struct Connection {
226260 tx : TcpStream ,
227261 rx : Lines < BufReader < TcpStream > > ,
@@ -516,6 +550,7 @@ pub struct Daemon {
516550 daemon_dir : PathBuf ,
517551 blocks_dir : PathBuf ,
518552 network : Network ,
553+ connection_config : ConnectionConfig ,
519554 conn : Mutex < Connection > ,
520555 message_id : Counter , // for monotonic JSONRPC 'id'
521556 signal : Waiter ,
@@ -542,17 +577,20 @@ impl Daemon {
542577 metrics : & Metrics ,
543578 conn_max_age : Option < Duration > ,
544579 ) -> Result < Daemon > {
580+ let connection_config = ConnectionConfig {
581+ addr : daemon_rpc_addr,
582+ fallback : daemon_rpc_fallback_addr,
583+ cookie_getter,
584+ signal : signal. clone ( ) ,
585+ max_age : conn_max_age,
586+ } ;
587+ let conn = connection_config. connect ( ) ?;
545588 let daemon = Daemon {
546589 daemon_dir : daemon_dir. clone ( ) ,
547590 blocks_dir : blocks_dir. clone ( ) ,
548591 network,
549- conn : Mutex :: new ( Connection :: new (
550- daemon_rpc_addr,
551- daemon_rpc_fallback_addr,
552- cookie_getter,
553- signal. clone ( ) ,
554- conn_max_age,
555- ) ?) ,
592+ connection_config,
593+ conn : Mutex :: new ( conn) ,
556594 message_id : Counter :: new ( ) ,
557595 signal : signal. clone ( ) ,
558596 conn_max_age,
@@ -616,6 +654,7 @@ impl Daemon {
616654 daemon_dir : self . daemon_dir . clone ( ) ,
617655 blocks_dir : self . blocks_dir . clone ( ) ,
618656 network : self . network ,
657+ connection_config : self . connection_config . clone ( ) ,
619658 conn : Mutex :: new ( self . conn . lock ( ) . unwrap ( ) . reconnect ( ) ?) ,
620659 message_id : Counter :: new ( ) ,
621660 signal : self . signal . clone ( ) ,
@@ -664,8 +703,12 @@ impl Daemon {
664703 }
665704
666705 #[ trace]
667- fn call_jsonrpc ( & self , method : & str , request : & Value ) -> Result < Value > {
668- let mut conn = self . conn . lock ( ) . unwrap ( ) ;
706+ fn call_jsonrpc_on_connection (
707+ & self ,
708+ method : & str ,
709+ request : & Value ,
710+ conn : & mut Connection ,
711+ ) -> Result < Value > {
669712 // Proactively recycle connections older than the configured max age. Re-establishing
670713 // the TCP connection lets a fronting load balancer (e.g. a Kubernetes ClusterSetIP)
671714 // re-select a backend, so a long-lived connection does not stay pinned to a stale
@@ -711,6 +754,12 @@ impl Daemon {
711754 Ok ( result)
712755 }
713756
757+ #[ trace]
758+ fn call_jsonrpc ( & self , method : & str , request : & Value ) -> Result < Value > {
759+ let mut conn = self . conn . lock ( ) . unwrap ( ) ;
760+ self . call_jsonrpc_on_connection ( method, request, & mut conn)
761+ }
762+
714763 #[ trace( method = %method) ]
715764 fn handle_request ( & self , method : & str , params : & Value ) -> Result < Value > {
716765 let id = self . message_id . next ( ) ;
@@ -746,9 +795,15 @@ impl Daemon {
746795 self . retry_request ( method, & params)
747796 }
748797
798+ /// Perform one RPC on a fresh connection isolated from singleton RPC users.
799+ /// Connection and warmup failures are returned to the caller without retrying.
749800 #[ trace]
750- fn request_no_retry ( & self , method : & str , params : Value ) -> Result < Value > {
751- self . handle_request ( method, & params)
801+ fn request_once ( & self , method : & str , params : Value ) -> Result < Value > {
802+ let id = self . message_id . next ( ) ;
803+ let req = json ! ( { "method" : method, "params" : params, "id" : id} ) ;
804+ let mut conn = self . connection_config . connect_once ( ) ?;
805+ let reply = self . call_jsonrpc_on_connection ( method, & req, & mut conn) ?;
806+ parse_jsonrpc_reply ( reply, method, id)
752807 }
753808
754809 #[ trace]
@@ -938,9 +993,20 @@ impl Daemon {
938993 Ok ( serde_json:: from_value ( res) . chain_err ( || "invalid getrawmempool reply" ) ?)
939994 }
940995
996+ #[ cfg( not( feature = "liquid" ) ) ]
941997 #[ trace]
942998 pub fn getblocktemplate ( & self , rules : & [ & str ] ) -> Result < Value > {
943- self . request_no_retry ( "getblocktemplate" , json ! ( [ { "rules" : rules } ] ) )
999+ self . request_once ( "getblocktemplate" , json ! ( [ { "rules" : rules } ] ) )
1000+ }
1001+
1002+ #[ cfg( feature = "liquid" ) ]
1003+ #[ trace]
1004+ pub fn getnewblockhex ( & self ) -> Result < String > {
1005+ let value = self . request_once ( "getnewblockhex" , json ! ( [ ] ) ) ?;
1006+ value
1007+ . as_str ( )
1008+ . map ( str:: to_owned)
1009+ . chain_err ( || "non-string getnewblockhex response" )
9441010 }
9451011
9461012 #[ trace]
0 commit comments