Skip to content

Commit

Permalink
refactor: use links only from the root config (#3190)
Browse files Browse the repository at this point in the history
  • Loading branch information
meskill authored Dec 10, 2024
1 parent 198b8ad commit 0f3721b
Show file tree
Hide file tree
Showing 37 changed files with 128 additions and 660 deletions.
2 changes: 1 addition & 1 deletion src/core/config/config_module/fixtures/router.graphql
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
schema {
schema @server(port: 8000) @upstream(httpCache: 42, batch: {delay: 100}) {
# @link(src: "http://localhost:4000", type: SubGraph, meta: {name: "Users"})
# @link(src: "http://localhost:5000", type: SubGraph, meta: {name: "Posts"})
query: Query
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
schema @server(port: 8000) @upstream(httpCache: 42, batch: {delay: 100}) {
schema {
query: Query
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
schema @server(port: 8000) @upstream(httpCache: 42, batch: {delay: 100}) {
schema {
query: Query
}

Expand Down
32 changes: 28 additions & 4 deletions src/core/config/config_module/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use indexmap::IndexMap;
use tailcall_valid::{Valid, Validator};

use super::{Cache, ConfigModule};
use crate::core;
use crate::core::config::{Arg, Config, Enum, Field, Type};
use crate::core::config::{Arg, Config, Enum, Field, RootSchema, Type};
use crate::core::merge_right::MergeRight;
use crate::core::variance::{Contravariant, Covariant, Invariant};
use crate::core::{self};

impl core::Type {
fn merge(self, other: Self, non_null_merge: fn(bool, bool) -> bool) -> Valid<Self, String> {
Expand Down Expand Up @@ -183,6 +183,24 @@ impl Covariant for Enum {
}
}

impl Invariant for RootSchema {
fn unify(self, other: Self) -> Valid<Self, String> {
fn unify_option<T>(left: Option<T>, right: Option<T>) -> Option<T> {
match (left, right) {
(None, None) => None,
(None, Some(that)) => Some(that),
(Some(this), _) => Some(this),
}
}

Valid::succeed(Self {
query: unify_option(self.query, other.query),
mutation: unify_option(self.mutation, other.mutation),
subscription: unify_option(self.subscription, other.subscription),
})
}
}

impl Invariant for Cache {
fn unify(self, other: Self) -> Valid<Self, String> {
let mut types = self.config.types;
Expand Down Expand Up @@ -270,12 +288,18 @@ impl Invariant for Cache {
.map(|en| (name, en))
.trace(&trace_name)
}))
.map( |(merged_types, merged_enums)| {
.fuse(self.config.schema.unify(other.config.schema))
.map( |(merged_types, merged_enums, schema)| {
types.extend(merged_types);
enums.extend(merged_enums);

let config = Config {
types, enums, unions: self.config.unions.merge_right(other.config.unions), server: self.config.server.merge_right(other.config.server), upstream: self.config.upstream.merge_right(other.config.upstream), schema: self.config.schema.merge_right(other.config.schema), links: self.config.links.merge_right(other.config.links), telemetry: self.config.telemetry.merge_right(other.config.telemetry) };
types,
enums,
unions: self.config.unions.merge_right(other.config.unions),
schema,
..self.config
};

Cache {
config,
Expand Down
57 changes: 32 additions & 25 deletions src/core/config/reader.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::path::Path;

use futures_util::future::join_all;
use rustls_pemfile;
use rustls_pki_types::{
CertificateDer, PrivateKeyDer, PrivatePkcs1KeyDer, PrivatePkcs8KeyDer, PrivateSec1KeyDer,
};
use tailcall_valid::{Valid, Validator};
use tailcall_valid::{Valid, ValidationError, Validator};
use url::Url;

use super::{ConfigModule, Content, Link, LinkType, PrivateKey};
Expand Down Expand Up @@ -34,11 +35,10 @@ impl ConfigReader {
}

/// Reads the links in a Config and fill the content
#[async_recursion::async_recursion]
async fn ext_links(
&self,
config_module: ConfigModule,
parent_dir: Option<&'async_recursion Path>,
parent_dir: Option<&Path>,
) -> anyhow::Result<ConfigModule> {
let reader_ctx = ConfigReaderContext::new(&self.runtime);

Expand Down Expand Up @@ -77,14 +77,6 @@ impl ConfigReader {
config_module = config_module.and_then(|config_module| {
config_module.unify(ConfigModule::from(config.clone()))
});

if !config.links.is_empty() {
let cfg_module = self
.ext_links(ConfigModule::from(config), Path::new(&link.src).parent())
.await?;
config_module =
config_module.and_then(|config_module| config_module.unify(cfg_module));
}
}
LinkType::Protobuf => {
let meta = self.proto_reader.read(path, None).await?;
Expand Down Expand Up @@ -200,24 +192,32 @@ impl ConfigReader {
.map(|file| file.render(&reader_ctx))
.collect::<Vec<_>>();

let mut config_module = Valid::succeed(ConfigModule::default());

for file in files.iter() {
let mut config_modules = join_all(files.iter().map(|file| async {
let source = Source::detect(&file.path)?;
let schema = &file.content;

// Create initial config module
let new_config_module = self
.resolve(
Config::from_source(source, schema)?,
Path::new(&file.path).parent(),
)
.await?;

// Merge it with the original config set
config_module =
config_module.and_then(|config_module| config_module.unify(new_config_module));
}
self.resolve(
Config::from_source(source, schema)?,
Path::new(&file.path).parent(),
)
.await
}))
.await
.into_iter();

let config_module = Valid::from(
config_modules
.next()
.ok_or(anyhow::anyhow!("At least one config should be defined"))?
.map_err(to_validation_error),
);

let config_module = config_modules.fold(config_module, |acc, other| {
acc.and_then(|cfg| {
Valid::from(other.map_err(to_validation_error)).and_then(|other| cfg.unify(other))
})
});

Ok(config_module.to_result()?)
}
Expand Down Expand Up @@ -256,6 +256,13 @@ impl ConfigReader {
}
}

fn to_validation_error(error: anyhow::Error) -> ValidationError<String> {
match error.downcast::<ValidationError<String>>() {
Ok(err) => err,
Err(err) => ValidationError::new(err.to_string()),
}
}

#[cfg(test)]
mod reader_tests {
use std::path::{Path, PathBuf};
Expand Down
17 changes: 0 additions & 17 deletions tests/core/snapshots/https.md_0.snap

This file was deleted.

16 changes: 0 additions & 16 deletions tests/core/snapshots/https.md_client.snap

This file was deleted.

16 changes: 0 additions & 16 deletions tests/core/snapshots/https.md_merged.snap

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
source: tests/core/spec.rs
expression: formatted
snapshot_kind: text
---
enum Foo {
BAR
BAZ
type Foo {
foo: String
}

type Post {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
---
source: tests/core/spec.rs
expression: formatter
snapshot_kind: text
---
schema
@server
@upstream
@link(src: "graphql-with-link.graphql", type: Config)
@link(src: "link-enum.graphql", type: Config)
@link(src: "link-enum.graphql", type: Config) {
@server(port: 8000)
@upstream(batch: {delay: 10, headers: []}, httpCache: 10)
@link(src: "link-1.graphql", type: Config)
@link(src: "link-2.graphql", type: Config) {
query: Query
}

enum Foo {
BAR
BAZ
type Foo {
foo: String
}

type Post {
Expand Down
18 changes: 0 additions & 18 deletions tests/core/snapshots/on-request-body-grpc.md_0.snap

This file was deleted.

18 changes: 0 additions & 18 deletions tests/core/snapshots/on-request-body-grpc.md_client.snap

This file was deleted.

28 changes: 0 additions & 28 deletions tests/core/snapshots/on-request-body-grpc.md_merged.snap

This file was deleted.

41 changes: 0 additions & 41 deletions tests/core/snapshots/recursive-types-json.md_0.snap

This file was deleted.

Loading

1 comment on commit 0f3721b

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running 30s test @ http://localhost:8000/graphql

4 threads and 100 connections

Thread Stats Avg Stdev Max +/- Stdev
Latency 4.06ms 1.98ms 30.69ms 80.84%
Req/Sec 6.34k 0.86k 6.93k 93.83%

756647 requests in 30.01s, 3.79GB read

Requests/sec: 25213.21

Transfer/sec: 129.41MB

Please sign in to comment.