Skip to main content

apollo_router/services/
execution.rs

1#![allow(missing_docs)] // FIXME
2
3use std::sync::Arc;
4
5use serde_json_bytes::Value;
6use static_assertions::assert_impl_all;
7use tokio::sync::mpsc;
8use tower::BoxError;
9
10use crate::Context;
11use crate::graphql;
12
13pub(crate) mod service;
14
15pub type BoxService = tower::util::BoxService<Request, Response, BoxError>;
16pub type BoxCloneService = tower::util::BoxCloneService<Request, Response, BoxError>;
17pub type ServiceResult = Result<Response, BoxError>;
18
19// Reachable from Request
20use crate::plugins::subscription::SubscriptionTaskParams;
21pub use crate::query_planner::QueryPlan;
22
23assert_impl_all!(Request: Send);
24#[non_exhaustive]
25pub struct Request {
26    /// Original request to the Router.
27    pub supergraph_request: http::Request<graphql::Request>,
28
29    pub query_plan: Arc<QueryPlan>,
30
31    pub context: Context,
32    /// Initial data coming from subscription event if it's a subscription
33    pub(crate) source_stream_value: Option<Value>,
34    /// Channel to send all parameters needed for the subscription
35    pub(crate) subscription_tx: Option<mpsc::Sender<SubscriptionTaskParams>>,
36}
37
38#[buildstructor::buildstructor]
39impl Request {
40    /// This is the constructor (or builder) to use when constructing a real ExecutionRequest.
41    ///
42    /// The parameters are not optional, because in a live situation all of these properties must be
43    /// set and be correct to create a ExecutionRequest.
44    #[builder(visibility = "pub")]
45    fn new(
46        supergraph_request: http::Request<graphql::Request>,
47        query_plan: Arc<QueryPlan>,
48        context: Context,
49        source_stream_value: Option<Value>,
50        subscription_tx: Option<mpsc::Sender<SubscriptionTaskParams>>,
51    ) -> Request {
52        Self {
53            supergraph_request,
54            query_plan,
55            context,
56            source_stream_value,
57            subscription_tx,
58        }
59    }
60
61    #[builder(visibility = "pub(crate)")]
62    #[allow(clippy::needless_lifetimes)] // needed by buildstructor-generated code
63    async fn internal_new(
64        supergraph_request: http::Request<graphql::Request>,
65        query_plan: Arc<QueryPlan>,
66        context: Context,
67        source_stream_value: Option<Value>,
68        subscription_tx: Option<mpsc::Sender<SubscriptionTaskParams>>,
69    ) -> Request {
70        Self {
71            supergraph_request,
72            query_plan,
73            context,
74            source_stream_value,
75            subscription_tx,
76        }
77    }
78
79    /// This is the constructor (or builder) to use when constructing a "fake" ExecutionRequest.
80    ///
81    /// This does not enforce the provision of the data that is required for a fully functional
82    /// ExecutionRequest. It's usually enough for testing, when a fully constructed ExecutionRequest is
83    /// difficult to construct and not required for the purposes of the test.
84    ///
85    /// # Example
86    /// ```
87    /// use apollo_router::services::execution;
88    /// use apollo_router::Context;
89    ///
90    /// // This builder must remain usable from external crates for plugin testing.
91    /// let request = execution::Request::fake_builder()
92    ///     .context(Context::default())
93    ///     .build();
94    /// ```
95    // WARN: make sure to keep the example in the doc test; it gets compiled as an external crate,
96    // which is very useful in determining whether the public API has changed. In particular, we
97    // had an issue with SubscriptionTaskParams going from pub to pub(crate), preventing folks from
98    // compiling their unit tests for plugins because of the visibility change for the fake_builder
99    #[builder(visibility = "pub")]
100    fn fake_new(
101        supergraph_request: Option<http::Request<graphql::Request>>,
102        query_plan: Option<QueryPlan>,
103        context: Option<Context>,
104        source_stream_value: Option<Value>,
105        subscription_tx: Option<mpsc::Sender<SubscriptionTaskParams>>,
106    ) -> Request {
107        Request::new(
108            supergraph_request.unwrap_or_default(),
109            Arc::new(query_plan.unwrap_or_else(|| QueryPlan::fake_builder().build())),
110            context.unwrap_or_default(),
111            source_stream_value,
112            subscription_tx,
113        )
114    }
115}
116
117/// The response type for execution services is the same as for supergraph services.
118pub type Response = super::supergraph::Response;