11
11
12
12
//! Esplora by way of `reqwest` HTTP client.
13
13
14
- use async_std:: task;
15
14
use std:: collections:: HashMap ;
15
+ use std:: marker:: PhantomData ;
16
16
use std:: str:: FromStr ;
17
17
18
18
use bitcoin:: consensus:: { deserialize, serialize, Decodable , Encodable } ;
@@ -35,16 +35,19 @@ use crate::{
35
35
} ;
36
36
37
37
#[ derive( Debug , Clone ) ]
38
- pub struct AsyncClient {
38
+ pub struct AsyncClient < S = DefaultSleeper > {
39
39
/// The URL of the Esplora Server.
40
40
url : String ,
41
41
/// The inner [`reqwest::Client`] to make HTTP requests.
42
42
client : Client ,
43
43
/// Number of times to retry a request
44
44
max_retries : usize ,
45
+
46
+ /// Marker for the type of sleeper used
47
+ marker : PhantomData < S > ,
45
48
}
46
49
47
- impl AsyncClient {
50
+ impl < S : Sleeper > AsyncClient < S > {
48
51
/// Build an async client from a builder
49
52
pub fn from_builder ( builder : Builder ) -> Result < Self , Error > {
50
53
let mut client_builder = Client :: builder ( ) ;
@@ -75,15 +78,16 @@ impl AsyncClient {
75
78
url : builder. base_url ,
76
79
client : client_builder. build ( ) ?,
77
80
max_retries : builder. max_retries ,
81
+ marker : PhantomData ,
78
82
} )
79
83
}
80
84
81
- /// Build an async client from the base url and [`Client`]
82
85
pub fn from_client ( url : String , client : Client ) -> Self {
83
86
AsyncClient {
84
87
url,
85
88
client,
86
89
max_retries : crate :: DEFAULT_MAX_RETRIES ,
90
+ marker : PhantomData ,
87
91
}
88
92
}
89
93
@@ -460,7 +464,7 @@ impl AsyncClient {
460
464
loop {
461
465
match self . client . get ( url) . send ( ) . await ? {
462
466
resp if attempts < self . max_retries && is_status_retryable ( resp. status ( ) ) => {
463
- task :: sleep ( delay) . await ;
467
+ S :: sleep ( delay) . await ;
464
468
attempts += 1 ;
465
469
delay *= 2 ;
466
470
}
@@ -473,3 +477,20 @@ impl AsyncClient {
473
477
fn is_status_retryable ( status : reqwest:: StatusCode ) -> bool {
474
478
RETRYABLE_ERROR_CODES . contains ( & status. as_u16 ( ) )
475
479
}
480
+
481
+ pub trait Sleeper : ' static {
482
+ type Sleep : std:: future:: Future < Output = ( ) > ;
483
+ fn sleep ( dur : std:: time:: Duration ) -> Self :: Sleep ;
484
+ }
485
+
486
+ #[ derive( Debug , Clone , Copy ) ]
487
+ pub struct DefaultSleeper ;
488
+
489
+ #[ cfg( any( test, feature = "tokio" ) ) ]
490
+ impl Sleeper for DefaultSleeper {
491
+ type Sleep = tokio:: time:: Sleep ;
492
+
493
+ fn sleep ( dur : std:: time:: Duration ) -> Self :: Sleep {
494
+ tokio:: time:: sleep ( dur)
495
+ }
496
+ }
0 commit comments