@@ -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,53 @@ 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 > (
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 = match self . base_layer . get_url ( ) . await {
36+ Ok ( url) => url,
37+ Err ( e) => return Some ( Err ( e) ) ,
38+ } ;
39+ // Otherwise, cycle the URL so we can try again. Return error in case it fails to cycle.
40+ match self . base_layer . cycle_provider_url ( ) . await {
41+ Ok ( ( ) ) => ( ) ,
42+ Err ( e) => return Some ( Err ( e) ) ,
43+ } ;
44+ // Get the new URL (return error in case it fails to get it).
45+ let new_url = match self . base_layer . get_url ( ) . await {
46+ Ok ( url) => url,
47+ Err ( e) => return Some ( Err ( e) ) ,
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+ let error_value = result. err ( ) . expect ( "result is checked at start of function" ) ;
58+ info ! (
59+ "Cycled back to start URL {:?}, returning error {:?}." ,
60+ to_safe_string( start_url) ,
61+ error_value
62+ ) ;
63+ return Some ( Err ( error_value) ) ;
64+ }
65+ // If we cycled but still haven't reached the start URL, we return None to signal that we
66+ // should try again with the new URL.
67+ None
68+ }
2169}
2270
2371#[ async_trait]
@@ -31,12 +79,8 @@ impl<B: BaseLayerContract + Send + Sync> BaseLayerContract for CyclicBaseLayerWr
3179 let start_url = self . base_layer . get_url ( ) . await ?;
3280 loop {
3381 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;
82+ if let Some ( result) = self . cycle_url_on_error ( & start_url, result) . await {
83+ return result; // Could return a success or an error.
4084 }
4185 }
4286 }
@@ -45,12 +89,8 @@ impl<B: BaseLayerContract + Send + Sync> BaseLayerContract for CyclicBaseLayerWr
4589 let start_url = self . base_layer . get_url ( ) . await ?;
4690 loop {
4791 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;
92+ if let Some ( result) = self . cycle_url_on_error ( & start_url, result) . await {
93+ return result; // Could return a success or an error.
5494 }
5595 }
5696 }
@@ -62,12 +102,8 @@ impl<B: BaseLayerContract + Send + Sync> BaseLayerContract for CyclicBaseLayerWr
62102 let start_url = self . base_layer . get_url ( ) . await ?;
63103 loop {
64104 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;
105+ if let Some ( result) = self . cycle_url_on_error ( & start_url, result) . await {
106+ return result; // Could return a success or an error.
71107 }
72108 }
73109 }
@@ -80,12 +116,8 @@ impl<B: BaseLayerContract + Send + Sync> BaseLayerContract for CyclicBaseLayerWr
80116 let start_url = self . base_layer . get_url ( ) . await ?;
81117 loop {
82118 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;
119+ if let Some ( result) = self . cycle_url_on_error ( & start_url, result) . await {
120+ return result; // Could return a success or an error.
89121 }
90122 }
91123 }
@@ -97,12 +129,8 @@ impl<B: BaseLayerContract + Send + Sync> BaseLayerContract for CyclicBaseLayerWr
97129 let start_url = self . base_layer . get_url ( ) . await ?;
98130 loop {
99131 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;
132+ if let Some ( result) = self . cycle_url_on_error ( & start_url, result) . await {
133+ return result; // Could return a success or an error.
106134 }
107135 }
108136 }
@@ -126,3 +154,8 @@ impl<B: BaseLayerContract + Send + Sync> BaseLayerContract for CyclicBaseLayerWr
126154 self . base_layer . cycle_provider_url ( ) . await
127155 }
128156}
157+
158+ fn to_safe_string ( url : & Url ) -> String {
159+ // We print only the hostnames to avoid leaking the API keys.
160+ url. host ( ) . map_or_else ( || "no host in url!" . to_string ( ) , |host| host. to_string ( ) )
161+ }
0 commit comments