Skip to content

Commit

Permalink
Merge pull request #3187 from autonomys/propagate-snap-errors
Browse files Browse the repository at this point in the history
Exit when snap sync needs user intervention
  • Loading branch information
teor2345 authored Oct 29, 2024
2 parents 980c71e + 6731ba9 commit 85e8184
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 6 deletions.
5 changes: 4 additions & 1 deletion crates/subspace-service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,10 @@ where
Box::pin(async move {
// Run snap-sync before DSN-sync.
if config.sync == ChainSyncMode::Snap {
snap_sync_task.await;
if let Err(error) = snap_sync_task.await {
error!(%error, "Snap sync exited with a fatal error");
return;
}
}

if let Err(error) = worker.await {
Expand Down
49 changes: 44 additions & 5 deletions crates/subspace-service/src/sync_from_dsn/snap_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use sc_consensus_subspace::archiver::{decode_block, SegmentHeadersStore};
use sc_network::{NetworkBlock, PeerId};
use sc_network_sync::service::network::NetworkServiceHandle;
use sc_network_sync::SyncingService;
use sc_service::Error;
use sp_api::ProvideRuntimeApi;
use sp_blockchain::HeaderBackend;
use sp_consensus::BlockOrigin;
Expand All @@ -31,6 +30,35 @@ use subspace_networking::Node;
use tokio::time::sleep;
use tracing::{debug, error};

/// Error type for snap sync.
#[derive(thiserror::Error, Debug)]
pub enum Error {
/// A fatal snap sync error which requires user intervention.
/// Most snap sync errors are non-fatal, because we can just continue with regular sync.
#[error("Snap Sync requires user action: {0}")]
SnapSyncImpossible(String),

/// Substrate service error.
#[error(transparent)]
Sub(#[from] sc_service::Error),

/// Substrate blockchain client error.
#[error(transparent)]
Client(#[from] sp_blockchain::Error),

/// Other.
#[error("Snap sync error: {0}")]
Other(String),
}

impl From<String> for Error {
fn from(error: String) -> Self {
Error::Other(error)
}
}

/// Run a snap sync, return an error if snap sync is impossible and user intervention is required.
/// Otherwise, just log the error and return `Ok(())` so that regular sync continues.
#[allow(clippy::too_many_arguments)]
pub(crate) async fn snap_sync<Block, AS, Client, PG>(
segment_headers_store: SegmentHeadersStore<AS>,
Expand All @@ -43,7 +71,8 @@ pub(crate) async fn snap_sync<Block, AS, Client, PG>(
sync_service: Arc<SyncingService<Block>>,
network_service_handle: NetworkServiceHandle,
erasure_coding: ErasureCoding,
) where
) -> Result<(), Error>
where
Block: BlockT,
AS: AuxStore,
Client: HeaderBackend<Block>
Expand Down Expand Up @@ -81,6 +110,13 @@ pub(crate) async fn snap_sync<Block, AS, Client, PG>(
debug!("Snap sync finished successfully");
}
Err(error) => {
// A fatal snap sync error requiring user intervention. The caller will log this error,
// so just return it to terminate the task.
if matches!(error, Error::SnapSyncImpossible(_)) {
return Err(error);
}

// Other errors are non-fatal
error!(%error, "Snap sync failed");
}
}
Expand All @@ -95,6 +131,8 @@ pub(crate) async fn snap_sync<Block, AS, Client, PG>(
} else {
debug!("Snap sync can only work with genesis state, skipping");
}

Ok(())
}

// Get blocks from the last segment or from the segment containing the target block.
Expand Down Expand Up @@ -166,11 +204,12 @@ where

// We don't have the genesis state when we choose to snap sync.
if target_segment_index <= SegmentIndex::ONE {
error!(
// The caller logs this error
return Err(Error::SnapSyncImpossible(
"Snap sync is impossible - not enough archived history: \
wipe the DB folder and rerun with --sync=full"
);
return Err("Snap sync is impossible - not enough archived history".into());
.into(),
));
}

// Identify all segment headers that would need to be reconstructed in order to get first
Expand Down

0 comments on commit 85e8184

Please sign in to comment.