Skip to content

Commit 1900ab5

Browse files
committed
papyrus_base_layer: extract check and cycle URLs into a helper function with logging
1 parent 4aaeef9 commit 1900ab5

File tree

2 files changed

+68
-36
lines changed

2 files changed

+68
-36
lines changed

crates/papyrus_base_layer/src/cyclic_base_layer_wrapper.rs

Lines changed: 62 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::ops::RangeInclusive;
22

33
use async_trait::async_trait;
44
use starknet_api::block::BlockHashAndNumber;
5+
use tracing::info;
56
use url::Url;
67

78
use 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+
}

crates/papyrus_base_layer/src/cyclic_base_layer_wrapper_test.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const NUM_URLS: usize = 2;
3030
async fn cycle_get_proved_block_at(#[case] num_failing_calls: usize) {
3131
// Setup.
3232
let success = num_failing_calls < NUM_URLS;
33-
let expected_num_url_calls = num_failing_calls + 1;
33+
let expected_num_url_calls = num_failing_calls * 2 + 1;
3434
let num_url_calls_made = Arc::new(AtomicUsize::new(0));
3535
let num_url_calls_made_clone = num_url_calls_made.clone();
3636
let num_url_calls_made_clone2 = num_url_calls_made.clone();
@@ -73,7 +73,7 @@ async fn cycle_get_proved_block_at(#[case] num_failing_calls: usize) {
7373
async fn cycle_latest_l1_block_number(#[case] num_failing_calls: usize) {
7474
// Setup.
7575
let success = num_failing_calls < NUM_URLS;
76-
let expected_num_url_calls = num_failing_calls + 1;
76+
let expected_num_url_calls = num_failing_calls * 2 + 1;
7777
let num_url_calls_made = Arc::new(AtomicUsize::new(0));
7878
let num_url_calls_made_clone = num_url_calls_made.clone();
7979
let num_url_calls_made_clone2 = num_url_calls_made.clone();
@@ -113,7 +113,7 @@ async fn cycle_latest_l1_block_number(#[case] num_failing_calls: usize) {
113113
async fn cycle_l1_block_at(#[case] num_failing_calls: usize) {
114114
// Setup.
115115
let success = num_failing_calls < NUM_URLS;
116-
let expected_num_url_calls = num_failing_calls + 1;
116+
let expected_num_url_calls = num_failing_calls * 2 + 1;
117117
let num_url_calls_made = Arc::new(AtomicUsize::new(0));
118118
let num_url_calls_made_clone = num_url_calls_made.clone();
119119
let num_url_calls_made_clone2 = num_url_calls_made.clone();
@@ -156,7 +156,7 @@ async fn cycle_l1_block_at(#[case] num_failing_calls: usize) {
156156
async fn cycle_events(#[case] num_failing_calls: usize) {
157157
// Setup.
158158
let success = num_failing_calls < NUM_URLS;
159-
let expected_num_url_calls = num_failing_calls + 1;
159+
let expected_num_url_calls = num_failing_calls * 2 + 1;
160160
let num_url_calls_made = Arc::new(AtomicUsize::new(0));
161161
let num_url_calls_made_clone = num_url_calls_made.clone();
162162
let num_url_calls_made_clone2 = num_url_calls_made.clone();
@@ -196,7 +196,7 @@ async fn cycle_events(#[case] num_failing_calls: usize) {
196196
async fn cycle_get_block_header(#[case] num_failing_calls: usize) {
197197
// Setup.
198198
let success = num_failing_calls < NUM_URLS;
199-
let expected_num_url_calls = num_failing_calls + 1;
199+
let expected_num_url_calls = num_failing_calls * 2 + 1;
200200
let num_url_calls_made = Arc::new(AtomicUsize::new(0));
201201
let num_url_calls_made_clone = num_url_calls_made.clone();
202202
let num_url_calls_made_clone2 = num_url_calls_made.clone();
@@ -255,7 +255,7 @@ async fn get_block_header_fails_after_cycle_error() {
255255
let mut base_layer = MockBaseLayerContract::new();
256256
base_layer
257257
.expect_get_url()
258-
.times(1)
258+
.times(2)
259259
.returning(move || Ok(Url::parse("http://first_endpoint").unwrap()));
260260
base_layer.expect_get_block_header().times(1).returning(move |_| Err(MockError::MockError));
261261
base_layer.expect_cycle_provider_url().times(1).returning(move || Err(MockError::MockError));

0 commit comments

Comments
 (0)