Skip to content

Commit 47b7b17

Browse files
committed
feat:rearchive range
Signed-off-by: Chen Kai <[email protected]>
1 parent 82ea105 commit 47b7b17

File tree

5 files changed

+144
-83
lines changed

5 files changed

+144
-83
lines changed

bin/archiver/src/archiver.rs

Lines changed: 84 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
use again::RetryPolicy;
2+
use blob_archiver_beacon::beacon_client::BeaconClient;
23
use blob_archiver_storage::{
34
BackfillProcess, BackfillProcesses, BlobData, BlobSidecars, Header, LockFile, Storage,
45
};
6+
use eth2::types::Slot;
57
use eth2::types::{BlockHeaderData, BlockId, Hash256};
6-
use eyre::Result;
8+
use eth2::Error;
9+
use eyre::{eyre, Result};
710
use serde::{Deserialize, Serialize};
811
use std::sync::atomic::{AtomicU64, Ordering};
912
use std::sync::Arc;
1013
use std::time::Duration;
1114
use tokio::sync::watch::Receiver;
1215
use tokio::time::{interval, sleep};
1316
use tracing::log::{debug, error, info, trace};
14-
use blob_archiver_beacon::beacon_client::BeaconClient;
1517

1618
#[allow(dead_code)]
1719
const LIVE_FETCH_BLOB_MAXIMUM_RETRIES: usize = 10;
1820
#[allow(dead_code)]
19-
const STARTUP_FETCH_BLOB_MAXIMUM_RETRIES: i32 = 3;
21+
const STARTUP_FETCH_BLOB_MAXIMUM_RETRIES: usize = 3;
2022
#[allow(dead_code)]
21-
const REARCHIVE_MAXIMUM_RETRIES: i32 = 3;
23+
const REARCHIVE_MAXIMUM_RETRIES: usize = 3;
2224
#[allow(dead_code)]
2325
const BACKFILL_ERROR_RETRY_INTERVAL: Duration = Duration::from_secs(5);
2426
#[allow(dead_code)]
@@ -30,6 +32,13 @@ const OBTAIN_LOCK_RETRY_INTERVAL_SECS: u64 = 10;
3032
#[allow(dead_code)]
3133
static OBTAIN_LOCK_RETRY_INTERVAL: AtomicU64 = AtomicU64::new(OBTAIN_LOCK_RETRY_INTERVAL_SECS);
3234

35+
#[derive(Debug, Serialize, Deserialize)]
36+
pub struct RearchiveResp {
37+
pub from: u64,
38+
pub to: u64,
39+
pub error: Option<String>,
40+
}
41+
3342
#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)]
3443
pub struct Config {
3544
pub poll_interval: Duration,
@@ -43,9 +52,9 @@ pub struct Archiver {
4352
pub beacon_client: Arc<dyn BeaconClient>,
4453

4554
storage: Arc<dyn Storage>,
46-
#[allow(dead_code)]
55+
4756
id: String,
48-
#[allow(dead_code)]
57+
4958
pub config: Config,
5059

5160
shutdown_rx: Receiver<bool>,
@@ -70,20 +79,20 @@ impl Archiver {
7079
&self,
7180
block_id: BlockId,
7281
overwrite: bool,
73-
) -> Result<(BlockHeaderData, bool)> {
82+
) -> Result<Option<(BlockHeaderData, bool)>> {
7483
let header_resp_opt = self
7584
.beacon_client
7685
.get_beacon_headers_block_id(block_id)
7786
.await
7887
.map_err(|e| eyre::eyre!(e))?;
7988

8089
match header_resp_opt {
81-
None => Err(eyre::eyre!("No header response")),
90+
None => Ok(None),
8291
Some(header) => {
8392
let exists = self.storage.exists(&header.data.root).await;
8493

8594
if exists && !overwrite {
86-
return Ok((header.data, true));
95+
return Ok(Some((header.data, true)));
8796
}
8897

8998
let blobs_resp_opt = self
@@ -103,9 +112,9 @@ impl Archiver {
103112
);
104113
self.storage.write_blob_data(blob_data).await?;
105114
trace!("Persisting blobs for block: {:?}", blob_data);
106-
return Ok((header.data, exists));
115+
return Ok(Some((header.data, exists)));
107116
}
108-
Ok((header.data, exists))
117+
Ok(Some((header.data, exists)))
109118
}
110119
}
111120
}
@@ -228,7 +237,7 @@ impl Archiver {
228237
&process.current_block,
229238
&mut processes,
230239
)
231-
.await;
240+
.await;
232241
}
233242
}
234243
Err(e) => {
@@ -248,7 +257,7 @@ impl Archiver {
248257
let mut curr = current.clone();
249258
let mut already_exists = false;
250259
let mut count = 0;
251-
let mut res: Result<(BlockHeaderData, bool)>;
260+
let mut res: Result<Option<(BlockHeaderData, bool)>>;
252261
let shutdown_rx = self.shutdown_rx.clone();
253262
info!("backfill process initiated, curr_hash: {:#?}, curr_slot: {:#?}, start_hash: {:#?},start_slot: {:#?}", curr.root, curr.header.message.slot.clone(), start.root, start.header.message.slot.clone());
254263

@@ -276,7 +285,14 @@ impl Archiver {
276285
continue;
277286
};
278287

279-
let (parent, parent_exists) = res.unwrap();
288+
let Some((parent, parent_exists)) = res.unwrap() else {
289+
error!(
290+
"failed to persist blobs for block, will retry, hash: {:#?}",
291+
curr.header.message.parent_root
292+
);
293+
sleep(BACKFILL_ERROR_RETRY_INTERVAL).await;
294+
continue;
295+
};
280296
curr = parent;
281297
already_exists = parent_exists;
282298

@@ -322,7 +338,7 @@ impl Archiver {
322338
let mut current_block_id = BlockId::Head;
323339

324340
loop {
325-
let retry_policy = RetryPolicy::exponential(Duration::from_secs(1))
341+
let retry_policy = RetryPolicy::exponential(Duration::from_millis(250))
326342
.with_jitter(true)
327343
.with_max_delay(Duration::from_secs(10))
328344
.with_max_retries(LIVE_FETCH_BLOB_MAXIMUM_RETRIES);
@@ -335,7 +351,11 @@ impl Archiver {
335351
return;
336352
}
337353

338-
let (curr, already_exists) = res.unwrap();
354+
let Some((curr, already_exists)) = res.unwrap() else {
355+
error!("Error fetching blobs for block");
356+
return;
357+
};
358+
339359
if start.is_none() {
340360
start = Some(curr.clone());
341361
}
@@ -376,6 +396,52 @@ impl Archiver {
376396

377397
#[allow(dead_code)]
378398
async fn start(&self) {}
399+
400+
#[allow(dead_code)]
401+
async fn rearchive_range(&self, from: u64, to: u64) -> RearchiveResp {
402+
for i in from..=to {
403+
info!("rearchiving block: {}", i);
404+
let retry_policy = RetryPolicy::exponential(Duration::from_millis(250))
405+
.with_jitter(true)
406+
.with_max_delay(Duration::from_secs(10))
407+
.with_max_retries(REARCHIVE_MAXIMUM_RETRIES);
408+
let r = retry_policy.retry(|| self.rearchive(i)).await;
409+
410+
match r {
411+
Err(e) => {
412+
error!("Error fetching blobs for block: {:#?}", e);
413+
return RearchiveResp {
414+
from,
415+
to,
416+
error: Some(e.downcast::<Error>().unwrap().to_string()),
417+
};
418+
}
419+
Ok(false) => {
420+
info!("block not found, skipping");
421+
}
422+
Ok(true) => {
423+
info!("block rearchived successfully")
424+
}
425+
}
426+
}
427+
RearchiveResp {
428+
from,
429+
to,
430+
error: None,
431+
}
432+
}
433+
434+
async fn rearchive(&self, i: u64) -> Result<bool> {
435+
let res = self
436+
.persist_blobs_for_block(BlockId::Slot(Slot::new(i)), true)
437+
.await;
438+
439+
match res {
440+
Err(e) => Err(eyre!(e)),
441+
Ok(None) => Ok(false),
442+
Ok(Some(_)) => Ok(true),
443+
}
444+
}
379445
}
380446

381447
#[cfg(test)]
@@ -385,9 +451,9 @@ mod tests {
385451
use std::time::Duration;
386452

387453
use super::*;
454+
use blob_archiver_beacon::beacon_client::BeaconClientEth2;
388455
use blob_archiver_storage::fs::FSStorage;
389456
use eth2::{BeaconNodeHttpClient, SensitiveUrl, Timeouts};
390-
use blob_archiver_beacon::beacon_client::BeaconClientEth2;
391457

392458
#[tokio::test]
393459
async fn test_persist_blobs_for_block() {
@@ -399,9 +465,7 @@ mod tests {
399465
let storage = FSStorage::new(dir.clone()).await.unwrap();
400466
tokio::fs::create_dir_all(dir).await.unwrap();
401467
let (_, rx) = tokio::sync::watch::channel(false);
402-
let beacon_client_eth2 = BeaconClientEth2 {
403-
beacon_client,
404-
};
468+
let beacon_client_eth2 = BeaconClientEth2 { beacon_client };
405469
let archiver = Archiver::new(Arc::new(beacon_client_eth2), Arc::new(storage), rx);
406470

407471
let block_id = BlockId::Head;

bin/archiver/src/main.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ use std::sync::Arc;
44
use std::time::Duration;
55

66
use crate::archiver::Archiver;
7+
use blob_archiver_beacon::beacon_client::BeaconClientEth2;
78
use blob_archiver_storage::fs::FSStorage;
89
use eth2::types::BlockId;
910
use eth2::{BeaconNodeHttpClient, SensitiveUrl, Timeouts};
10-
use blob_archiver_beacon::beacon_client::BeaconClientEth2;
1111

1212
mod archiver;
1313

@@ -19,9 +19,7 @@ async fn main() {
1919
);
2020
let storage = FSStorage::new(PathBuf::from("test_dir")).await.unwrap();
2121
let (_, shutdown_rx) = tokio::sync::watch::channel(false);
22-
let beacon_client_eth2 = BeaconClientEth2 {
23-
beacon_client,
24-
};
22+
let beacon_client_eth2 = BeaconClientEth2 { beacon_client };
2523
let archiver = Archiver::new(Arc::new(beacon_client_eth2), Arc::new(storage), shutdown_rx);
2624

2725
let block_id = BlockId::Head;

crates/beacon/src/beacon_client.rs

Lines changed: 50 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
use std::collections::HashMap;
22

33
use async_trait::async_trait;
4+
use eth2::types::{
5+
BeaconBlockHeader, BlobSidecarList, BlockHeaderAndSignature, BlockHeaderData, BlockId, EthSpec,
6+
ExecutionOptimisticFinalizedResponse, GenericResponse, Hash256, MainnetEthSpec, SignatureBytes,
7+
Slot,
8+
};
49
use eth2::{BeaconNodeHttpClient, Error};
5-
use eth2::types::{BeaconBlockHeader, BlobSidecarList, BlockHeaderAndSignature, BlockHeaderData, BlockId, EthSpec, ExecutionOptimisticFinalizedResponse, GenericResponse, Hash256, MainnetEthSpec, SignatureBytes, Slot};
610

7-
use crate::blob_test_helper::{FIVE, FOUR, new_blob_sidecars, ONE, ORIGIN_BLOCK, START_SLOT, THREE, TWO};
11+
use crate::blob_test_helper::{
12+
new_blob_sidecars, FIVE, FOUR, ONE, ORIGIN_BLOCK, START_SLOT, THREE, TWO,
13+
};
814

915
#[async_trait]
1016
pub trait BeaconClient {
@@ -27,7 +33,10 @@ pub struct BeaconClientStub<E: EthSpec> {
2733

2834
#[async_trait]
2935
impl BeaconClient for BeaconClientStub<MainnetEthSpec> {
30-
async fn get_beacon_headers_block_id(&self, block_id: BlockId) -> Result<Option<ExecutionOptimisticFinalizedResponse<BlockHeaderData>>, Error> {
36+
async fn get_beacon_headers_block_id(
37+
&self,
38+
block_id: BlockId,
39+
) -> Result<Option<ExecutionOptimisticFinalizedResponse<BlockHeaderData>>, Error> {
3140
let header = self.headers.get(block_id.to_string().as_str());
3241

3342
Ok(header.map(|h| ExecutionOptimisticFinalizedResponse {
@@ -37,12 +46,14 @@ impl BeaconClient for BeaconClientStub<MainnetEthSpec> {
3746
}))
3847
}
3948

40-
async fn get_blobs(&self, block_id: BlockId, _indices: Option<&[u64]>) -> Result<Option<GenericResponse<BlobSidecarList<MainnetEthSpec>>>, Error> {
49+
async fn get_blobs(
50+
&self,
51+
block_id: BlockId,
52+
_indices: Option<&[u64]>,
53+
) -> Result<Option<GenericResponse<BlobSidecarList<MainnetEthSpec>>>, Error> {
4154
let blobs = self.blobs.get(block_id.to_string().as_str());
4255

43-
Ok(blobs.map(|b| GenericResponse {
44-
data: b.clone(),
45-
}))
56+
Ok(blobs.map(|b| GenericResponse { data: b.clone() }))
4657
}
4758
}
4859

@@ -83,22 +94,10 @@ impl Default for BeaconClientStub<MainnetEthSpec> {
8394
ONE.to_string(),
8495
make_header(start_slot + 1, *ONE, *ORIGIN_BLOCK),
8596
),
86-
(
87-
TWO.to_string(),
88-
make_header(start_slot + 2, *TWO, *ONE),
89-
),
90-
(
91-
THREE.to_string(),
92-
make_header(start_slot + 3, *THREE, *TWO),
93-
),
94-
(
95-
FOUR.to_string(),
96-
make_header(start_slot + 4, *FOUR, *THREE),
97-
),
98-
(
99-
FIVE.to_string(),
100-
make_header(start_slot + 5, *FIVE, *FOUR),
101-
),
97+
(TWO.to_string(), make_header(start_slot + 2, *TWO, *ONE)),
98+
(THREE.to_string(), make_header(start_slot + 3, *THREE, *TWO)),
99+
(FOUR.to_string(), make_header(start_slot + 4, *FOUR, *THREE)),
100+
(FIVE.to_string(), make_header(start_slot + 5, *FIVE, *FOUR)),
102101
(
103102
"head".to_string(),
104103
make_header(start_slot + 5, *FIVE, *FOUR),
@@ -134,34 +133,20 @@ impl Default for BeaconClientStub<MainnetEthSpec> {
134133
]),
135134

136135
blobs: HashMap::from([
137-
(ORIGIN_BLOCK.to_string(),
138-
origin_blobs.clone()),
139-
(ONE.to_string(),
140-
one_blobs.clone()),
141-
(TWO.to_string(),
142-
two_blobs.clone()),
143-
(THREE.to_string(),
144-
three_blobs.clone()),
145-
(FOUR.to_string(),
146-
four_blobs.clone()),
147-
(FIVE.to_string(),
148-
five_blobs.clone()),
149-
("head".to_string(),
150-
five_blobs.clone()),
151-
("finalized".to_string(),
152-
three_blobs.clone()),
153-
(start_slot.as_u64().to_string(),
154-
origin_blobs.clone()),
155-
((start_slot + 1).as_u64().to_string(),
156-
one_blobs.clone()),
157-
((start_slot + 2).as_u64().to_string(),
158-
two_blobs.clone()),
159-
((start_slot + 3).as_u64().to_string(),
160-
three_blobs.clone()),
161-
((start_slot + 4).as_u64().to_string(),
162-
four_blobs.clone()),
163-
((start_slot + 5).as_u64().to_string(),
164-
five_blobs.clone()),
136+
(ORIGIN_BLOCK.to_string(), origin_blobs.clone()),
137+
(ONE.to_string(), one_blobs.clone()),
138+
(TWO.to_string(), two_blobs.clone()),
139+
(THREE.to_string(), three_blobs.clone()),
140+
(FOUR.to_string(), four_blobs.clone()),
141+
(FIVE.to_string(), five_blobs.clone()),
142+
("head".to_string(), five_blobs.clone()),
143+
("finalized".to_string(), three_blobs.clone()),
144+
(start_slot.as_u64().to_string(), origin_blobs.clone()),
145+
((start_slot + 1).as_u64().to_string(), one_blobs.clone()),
146+
((start_slot + 2).as_u64().to_string(), two_blobs.clone()),
147+
((start_slot + 3).as_u64().to_string(), three_blobs.clone()),
148+
((start_slot + 4).as_u64().to_string(), four_blobs.clone()),
149+
((start_slot + 5).as_u64().to_string(), five_blobs.clone()),
165150
]),
166151
}
167152
}
@@ -182,11 +167,21 @@ pub struct BeaconClientEth2 {
182167

183168
#[async_trait]
184169
impl BeaconClient for BeaconClientEth2 {
185-
async fn get_beacon_headers_block_id(&self, block_id: BlockId) -> Result<Option<ExecutionOptimisticFinalizedResponse<BlockHeaderData>>, Error> {
186-
return self.beacon_client.get_beacon_headers_block_id(block_id).await;
170+
async fn get_beacon_headers_block_id(
171+
&self,
172+
block_id: BlockId,
173+
) -> Result<Option<ExecutionOptimisticFinalizedResponse<BlockHeaderData>>, Error> {
174+
return self
175+
.beacon_client
176+
.get_beacon_headers_block_id(block_id)
177+
.await;
187178
}
188179

189-
async fn get_blobs(&self, block_id: BlockId, indices: Option<&[u64]>) -> Result<Option<GenericResponse<BlobSidecarList<MainnetEthSpec>>>, Error> {
180+
async fn get_blobs(
181+
&self,
182+
block_id: BlockId,
183+
indices: Option<&[u64]>,
184+
) -> Result<Option<GenericResponse<BlobSidecarList<MainnetEthSpec>>>, Error> {
190185
return self.beacon_client.get_blobs(block_id, indices).await;
191186
}
192-
}
187+
}

0 commit comments

Comments
 (0)