Skip to content

Commit 4b7e513

Browse files
authored
Update supergraph resolution order (#2214)
This ensures that any remote supergraph configs from a `--graph-ref` flag are replaced by the local supergraph config file
1 parent a227a65 commit 4b7e513

File tree

2 files changed

+88
-83
lines changed

2 files changed

+88
-83
lines changed

src/composition/supergraph/config/mod.rs

+81-74
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ mod state {
3333
use apollo_federation_types::config::{FederationVersion, SupergraphConfig};
3434
use camino::Utf8PathBuf;
3535

36-
pub struct LoadSupergraphConfig {
36+
pub struct LoadRemoteSubgraphs {
3737
pub federation_version: Option<FederationVersion>,
3838
}
39-
pub struct LoadRemoteSubgraphs {
40-
pub origin_path: Option<Utf8PathBuf>,
39+
pub struct LoadSupergraphConfig {
40+
pub federation_version: Option<FederationVersion>,
4141
pub supergraph_config: Option<SupergraphConfig>,
4242
}
4343
pub struct ResolveSubgraphs {
@@ -56,22 +56,59 @@ pub struct SupergraphConfigResolver<State> {
5656
state: State,
5757
}
5858

59-
impl SupergraphConfigResolver<LoadSupergraphConfig> {
59+
impl SupergraphConfigResolver<LoadRemoteSubgraphs> {
6060
pub fn new(
6161
federation_version: Option<FederationVersion>,
62-
) -> SupergraphConfigResolver<LoadSupergraphConfig> {
62+
) -> SupergraphConfigResolver<LoadRemoteSubgraphs> {
6363
SupergraphConfigResolver {
64-
state: LoadSupergraphConfig { federation_version },
64+
state: LoadRemoteSubgraphs { federation_version },
6565
}
6666
}
6767
}
6868

69-
impl Default for SupergraphConfigResolver<LoadSupergraphConfig> {
69+
impl Default for SupergraphConfigResolver<LoadRemoteSubgraphs> {
7070
fn default() -> Self {
7171
Self::new(None)
7272
}
7373
}
7474

75+
#[derive(thiserror::Error, Debug)]
76+
pub enum LoadRemoteSubgraphsError {
77+
#[error(transparent)]
78+
FetchRemoteSubgraphsError(Box<dyn std::error::Error + Send + Sync>),
79+
}
80+
81+
impl SupergraphConfigResolver<LoadRemoteSubgraphs> {
82+
pub async fn load_remote_subgraphs(
83+
self,
84+
fetch_remote_subgraphs_impl: &impl FetchRemoteSubgraphs,
85+
graph_ref: Option<&GraphRef>,
86+
) -> Result<SupergraphConfigResolver<LoadSupergraphConfig>, LoadRemoteSubgraphsError> {
87+
if let Some(graph_ref) = graph_ref {
88+
let remote_subgraphs = fetch_remote_subgraphs_impl
89+
.fetch_remote_subgraphs(graph_ref)
90+
.await
91+
.map_err(|err| {
92+
LoadRemoteSubgraphsError::FetchRemoteSubgraphsError(Box::new(err))
93+
})?;
94+
let remote_supergraph_config = SupergraphConfig::new(remote_subgraphs, None);
95+
Ok(SupergraphConfigResolver {
96+
state: LoadSupergraphConfig {
97+
federation_version: self.state.federation_version,
98+
supergraph_config: Some(remote_supergraph_config),
99+
},
100+
})
101+
} else {
102+
Ok(SupergraphConfigResolver {
103+
state: LoadSupergraphConfig {
104+
federation_version: self.state.federation_version,
105+
supergraph_config: None,
106+
},
107+
})
108+
}
109+
}
110+
}
111+
75112
#[derive(thiserror::Error, Debug)]
76113
pub enum LoadSupergraphConfigError {
77114
#[error("Failed to parse the supergraph config. Error: {0}")]
@@ -85,7 +122,7 @@ impl SupergraphConfigResolver<LoadSupergraphConfig> {
85122
self,
86123
read_stdin_impl: &mut impl ReadStdin,
87124
file_descriptor_type: Option<&FileDescriptorType>,
88-
) -> Result<SupergraphConfigResolver<LoadRemoteSubgraphs>, LoadSupergraphConfigError> {
125+
) -> Result<SupergraphConfigResolver<ResolveSubgraphs>, LoadSupergraphConfigError> {
89126
if let Some(file_descriptor_type) = file_descriptor_type {
90127
let mut supergraph_config = file_descriptor_type
91128
.read_file_descriptor("supergraph config", read_stdin_impl)
@@ -98,63 +135,38 @@ impl SupergraphConfigResolver<LoadSupergraphConfig> {
98135
FileDescriptorType::File(file) => Some(file.clone()),
99136
FileDescriptorType::Stdin => None,
100137
};
101-
if let Some(federation_version) = self.state.federation_version {
102-
supergraph_config.set_federation_version(federation_version);
138+
if let Some(federation_version) = &self.state.federation_version {
139+
supergraph_config.set_federation_version(federation_version.clone());
103140
}
104-
Ok(SupergraphConfigResolver {
105-
state: LoadRemoteSubgraphs {
106-
origin_path,
107-
supergraph_config: Some(supergraph_config),
108-
},
109-
})
110-
} else {
111-
Ok(SupergraphConfigResolver {
112-
state: LoadRemoteSubgraphs {
113-
origin_path: None,
114-
supergraph_config: None,
115-
},
116-
})
117-
}
118-
}
119-
}
120-
121-
#[derive(thiserror::Error, Debug)]
122-
pub enum LoadRemoteSubgraphsError {
123-
#[error(transparent)]
124-
FetchRemoteSubgraphsError(Box<dyn std::error::Error + Send + Sync>),
125-
}
126-
127-
impl SupergraphConfigResolver<LoadRemoteSubgraphs> {
128-
pub async fn load_remote_subgraphs(
129-
self,
130-
fetch_remote_subgraphs_impl: &impl FetchRemoteSubgraphs,
131-
graph_ref: Option<&GraphRef>,
132-
) -> Result<SupergraphConfigResolver<ResolveSubgraphs>, LoadRemoteSubgraphsError> {
133-
if let Some(graph_ref) = graph_ref {
134-
let remote_supergraph_config = fetch_remote_subgraphs_impl
135-
.fetch_remote_subgraphs(graph_ref)
136-
.await
137-
.map_err(|err| {
138-
LoadRemoteSubgraphsError::FetchRemoteSubgraphsError(Box::new(err))
139-
})?;
140141
Ok(SupergraphConfigResolver {
141142
state: ResolveSubgraphs {
142-
origin_path: self.state.origin_path,
143+
origin_path,
143144
supergraph_config: self
144145
.state
145146
.supergraph_config
146-
.map(|mut supergraph_config| {
147-
supergraph_config.merge_subgraphs(&remote_supergraph_config);
148-
supergraph_config
147+
.map(|mut remote_supergraph_config| {
148+
remote_supergraph_config.merge_subgraphs(&supergraph_config);
149+
if let Some(federation_version) =
150+
supergraph_config.get_federation_version()
151+
{
152+
remote_supergraph_config.set_federation_version(federation_version);
153+
}
154+
remote_supergraph_config
149155
})
150-
.or_else(|| Some(remote_supergraph_config)),
156+
.or_else(|| Some(supergraph_config)),
151157
},
152158
})
153159
} else {
160+
let supergraph_config = self.state.supergraph_config.map(|mut supergraph_config| {
161+
if let Some(federation_version) = &self.state.federation_version {
162+
supergraph_config.set_federation_version(federation_version.clone());
163+
}
164+
supergraph_config
165+
});
154166
Ok(SupergraphConfigResolver {
155167
state: ResolveSubgraphs {
156-
origin_path: self.state.origin_path,
157-
supergraph_config: self.state.supergraph_config,
168+
origin_path: None,
169+
supergraph_config,
158170
},
159171
})
160172
}
@@ -452,10 +464,6 @@ mod tests {
452464
// init resolver with a target fed version
453465
let resolver = SupergraphConfigResolver::new(Some(target_federation_version.clone()));
454466

455-
// load from the file descriptor
456-
let resolver = resolver
457-
.load_from_file_descriptor(&mut mock_read_stdin, Some(&file_descriptor_type))?;
458-
459467
// determine whether to try to load from graph refs
460468
let graph_ref = remote_subgraph_scenario
461469
.as_ref()
@@ -472,6 +480,10 @@ mod tests {
472480
.load_remote_subgraphs(&mock_fetch_remote_subgraphs, graph_ref.as_ref())
473481
.await?;
474482

483+
// load from the file descriptor
484+
let resolver = resolver
485+
.load_from_file_descriptor(&mut mock_read_stdin, Some(&file_descriptor_type))?;
486+
475487
// validate that the correct effect has been invoked
476488
mock_fetch_remote_subgraphs.checkpoint();
477489

@@ -631,10 +643,6 @@ mod tests {
631643
// init resolver with no target fed version
632644
let resolver = SupergraphConfigResolver::new(None);
633645

634-
// load from the file descriptor
635-
let resolver = resolver
636-
.load_from_file_descriptor(&mut mock_read_stdin, Some(&file_descriptor_type))?;
637-
638646
// determine whether to try to load from graph refs
639647
let graph_ref = remote_subgraph_scenario
640648
.as_ref()
@@ -651,6 +659,10 @@ mod tests {
651659
.load_remote_subgraphs(&mock_fetch_remote_subgraphs, graph_ref.as_ref())
652660
.await?;
653661

662+
// load from the file descriptor
663+
let resolver = resolver
664+
.load_from_file_descriptor(&mut mock_read_stdin, Some(&file_descriptor_type))?;
665+
654666
// validate that the correct effect has been invoked
655667
mock_fetch_remote_subgraphs.checkpoint();
656668

@@ -805,10 +817,6 @@ mod tests {
805817
// init resolver with no target fed version
806818
let resolver = SupergraphConfigResolver::new(None);
807819

808-
// load from the file descriptor
809-
let resolver = resolver
810-
.load_from_file_descriptor(&mut mock_read_stdin, Some(&file_descriptor_type))?;
811-
812820
// determine whether to try to load from graph refs
813821
let graph_ref = remote_subgraph_scenario
814822
.as_ref()
@@ -825,6 +833,10 @@ mod tests {
825833
.load_remote_subgraphs(&mock_fetch_remote_subgraphs, graph_ref.as_ref())
826834
.await?;
827835

836+
// load from the file descriptor
837+
let resolver = resolver
838+
.load_from_file_descriptor(&mut mock_read_stdin, Some(&file_descriptor_type))?;
839+
828840
// validate that the correct effect has been invoked
829841
mock_fetch_remote_subgraphs.checkpoint();
830842

@@ -906,17 +918,12 @@ mod tests {
906918
.times(1)
907919
.with(predicate::eq(remote_subgraph_scenario.graph_ref.clone()))
908920
.returning({
909-
let remote_supergraph_federation_version =
910-
remote_supergraph_federation_version.clone();
911921
let subgraph_name = remote_subgraph_scenario.subgraph_name.to_string();
912922
move |_| {
913-
Ok(SupergraphConfig::new(
914-
BTreeMap::from_iter([(
915-
subgraph_name.to_string(),
916-
subgraph_config.clone(),
917-
)]),
918-
remote_supergraph_federation_version.clone(),
919-
))
923+
Ok(BTreeMap::from_iter([(
924+
subgraph_name.to_string(),
925+
subgraph_config.clone(),
926+
)]))
920927
}
921928
});
922929
}

src/utils/effect/fetch_remote_subgraphs.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use apollo_federation_types::config::SupergraphConfig;
1+
use std::collections::BTreeMap;
2+
3+
use apollo_federation_types::config::SubgraphConfig;
24
use async_trait::async_trait;
35
use rover_client::{
46
blocking::StudioClient,
@@ -22,7 +24,7 @@ pub trait FetchRemoteSubgraphs {
2224
async fn fetch_remote_subgraphs(
2325
&self,
2426
graph_ref: &GraphRef,
25-
) -> Result<SupergraphConfig, Self::Error>;
27+
) -> Result<BTreeMap<String, SubgraphConfig>, Self::Error>;
2628
}
2729

2830
#[async_trait]
@@ -32,11 +34,8 @@ impl FetchRemoteSubgraphs for StudioClient {
3234
async fn fetch_remote_subgraphs(
3335
&self,
3436
graph_ref: &GraphRef,
35-
) -> Result<SupergraphConfig, Self::Error> {
36-
let SubgraphFetchAllResponse {
37-
subgraphs,
38-
federation_version,
39-
} = subgraph::fetch_all::run(
37+
) -> Result<BTreeMap<String, SubgraphConfig>, Self::Error> {
38+
let SubgraphFetchAllResponse { subgraphs, .. } = subgraph::fetch_all::run(
4039
SubgraphFetchAllInput {
4140
graph_ref: graph_ref.clone(),
4241
},
@@ -47,7 +46,6 @@ impl FetchRemoteSubgraphs for StudioClient {
4746
.into_iter()
4847
.map(|subgraph| (subgraph.name().clone(), subgraph.into()))
4948
.collect();
50-
let supergraph_config = SupergraphConfig::new(subgraphs, federation_version);
51-
Ok(supergraph_config)
49+
Ok(subgraphs)
5250
}
5351
}

0 commit comments

Comments
 (0)