11use crate :: auth:: { ClientCertificate , ConnectionTLSConfig , MutualTLS } ;
22use crate :: errors:: { Error , Result } ;
3+ use backon:: ExponentialBuilder ;
34#[ cfg( feature = "unstable-bolt-protocol-impl-v2" ) ]
45use serde:: { Deserialize , Deserializer , Serialize } ;
56use std:: path:: Path ;
@@ -67,6 +68,87 @@ pub struct LiveConfig {
6768 pub ( crate ) fetch_size : usize ,
6869}
6970
71+ #[ derive( Debug , Clone , PartialEq ) ]
72+ pub struct BackoffConfig {
73+ pub ( crate ) multiplier : Option < f32 > ,
74+ pub ( crate ) min_delay_ms : Option < u64 > ,
75+ pub ( crate ) max_delay_ms : Option < u64 > ,
76+ pub ( crate ) total_delay_ms : Option < u64 > ,
77+ }
78+
79+ impl Default for BackoffConfig {
80+ fn default ( ) -> Self {
81+ BackoffConfig {
82+ multiplier : Some ( 2.0 ) ,
83+ min_delay_ms : Some ( 1 ) ,
84+ max_delay_ms : Some ( 10000 ) ,
85+ total_delay_ms : Some ( 60000 ) ,
86+ }
87+ }
88+ }
89+
90+ impl BackoffConfig {
91+ pub fn to_exponential_builder ( & self ) -> ExponentialBuilder {
92+ ExponentialBuilder :: new ( )
93+ . with_jitter ( )
94+ . with_factor ( self . multiplier . unwrap_or ( 2.0 ) )
95+ . without_max_times ( )
96+ . with_min_delay ( std:: time:: Duration :: from_millis (
97+ self . min_delay_ms . unwrap_or ( 1 ) ,
98+ ) )
99+ . with_max_delay ( std:: time:: Duration :: from_millis (
100+ self . max_delay_ms . unwrap_or ( 10_000 ) ,
101+ ) )
102+ . with_total_delay ( Some ( std:: time:: Duration :: from_millis (
103+ self . total_delay_ms . unwrap_or ( 60_000 ) ,
104+ ) ) )
105+ }
106+ }
107+
108+ #[ derive( Default ) ]
109+ pub struct BackoffConfigBuilder {
110+ multiplier : Option < f32 > ,
111+ min_delay_ms : Option < u64 > ,
112+ max_delay_ms : Option < u64 > ,
113+ total_delay_ms : Option < u64 > ,
114+ }
115+
116+ #[ allow( dead_code) ]
117+ impl BackoffConfigBuilder {
118+ pub fn new ( ) -> Self {
119+ Self :: default ( )
120+ }
121+
122+ pub fn with_multiplier ( mut self , multiplier : f32 ) -> Self {
123+ self . multiplier = Some ( multiplier) ;
124+ self
125+ }
126+
127+ pub fn with_min_delay_ms ( mut self , min_delay_ms : u64 ) -> Self {
128+ self . min_delay_ms = Some ( min_delay_ms) ;
129+ self
130+ }
131+
132+ pub fn with_max_delay_ms ( mut self , max_delay_ms : u64 ) -> Self {
133+ self . max_delay_ms = Some ( max_delay_ms) ;
134+ self
135+ }
136+
137+ pub fn with_total_delay_ms ( mut self , max_total_delay_ms : Option < u64 > ) -> Self {
138+ self . total_delay_ms = max_total_delay_ms;
139+ self
140+ }
141+
142+ pub fn build ( self ) -> BackoffConfig {
143+ BackoffConfig {
144+ multiplier : self . multiplier ,
145+ min_delay_ms : self . min_delay_ms ,
146+ max_delay_ms : self . max_delay_ms ,
147+ total_delay_ms : self . total_delay_ms ,
148+ }
149+ }
150+ }
151+
70152/// The configuration used to connect to the database, see [`crate::Graph::connect`].
71153#[ derive( Debug , Clone ) ]
72154pub struct Config {
@@ -77,6 +159,7 @@ pub struct Config {
77159 pub ( crate ) db : Option < Database > ,
78160 pub ( crate ) fetch_size : usize ,
79161 pub ( crate ) tls_config : ConnectionTLSConfig ,
162+ pub ( crate ) backoff : Option < BackoffConfig > ,
80163}
81164
82165impl Config {
@@ -97,6 +180,7 @@ pub struct ConfigBuilder {
97180 fetch_size : usize ,
98181 max_connections : usize ,
99182 tls_config : ConnectionTLSConfig ,
183+ backoff_config : Option < BackoffConfig > ,
100184}
101185
102186impl ConfigBuilder {
@@ -178,6 +262,11 @@ impl ConfigBuilder {
178262 self
179263 }
180264
265+ pub fn with_backoff ( mut self , backoff : Option < BackoffConfig > ) -> Self {
266+ self . backoff_config = backoff;
267+ self
268+ }
269+
181270 pub fn build ( self ) -> Result < Config > {
182271 if let ( Some ( uri) , Some ( user) , Some ( password) ) = ( self . uri , self . user , self . password ) {
183272 Ok ( Config {
@@ -188,6 +277,7 @@ impl ConfigBuilder {
188277 max_connections : self . max_connections ,
189278 db : self . db ,
190279 tls_config : self . tls_config ,
280+ backoff : self . backoff_config ,
191281 } )
192282 } else {
193283 Err ( Error :: InvalidConfig )
@@ -205,6 +295,7 @@ impl Default for ConfigBuilder {
205295 max_connections : DEFAULT_MAX_CONNECTIONS ,
206296 fetch_size : DEFAULT_FETCH_SIZE ,
207297 tls_config : ConnectionTLSConfig :: None ,
298+ backoff_config : Some ( BackoffConfig :: default ( ) ) ,
208299 }
209300 }
210301}
@@ -222,6 +313,7 @@ mod tests {
222313 . db ( "some_db" )
223314 . fetch_size ( 10 )
224315 . max_connections ( 5 )
316+ . with_backoff ( None )
225317 . build ( )
226318 . unwrap ( ) ;
227319 assert_eq ! ( config. uri, "127.0.0.1:7687" ) ;
@@ -231,6 +323,7 @@ mod tests {
231323 assert_eq ! ( config. fetch_size, 10 ) ;
232324 assert_eq ! ( config. max_connections, 5 ) ;
233325 assert_eq ! ( config. tls_config, ConnectionTLSConfig :: None ) ;
326+ assert_eq ! ( config. backoff, None ) ;
234327 }
235328
236329 #[ test]
@@ -248,6 +341,8 @@ mod tests {
248341 assert_eq ! ( config. fetch_size, 200 ) ;
249342 assert_eq ! ( config. max_connections, 16 ) ;
250343 assert_eq ! ( config. tls_config, ConnectionTLSConfig :: None ) ;
344+ assert ! ( config. backoff. is_some( ) ) ;
345+ assert_eq ! ( config. backoff. as_ref( ) . unwrap( ) , & BackoffConfig :: default ( ) ) ;
251346 }
252347
253348 #[ test]
@@ -257,6 +352,9 @@ mod tests {
257352 . user ( "some_user" )
258353 . password ( "some_password" )
259354 . skip_ssl_validation ( )
355+ . with_backoff ( Some (
356+ BackoffConfigBuilder :: new ( ) . with_multiplier ( 2.0 ) . build ( ) ,
357+ ) )
260358 . build ( )
261359 . unwrap ( ) ;
262360 assert_eq ! ( config. uri, "127.0.0.1:7687" ) ;
@@ -266,6 +364,8 @@ mod tests {
266364 assert_eq ! ( config. fetch_size, 200 ) ;
267365 assert_eq ! ( config. max_connections, 16 ) ;
268366 assert_eq ! ( config. tls_config, ConnectionTLSConfig :: NoSSLValidation ) ;
367+ assert ! ( config. backoff. is_some( ) ) ;
368+ assert_eq ! ( config. backoff. as_ref( ) . unwrap( ) . multiplier. unwrap( ) , 2.0 ) ;
269369 }
270370
271371 #[ test]
0 commit comments