Skip to content

Commit 24f9608

Browse files
chore: refactor subgraph fetch (#575)
1 parent ddcd34d commit 24f9608

File tree

6 files changed

+97
-49
lines changed

6 files changed

+97
-49
lines changed

crates/rover-client/src/query/subgraph/fetch.graphql crates/rover-client/src/query/subgraph/fetch/fetch_query.graphql

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
query FetchSubgraphQuery($variant: String!, $graphID: ID!) {
2-
service(id: $graphID) {
1+
query SubgraphFetchQuery($graph_id: ID!, $variant: String!) {
2+
service(id: $graph_id) {
33
implementingServices(graphVariant: $variant) {
44
__typename
55
... on FederatedImplementingServices {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub mod query_runner;
2+
pub(crate) mod types;
3+
pub use types::{SubgraphFetchInput, SubgraphFetchResponse};

crates/rover-client/src/query/subgraph/fetch.rs crates/rover-client/src/query/subgraph/fetch/query_runner.rs

+40-38
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::types::*;
12
use crate::blocking::StudioClient;
23
use crate::RoverClientError;
34
use graphql_client::*;
@@ -6,66 +7,69 @@ use graphql_client::*;
67
// The paths are relative to the directory where your `Cargo.toml` is located.
78
// Both json and the GraphQL schema language are supported as sources for the schema
89
#[graphql(
9-
query_path = "src/query/subgraph/fetch.graphql",
10+
query_path = "src/query/subgraph/fetch/fetch_query.graphql",
1011
schema_path = ".schema/schema.graphql",
1112
response_derives = "PartialEq, Debug, Serialize, Deserialize",
1213
deprecated = "warn"
1314
)]
1415
/// This struct is used to generate the module containing `Variables` and
1516
/// `ResponseData` structs.
16-
/// Snake case of this name is the mod name. i.e. fetch_subgraph_query
17-
pub struct FetchSubgraphQuery;
17+
/// Snake case of this name is the mod name. i.e. subgraph_fetch_query
18+
pub(crate) struct SubgraphFetchQuery;
1819

1920
/// Fetches a schema from apollo studio and returns its SDL (String)
2021
pub fn run(
21-
variables: fetch_subgraph_query::Variables,
22+
input: SubgraphFetchInput,
2223
client: &StudioClient,
23-
// we can't specify this as a variable in the op, so we have to filter the
24-
// operation response by this name
25-
subgraph: &str,
26-
) -> Result<String, RoverClientError> {
27-
let graph = variables.graph_id.clone();
28-
let response_data = client.post::<FetchSubgraphQuery>(variables)?;
29-
let services = get_services_from_response_data(response_data, graph)?;
30-
get_sdl_for_service(services, subgraph)
31-
// if we want json, we can parse & serialize it here
24+
) -> Result<SubgraphFetchResponse, RoverClientError> {
25+
let variables: SubgraphFetchVariables = input.clone().into();
26+
let response_data = client.post::<SubgraphFetchQuery>(variables.into())?;
27+
get_sdl_from_response_data(input, response_data)
28+
}
29+
30+
fn get_sdl_from_response_data(
31+
input: SubgraphFetchInput,
32+
response_data: SubgraphFetchResponseData,
33+
) -> Result<SubgraphFetchResponse, RoverClientError> {
34+
let service_list = get_services_from_response_data(&input.graph_id, response_data)?;
35+
let sdl = get_sdl_for_service(&input.subgraph, service_list)?;
36+
Ok(SubgraphFetchResponse { sdl })
3237
}
3338

34-
type ServiceList = Vec<fetch_subgraph_query::FetchSubgraphQueryServiceImplementingServicesOnFederatedImplementingServicesServices>;
3539
fn get_services_from_response_data(
36-
response_data: fetch_subgraph_query::ResponseData,
37-
graph: String,
40+
graph_id: &str,
41+
response_data: SubgraphFetchResponseData,
3842
) -> Result<ServiceList, RoverClientError> {
3943
let service_data = response_data.service.ok_or(RoverClientError::NoService {
40-
graph: graph.clone(),
44+
graph: graph_id.to_string(),
4145
})?;
4246

4347
// get list of services
4448
let services = match service_data.implementing_services {
4549
Some(services) => Ok(services),
46-
// this case may be removable in the near future as unreachable, since
47-
// you should still get an `implementingServices` response in the case
48-
// of a non-federated graph. Fow now, this case still exists, but
49-
// wont' for long. Check on this later (Jake) :)
5050
None => Err(RoverClientError::ExpectedFederatedGraph {
51-
graph: graph.clone(),
51+
graph: graph_id.to_string(),
5252
can_operation_convert: false,
5353
}),
5454
}?;
5555

5656
match services {
57-
fetch_subgraph_query::FetchSubgraphQueryServiceImplementingServices::FederatedImplementingServices (services) => {
58-
Ok(services.services)
59-
},
60-
fetch_subgraph_query::FetchSubgraphQueryServiceImplementingServices::NonFederatedImplementingService => {
61-
Err(RoverClientError::ExpectedFederatedGraph { graph, can_operation_convert: false })
57+
Services::FederatedImplementingServices(services) => Ok(services.services),
58+
Services::NonFederatedImplementingService => {
59+
Err(RoverClientError::ExpectedFederatedGraph {
60+
graph: graph_id.to_string(),
61+
can_operation_convert: false,
62+
})
6263
}
6364
}
6465
}
6566

66-
fn get_sdl_for_service(services: ServiceList, subgraph: &str) -> Result<String, RoverClientError> {
67+
fn get_sdl_for_service(
68+
subgraph_name: &str,
69+
services: ServiceList,
70+
) -> Result<String, RoverClientError> {
6771
// find the right service by name
68-
let service = services.iter().find(|svc| svc.name == subgraph);
72+
let service = services.iter().find(|svc| svc.name == subgraph_name);
6973

7074
// if there is a service, get it's active sdl, otherwise, error and list
7175
// available services to fetch
@@ -75,7 +79,7 @@ fn get_sdl_for_service(services: ServiceList, subgraph: &str) -> Result<String,
7579
let valid_subgraphs: Vec<String> = services.iter().map(|svc| svc.name.clone()).collect();
7680

7781
Err(RoverClientError::NoSubgraphInGraph {
78-
invalid_subgraph: subgraph.to_string(),
82+
invalid_subgraph: subgraph_name.to_string(),
7983
valid_subgraphs,
8084
})
8185
}
@@ -109,9 +113,8 @@ mod tests {
109113
}
110114
}
111115
});
112-
let data: fetch_subgraph_query::ResponseData =
113-
serde_json::from_value(json_response).unwrap();
114-
let output = get_services_from_response_data(data, "mygraph".to_string());
116+
let data: SubgraphFetchResponseData = serde_json::from_value(json_response).unwrap();
117+
let output = get_services_from_response_data("mygraph", data);
115118

116119
let expected_json = json!([
117120
{
@@ -140,9 +143,8 @@ mod tests {
140143
"implementingServices": null
141144
}
142145
});
143-
let data: fetch_subgraph_query::ResponseData =
144-
serde_json::from_value(json_response).unwrap();
145-
let output = get_services_from_response_data(data, "mygraph".to_string());
146+
let data: SubgraphFetchResponseData = serde_json::from_value(json_response).unwrap();
147+
let output = get_services_from_response_data("mygraph", data);
146148
assert!(output.is_err());
147149
}
148150

@@ -163,7 +165,7 @@ mod tests {
163165
}
164166
]);
165167
let service_list: ServiceList = serde_json::from_value(json_service_list).unwrap();
166-
let output = get_sdl_for_service(service_list, "accounts2");
168+
let output = get_sdl_for_service("accounts2", service_list);
167169
assert_eq!(
168170
output.unwrap(),
169171
"extend type User @key(fields: \"id\") {\n id: ID! @external\n age: Int\n}\n"
@@ -188,7 +190,7 @@ mod tests {
188190
}
189191
]);
190192
let service_list: ServiceList = serde_json::from_value(json_service_list).unwrap();
191-
let output = get_sdl_for_service(service_list, "harambe-was-an-inside-job");
193+
let output = get_sdl_for_service("harambe-was-an-inside-job", service_list);
192194
assert!(output.is_err());
193195
}
194196
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use super::query_runner::subgraph_fetch_query;
2+
3+
pub(crate) type ServiceList = Vec<subgraph_fetch_query::SubgraphFetchQueryServiceImplementingServicesOnFederatedImplementingServicesServices>;
4+
pub(crate) type SubgraphFetchResponseData = subgraph_fetch_query::ResponseData;
5+
pub(crate) type Services = subgraph_fetch_query::SubgraphFetchQueryServiceImplementingServices;
6+
pub(crate) type QueryVariables = subgraph_fetch_query::Variables;
7+
8+
#[derive(Debug, Clone, PartialEq)]
9+
pub struct SubgraphFetchInput {
10+
pub graph_id: String,
11+
pub variant: String,
12+
pub subgraph: String,
13+
}
14+
15+
#[derive(Debug, Clone, PartialEq)]
16+
pub(crate) struct SubgraphFetchVariables {
17+
graph_id: String,
18+
variant: String,
19+
}
20+
21+
impl From<SubgraphFetchInput> for SubgraphFetchVariables {
22+
fn from(input: SubgraphFetchInput) -> Self {
23+
Self {
24+
graph_id: input.graph_id,
25+
variant: input.variant,
26+
}
27+
}
28+
}
29+
30+
impl From<SubgraphFetchVariables> for QueryVariables {
31+
fn from(fetch_variables: SubgraphFetchVariables) -> Self {
32+
Self {
33+
graph_id: fetch_variables.graph_id,
34+
variant: fetch_variables.variant,
35+
}
36+
}
37+
}
38+
39+
#[derive(Debug, Clone, PartialEq)]
40+
pub struct SubgraphFetchResponse {
41+
pub sdl: String,
42+
}

src/command/subgraph/fetch.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use ansi_term::Colour::{Cyan, Yellow};
22
use serde::Serialize;
33
use structopt::StructOpt;
44

5-
use rover_client::query::subgraph::fetch;
5+
use rover_client::query::subgraph::fetch::{query_runner, SubgraphFetchInput};
66

77
use crate::command::RoverStdout;
88
use crate::utils::client::StudioClientConfig;
@@ -39,15 +39,15 @@ impl Fetch {
3939
Yellow.normal().paint(&self.profile_name)
4040
);
4141

42-
let sdl = fetch::run(
43-
fetch::fetch_subgraph_query::Variables {
42+
let result = query_runner::run(
43+
SubgraphFetchInput {
4444
graph_id: self.graph.name.clone(),
4545
variant: self.graph.variant.clone(),
46+
subgraph: self.subgraph.clone(),
4647
},
4748
&client,
48-
&self.subgraph,
4949
)?;
5050

51-
Ok(RoverStdout::Sdl(sdl))
51+
Ok(RoverStdout::Sdl(result.sdl))
5252
}
5353
}

src/command/supergraph/compose/do_compose.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{anyhow, command::RoverStdout, error::RoverError, Result, Suggestion}
55
use ansi_term::Colour::Red;
66
use camino::Utf8PathBuf;
77

8+
use rover_client::query::subgraph::fetch::SubgraphFetchInput;
89
use rover_client::{
910
blocking::GraphQLClient,
1011
query::subgraph::{fetch, introspect},
@@ -122,13 +123,13 @@ pub(crate) fn get_subgraph_definitions(
122123
// obtain SDL and add it to subgraph_definition.
123124
let client = client_config.get_client(&profile_name)?;
124125
let graphref = parse_graph_ref(graphref)?;
125-
let schema = fetch::run(
126-
fetch::fetch_subgraph_query::Variables {
126+
let result = fetch::query_runner::run(
127+
SubgraphFetchInput {
127128
graph_id: graphref.name.clone(),
128129
variant: graphref.variant.clone(),
130+
subgraph: subgraph.clone(),
129131
},
130132
&client,
131-
subgraph,
132133
)?;
133134

134135
// We don't require a routing_url for this variant of a schema,
@@ -138,7 +139,7 @@ pub(crate) fn get_subgraph_definitions(
138139
// and use that when no routing_url is provided.
139140
let url = &subgraph_data.routing_url.clone().unwrap_or_default();
140141

141-
let subgraph_definition = SubgraphDefinition::new(subgraph_name, url, &schema);
142+
let subgraph_definition = SubgraphDefinition::new(subgraph_name, url, &result.sdl);
142143
subgraphs.push(subgraph_definition);
143144
}
144145
}

0 commit comments

Comments
 (0)