@@ -23,6 +23,7 @@ use bp_header_chain::{FinalityProof, FindEquivocations as FindEquivocationsT};
2323use finality_relay:: FinalityProofsBuf ;
2424use futures:: future:: { BoxFuture , FutureExt } ;
2525use num_traits:: Saturating ;
26+ use std:: time:: Duration ;
2627
2728/// First step in the block checking state machine.
2829///
@@ -217,6 +218,44 @@ impl<P: EquivocationDetectionPipeline> BlockChecker<P> {
217218 Self :: ReadSyncedHeaders ( ReadSyncedHeaders { target_block_num } )
218219 }
219220
221+ pub fn run_with_retry < ' a , SC : SourceClient < P > , TC : TargetClient < P > > (
222+ self ,
223+ source_client : & ' a mut SC ,
224+ target_client : & ' a mut TC ,
225+ finality_proofs_buf : & ' a mut FinalityProofsBuf < P > ,
226+ reporter : & ' a mut EquivocationsReporter < P , SC > ,
227+ retry_params : ( u32 , Duration ) ,
228+ ) -> BoxFuture < ' a , Result < ( ) , Self > > {
229+ let ( max_attempts, retry_tick) = retry_params;
230+ async move {
231+ let mut block_checker = self ;
232+ let mut retry_range = ( 0 ..max_attempts) . peekable ( ) ;
233+ while let Some ( _) = retry_range. next ( ) {
234+ block_checker = match block_checker
235+ . run ( source_client, target_client, finality_proofs_buf, reporter)
236+ . await
237+ {
238+ Ok ( _) => return Ok ( ( ) ) ,
239+ Err ( err) => err,
240+ } ;
241+
242+ // We don't need to sleep after the last attempt
243+ if retry_range. peek ( ) . is_some ( ) {
244+ tracing:: warn!(
245+ target: "bridge" ,
246+ source=%P :: SOURCE_NAME ,
247+ target=%P :: TARGET_NAME ,
248+ "Error running block checker. Retrying."
249+ ) ;
250+ tokio:: time:: sleep ( retry_tick) . await ;
251+ }
252+ }
253+
254+ Err ( block_checker)
255+ }
256+ . boxed ( )
257+ }
258+
220259 pub fn run < ' a , SC : SourceClient < P > , TC : TargetClient < P > > (
221260 self ,
222261 source_client : & ' a mut SC ,
0 commit comments