@@ -2,6 +2,7 @@ use std::ops::RangeInclusive;
22
33use async_trait:: async_trait;
44use starknet_api:: block:: BlockHashAndNumber ;
5+ use tracing:: info;
56use url:: Url ;
67
78use crate :: { BaseLayerContract , L1BlockHeader , L1BlockNumber , L1BlockReference , L1Event } ;
@@ -18,6 +19,52 @@ impl<B: BaseLayerContract + Send + Sync> CyclicBaseLayerWrapper<B> {
1819 pub fn new ( base_layer : B ) -> Self {
1920 Self { base_layer }
2021 }
22+
23+ // Check the result of a function call to the base layer. If it fails, cycle the URL and signal
24+ // the caller that we should try again (by returning None).
25+ async fn cycle_url_on_error < ReturnType : std:: fmt:: Debug > (
26+ & mut self ,
27+ start_url : & Url ,
28+ result : Result < ReturnType , B :: Error > ,
29+ ) -> Option < Result < ReturnType , B :: Error > > {
30+ // In case we succeed, just return the (successful) result.
31+ if result. is_ok ( ) {
32+ return Some ( result) ;
33+ }
34+ // Get the current URL (return error in case it fails to get it).
35+ let current_url_result = self . base_layer . get_url ( ) . await ;
36+ let Ok ( current_url) = current_url_result else {
37+ return Some ( Err ( current_url_result. expect_err ( "result is checked at let-else" ) ) ) ;
38+ } ;
39+ // Otherwise, cycle the URL so we can try again. Return error in case it fails to cycle.
40+ let cycle_url_result = self . base_layer . cycle_provider_url ( ) . await ;
41+ let Ok ( ( ) ) = cycle_url_result else {
42+ return Some ( Err ( cycle_url_result. expect_err ( "result is checked at let-else" ) ) ) ;
43+ } ;
44+ // Get the new URL (return error in case it fails to get it).
45+ let new_url_result = self . base_layer . get_url ( ) . await ;
46+ let Ok ( new_url) = new_url_result else {
47+ return Some ( Err ( new_url_result. expect_err ( "result is checked at let-else" ) ) ) ;
48+ } ;
49+ info ! (
50+ "Cycling URL from {:?} to {:?}" ,
51+ to_safe_string( & current_url) ,
52+ to_safe_string( & new_url)
53+ ) ;
54+
55+ // If we've cycled back to the start URL, we need to return the last error we got.
56+ if & new_url == start_url {
57+ info ! (
58+ "Cycled back to start URL {:?}, returning error {:?}." ,
59+ to_safe_string( start_url) ,
60+ result
61+ ) ;
62+ return Some ( result) ;
63+ }
64+ // If we cycled but still haven't reached the start URL, we return None to signal that we
65+ // should try again with the new URL.
66+ None
67+ }
2168}
2269
2370#[ async_trait]
@@ -31,12 +78,8 @@ impl<B: BaseLayerContract + Send + Sync> BaseLayerContract for CyclicBaseLayerWr
3178 let start_url = self . base_layer . get_url ( ) . await ?;
3279 loop {
3380 let result = self . base_layer . get_proved_block_at ( l1_block) . await ;
34- if result. is_ok ( ) {
35- return result;
36- }
37- self . base_layer . cycle_provider_url ( ) . await ?;
38- if self . base_layer . get_url ( ) . await ? == start_url {
39- return result;
81+ if let Some ( result) = self . cycle_url_on_error ( & start_url, result) . await {
82+ return result; // Could return a success or an error.
4083 }
4184 }
4285 }
@@ -45,12 +88,8 @@ impl<B: BaseLayerContract + Send + Sync> BaseLayerContract for CyclicBaseLayerWr
4588 let start_url = self . base_layer . get_url ( ) . await ?;
4689 loop {
4790 let result = self . base_layer . latest_l1_block_number ( ) . await ;
48- if result. is_ok ( ) {
49- return result;
50- }
51- self . base_layer . cycle_provider_url ( ) . await ?;
52- if self . base_layer . get_url ( ) . await ? == start_url {
53- return result;
91+ if let Some ( result) = self . cycle_url_on_error ( & start_url, result) . await {
92+ return result; // Could return a success or an error.
5493 }
5594 }
5695 }
@@ -62,12 +101,8 @@ impl<B: BaseLayerContract + Send + Sync> BaseLayerContract for CyclicBaseLayerWr
62101 let start_url = self . base_layer . get_url ( ) . await ?;
63102 loop {
64103 let result = self . base_layer . l1_block_at ( block_number) . await ;
65- if result. is_ok ( ) {
66- return result;
67- }
68- self . base_layer . cycle_provider_url ( ) . await ?;
69- if self . base_layer . get_url ( ) . await ? == start_url {
70- return result;
104+ if let Some ( result) = self . cycle_url_on_error ( & start_url, result) . await {
105+ return result; // Could return a success or an error.
71106 }
72107 }
73108 }
@@ -80,12 +115,8 @@ impl<B: BaseLayerContract + Send + Sync> BaseLayerContract for CyclicBaseLayerWr
80115 let start_url = self . base_layer . get_url ( ) . await ?;
81116 loop {
82117 let result = self . base_layer . events ( block_range. clone ( ) , event_identifiers) . await ;
83- if result. is_ok ( ) {
84- return result;
85- }
86- self . base_layer . cycle_provider_url ( ) . await ?;
87- if self . base_layer . get_url ( ) . await ? == start_url {
88- return result;
118+ if let Some ( result) = self . cycle_url_on_error ( & start_url, result) . await {
119+ return result; // Could return a success or an error.
89120 }
90121 }
91122 }
@@ -97,12 +128,8 @@ impl<B: BaseLayerContract + Send + Sync> BaseLayerContract for CyclicBaseLayerWr
97128 let start_url = self . base_layer . get_url ( ) . await ?;
98129 loop {
99130 let result = self . base_layer . get_block_header ( block_number) . await ;
100- if result. is_ok ( ) {
101- return result;
102- }
103- self . base_layer . cycle_provider_url ( ) . await ?;
104- if self . base_layer . get_url ( ) . await ? == start_url {
105- return result;
131+ if let Some ( result) = self . cycle_url_on_error ( & start_url, result) . await {
132+ return result; // Could return a success or an error.
106133 }
107134 }
108135 }
@@ -126,3 +153,8 @@ impl<B: BaseLayerContract + Send + Sync> BaseLayerContract for CyclicBaseLayerWr
126153 self . base_layer . cycle_provider_url ( ) . await
127154 }
128155}
156+
157+ fn to_safe_string ( url : & Url ) -> String {
158+ // We print only the hostnames to avoid leaking the API keys.
159+ url. host ( ) . map_or_else ( || "no host in url!" . to_string ( ) , |host| host. to_string ( ) )
160+ }
0 commit comments