@@ -3,7 +3,6 @@ use tracing::warn;
33use crate :: { data_state:: CanMakeProgress , Awaiting , DataState , ErrorBounds } ;
44use std:: fmt:: Debug ;
55use std:: ops:: Range ;
6- use std:: time:: { Duration , Instant } ;
76
87/// Automatically retries with a delay on failure until attempts are exhausted
98#[ derive( Debug ) ]
@@ -17,7 +16,7 @@ pub struct DataStateRetry<T, E: ErrorBounds = anyhow::Error> {
1716
1817 attempts_left : u8 ,
1918 inner : DataState < T , E > , // Not public to ensure resets happen as they should
20- next_allowed_attempt : Instant ,
19+ next_allowed_attempt : u128 ,
2120}
2221
2322impl < T , E : ErrorBounds > DataStateRetry < T , E > {
@@ -35,9 +34,8 @@ impl<T, E: ErrorBounds> DataStateRetry<T, E> {
3534 self . attempts_left
3635 }
3736
38- /// The instant that needs to be waited for before another attempt is
39- /// allowed
40- pub fn next_allowed_attempt ( & self ) -> Instant {
37+ /// The number of millis after the epoch that an attempt is allowed
38+ pub fn next_allowed_attempt ( & self ) -> u128 {
4139 self . next_allowed_attempt
4240 }
4341
@@ -112,17 +110,17 @@ impl<T, E: ErrorBounds> DataStateRetry<T, E> {
112110 format ! (
113111 "{} attempt(s) left. {} seconds before retry. {e}" ,
114112 self . attempts_left,
115- wait_left. as_secs ( )
113+ wait_left / 1000
116114 ) ,
117115 ) ;
118- if ui. button ( "Stop Trying" ) . clicked ( ) {
119- self . attempts_left = 0 ;
120- }
121116 let can_make_progress = self . start_or_poll ( fetch_fn) ;
122117 debug_assert ! (
123118 can_make_progress. is_able_to_make_progress( ) ,
124119 "This should be able to make progress"
125120 ) ;
121+ if ui. button ( "Stop Trying" ) . clicked ( ) {
122+ self . attempts_left = 0 ;
123+ }
126124 }
127125 CanMakeProgress :: AbleToMakeProgress
128126 }
@@ -140,12 +138,9 @@ impl<T, E: ErrorBounds> DataStateRetry<T, E> {
140138 DataState :: None => {
141139 // Going to make an attempt, set when the next attempt is allowed
142140 use rand:: Rng as _;
143- let wait_time_in_millis = rand:: thread_rng ( )
144- . gen_range ( self . retry_delay_millis . clone ( ) )
145- . into ( ) ;
146- self . next_allowed_attempt = Instant :: now ( )
147- . checked_add ( Duration :: from_millis ( wait_time_in_millis) )
148- . expect ( "failed to get random delay, value was out of range" ) ;
141+ let wait_time_in_millis =
142+ rand:: thread_rng ( ) . gen_range ( self . retry_delay_millis . clone ( ) ) ;
143+ self . next_allowed_attempt = millis_since_epoch ( ) + wait_time_in_millis as u128 ;
149144
150145 self . inner . start_request ( fetch_fn)
151146 }
@@ -162,7 +157,7 @@ impl<T, E: ErrorBounds> DataStateRetry<T, E> {
162157 CanMakeProgress :: UnableToMakeProgress
163158 } else {
164159 let wait_left = wait_before_next_attempt ( self . next_allowed_attempt ) ;
165- if wait_left. is_zero ( ) {
160+ if wait_left == 0 {
166161 warn ! ( ?err_msg, ?self . attempts_left, "retrying request" ) ;
167162 self . attempts_left -= 1 ;
168163 self . inner = DataState :: None ;
@@ -176,7 +171,7 @@ impl<T, E: ErrorBounds> DataStateRetry<T, E> {
176171 /// Resets the attempts taken
177172 pub fn reset_attempts ( & mut self ) {
178173 self . attempts_left = self . max_attempts ;
179- self . next_allowed_attempt = Instant :: now ( ) ;
174+ self . next_allowed_attempt = millis_since_epoch ( ) ;
180175 }
181176
182177 /// Clear stored data
@@ -214,7 +209,7 @@ impl<T, E: ErrorBounds> Default for DataStateRetry<T, E> {
214209 max_attempts : 3 ,
215210 retry_delay_millis : 1000 ..5000 ,
216211 attempts_left : 3 ,
217- next_allowed_attempt : Instant :: now ( ) ,
212+ next_allowed_attempt : millis_since_epoch ( ) ,
218213 }
219214 }
220215}
@@ -232,8 +227,15 @@ impl<T, E: ErrorBounds> AsMut<DataStateRetry<T, E>> for DataStateRetry<T, E> {
232227}
233228
234229/// The duration before the next attempt will be made
235- fn wait_before_next_attempt ( next_allowed_attempt : Instant ) -> Duration {
236- next_allowed_attempt. saturating_duration_since ( Instant :: now ( ) )
230+ fn wait_before_next_attempt ( next_allowed_attempt : u128 ) -> u128 {
231+ next_allowed_attempt. saturating_sub ( millis_since_epoch ( ) )
232+ }
233+
234+ fn millis_since_epoch ( ) -> u128 {
235+ web_time:: SystemTime :: UNIX_EPOCH
236+ . elapsed ( )
237+ . expect ( "expected date on system to be after the epoch" )
238+ . as_millis ( )
237239}
238240
239241// TODO 4: Use mocking to add tests ensuring retires are executed
0 commit comments