Skip to content

Commit

Permalink
chore: dropped pub fields from config module (#2274)
Browse files Browse the repository at this point in the history
Co-authored-by: Tushar Mathur <[email protected]>
  • Loading branch information
bnchi and tusharmath authored Jul 3, 2024
1 parent 65474b7 commit ec7d604
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 52 deletions.
4 changes: 3 additions & 1 deletion src/core/blueprint/from_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use self::telemetry::to_opentelemetry;
use super::{Server, TypeLike};
use crate::core::blueprint::compress::compress;
use crate::core::blueprint::*;
use crate::core::config::transformer::Required;
use crate::core::config::{Arg, Batch, Config, ConfigModule, Field};
use crate::core::ir::model::{IO, IR};
use crate::core::json::JsonSchema;
Expand Down Expand Up @@ -124,7 +125,8 @@ impl TryFrom<&ConfigModule> for Blueprint {
fn try_from(config_module: &ConfigModule) -> Result<Self, Self::Error> {
config_blueprint()
.try_fold(
&config_module.clone().normalize_default().to_result()?,
// Apply required transformers to the configuration
&config_module.to_owned().transform(Required).to_result()?,
Blueprint::default(),
)
.and_then(|blueprint| {
Expand Down
104 changes: 62 additions & 42 deletions src/core/config/config_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,96 @@ use std::collections::{HashMap, HashSet};
use std::ops::Deref;
use std::sync::Arc;

use derive_getters::Getters;
use jsonwebtoken::jwk::JwkSet;
use prost_reflect::prost_types::{FileDescriptorProto, FileDescriptorSet};
use rustls_pki_types::{CertificateDer, PrivateKeyDer};

use super::transformer::{AmbiguousType, NestedUnions, UnionInputType};
use crate::core::config::Config;
use crate::core::macros::MergeRight;
use crate::core::merge_right::MergeRight;
use crate::core::proto_reader::ProtoMetadata;
use crate::core::rest::{EndpointSet, Unchecked};
use crate::core::transform::{Transform, TransformerOps};
use crate::core::valid::{Valid, Validator};
use crate::core::Transform;

/// A wrapper on top of Config that contains all the resolved extensions and
/// computed values.
#[derive(Clone, Debug, Default, Getters)]
#[derive(Clone, Debug, Default, MergeRight)]
pub struct ConfigModule {
config: Config,
extensions: Extensions,
cache: Cache,
}

/// A cache that store resolved input, output and interface types so that it's
/// not computed again and again.
#[derive(Clone, Debug, Default)]
struct Cache {
config: Config,
input_types: HashSet<String>,
output_types: HashSet<String>,
interface_types: HashSet<String>,
}

impl MergeRight for ConfigModule {
impl From<Config> for Cache {
fn from(value: Config) -> Self {
let input_types = value.input_types();
let output_types = value.output_types();
let interface_types = value.interface_types();

Cache {
config: value,
input_types: input_types.clone(),
output_types: output_types.clone(),
interface_types: interface_types.clone(),
}
}
}

impl MergeRight for Cache {
fn merge_right(self, other: Self) -> Self {
ConfigModule::new(
self.config.merge_right(other.config),
self.extensions.merge_right(other.extensions),
)
Cache::from(self.config.merge_right(other.config))
}
}

impl ConfigModule {
pub fn new(config: Config, extensions: Extensions) -> Self {
let input_types = config.input_types();
let output_types = config.output_types();
let interface_types = config.interface_types();

ConfigModule {
config,
extensions,
input_types,
output_types,
interface_types,
}
ConfigModule { cache: Cache::from(config), extensions }
}

/// Normalizes current config with default preset
pub fn normalize_default(self) -> Valid<Self, String> {
// TODO: migrate to preset. That will change many snapshots in repo
let transformer = NestedUnions
.pipe(UnionInputType)
.pipe(AmbiguousType::default());
let ConfigModule { config, extensions, .. } = self;
pub fn set_extensions(mut self, extensions: Extensions) -> Self {
self.extensions = extensions;
self
}

pub fn merge_extensions(mut self, extensions: Extensions) -> Self {
self.extensions = self.extensions.merge_right(extensions);
self
}

pub fn config(&self) -> &Config {
&self.cache.config
}

pub fn extensions(&self) -> &Extensions {
&self.extensions
}

pub fn input_types(&self) -> &HashSet<String> {
&self.cache.input_types
}

pub fn output_types(&self) -> &HashSet<String> {
&self.cache.output_types
}

pub fn interface_types(&self) -> &HashSet<String> {
&self.cache.interface_types
}

pub fn transform<T: Transform<Value = Config>>(self, transformer: T) -> Valid<Self, T::Error> {
transformer
.transform(config)
.map(|config| ConfigModule::new(config, extensions))
.transform(self.cache.config)
.map(|config| ConfigModule::new(config, self.extensions))
}
}

Expand Down Expand Up @@ -131,22 +161,12 @@ impl MergeRight for FileDescriptorSet {
impl Deref for ConfigModule {
type Target = Config;
fn deref(&self) -> &Self::Target {
&self.config
self.config()
}
}

impl From<Config> for ConfigModule {
fn from(config: Config) -> Self {
let input_types = config.input_types();
let output_types = config.output_types();
let interface_types = config.interface_types();

ConfigModule {
config,
input_types,
output_types,
interface_types,
..Default::default()
}
ConfigModule { cache: Cache::from(config), ..Default::default() }
}
}
10 changes: 5 additions & 5 deletions src/core/config/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl ConfigReader {
#[async_recursion::async_recursion]
async fn ext_links(
&self,
config_module: ConfigModule,
mut config_module: ConfigModule,
parent_dir: Option<&'async_recursion Path>,
) -> anyhow::Result<ConfigModule> {
let links: Vec<Link> = config_module
Expand All @@ -58,7 +58,7 @@ impl ConfigReader {
}

let mut extensions = config_module.extensions().clone();
let mut base_config = config_module.config().clone();
// let mut base_config = config_module.config().clone();

for link in links.iter() {
let path = Self::resolve_path(&link.src, parent_dir);
Expand All @@ -69,13 +69,13 @@ impl ConfigReader {
let content = source.content;

let config = Config::from_source(Source::detect(&source.path)?, &content)?;
base_config = base_config.merge_right(config.clone());
config_module = config_module.merge_right(config.clone().into());

if !config.links.is_empty() {
let cfg_module = self
.ext_links(ConfigModule::from(config), Path::new(&link.src).parent())
.await?;
base_config = base_config.merge_right(cfg_module.config().clone());
config_module = config_module.merge_right(cfg_module.clone());
}
}
LinkType::Protobuf => {
Expand Down Expand Up @@ -134,7 +134,7 @@ impl ConfigReader {

// Recreating the ConfigModule in order to recompute the values of
// `input_types`, `output_types` and `interface_types`
Ok(ConfigModule::new(base_config, extensions))
Ok(config_module.set_extensions(extensions))
}

/// Reads the certificate from a given file
Expand Down
2 changes: 2 additions & 0 deletions src/core/config/transformer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod improve_type_names;
mod merge_types;
mod nested_unions;
mod preset;
mod required;
mod tree_shake;
mod union_input_type;

Expand All @@ -13,5 +14,6 @@ pub use improve_type_names::ImproveTypeNames;
pub use merge_types::TypeMerger;
pub use nested_unions::NestedUnions;
pub use preset::Preset;
pub use required::Required;
pub use tree_shake::TreeShake;
pub use union_input_type::UnionInputType;
4 changes: 1 addition & 3 deletions src/core/config/transformer/preset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@ impl Transform for Preset {
config: Self::Value,
) -> crate::core::valid::Valid<Self::Value, Self::Error> {
transform::default()
.pipe(super::NestedUnions)
.pipe(super::UnionInputType)
.pipe(super::Required)
.pipe(super::TreeShake.when(self.tree_shake))
.pipe(super::TypeMerger::new(self.merge_type))
.pipe(super::ImproveTypeNames.when(self.use_better_names))
.pipe(super::AmbiguousType::default())
.pipe(super::ConsolidateURL::new(self.consolidate_url))
.transform(config)
}
Expand Down
23 changes: 23 additions & 0 deletions src/core/config/transformer/required.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use crate::core::config::Config;
use crate::core::transform::{self, Transform, TransformerOps};

/// Defines a set of required transformers that must be applied to every
/// configuration to make it work with GraphQL.
#[derive(Debug, PartialEq, Default)]
pub struct Required;

impl Transform for Required {
type Value = Config;
type Error = String;

fn transform(
&self,
config: Self::Value,
) -> crate::core::valid::Valid<Self::Value, Self::Error> {
transform::default()
.pipe(super::NestedUnions)
.pipe(super::UnionInputType)
.pipe(super::AmbiguousType::default())
.transform(config)
}
}
1 change: 1 addition & 0 deletions src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ use http::Response;
use ir::model::IoId;
pub use mustache::Mustache;
pub use tailcall_macros as macros;
pub use transform::Transform;

pub trait EnvIO: Send + Sync + 'static {
fn get(&self, key: &str) -> Option<Cow<'_, str>>;
Expand Down
4 changes: 3 additions & 1 deletion tests/core/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use tailcall::core::app_context::AppContext;
use tailcall::core::async_graphql_hyper::{GraphQLBatchRequest, GraphQLRequest};
use tailcall::core::blueprint::Blueprint;
use tailcall::core::config::reader::ConfigReader;
use tailcall::core::config::transformer::Required;
use tailcall::core::config::{Config, ConfigModule, Source};
use tailcall::core::http::handle_request;
use tailcall::core::merge_right::MergeRight;
Expand Down Expand Up @@ -250,7 +251,8 @@ async fn test_spec(spec: ExecutionSpec) {
let merged = server
.iter()
.fold(ConfigModule::default(), |acc, c| acc.merge_right(c.clone()))
.normalize_default()
// Apply required transformers to the configuration
.transform(Required)
.to_result()
.unwrap()
.to_sdl();
Expand Down

1 comment on commit ec7d604

@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 7.47ms 5.14ms 199.45ms 89.63%
Req/Sec 3.45k 193.08 3.78k 91.50%

412200 requests in 30.00s, 2.07GB read

Requests/sec: 13738.38

Transfer/sec: 70.51MB

Please sign in to comment.