diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index 39ec9cc134..9ff18f2bdc 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -50,11 +50,20 @@ By [@bnjjj](https://github.com/bnjjj) in https://github.com/apollographql/router ## 🐛 Fixes +### Follow directives from Uplink ([Issue #1494](https://github.com/apollographql/router/issues/1494) [Issue #1539](https://github.com/apollographql/router/issues/1539)) + +The Uplink API returns actionable info in its responses: +- some error codes indicate an unrecoverable issue, for which the router should not retry the query (example: non-existing graph) +- it can tell the router when it should retry the query + +By [@Geal](https://github.com/Geal) in https://github.com/apollographql/router/pull/2001 + ### Fix the rhai SDL print function [Issue #2005](https://github.com/apollographql/router/issues/2005)) A recent change to the way we provide the SDL to plugins broke the rhai SDL print. This fixes it. By [@fernando-apollo](https://github.com/fernando-apollo) in https://github.com/apollographql/router/pull/2007 + ## 🛠 Maintenance ### Split the configuration file management in multiple modules [Issue #1790](https://github.com/apollographql/router/issues/1790)) diff --git a/apollo-router/src/router.rs b/apollo-router/src/router.rs index 2bcd4b6d3e..db6ff01c0c 100644 --- a/apollo-router/src/router.rs +++ b/apollo-router/src/router.rs @@ -229,10 +229,7 @@ impl SchemaSource { future::ready(match res { Ok(schema_result) => Some(UpdateSchema(schema_result.schema)), Err(e) => { - tracing::error!( - "error downloading the schema from Uplink: {:?}", - e - ); + tracing::error!("{}", e); None } }) diff --git a/apollo-router/src/uplink/mod.rs b/apollo-router/src/uplink/mod.rs index 5d47c2959d..1c9f55b9e8 100644 --- a/apollo-router/src/uplink/mod.rs +++ b/apollo-router/src/uplink/mod.rs @@ -17,6 +17,8 @@ use tokio_stream::wrappers::ReceiverStream; use tracing::instrument::WithSubscriber; use url::Url; +use self::supergraph_sdl::SupergraphSdlRouterConfigOnFetchError; + const GCP_URL: &str = "https://uplink.api.apollographql.com/graphql"; const AWS_URL: &str = "https://aws.uplink.api.apollographql.com/graphql"; @@ -35,13 +37,6 @@ pub(crate) struct SupergraphSdl; pub(crate) enum Error { Reqwest(reqwest::Error), EmptyResponse, - UpLink { - // The lint ignores uses in the `Debug` impl, but this is where these fields are useful. - #[allow(dead_code)] - code: FetchErrorCode, - #[allow(dead_code)] - message: String, - }, } impl From for Error { @@ -60,14 +55,13 @@ pub(crate) fn stream_supergraph( api_key: String, graph_ref: String, urls: Option>, - interval: Duration, -) -> impl Stream> { + mut interval: Duration, +) -> impl Stream> { let (sender, receiver) = channel(2); let _ = tokio::task::spawn(async move { let mut composition_id = None; - - let mut interval = tokio::time::interval(interval); let mut current_url_idx = 0; + loop { match fetch_supergraph( api_key.to_string(), @@ -91,24 +85,38 @@ pub(crate) fn stream_supergraph( { break; } + // this will truncate the number of seconds to under u64::MAX, which should be + // a large enough delay anyway + interval = Duration::from_secs(schema_config.min_delay_seconds.round() as u64); } supergraph_sdl::SupergraphSdlRouterConfig::Unchanged => { tracing::trace!("schema did not change"); } - supergraph_sdl::SupergraphSdlRouterConfig::FetchError(e) => { - if let Some(urls) = &urls { - current_url_idx = (current_url_idx + 1) % urls.len(); + supergraph_sdl::SupergraphSdlRouterConfig::FetchError( + SupergraphSdlRouterConfigOnFetchError { code, message }, + ) => { + if code == FetchErrorCode::RETRY_LATER { + if let Some(urls) = &urls { + current_url_idx = (current_url_idx + 1) % urls.len(); + } + + if sender + .send(Err(format!("error downloading the schema from Uplink: {}", message))) + .await + .is_err() + { + break; } - if sender - .send(Err(Error::UpLink { - code: e.code, - message: e.message, - })) + } else { + if sender + .send(Err(format!("{:?} error downloading the schema from Uplink, the router will not try again: {}", code, message))) .await .is_err() { break; } + break; + } } }, Err(err) => { @@ -116,13 +124,11 @@ pub(crate) fn stream_supergraph( if let Some(urls) = &urls { current_url_idx = (current_url_idx + 1) % urls.len(); } - if sender.send(Err(err)).await.is_err() { - break; - } + tracing::error!("error downloading the schema from Uplink: {:?}", err); } } - interval.tick().await; + tokio::time::sleep(interval).await; } }) .with_current_subscriber(); diff --git a/apollo-router/src/uplink/query.graphql b/apollo-router/src/uplink/query.graphql index 03847c1cb2..5e7ed86bb8 100644 --- a/apollo-router/src/uplink/query.graphql +++ b/apollo-router/src/uplink/query.graphql @@ -4,6 +4,7 @@ query SupergraphSdl($apiKey: String!, $graph_ref: String!, $ifAfterId: ID) { ... on RouterConfigResult { id supergraphSdl: supergraphSDL + minDelaySeconds } ... on FetchError { code