-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Subgraph Compositions: Validations #5770
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,16 @@ use crate::{ | |
blockchain::{block_stream::EntitySourceOperation, Block, Blockchain}, | ||
components::{link_resolver::LinkResolver, store::BlockNumber}, | ||
data::{ | ||
subgraph::{calls_host_fn, SPEC_VERSION_1_3_0}, | ||
subgraph::{ | ||
calls_host_fn, SubgraphManifest, UnresolvedSubgraphManifest, LATEST_VERSION, | ||
SPEC_VERSION_1_3_0, | ||
}, | ||
value::Word, | ||
}, | ||
data_source::{self, common::DeclaredCall}, | ||
ensure, | ||
prelude::{CheapClone, DataSourceContext, DeploymentHash, Link}, | ||
schema::TypeKind, | ||
}; | ||
use anyhow::{anyhow, Context, Error, Result}; | ||
use futures03::{stream::FuturesOrdered, TryStreamExt}; | ||
|
@@ -211,8 +215,62 @@ pub struct UnresolvedMapping { | |
} | ||
|
||
impl UnresolvedDataSource { | ||
fn validate_mapping_entities<C: Blockchain>( | ||
mapping_entities: &[String], | ||
source_manifest: &SubgraphManifest<C>, | ||
) -> Result<(), Error> { | ||
for entity in mapping_entities { | ||
let type_kind = source_manifest.schema.kind_of_declared_type(&entity); | ||
|
||
match type_kind { | ||
Some(TypeKind::Interface) => { | ||
return Err(anyhow!( | ||
"Entity {} is an interface and cannot be used as a mapping entity", | ||
entity | ||
)); | ||
} | ||
Some(TypeKind::Aggregation) => { | ||
return Err(anyhow!( | ||
"Entity {} is an aggregation and cannot be used as a mapping entity", | ||
entity | ||
)); | ||
} | ||
None => { | ||
return Err(anyhow!("Entity {} not found in source manifest", entity)); | ||
} | ||
Some(TypeKind::Object) => {} | ||
} | ||
} | ||
Ok(()) | ||
} | ||
|
||
async fn resolve_source_manifest<C: Blockchain>( | ||
&self, | ||
resolver: &Arc<dyn LinkResolver>, | ||
logger: &Logger, | ||
) -> Result<Arc<SubgraphManifest<C>>, Error> { | ||
let source_raw = resolver | ||
.cat(logger, &self.source.address.to_ipfs_link()) | ||
.await | ||
.context("Failed to resolve source subgraph manifest")?; | ||
|
||
let source_raw: serde_yaml::Mapping = serde_yaml::from_slice(&source_raw) | ||
.context("Failed to parse source subgraph manifest as YAML")?; | ||
|
||
let deployment_hash = self.source.address.clone(); | ||
|
||
let source_manifest = UnresolvedSubgraphManifest::<C>::parse(deployment_hash, source_raw) | ||
.context("Failed to parse source subgraph manifest")?; | ||
|
||
source_manifest | ||
.resolve(resolver, logger, LATEST_VERSION.clone()) | ||
.await | ||
.context("Failed to resolve source subgraph manifest") | ||
.map(Arc::new) | ||
} | ||
|
||
#[allow(dead_code)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we still need this tag? |
||
pub(super) async fn resolve( | ||
pub(super) async fn resolve<C: Blockchain>( | ||
self, | ||
resolver: &Arc<dyn LinkResolver>, | ||
logger: &Logger, | ||
|
@@ -224,7 +282,38 @@ impl UnresolvedDataSource { | |
"source" => format_args!("{:?}", &self.source), | ||
); | ||
|
||
let kind = self.kind; | ||
let kind = self.kind.clone(); | ||
let source_manifest = self.resolve_source_manifest::<C>(resolver, logger).await?; | ||
let source_spec_version = &source_manifest.spec_version; | ||
|
||
if source_spec_version < &SPEC_VERSION_1_3_0 { | ||
return Err(anyhow!( | ||
"Source subgraph manifest spec version {} is not supported, minimum supported version is {}", | ||
source_spec_version, | ||
SPEC_VERSION_1_3_0 | ||
)); | ||
} | ||
|
||
let pruning_enabled = match source_manifest.indexer_hints.as_ref() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pruning can also be set outside of the manifest right? Is there are a way we check that too? |
||
None => false, | ||
Some(hints) => hints.prune.is_some(), | ||
}; | ||
|
||
if pruning_enabled { | ||
return Err(anyhow!( | ||
"Pruning is enabled for source subgraph, which is not supported" | ||
)); | ||
} | ||
|
||
let mapping_entities: Vec<String> = self | ||
.mapping | ||
.handlers | ||
.iter() | ||
.map(|handler| handler.entity.clone()) | ||
.collect(); | ||
|
||
Self::validate_mapping_entities(&mapping_entities, &source_manifest)?; | ||
|
||
let source = Source { | ||
address: self.source.address, | ||
start_block: self.source.start_block, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
specVersion: 0.0.8 | ||
specVersion: 1.3.0 | ||
schema: | ||
file: ./schema.graphql | ||
dataSources: | ||
|
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add some tests for this as well?