We're getting closer and closer to our 1.0 release and with that we have a lot of polish that we're applying to our API to get it ready for it to be a durable surface area for our consumers to depend on. Due to various learnings we've had during the pre-1.0 phases of the Router, we are evolving our API to match what we now know.
We do not intend on doing this much moving around of things again soon, but anyone who has been following the repository the last couple weeks knows there has been a lot of activity and discussion about where things should live. This means that this release has an abnormally high number of breaking changes, though we believe you'll find most of them to be relatively straightforward to pivot away from.
Please review the full change log to get all the details, but for the most part the changes in this release consist of:
- a lot of renames of existing symbols
- the re-location of exported symbols to more appropriate modules
- the privatization of functions which we don't believe users needed directly (see below if any of these turn out to be a problem).
During each step of the migration, we recommend searching this changelog for a symbol to find advice on how to migrate it. We've tried to make the instructions and path forward as clear as possible.
- If you find yourself needing help migrating to the new patterns, please first take a close look at the examples provided in this change log and if you still need help, please open a discussion.
- If you find yourself unable to do something you had previously been able to do, please open an issue. Please make sure you include your use-case so we can understand better and document it for posterity!
We appreciate your patience working through these and we're excited for the steps ahead!
β BREAKING β
Remove QueryPlannerService
(PR #1552)
This service was redundant, since anything done as part of the QueryPlannerService
could be done either at the SupergraphService
or at the ExecutionService
level.
By @o0Ignition0o in https://github.com/apollographql/router/pull/1552
Rename map_future_with_context
to map_future_with_request_data
(PR #1547)
The function is not very well named since it's in fact used to extract any data from a request for use in a future. This rename makes it clear.
By @garypen in https://github.com/apollographql/router/pull/1547
Rename traffic shaping deduplication options (PR #1540)
In the traffic shaping module:
variables_deduplication
configuration option is renamed to deduplicate_variables
.
query_deduplication
configuration option is renamed to deduplicate_query
.
- traffic_shaping:
- variables_deduplication: true # Enable the variables deduplication optimization
- all:
- query_deduplication: true # Enable query deduplication for all subgraphs.
- subgraphs:
- products:
- query_deduplication: false # Disable query deduplication for products.
+ traffic_shaping:
+ deduplicate_variables: true # Enable the variables deduplication optimization
+ all:
+ deduplicate_query: true # Enable query deduplication for all subgraphs.
+ subgraphs:
+ products:
+ deduplicate_query: false # Disable query deduplication for products.
By @garypen in https://github.com/apollographql/router/pull/1540
Make query_plan_options
private and wrap QueryPlanContent
in an opaque type (PR #1486)
QueryPlanOptions::query_plan_options
is no longer public. If you still necessitate usage of this, please open an issue with your use case.
By @bnjjj in https://github.com/apollographql/router/pull/1486
Removed delay_interval
in telemetry configuration. (PR #1498)
It was doing nothing.
telemetry:
metrics:
common:
# Removed, will now cause an error on Router startup:
delay_interval:
secs: 9
nanos: 500000000
By @SimonSapin in https://github.com/apollographql/router/pull/1498
Remove telemetry configuration hot reloading (PR #1463)
Configuration hot reloading is not very useful for telemetry, and is the
source of regular bugs that are hard to fix.
This removes the support for configuration reloading entirely. Now, the
router will reject a configuration reload with an error log if the
telemetry configuration changed.
It is now possible to create a subscriber and pass it explicitely to the telemetry plugin
when creating it. It will then be modified to integrate the telemetry plugin's layer.
By @geal in https://github.com/apollographql/router/pull/1463
Reorder query planner execution (PR #1484)
Query planning is deterministic and only depends on the query, operation name and query planning
options. As such, we can cache the result of the entire process.
This changes the pipeline to apply query planner plugins between the cache and the bridge planner,
so those plugins will only be called once on the same query. If changes must be done per query,
they should happen in a supergraph service.
By @Geal in https://github.com/apollographql/router/pull/1464
Remove Buffer
from Mock*Service
(PR #1440
This removes the usage of tower_test::mock::Mock
in mocked services because it isolated the service in a task
so panics triggered by mockall were not transmitted up to the unit test that should catch it.
This rewrites the mocked services API to remove the build()
method, and make them clonable if needed,
using an expect_clone
call with mockall.
By @Geal in https://github.com/apollographql/router/pull/1440
At the crate root:
SchemaKind
β SchemaSource
SchemaKind::String(String)
β SchemaSource::Static { schema_sdl: String }
ConfigurationKind
β ConfigurationSource
ConfigurationKind::Instance
β ConfigurationSource::Static
ShutdownKind
β ShutdownSource
ApolloRouter
β RouterHttpServer
In the apollo_router::plugin::Plugin
trait:
router_service
β supergraph_service
In the apollo_router::services
module, to new public sub-modules:
SupergraphRequest
β supergraph::Request
SupergraphResponse
β supergraph::Response
ExecutionRequest
β execution::Request
ExecutionResponse
β execution::Response
SubgraphRequest
β subgraph::Request
SubgraphResponse
β subgraph::Response
For convenience, these new sub-modules each contain type aliases
base on their respective Request
and Response
types.
pub type BoxService = tower::util::BoxService<Request, Response, tower::BoxError>;
pub type BoxCloneService = tower::util::BoxCloneService<Request, Response, tower::BoxError>;
pub type ServiceResult = Result<Response, tower::BoxError>;
Migration example:
-use tower::util::BoxService;
-use tower::BoxError;
-use apollo_router::services::{RouterRequest, RouterResponse};
+use apollo_router::services::router;
-async fn example(service: BoxService<RouterRequest, RouterResponse, BoxError>) -> RouterResponse {
+async fn example(service: router::BoxService) -> router::Response {
- let request = RouterRequest::builder()/*β¦*/.build();
+ let request = router::Request::builder()/*β¦*/.build();
service.oneshot(request).await
}
By @SimonSapin in https://github.com/apollographql/router/pull/1487, https://github.com/apollographql/router/pull/1534, https://github.com/apollographql/router/pull/1555, https://github.com/apollographql/router/pull/1563
Some items were removed from the public API (PR #1487 PR #1535)
If you used some of them and donβt find a replacement,
please file an issue
with details about the use case.
apollo_router::Configuration::boxed
apollo_router::Configuration::is_compatible
apollo_router::errors::CacheResolverError
apollo_router::errors::JsonExtError
apollo_router::errors::ParsesError::print
apollo_router::errors::PlanError
apollo_router::errors::PlannerError
apollo_router::errors::PlannerErrors
apollo_router::errors::QueryPlannerError
apollo_router::errors::ServiceBuildError
apollo_router::json_ext
apollo_router::layers::ServiceBuilderExt::cache
apollo_router::mock_service!
apollo_router::plugins
apollo_router::plugin::plugins
apollo_router::plugin::PluginFactory
apollo_router::plugin::DynPlugin
apollo_router::plugin::Handler
apollo_router::plugin::test::IntoSchema
apollo_router::plugin::test::MockSubgraphFactory
apollo_router::plugin::test::PluginTestHarness
apollo_router::query_planner::QueryPlan::execute
apollo_router::services
apollo_router::Schema
By @SimonSapin
Router startup API changes (PR #1487)
The RouterHttpServer::serve
method and its return type RouterHandle
were removed,
their functionality merged into RouterHttpServer
(formerly ApolloRouter
).
The builder for RouterHttpServer
now ends with a start
method instead of build
.
This method immediatly starts the server in a new Tokio task.
RouterHttpServer::builder()
.configuration(configuration)
.schema(schema)
- .build()
- .serve()
+ .start()
.await
By @SimonSapin in https://github.com/apollographql/router/pull/1487
router_builder_fn
replaced by shutdown
in the Executable
builder (PR #1487)
The builder for apollo_router::Executable
had a router_builder_fn
method
allowing the specification of how a RouterHttpServer
(previously ApolloRouter
) was to be created
with a provided configuration and schema.
Since the only possible variation was specifying when the server should shut down
(with a ShutdownSource
parameter) the router_builder_fn
was replaced with a new shutdown
method.
use apollo_router::Executable;
-use apollo_router::RouterHttpServer;
use apollo_router::ShutdownSource;
Executable::builder()
- .router_builder_fn(|configuration, schema| RouterHttpServer::builder()
- .configuration(configuration)
- .schema(schema)
- .shutdown(ShutdownSource::None)
- .start())
+ .shutdown(ShutdownSource::None)
.start()
.await
By @SimonSapin in https://github.com/apollographql/router/pull/1487
Removed constructors when there is a public builder (PR #1487)
Many types in the Router API can be constructed with the builder pattern.
We use the buildstructor
crate
to auto-generate builder boilerplate based on the parameters of a constructor.
These constructors have been made private so that users must go through the builder instead,
which will allow us to add parameters in the future without a breaking API change.
If you were using one of these constructors, the migration generally looks like this:
-apollo_router::graphql::Error::new(m, vec![l], Some(p), Default::default())
+apollo_router::graphql::Error::build()
+ .message(m)
+ .location(l)
+ .path(p)
+ .build()
By @SimonSapin in https://github.com/apollographql/router/pull/1487
Removed deprecated type aliases (PR #1487)
A few versions ago, some types were moved from the crate root to a new graphql
module.
To help the transition, type aliases were left at the old location with a deprecation warning.
These aliases are now removed and remaining imports must be changed to the new locations:
-use apollo_router::Error;
-use apollo_router::Request;
-use apollo_router::Response;
+use apollo_router::graphql::Error;
+use apollo_router::graphql::Request;
+use apollo_router::graphql::Response;
Alternatively, import the module with use apollo_router::graphql
then use qualified paths such as graphql::Request
.
This can help disambiguate when multiple types share a name.
By @SimonSapin in https://github.com/apollographql/router/pull/1487
RouterRequest::fake_builder
defaults to Content-Type: application/json
(PR #1487)
apollo_router::services::RouterRequest
has a builder for creating a βfakeβ request during tests.
When no Content-Type
header is specified, this builder will now default to application/json
.
This will help tests where a request goes through mandatory plugins, including CSRF protection,
which makes the request be accepted by CSRF protection.
If a test requires a request specifically without a Content-Type
header,
this default can be removed from a RouterRequest
after building it:
let mut router_request = RouterRequest::fake_builder().build();
router_request.originating_request.headers_mut().remove("content-type");
By @SimonSapin in https://github.com/apollographql/router/pull/1487
Plugins return a service
to create custom endpoints (Issue #1481)
Rust plugins can implement the Plugin::custom_endpoint
trait method
to handle non-GraphQL HTTP requests.
Previously, the return type of this method was Option<apollo_router::plugin::Handler>
,
where a Handler
could be created with:
impl Handler {
pub fn new(service: tower::util::BoxService<
apollo_router::http_ext::Request<bytes::Bytes>,
apollo_router::http_ext::Response<bytes::Bytes>,
tower::BoxError
>) -> Self {/* β¦ */}
}
Handler
has been removed from the public API and plugins now return a BoxService
directly.
Additionally, the type for HTTP request and response bodies was changed
from bytes::Bytes
to hyper::Body
which is more flexible and is compatible with streams (which are necessary in future versions of the Router).
The changes needed if using custom endpoints are:
- Replace
Handler::new(service)
with service
- To read the full request body,
use
hyper::body::to_bytes
or hyper::body::aggregate
.
- A response
Body
can be created through conversion traits from various types.
For example: "string".into()
By @SimonSapin in https://github.com/apollographql/router/pull/1533
π Features
rhai logging functions now accept Dynamic parameters (PR #1521)
Prior to this change, rhai logging functions worked with string parameters. This change means that any valid rhai object
may now be passed as a logging parameter.
By @garypen
Reduce initial memory footprint by lazily populating introspection query cache (Issue #1517)
In an early alpha release of the Router, we only executed certain "known" introspection queries because of prior technical constraints that prohibited us from doing something more flexible. Because the set of introspection queries was "known", it made sense to cache them.
As of https://github.com/apollographql/router/pull/802, this special-casing is (thankfully) no longer necessary and we no longer need to know (and constrain!) the introspection queries that the Router supports.
We could have kept caching those "known" queries, however we were finding that the resulting cache size was quite large and making the Router's minimum memory footprint larger than need be since we were caching many introspection results which the Router instance would never encounter.
This change removes the cache entirely and allows introspection queries served by the Router to merely be lazily calculated and cached on-demand, thereby reducing the initial memory footprint. Disabling introspection entirely will prevent any use of this cache since no introspection will be possible.
By @o0Ignition0o in https://github.com/apollographql/router/pull/1517
Expose query plan in extensions of GraphQL response (experimental) (PR #1470)
When enabled in configuration, it is now possible to expose the query plan in the GraphQL response extensions
. This is only experimental at the moment, and we plan to integrate it into an upcoming version of Apollo Studio. Currently, no documentation is available.
By @bnjjj in https://github.com/apollographql/router/pull/1470
Add support of global rate limit and timeout. PR #1347
Additions to the traffic shaping plugin:
- Global rate limit - If you want to rate limit requests to subgraphs or to the router itself.
- Timeout: - Set a timeout to subgraphs and router requests.
traffic_shaping:
router: # Rules applied to requests from clients to the router
global_rate_limit: # Accept a maximum of 10 requests per 5 secs. Excess requests must be rejected.
capacity: 10
interval: 5s # Value in milliseconds must be greater than 0 and less than the max of a 64-bit integer (2^64-1).
timeout: 50s # If a request to the router takes more than 50secs then cancel the request (30 sec by default)
subgraphs: # Rules applied to requests from the router to individual subgraphs
products:
global_rate_limit: # Accept a maximum of 10 requests per 5 secs from the router. Excess requests must be rejected.
capacity: 10
interval: 5s # Value in milliseconds must be greater than 0 and less than the max of a 64-bit integer (2^64-1).
timeout: 50s # If a request to the subgraph 'products' takes more than 50secs then cancel the request (30 sec by default)
By @bnjjj in https://github.com/apollographql/router/pull/1347
Explicit shutdown
for RouterHttpServer
handle (PR #1487)
If you explicitly create a RouterHttpServer
handle,
dropping it while the server is running instructs the server shut down gracefuly.
However with the handle dropped, there is no way to wait for shutdown to end
or check that it went without error.
Instead, the new shutdown
async method can be called explicitly
to obtain a Result
:
use RouterHttpServer;
let server = RouterHttpServer::builder().schema("schema").start();
// β¦
-drop(server);
+server.shutdown().await.unwrap();
By @SimonSapin in https://github.com/apollographql/router/pull/1487
Added apollo_router::TestHarness
(PR #1487)
This is a builder for the part of an Apollo Router that handles GraphQL requests,
as a tower::Service
.
This allows tests, benchmarks, etc
to manipulate request and response objects in memory without going over the network.
See the API documentation for an example. (It can be built with cargo doc --open
.)
By @SimonSapin in https://github.com/apollographql/router/pull/1487
Introduce map_deferred_response
method for deferred responses (PR #1501)
The map_deferred_response
method is now available for the router service and execution
service in Rhai. When using the @defer
directive, we get the data in a serie of graphql
responses. The first one is available with the map_response
method, where the HTTP headers
and the response body can be modified. The following responses are available through
map_deferred_response
, which only has access to the response body.
By @geal in https://github.com/apollographql/router/pull/1501
π Fixes
Return HTTP status code 400 when variables
validation fails (Issue #1403)
Failure to validate out-of-band variables
against both the query
and the corresponding schema will now result in an HTTP status code of 400 being returned to the client. This instructs the client not to bother retrying without changing something about what it previously sent since subsequent retries would just fail validation again and again.
By @o0Ignition0o
Include usage reporting data in the context even when the query plan has been cached (#1559)
Include usage reporting data in the context even when the query plan has been cached when calling CachingQueryPlanner
.
By @bnjjj in https://github.com/apollographql/router/pull/1559
Accept SIGTERM
as shutdown signal (PR #1497)
This will make containers stop faster as they will not have to wait until a SIGKILL
to stop the router (which generally comes several seconds later).
By @Geal in https://github.com/apollographql/router/pull/1497
Set the response path
for deferred responses (PR #1529)
Some GraphQL clients rely on the response path
to find out which
fragment created a deferred response, and generate code that checks the
type of the value at that path.
Previously the router was generating a value that starts at the root
for every deferred response. Now it checks the path
returned by the query
plan execution and creates a response for each value that matches that
path.
In particular, for deferred fragments on an object inside an array, it
will create a separate response for each element of the array.
By @Geal in https://github.com/apollographql/router/pull/1529
Activate defer support in introspection (PR #1557)
Introspection queries will now see the @defer
directive if it was activated in the configuration file.
By @Geal in https://github.com/apollographql/router/pull/1557
Support the incremental response field (PR #1551)
Recent changes in the @defer
specification now mandate that the deferred responses are transmitted
as an array in the new incremental
field of the JSON response.
By @Geal in https://github.com/apollographql/router/pull/1551
π Maintenance
These are generally internal improvements to the Router repository on GitHub.
Display licenses.html
diff in CI if the check failed (#1524)
The CI check that ensures that the license.html
file is up to date now displays what has changed when the file is out of sync.
By @o0Ignition0o
π Features
Helm: Rhai script and Istio virtualservice support (#1478)
You can now pass a Rhai script file to the helm chart.
You can also provide an Istio VirtualService
configuration, as well as custom Egress
rules.
Head over to the helm chart default values to get started.
By @o0Ignition0o in https://github.com/apollographql/router/pull/1478
π Documentation
Clarify path parameter usage (PR #1473)
Add an inline example of path parameter usage to the section of the docs explaining that you cannot specify a wildcard in the middle of a path.
By @EverlastingBugstopper in https://github.com/apollographql/router/pull/1473
Source code(tar.gz)
Source code(zip)
md5sums.txt(206 bytes)
router-0.16.0-x86_64-linux.tar.gz(31.85 MB)
router-0.16.0-x86_64-macos.tar.gz(26.55 MB)
router-0.16.0-x86_64-windows.tar.gz(22.72 MB)
sha1sums.txt(230 bytes)
sha256sums.txt(302 bytes)