mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 17:31:56 +03:00
more explicit data flow in metadata resolver (#403)
<!-- Thank you for submitting this PR! :) --> ## Description As noted in https://github.com/hasura/v3-engine/pull/398, the metadata resolver works by passing a lot of mutable references around, making the flow of data quite difficult to follow. This changes the passing of `types` to make it more explicit. Where possible, any mutation is pushed up to the top-level, or we return owned values. V3_GIT_ORIGIN_REV_ID: 61251929cbc9b9410fabba85b58738037dfcb586
This commit is contained in:
parent
ea98418833
commit
dda2fb8eca
@ -113,43 +113,39 @@ pub fn resolve_metadata(metadata: open_dds::Metadata) -> Result<Metadata, Error>
|
|||||||
// resolve data connectors
|
// resolve data connectors
|
||||||
let mut data_connectors = resolve_data_connectors(&metadata_accessor)?;
|
let mut data_connectors = resolve_data_connectors(&metadata_accessor)?;
|
||||||
|
|
||||||
let mut types: HashMap<Qualified<CustomTypeName>, TypeRepresentation> = HashMap::new();
|
|
||||||
let mut existing_graphql_types: HashSet<ast::TypeName> = HashSet::new();
|
let mut existing_graphql_types: HashSet<ast::TypeName> = HashSet::new();
|
||||||
|
|
||||||
// we collect all the types with global id fields, and models with global id source for that field. this is used
|
// we collect all the types with global id fields, and models with global id source for that field. this is used
|
||||||
// later for validation, such that a type with global id field must have atleast one model with global id source
|
// later for validation, such that a type with global id field must have atleast one model with global id source
|
||||||
let mut global_id_enabled_types: HashMap<Qualified<CustomTypeName>, Vec<Qualified<ModelName>>> =
|
let mut global_id_enabled_types: HashMap<Qualified<CustomTypeName>, Vec<Qualified<ModelName>>> =
|
||||||
HashMap::new();
|
HashMap::new();
|
||||||
|
|
||||||
let mut apollo_federation_entity_enabled_types: HashMap<
|
let mut apollo_federation_entity_enabled_types: HashMap<
|
||||||
Qualified<CustomTypeName>,
|
Qualified<CustomTypeName>,
|
||||||
Option<Qualified<ModelName>>,
|
Option<Qualified<ModelName>>,
|
||||||
> = HashMap::new();
|
> = HashMap::new();
|
||||||
|
|
||||||
// resolve object types
|
// resolve object types
|
||||||
// TODO: make this return more values rather than blindly mutating it's inputs
|
let (data_connector_type_mappings, types) = resolve_data_connector_type_mappings_and_objects(
|
||||||
let data_connector_type_mappings = resolve_data_connector_type_mappings_and_objects(
|
|
||||||
&metadata_accessor,
|
&metadata_accessor,
|
||||||
&data_connectors,
|
&data_connectors,
|
||||||
&mut types,
|
|
||||||
&mut existing_graphql_types,
|
&mut existing_graphql_types,
|
||||||
&mut global_id_enabled_types,
|
&mut global_id_enabled_types,
|
||||||
&mut apollo_federation_entity_enabled_types,
|
&mut apollo_federation_entity_enabled_types,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// resolve scalar types
|
// resolve scalar types
|
||||||
// TODO: make this return values rather than blindly mutating it's inputs
|
let scalar_types = resolve_scalar_types(&metadata_accessor, &mut existing_graphql_types)?;
|
||||||
resolve_scalar_types(&metadata_accessor, &mut types, &mut existing_graphql_types)?;
|
|
||||||
|
|
||||||
// resolve type permissions
|
// resolve type permissions
|
||||||
// TODO: make this return values rather than blindly mutating it's inputs
|
let types = resolve_type_permissions(&metadata_accessor, extend_types(types, scalar_types)?)?;
|
||||||
resolve_type_permissions(&metadata_accessor, &mut types)?;
|
|
||||||
|
|
||||||
// resolve object boolean expression types
|
// resolve object boolean expression types
|
||||||
let boolean_expression_types = resolve_boolean_expression_types(
|
let boolean_expression_types = resolve_boolean_expression_types(
|
||||||
&metadata_accessor,
|
&metadata_accessor,
|
||||||
&data_connectors,
|
&data_connectors,
|
||||||
&data_connector_type_mappings,
|
&data_connector_type_mappings,
|
||||||
&mut types,
|
&types,
|
||||||
&mut existing_graphql_types,
|
&mut existing_graphql_types,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -158,7 +154,7 @@ pub fn resolve_metadata(metadata: open_dds::Metadata) -> Result<Metadata, Error>
|
|||||||
resolve_data_connector_scalar_representations(
|
resolve_data_connector_scalar_representations(
|
||||||
&metadata_accessor,
|
&metadata_accessor,
|
||||||
&mut data_connectors,
|
&mut data_connectors,
|
||||||
&mut types,
|
&types,
|
||||||
&mut existing_graphql_types,
|
&mut existing_graphql_types,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -171,7 +167,7 @@ pub fn resolve_metadata(metadata: open_dds::Metadata) -> Result<Metadata, Error>
|
|||||||
&metadata_accessor,
|
&metadata_accessor,
|
||||||
&data_connectors,
|
&data_connectors,
|
||||||
&data_connector_type_mappings,
|
&data_connector_type_mappings,
|
||||||
&mut types,
|
&types,
|
||||||
&mut existing_graphql_types,
|
&mut existing_graphql_types,
|
||||||
&mut global_id_enabled_types,
|
&mut global_id_enabled_types,
|
||||||
&mut apollo_federation_entity_enabled_types,
|
&mut apollo_federation_entity_enabled_types,
|
||||||
@ -205,11 +201,10 @@ pub fn resolve_metadata(metadata: open_dds::Metadata) -> Result<Metadata, Error>
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
// resolve relationships
|
// resolve relationships
|
||||||
// TODO: make this return values rather than blindly mutating it's inputs
|
let types = resolve_relationships(
|
||||||
resolve_relationships(
|
|
||||||
&metadata_accessor,
|
&metadata_accessor,
|
||||||
&data_connectors,
|
&data_connectors,
|
||||||
&mut types,
|
types,
|
||||||
&models,
|
&models,
|
||||||
&commands,
|
&commands,
|
||||||
)?;
|
)?;
|
||||||
@ -304,15 +299,21 @@ fn resolve_data_connectors(
|
|||||||
fn resolve_data_connector_type_mappings_and_objects(
|
fn resolve_data_connector_type_mappings_and_objects(
|
||||||
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
||||||
data_connectors: &HashMap<Qualified<DataConnectorName>, DataConnectorContext>,
|
data_connectors: &HashMap<Qualified<DataConnectorName>, DataConnectorContext>,
|
||||||
types: &mut HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
|
||||||
existing_graphql_types: &mut HashSet<ast::TypeName>,
|
existing_graphql_types: &mut HashSet<ast::TypeName>,
|
||||||
global_id_enabled_types: &mut HashMap<Qualified<CustomTypeName>, Vec<Qualified<ModelName>>>,
|
global_id_enabled_types: &mut HashMap<Qualified<CustomTypeName>, Vec<Qualified<ModelName>>>,
|
||||||
apollo_federation_entity_enabled_types: &mut HashMap<
|
apollo_federation_entity_enabled_types: &mut HashMap<
|
||||||
Qualified<CustomTypeName>,
|
Qualified<CustomTypeName>,
|
||||||
Option<Qualified<open_dds::models::ModelName>>,
|
Option<Qualified<open_dds::models::ModelName>>,
|
||||||
>,
|
>,
|
||||||
) -> Result<DataConnectorTypeMappings, Error> {
|
) -> Result<
|
||||||
|
(
|
||||||
|
DataConnectorTypeMappings,
|
||||||
|
HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
||||||
|
),
|
||||||
|
Error,
|
||||||
|
> {
|
||||||
let mut data_connector_type_mappings = DataConnectorTypeMappings::new();
|
let mut data_connector_type_mappings = DataConnectorTypeMappings::new();
|
||||||
|
let mut types = HashMap::new();
|
||||||
|
|
||||||
for open_dds::accessor::QualifiedObject {
|
for open_dds::accessor::QualifiedObject {
|
||||||
subgraph,
|
subgraph,
|
||||||
@ -370,17 +371,34 @@ fn resolve_data_connector_type_mappings_and_objects(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(data_connector_type_mappings)
|
Ok((data_connector_type_mappings, types))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// combine two sets of types, returning a `DuplicateTypeDefinition` error if we find duplicates
|
||||||
|
/// along the way
|
||||||
|
fn extend_types(
|
||||||
|
mut old_types: HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
||||||
|
new_types: HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
||||||
|
) -> Result<HashMap<Qualified<CustomTypeName>, TypeRepresentation>, Error> {
|
||||||
|
for new_type_name in new_types.keys() {
|
||||||
|
if old_types.contains_key(new_type_name) {
|
||||||
|
return Err(Error::DuplicateTypeDefinition {
|
||||||
|
name: new_type_name.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
old_types.extend(new_types);
|
||||||
|
Ok(old_types)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// resolve scalar types
|
/// resolve scalar types
|
||||||
/// this currently works by mutating `types` and `existing_graphql_types`, we should try
|
/// this currently works by mutating `existing_graphql_types`, we should try
|
||||||
/// and change this to return new values here and make the caller combine them together
|
/// and change this to return new values here and make the caller combine them together
|
||||||
fn resolve_scalar_types(
|
fn resolve_scalar_types(
|
||||||
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
||||||
types: &mut HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
|
||||||
existing_graphql_types: &mut HashSet<ast::TypeName>,
|
existing_graphql_types: &mut HashSet<ast::TypeName>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<HashMap<Qualified<CustomTypeName>, TypeRepresentation>, Error> {
|
||||||
|
let mut scalar_types = HashMap::new();
|
||||||
for open_dds::accessor::QualifiedObject {
|
for open_dds::accessor::QualifiedObject {
|
||||||
subgraph,
|
subgraph,
|
||||||
object: scalar_type,
|
object: scalar_type,
|
||||||
@ -392,9 +410,11 @@ fn resolve_scalar_types(
|
|||||||
.map(ast::TypeName)
|
.map(ast::TypeName)
|
||||||
.map(Some),
|
.map(Some),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let qualified_scalar_type_name =
|
let qualified_scalar_type_name =
|
||||||
Qualified::new(subgraph.to_string(), scalar_type.name.clone());
|
Qualified::new(subgraph.to_string(), scalar_type.name.clone());
|
||||||
if types
|
|
||||||
|
if scalar_types
|
||||||
.insert(
|
.insert(
|
||||||
qualified_scalar_type_name.clone(),
|
qualified_scalar_type_name.clone(),
|
||||||
TypeRepresentation::ScalarType(ScalarTypeRepresentation {
|
TypeRepresentation::ScalarType(ScalarTypeRepresentation {
|
||||||
@ -410,16 +430,15 @@ fn resolve_scalar_types(
|
|||||||
}
|
}
|
||||||
check_conflicting_graphql_types(existing_graphql_types, graphql_type_name.as_ref())?;
|
check_conflicting_graphql_types(existing_graphql_types, graphql_type_name.as_ref())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(scalar_types)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// resolve type permissions
|
/// resolve type permissions
|
||||||
/// this currently works by blindly mutation `types`, let's change it to more explicitly
|
/// this works by mutating `types`, and returning an owned value
|
||||||
/// return new values if possible
|
|
||||||
fn resolve_type_permissions(
|
fn resolve_type_permissions(
|
||||||
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
||||||
types: &mut HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
mut types: HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<HashMap<Qualified<CustomTypeName>, TypeRepresentation>, Error> {
|
||||||
// resolve type permissions
|
// resolve type permissions
|
||||||
for open_dds::accessor::QualifiedObject {
|
for open_dds::accessor::QualifiedObject {
|
||||||
subgraph,
|
subgraph,
|
||||||
@ -441,7 +460,7 @@ fn resolve_type_permissions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(types)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// resolve object boolean expression types
|
/// resolve object boolean expression types
|
||||||
@ -449,7 +468,7 @@ fn resolve_boolean_expression_types(
|
|||||||
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
||||||
data_connectors: &HashMap<Qualified<DataConnectorName>, DataConnectorContext>,
|
data_connectors: &HashMap<Qualified<DataConnectorName>, DataConnectorContext>,
|
||||||
data_connector_type_mappings: &DataConnectorTypeMappings,
|
data_connector_type_mappings: &DataConnectorTypeMappings,
|
||||||
types: &mut HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
types: &HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
||||||
existing_graphql_types: &mut HashSet<ast::TypeName>,
|
existing_graphql_types: &mut HashSet<ast::TypeName>,
|
||||||
) -> Result<HashMap<Qualified<CustomTypeName>, ObjectBooleanExpressionType>, Error> {
|
) -> Result<HashMap<Qualified<CustomTypeName>, ObjectBooleanExpressionType>, Error> {
|
||||||
let mut boolean_expression_types = HashMap::new();
|
let mut boolean_expression_types = HashMap::new();
|
||||||
@ -479,12 +498,12 @@ fn resolve_boolean_expression_types(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// resolve data connector scalar representations
|
/// resolve data connector scalar representations
|
||||||
/// this currently works by mutating `types` and `existing_graphql_types`, let's change it to
|
/// this currently works by mutating `existing_graphql_types`, let's change it to
|
||||||
/// return new values instead if possible
|
/// return new values instead if possible
|
||||||
fn resolve_data_connector_scalar_representations(
|
fn resolve_data_connector_scalar_representations(
|
||||||
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
||||||
data_connectors: &mut HashMap<Qualified<DataConnectorName>, DataConnectorContext>,
|
data_connectors: &mut HashMap<Qualified<DataConnectorName>, DataConnectorContext>,
|
||||||
types: &mut HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
types: &HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
||||||
existing_graphql_types: &mut HashSet<ast::TypeName>,
|
existing_graphql_types: &mut HashSet<ast::TypeName>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
for open_dds::accessor::QualifiedObject {
|
for open_dds::accessor::QualifiedObject {
|
||||||
@ -562,7 +581,7 @@ fn resolve_models(
|
|||||||
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
||||||
data_connectors: &HashMap<Qualified<DataConnectorName>, DataConnectorContext>,
|
data_connectors: &HashMap<Qualified<DataConnectorName>, DataConnectorContext>,
|
||||||
data_connector_type_mappings: &DataConnectorTypeMappings,
|
data_connector_type_mappings: &DataConnectorTypeMappings,
|
||||||
types: &mut HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
types: &HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
||||||
existing_graphql_types: &mut HashSet<ast::TypeName>,
|
existing_graphql_types: &mut HashSet<ast::TypeName>,
|
||||||
global_id_enabled_types: &mut HashMap<Qualified<CustomTypeName>, Vec<Qualified<ModelName>>>,
|
global_id_enabled_types: &mut HashMap<Qualified<CustomTypeName>, Vec<Qualified<ModelName>>>,
|
||||||
apollo_federation_entity_enabled_types: &mut HashMap<
|
apollo_federation_entity_enabled_types: &mut HashMap<
|
||||||
@ -641,15 +660,14 @@ fn resolve_models(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// resolve relationships
|
/// resolve relationships
|
||||||
/// this currently works by mutating `types`, let's change it to
|
/// returns updated `types` value
|
||||||
/// return new values instead where possible
|
|
||||||
fn resolve_relationships(
|
fn resolve_relationships(
|
||||||
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
metadata_accessor: &open_dds::accessor::MetadataAccessor,
|
||||||
data_connectors: &HashMap<Qualified<DataConnectorName>, DataConnectorContext>,
|
data_connectors: &HashMap<Qualified<DataConnectorName>, DataConnectorContext>,
|
||||||
types: &mut HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
mut types: HashMap<Qualified<CustomTypeName>, TypeRepresentation>,
|
||||||
models: &IndexMap<Qualified<ModelName>, Model>,
|
models: &IndexMap<Qualified<ModelName>, Model>,
|
||||||
commands: &IndexMap<Qualified<CommandName>, command::Command>,
|
commands: &IndexMap<Qualified<CommandName>, command::Command>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<HashMap<Qualified<CustomTypeName>, TypeRepresentation>, Error> {
|
||||||
for open_dds::accessor::QualifiedObject {
|
for open_dds::accessor::QualifiedObject {
|
||||||
subgraph,
|
subgraph,
|
||||||
object: relationship,
|
object: relationship,
|
||||||
@ -695,7 +713,7 @@ fn resolve_relationships(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(types)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// resolve command permissions
|
/// resolve command permissions
|
||||||
|
Loading…
Reference in New Issue
Block a user