From dfb4dd0fe09827c8604818d0359d92e3b0df27dc Mon Sep 17 00:00:00 2001 From: Filipe Azevedo Date: Mon, 21 Aug 2023 15:09:27 +0100 Subject: [PATCH] Retry block_pointer_from_number on deploy Add retry to avoid a single failure while making the call prevent the subsgraph from being deployed Add warning for failed attempts --- core/src/subgraph/registrar.rs | 24 +++++++++++++++--------- graph/src/data/subgraph/mod.rs | 2 +- graph/src/lib.rs | 1 + graph/src/util/futures.rs | 16 ++++++++++++---- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/core/src/subgraph/registrar.rs b/core/src/subgraph/registrar.rs index b343487b280..a0196cd2c83 100644 --- a/core/src/subgraph/registrar.rs +++ b/core/src/subgraph/registrar.rs @@ -13,6 +13,9 @@ use graph::prelude::{ CreateSubgraphResult, SubgraphAssignmentProvider as SubgraphAssignmentProviderTrait, SubgraphRegistrar as SubgraphRegistrarTrait, *, }; +use graph::tokio_retry::Retry; +use graph::util::futures::retry_strategy; +use graph::util::futures::RETRY_DEFAULT_LIMIT; pub struct SubgraphRegistrar { logger: Logger, @@ -518,15 +521,18 @@ async fn resolve_start_block( .expect("cannot identify minimum start block because there are no data sources") { 0 => Ok(None), - min_start_block => chain - .block_pointer_from_number(logger, min_start_block - 1) - .await - .map(Some) - .map_err(move |_| { - SubgraphRegistrarError::ManifestValidationError(vec![ - SubgraphManifestValidationError::BlockNotFound(min_start_block.to_string()), - ]) - }), + min_start_block => Retry::spawn(retry_strategy(Some(2), RETRY_DEFAULT_LIMIT), move || { + chain + .block_pointer_from_number(&logger, min_start_block - 1) + .inspect_err(move |e| warn!(&logger, "Failed to get block number: {}", e)) + }) + .await + .map(Some) + .map_err(move |_| { + SubgraphRegistrarError::ManifestValidationError(vec![ + SubgraphManifestValidationError::BlockNotFound(min_start_block.to_string()), + ]) + }), } } diff --git a/graph/src/data/subgraph/mod.rs b/graph/src/data/subgraph/mod.rs index 886ad47aa0d..c4add562d5b 100644 --- a/graph/src/data/subgraph/mod.rs +++ b/graph/src/data/subgraph/mod.rs @@ -722,7 +722,7 @@ impl SubgraphManifest { features, spec_version, data_source_kinds: data_source_kinds.into_iter().collect_vec(), - network: network, + network, } } diff --git a/graph/src/lib.rs b/graph/src/lib.rs index 264bab1c221..54715109d27 100644 --- a/graph/src/lib.rs +++ b/graph/src/lib.rs @@ -53,6 +53,7 @@ pub use semver; pub use slog; pub use stable_hash_legacy; pub use tokio; +pub use tokio_retry; pub use tokio_stream; pub use url; diff --git a/graph/src/util/futures.rs b/graph/src/util/futures.rs index 5af1063d54d..33814db1cab 100644 --- a/graph/src/util/futures.rs +++ b/graph/src/util/futures.rs @@ -9,6 +9,8 @@ use thiserror::Error; use tokio_retry::strategy::{jitter, ExponentialBackoff}; use tokio_retry::Retry; +pub const RETRY_DEFAULT_LIMIT: Duration = Duration::from_secs(30); + /// Generic helper function for retrying async operations with built-in logging. /// /// To use this helper, do the following: @@ -271,7 +273,7 @@ where let mut attempt_count = 0; - Retry::spawn(retry_strategy(limit_opt), move || { + Retry::spawn(retry_strategy(limit_opt, RETRY_DEFAULT_LIMIT), move || { let operation_name = operation_name.clone(); let logger = logger.clone(); let condition = condition.clone(); @@ -347,11 +349,17 @@ where }) } -fn retry_strategy(limit_opt: Option) -> Box + Send> { +pub fn retry_strategy( + limit_opt: Option, + max_delay: Duration, +) -> Box + Send> { // Exponential backoff, but with a maximum - let max_delay_ms = 30_000; let backoff = ExponentialBackoff::from_millis(2) - .max_delay(Duration::from_millis(max_delay_ms)) + .max_delay(Duration::from_millis( + // This should be fine, if the value is too high it will crash during + // testing. + max_delay.as_millis().try_into().unwrap(), + )) .map(jitter); // Apply limit (maximum retry count)