Skip to content

Commit

Permalink
Make json schema small (#5061)
Browse files Browse the repository at this point in the history
Fix #5003

This reworks the json schema generation for the config so that it is reduced in size from approx 100k lines to jsut over 7k.

The fix involves three things:

* Enable references on json schema generation. This got disabled in the past because there were issues with the generated references, but by adding a schema visitor we can work around this.
* Adjust the schema generation for Extendable and Conditional. These previously relied on the scheme not using references.
* Modify orbiter metrics to redact only based on the properties in the schema rather than on validation metadata as this is not possible when using schema refs: Incomplete basic output Stranger6667/jsonschema#403
  • Loading branch information
BrynCooke authored and Geal committed May 6, 2024
1 parent 2da96d7 commit 838c28f
Show file tree
Hide file tree
Showing 11 changed files with 6,526 additions and 30,913 deletions.
7 changes: 7 additions & 0 deletions .changesets/fix_bryn_json_schema.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### Make json schema small ([PR #5061](https://github.com/apollographql/router/pull/5061))

The json schema for the router.yaml is reduced in size from approx 100k lines to just over 7k.

This reduces the startup time of the Router and a smaller schema is more friendly for code editors.

By [@BrynCooke](https://github.com/BrynCooke) in https://github.com/apollographql/router/pull/5061
46 changes: 42 additions & 4 deletions apollo-router/src/configuration/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@
use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt::Write;
use std::mem;
use std::sync::OnceLock;

use itertools::Itertools;
use jsonschema::error::ValidationErrorKind;
use jsonschema::Draft;
use jsonschema::JSONSchema;
use schemars::gen::SchemaSettings;
use schemars::schema::Metadata;
use schemars::schema::RootSchema;
use schemars::schema::SchemaObject;
use schemars::visit::visit_root_schema;
use schemars::visit::visit_schema_object;
use schemars::visit::Visitor;
use yaml_rust::scanner::Marker;

use super::expansion::coerce;
Expand All @@ -25,12 +31,39 @@ pub(crate) use crate::configuration::upgrade::upgrade_configuration;

const NUMBER_OF_PREVIOUS_LINES_TO_DISPLAY: usize = 5;

/// This needs to exist because Schemars incorrectly generates references with spaces in them.
/// We just rename them.
#[derive(Debug, Clone)]
struct RefRenameVisitor;

impl Visitor for RefRenameVisitor {
fn visit_root_schema(&mut self, root: &mut RootSchema) {
visit_root_schema(self, root);
root.definitions = mem::take(&mut root.definitions)
.into_iter()
.map(|(k, v)| (k.replace(' ', "_"), v))
.collect();
}
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
if let Some(reference) = &mut schema.reference {
schema.metadata = Some(Box::new(Metadata {
description: Some(reference.clone()),
..Default::default()
}));
*reference = reference.replace(' ', "_");
}

visit_schema_object(self, schema);
}
}

/// Generate a JSON schema for the configuration.
pub(crate) fn generate_config_schema() -> RootSchema {
let settings = SchemaSettings::draft07().with(|s| {
s.option_nullable = true;
s.option_add_null_type = false;
s.inline_subschemas = true;
s.inline_subschemas = false;
s.visitors = vec![Box::new(RefRenameVisitor)]
});

// Manually patch up the schema
Expand Down Expand Up @@ -89,10 +122,15 @@ pub(crate) fn validate_yaml_configuration(
let config_schema = serde_json::to_value(generate_config_schema())
.expect("failed to parse configuration schema");

JSONSchema::options()
let result = JSONSchema::options()
.with_draft(Draft::Draft7)
.compile(&config_schema)
.expect("failed to compile configuration schema")
.compile(&config_schema);
match result {
Ok(schema) => schema,
Err(e) => {
panic!("failed to compile configuration schema: {}", e)
}
}
});

if migration == Mode::Upgrade {
Expand Down
Loading

0 comments on commit 838c28f

Please sign in to comment.