diff --git a/graph/src/components/adapter.rs b/graph/src/components/adapter.rs index 6f54dc18f8b..c88392a9b54 100644 --- a/graph/src/components/adapter.rs +++ b/graph/src/components/adapter.rs @@ -34,7 +34,7 @@ pub enum ProviderManagerError { } #[async_trait] -trait NetIdentifiable: Clone + Sync + Send { +trait NetIdentifiable: Sync + Send { async fn net_identifiers(&self) -> Result; fn provider_name(&self) -> ProviderName; } @@ -53,11 +53,11 @@ struct Ident { /// provider for the same chain offers a different ChainIdentifier, this will be considered a /// failed validation and it will be disabled. #[derive(Debug)] -struct ProviderManager { +struct ProviderManager { inner: Arc>, } -impl ProviderManager { +impl ProviderManager { pub fn new( logger: Logger, adapters: impl Iterator)>, @@ -75,7 +75,7 @@ impl ProviderManager { // Get status index or add new status. let index = match status .iter() - .find_position(|(provider_name, _)| provider_name.eq(&provider_name)) + .find_position(|(ident, _)| ident.provider.eq(&name)) { Some((index, _)) => index, None => { @@ -116,7 +116,7 @@ impl ProviderManager { tasks.push(inner.verify_provider(index, adapter)); } - crate::prelude::futures03::future::join_all(tasks) + crate::futures03::future::join_all(tasks) .await .into_iter() .collect::, ProviderManagerError>>()?; @@ -357,7 +357,7 @@ mod test { static ref UNTESTABLE_ADAPTER: MockAdapter = MockAdapter{ provider: UNTESTABLE_CHAIN.into(), - ident: VALID_IDENT.clone(), + ident: FAILED_IDENT.clone(), checked_at: Some(Utc::now()), }; @@ -430,6 +430,7 @@ mod test { struct Case<'a> { name: &'a str, chain_id: &'a str, + status: Vec<(ProviderName, GenesisCheckStatus)>, adapters: Vec<(ChainId, Vec)>, idents: Vec<(ChainId, Option)>, expected: Result, ProviderManagerError>, @@ -439,40 +440,56 @@ mod test { Case { name: "no adapters", chain_id: EMPTY_CHAIN, + status: vec![], adapters: vec![], idents: vec![(VALID_CHAIN.into(), None)], expected: Ok(vec![]), }, Case { - name: "adapter temporary failure bypasses checks if Ident None", + name: "adapter temporary failure with Ident None", chain_id: VALID_CHAIN, - // utc::now means it was just tested so it's untestable at the moment. + status: vec![( + UNTESTABLE_CHAIN.to_string(), + GenesisCheckStatus::TemporaryFailure { + checked_at: UNTESTABLE_ADAPTER.checked_at.unwrap(), + }, + )], + // UNTESTABLE_ADAPTER has failed ident, will be valid cause idents has None value adapters: vec![(VALID_CHAIN.into(), vec![UNTESTABLE_ADAPTER.clone()])], idents: vec![(VALID_CHAIN.into(), None)], - expected: Ok(vec![&UNTESTABLE_ADAPTER]), + expected: Err(ProviderManagerError::NoProvidersAvailable( + VALID_CHAIN.to_string(), + )), }, Case { name: "adapter temporary failure", chain_id: VALID_CHAIN, - // utc::now means it was just tested so it's untestable at the moment. + status: vec![( + UNTESTABLE_CHAIN.to_string(), + GenesisCheckStatus::TemporaryFailure { + checked_at: Utc::now(), + }, + )], adapters: vec![(VALID_CHAIN.into(), vec![UNTESTABLE_ADAPTER.clone()])], - idents: vec![(VALID_CHAIN.into(), Some(VALID_IDENT.clone()))], + idents: vec![(VALID_CHAIN.into(), Some(FAILED_IDENT.clone()))], expected: Err(ProviderManagerError::NoProvidersAvailable( VALID_CHAIN.to_string(), )), }, Case { name: "chain ident None", - chain_id: FAILED_CHAIN, + chain_id: VALID_CHAIN, // Failed adapter has VALID_CHAIN as the ident, which is not validated if // the expected ident is None - adapters: vec![(FAILED_CHAIN.into(), vec![FAILED_ADAPTER.clone()])], - idents: vec![(FAILED_CHAIN.into(), None)], + status: vec![], + adapters: vec![(VALID_CHAIN.into(), vec![FAILED_ADAPTER.clone()])], + idents: vec![(VALID_CHAIN.into(), None)], expected: Ok(vec![&FAILED_ADAPTER]), }, Case { name: "wrong chain ident", chain_id: VALID_CHAIN, + status: vec![], adapters: vec![(VALID_CHAIN.into(), vec![MockAdapter::failed()])], idents: vec![(VALID_CHAIN.into(), Some(VALID_IDENT.clone()))], expected: Err(ProviderManagerError::AllProvidersFailed( @@ -482,9 +499,15 @@ mod test { Case { name: "all adapters ok or not checkable yet", chain_id: VALID_CHAIN, + status: vec![( + FAILED_CHAIN.to_string(), + GenesisCheckStatus::TemporaryFailure { + checked_at: Utc::now(), + }, + )], adapters: vec![( VALID_CHAIN.into(), - vec![VALID_ADAPTER.clone(), UNTESTABLE_ADAPTER.clone()], + vec![VALID_ADAPTER.clone(), FAILED_ADAPTER.clone()], )], idents: vec![(VALID_CHAIN.into(), Some(VALID_IDENT.clone()))], expected: Ok(vec![&VALID_ADAPTER]), @@ -492,6 +515,12 @@ mod test { Case { name: "all adapters ok or checkable", chain_id: VALID_CHAIN, + status: vec![( + TESTABLE_CHAIN.to_string(), + GenesisCheckStatus::TemporaryFailure { + checked_at: TESTABLE_ADAPTER.checked_at.unwrap(), + }, + )], adapters: vec![( VALID_CHAIN.into(), vec![VALID_ADAPTER.clone(), TESTABLE_ADAPTER.clone()], @@ -505,6 +534,7 @@ mod test { let Case { name, chain_id, + status, adapters, idents, expected, @@ -513,22 +543,19 @@ mod test { let logger = Logger::root(Discard, o!()); let manager = ProviderManager::new(logger, adapters.into_iter(), idents.into_iter()); - for (ident, status) in manager.inner.status.iter() { - match ident.chain_id.as_str() { - TESTABLE_CHAIN => { - let mut s = status.write().await; - *s = GenesisCheckStatus::TemporaryFailure { - checked_at: Utc::now().sub(Duration::seconds(1000000)), - }; - } - UNTESTABLE_CHAIN => { - let mut s = status.write().await; - *s = GenesisCheckStatus::TemporaryFailure { - checked_at: Utc::now(), - }; - } - _ => {} - } + + for (provider, status) in status.iter() { + let slot = manager + .inner + .status + .iter() + .find(|(ident, _)| ident.provider.eq(provider)) + .expect(&format!( + "case: {} - there should be a status for provider \"{}\"", + name, provider + )); + let mut s = slot.1.write().await; + *s = status.clone(); } let result = manager.get_all(chain_id.into()).await;