Skip to content

Commit

Permalink
Add unsupported access to parsed schema document.
Browse files Browse the repository at this point in the history
This eliminates the need for plugins to reparse the string versio in plugin init.

This is unsupported because apollo_rs is not 1.0 and may change before 1.0.

We WILL be changing the way we provide access to the parsed schema.

Use at your own reisk.
  • Loading branch information
bryn committed Feb 22, 2024
1 parent 3381128 commit 8992739
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 37 deletions.
72 changes: 68 additions & 4 deletions apollo-router/src/plugin/mod.rs
Expand Up @@ -19,6 +19,7 @@ pub mod test;

use std::any::TypeId;
use std::fmt;
use std::path::PathBuf;
use std::sync::Arc;
use std::task::Context;
use std::task::Poll;
Expand Down Expand Up @@ -50,6 +51,7 @@ use crate::ListenAddr;
type InstanceFactory = fn(
&serde_json::Value,
Arc<String>,
Arc<apollo_compiler::validation::Valid<apollo_compiler::Schema>>,
Notify<String, graphql::Response>,
) -> BoxFuture<Result<Box<dyn DynPlugin>, BoxError>>;

Expand All @@ -66,6 +68,9 @@ pub struct PluginInit<T> {
pub config: T,
/// Router Supergraph Schema (schema definition language)
pub supergraph_sdl: Arc<String>,
/// The supergraph schema (parsed)
pub(crate) supergraph_schema:
Arc<apollo_compiler::validation::Valid<apollo_compiler::schema::Schema>>,

pub(crate) notify: Notify<String, graphql::Response>,
}
Expand All @@ -79,6 +84,13 @@ where
pub fn new(config: T, supergraph_sdl: Arc<String>) -> Self {
Self::builder()
.config(config)
.supergraph_schema(Arc::new(
apollo_compiler::schema::Schema::parse_and_validate(
supergraph_sdl.to_string(),
PathBuf::from("synthetic"),
)
.expect("failed to parse supergraph schema"),
))
.supergraph_sdl(supergraph_sdl)
.notify(Notify::builder().build())
.build()
Expand All @@ -95,19 +107,48 @@ where
) -> Result<Self, BoxError> {
Self::try_builder()
.config(config)
.supergraph_schema(Arc::new(
apollo_compiler::Schema::parse_and_validate(
supergraph_sdl.to_string(),
PathBuf::from("synthetic"),
)
.map_err(|e| {
// This method is deprecated so we're not going to do anything fancy with the error
BoxError::from(e.errors.to_string())
})?,
))
.supergraph_sdl(supergraph_sdl)
.notify(Notify::builder().build())
.build()
}

#[cfg(test)]
pub(crate) fn fake_new(config: T, supergraph_sdl: Arc<String>) -> Self {
let supergraph_schema = Arc::new(if !supergraph_sdl.is_empty() {
apollo_compiler::Schema::parse_and_validate(
supergraph_sdl.to_string(),
PathBuf::from("synthetic"),
)
.expect("failed to parse supergraph schema")
} else {
apollo_compiler::validation::Valid::assume_valid(apollo_compiler::Schema::new())
});
PluginInit {
config,
supergraph_schema,
supergraph_sdl,
notify: Notify::for_tests(),
}
}

/// Returns the parsed Schema. This is unstable and may be changed or removed in future router releases.
/// In addition, Schema is not stable, and may be changed or removed in future apollo-rs releases.
#[doc(hidden)]
pub fn unsupported_supergraph_schema(
&self,
) -> Arc<apollo_compiler::validation::Valid<apollo_compiler::Schema>> {
self.supergraph_schema.clone()
}
}

#[buildstructor::buildstructor]
Expand All @@ -123,11 +164,13 @@ where
pub(crate) fn new_builder(
config: T,
supergraph_sdl: Arc<String>,
supergraph_schema: Arc<apollo_compiler::validation::Valid<apollo_compiler::schema::Schema>>,
notify: Notify<String, graphql::Response>,
) -> Self {
PluginInit {
config,
supergraph_sdl,
supergraph_schema,
notify,
}
}
Expand All @@ -140,12 +183,14 @@ where
pub(crate) fn try_new_builder(
config: serde_json::Value,
supergraph_sdl: Arc<String>,
supergraph_schema: Arc<apollo_compiler::validation::Valid<apollo_compiler::schema::Schema>>,
notify: Notify<String, graphql::Response>,
) -> Result<Self, BoxError> {
let config: T = serde_json::from_value(config)?;
Ok(PluginInit {
config,
supergraph_sdl,
supergraph_schema,
notify,
})
}
Expand All @@ -155,11 +200,19 @@ where
fn fake_new_builder(
config: T,
supergraph_sdl: Option<Arc<String>>,
supergraph_schema: Option<
Arc<apollo_compiler::validation::Valid<apollo_compiler::schema::Schema>>,
>,
notify: Option<Notify<String, graphql::Response>>,
) -> Self {
PluginInit {
config,
supergraph_sdl: supergraph_sdl.unwrap_or_default(),
supergraph_schema: supergraph_schema.unwrap_or_else(|| {
Arc::new(apollo_compiler::validation::Valid::assume_valid(
apollo_compiler::Schema::new(),
))
}),
notify: notify.unwrap_or_else(Notify::for_tests),
}
}
Expand Down Expand Up @@ -198,11 +251,12 @@ impl PluginFactory {
tracing::debug!(%plugin_factory_name, "creating plugin factory");
PluginFactory {
name: plugin_factory_name,
instance_factory: |configuration, schema, notify| {
instance_factory: |configuration, schema, supergraph_schema, notify| {
Box::pin(async move {
let init = PluginInit::try_builder()
.config(configuration.clone())
.supergraph_sdl(schema)
.supergraph_schema(supergraph_schema)
.notify(notify)
.build()?;
let plugin = P::new(init).await?;
Expand All @@ -225,11 +279,12 @@ impl PluginFactory {
tracing::debug!(%plugin_factory_name, "creating plugin factory");
PluginFactory {
name: plugin_factory_name,
instance_factory: |configuration, schema, notify| {
instance_factory: |configuration, schema, supergraph_schema, notify| {
Box::pin(async move {
let init = PluginInit::try_builder()
.config(configuration.clone())
.supergraph_sdl(schema)
.supergraph_schema(supergraph_schema)
.notify(notify)
.build()?;
let plugin = P::new(init).await?;
Expand All @@ -245,17 +300,26 @@ impl PluginFactory {
&self,
configuration: &serde_json::Value,
supergraph_sdl: Arc<String>,
supergraph_schema: Arc<apollo_compiler::validation::Valid<apollo_compiler::Schema>>,
notify: Notify<String, graphql::Response>,
) -> Result<Box<dyn DynPlugin>, BoxError> {
(self.instance_factory)(configuration, supergraph_sdl, notify).await
(self.instance_factory)(configuration, supergraph_sdl, supergraph_schema, notify).await
}

#[cfg(test)]
pub(crate) async fn create_instance_without_schema(
&self,
configuration: &serde_json::Value,
) -> Result<Box<dyn DynPlugin>, BoxError> {
(self.instance_factory)(configuration, Default::default(), Default::default()).await
(self.instance_factory)(
configuration,
Default::default(),
Arc::new(apollo_compiler::validation::Valid::assume_valid(
apollo_compiler::Schema::new(),
)),
Default::default(),
)
.await
}

pub(crate) fn create_schema(&self, gen: &mut SchemaGenerator) -> schemars::schema::Schema {
Expand Down
4 changes: 1 addition & 3 deletions apollo-router/src/plugins/override_url.rs
Expand Up @@ -98,16 +98,14 @@ mod tests {
let dyn_plugin: Box<dyn DynPlugin> = crate::plugin::plugins()
.find(|factory| factory.name == "apollo.override_subgraph_url")
.expect("Plugin not found")
.create_instance(
.create_instance_without_schema(
&Value::from_str(
r#"{
"test_one": "http://localhost:8001",
"test_two": "http://localhost:8002"
}"#,
)
.unwrap(),
Default::default(),
Default::default(),
)
.await
.unwrap();
Expand Down
14 changes: 11 additions & 3 deletions apollo-router/src/plugins/subscription.rs
Expand Up @@ -660,6 +660,7 @@ fn ensure_id_consistency(
#[cfg(test)]
mod tests {
use std::str::FromStr;
use std::sync::Arc;

use futures::StreamExt;
use serde_json::Value;
Expand Down Expand Up @@ -697,6 +698,9 @@ mod tests {
)
.unwrap(),
Default::default(),
Arc::new(apollo_compiler::validation::Valid::assume_valid(
apollo_compiler::Schema::new(),
)),
notify.clone(),
)
.await
Expand Down Expand Up @@ -835,6 +839,9 @@ mod tests {
)
.unwrap(),
Default::default(),
Arc::new(apollo_compiler::validation::Valid::assume_valid(
apollo_compiler::Schema::new(),
)),
notify.clone(),
)
.await
Expand Down Expand Up @@ -920,6 +927,9 @@ mod tests {
)
.unwrap(),
Default::default(),
Arc::new(apollo_compiler::validation::Valid::assume_valid(
apollo_compiler::Schema::new(),
)),
notify.clone(),
)
.await
Expand Down Expand Up @@ -1055,15 +1065,13 @@ mod tests {
let dyn_plugin: Box<dyn DynPlugin> = crate::plugin::plugins()
.find(|factory| factory.name == APOLLO_SUBSCRIPTION_PLUGIN)
.expect("Plugin not found")
.create_instance(
.create_instance_without_schema(
&Value::from_str(
r#"{
"enabled": false
}"#,
)
.unwrap(),
Default::default(),
Default::default(),
)
.await
.unwrap();
Expand Down
39 changes: 18 additions & 21 deletions apollo-router/src/plugins/telemetry/logging/mod.rs
Expand Up @@ -2,7 +2,6 @@
#[cfg(test)]
mod test {
use std::any::TypeId;
use std::sync::Arc;

use tower::BoxError;
use tower::ServiceBuilder;
Expand All @@ -11,8 +10,8 @@ mod test {

use crate::assert_snapshot_subscriber;
use crate::graphql;
use crate::plugin::DynPlugin;
use crate::plugin::Plugin;
use crate::plugin::PluginInit;
use crate::plugins::telemetry::Telemetry;
use crate::services::router;
use crate::services::subgraph;
Expand Down Expand Up @@ -151,39 +150,37 @@ mod test {
// For now let's try and increase the coverage of the telemetry plugin using this and see how it goes.

struct PluginTestHarness<T: Plugin> {
plugin: T,
plugin: Box<dyn DynPlugin>,
phantom: std::marker::PhantomData<T>,
}
#[buildstructor::buildstructor]
impl<T: Plugin> PluginTestHarness<T> {
#[builder]
async fn new(yaml: Option<&'static str>, supergraph: Option<&'static str>) -> Self {
async fn new(yaml: Option<&'static str>) -> Self {
let factory = crate::plugin::plugins()
.find(|factory| factory.type_id == TypeId::of::<T>())
.expect("plugin not registered");
let name = &factory.name.replace("apollo.", "");
let config = yaml
.map(|yaml| serde_yaml::from_str::<serde_yaml::Value>(yaml).unwrap())
.map(|yaml| serde_yaml::from_str::<serde_json::Value>(yaml).unwrap())
.map(|mut config| {
config
.as_mapping_mut()
.as_object_mut()
.expect("invalid yaml")
.remove(&serde_yaml::Value::String(name.to_string()))
.remove(name)
.expect("no config for plugin")
})
.unwrap_or_else(|| serde_yaml::Value::Mapping(Default::default()));

let supergraph_sdl = supergraph
.map(|s| Arc::new(s.to_string()))
.unwrap_or_default();
let plugin = T::new(PluginInit {
config: serde_yaml::from_value(config).expect("config was invalid"),
supergraph_sdl,
notify: Default::default(),
})
.await
.expect("failed to initialize plugin");

Self { plugin }
.unwrap_or_else(|| serde_json::Value::Object(Default::default()));

let plugin = factory
.create_instance_without_schema(&config)
.await
.expect("failed to create plugin");

Self {
plugin,
phantom: Default::default(),
}
}

#[allow(dead_code)]
Expand Down
6 changes: 2 additions & 4 deletions apollo-router/src/plugins/telemetry/mod.rs
Expand Up @@ -1854,7 +1854,7 @@ mod tests {
let mut plugin = crate::plugin::plugins()
.find(|factory| factory.name == "apollo.telemetry")
.expect("Plugin not found")
.create_instance(telemetry_config, Default::default(), Default::default())
.create_instance_without_schema(telemetry_config)
.await
.unwrap();

Expand Down Expand Up @@ -1929,10 +1929,8 @@ mod tests {
crate::plugin::plugins()
.find(|factory| factory.name == "apollo.telemetry")
.expect("Plugin not found")
.create_instance(
.create_instance_without_schema(
&serde_json::json!({"apollo": {"schema_id":"abc"}, "exporters": {"tracing": {}}}),
Default::default(),
Default::default(),
)
.await
.unwrap();
Expand Down

0 comments on commit 8992739

Please sign in to comment.