Skip to content

Commit f495ee7

Browse files
authored
Merge pull request #111 from mathstuf/cache-input-files
Cache input files
2 parents ee0bf0d + b0742a7 commit f495ee7

File tree

11 files changed

+99
-93
lines changed

11 files changed

+99
-93
lines changed

graphql_query_derive/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ proc-macro = true
1111

1212
[dependencies]
1313
failure = "0.1"
14+
lazy_static = "1.0"
1415
quote = "^0.6"
1516
syn = "0.14"
1617
proc-macro2 = { version = "0.4", features = [] }

graphql_query_derive/src/constants.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
use deprecation::DeprecationStatus;
22
use field_type::FieldType;
33
use objects::GqlObjectField;
4-
use proc_macro2::{Ident, Span};
54

65
pub(crate) const TYPENAME_FIELD: &str = "__typename";
76

8-
pub(crate) fn string_type() -> Ident {
9-
Ident::new("String", Span::call_site())
7+
pub(crate) fn string_type() -> String {
8+
"String".to_string()
109
}
1110

1211
#[cfg(test)]
13-
pub(crate) fn float_type() -> Ident {
14-
Ident::new("Float", Span::call_site())
12+
pub(crate) fn float_type() -> String {
13+
"Float".to_string()
1514
}
1615

1716
pub(crate) fn typename_field() -> GqlObjectField {

graphql_query_derive/src/enums.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ use proc_macro2::{Ident, Span, TokenStream};
22

33
pub const ENUMS_PREFIX: &str = "";
44

5-
#[derive(Debug, PartialEq)]
5+
#[derive(Debug, Clone, PartialEq)]
66
pub struct EnumVariant {
77
pub description: Option<String>,
88
pub name: String,
99
}
1010

11-
#[derive(Debug, PartialEq)]
11+
#[derive(Debug, Clone, PartialEq)]
1212
pub struct GqlEnum {
1313
pub description: Option<String>,
1414
pub name: String,

graphql_query_derive/src/field_type.rs

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use schema::DEFAULT_SCALARS;
77

88
#[derive(Clone, Debug, PartialEq, Hash)]
99
pub enum FieldType {
10-
Named(Ident),
10+
Named(String),
1111
Optional(Box<FieldType>),
1212
Vector(Box<FieldType>),
1313
}
@@ -21,27 +21,23 @@ impl FieldType {
2121
prefix.to_string()
2222
};
2323
match &self {
24-
FieldType::Named(name) => {
25-
let name_string = name.to_string();
26-
27-
let name = if context.schema.scalars.contains_key(&name_string) || DEFAULT_SCALARS
24+
FieldType::Named(ref name) => {
25+
let full_name = if context.schema.scalars.contains_key(name) || DEFAULT_SCALARS
2826
.iter()
29-
.any(|elem| elem == &name_string.as_str())
27+
.any(|elem| elem == name)
3028
{
3129
name.clone()
32-
} else if context.schema.enums.contains_key(&name_string) {
33-
Ident::new(
34-
&format!("{}{}", ENUMS_PREFIX, &name_string),
35-
Span::call_site(),
36-
)
30+
} else if context.schema.enums.contains_key(name) {
31+
format!("{}{}", ENUMS_PREFIX, name)
3732
} else {
3833
if prefix.is_empty() {
3934
panic!("Empty prefix for {:?}", self);
4035
}
41-
Ident::new(&prefix, Span::call_site())
36+
prefix
4237
};
38+
let full_name = Ident::new(&full_name, Span::call_site());
4339

44-
quote!(#name)
40+
quote!(#full_name)
4541
}
4642
FieldType::Optional(inner) => {
4743
let inner = inner.to_rust(context, &prefix);
@@ -89,7 +85,7 @@ fn from_schema_type_inner(inner: graphql_parser::schema::Type, non_null: bool) -
8985
}
9086
}
9187
graphql_parser::schema::Type::NamedType(name) => {
92-
let f = FieldType::Named(Ident::new(&name, Span::call_site()));
88+
let f = FieldType::Named(name);
9389
if non_null {
9490
f
9591
} else {
@@ -120,10 +116,7 @@ fn from_json_type_inner(inner: &introspection_response::TypeRef, non_null: bool)
120116
}
121117
}
122118
Some(_) => {
123-
let f = FieldType::Named(Ident::new(
124-
&inner.name.expect("type name"),
125-
Span::call_site(),
126-
));
119+
let f = FieldType::Named(inner.name.expect("type name").clone());
127120
if non_null {
128121
f
129122
} else {
@@ -157,17 +150,14 @@ mod tests {
157150
let ty = GqlParserType::NamedType("Cat".to_string());
158151
assert_eq!(
159152
FieldType::from(ty),
160-
FieldType::Optional(Box::new(FieldType::Named(Ident::new(
161-
"Cat",
162-
Span::call_site()
163-
))))
153+
FieldType::Optional(Box::new(FieldType::Named("Cat".to_string())))
164154
);
165155

166156
let ty = GqlParserType::NonNullType(Box::new(GqlParserType::NamedType("Cat".to_string())));
167157

168158
assert_eq!(
169159
FieldType::from(ty),
170-
FieldType::Named(Ident::new("Cat", Span::call_site()))
160+
FieldType::Named("Cat".to_string())
171161
);
172162
}
173163

@@ -182,10 +172,7 @@ mod tests {
182172
};
183173
assert_eq!(
184174
FieldType::from(ty),
185-
FieldType::Optional(Box::new(FieldType::Named(Ident::new(
186-
"Cat",
187-
Span::call_site()
188-
))))
175+
FieldType::Optional(Box::new(FieldType::Named("Cat".to_string())))
189176
);
190177

191178
let ty = FullTypeFieldsType {
@@ -201,7 +188,7 @@ mod tests {
201188
};
202189
assert_eq!(
203190
FieldType::from(ty),
204-
FieldType::Named(Ident::new("Cat", Span::call_site()))
191+
FieldType::Named("Cat".to_string())
205192
);
206193
}
207194
}

graphql_query_derive/src/inputs.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use query::QueryContext;
99
use std::collections::HashMap;
1010

1111
/// Represents an input object type from a GraphQL schema
12-
#[derive(Debug, PartialEq)]
12+
#[derive(Debug, Clone, PartialEq)]
1313
pub struct GqlInput {
1414
pub description: Option<String>,
1515
pub name: String,
@@ -116,10 +116,7 @@ mod tests {
116116
GqlObjectField {
117117
description: None,
118118
name: "offsprings".to_string(),
119-
type_: FieldType::Vector(Box::new(FieldType::Named(Ident::new(
120-
"Cat",
121-
Span::call_site(),
122-
)))),
119+
type_: FieldType::Vector(Box::new(FieldType::Named("Cat".to_string()))),
123120
deprecation: DeprecationStatus::Current,
124121
},
125122
),
@@ -128,10 +125,7 @@ mod tests {
128125
GqlObjectField {
129126
description: None,
130127
name: "requirements".to_string(),
131-
type_: FieldType::Optional(Box::new(FieldType::Named(Ident::new(
132-
"CatRequirements",
133-
Span::call_site(),
134-
)))),
128+
type_: FieldType::Optional(Box::new(FieldType::Named("CatRequirements".to_string()))),
135129
deprecation: DeprecationStatus::Current,
136130
},
137131
),

graphql_query_derive/src/interfaces.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::borrow::Cow;
88
use std::collections::HashSet;
99
use unions::union_variants;
1010

11-
#[derive(Debug, PartialEq)]
11+
#[derive(Debug, Clone, PartialEq)]
1212
pub struct GqlInterface {
1313
pub description: Option<String>,
1414
pub implemented_by: HashSet<String>,

graphql_query_derive/src/lib.rs

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
extern crate failure;
55
extern crate graphql_parser;
66
extern crate heck;
7+
#[macro_use]
8+
extern crate lazy_static;
79
extern crate proc_macro;
810
extern crate proc_macro2;
911
extern crate serde;
@@ -42,6 +44,13 @@ mod tests;
4244
use heck::*;
4345
use proc_macro2::{Ident, Span};
4446

47+
type CacheMap<T> = ::std::sync::Mutex<::std::collections::hash_map::HashMap<::std::path::PathBuf, T>>;
48+
49+
lazy_static! {
50+
static ref SCHEMA_CACHE: CacheMap<schema::Schema> = CacheMap::default();
51+
static ref QUERY_CACHE: CacheMap<(String, graphql_parser::query::Document)> = CacheMap::default();
52+
}
53+
4554
#[proc_macro_derive(GraphQLQuery, attributes(graphql))]
4655
pub fn graphql_query_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
4756
let input = TokenStream::from(input);
@@ -51,19 +60,19 @@ pub fn graphql_query_derive(input: proc_macro::TokenStream) -> proc_macro::Token
5160
}
5261

5362
fn read_file(
54-
path: impl AsRef<::std::path::Path> + ::std::fmt::Debug,
63+
path: &::std::path::Path,
5564
) -> Result<String, failure::Error> {
5665
use std::io::prelude::*;
5766

5867
let mut out = String::new();
59-
let mut file = ::std::fs::File::open(&path).map_err(|io_err| {
68+
let mut file = ::std::fs::File::open(path).map_err(|io_err| {
6069
let err: failure::Error = io_err.into();
6170
err.context(format!(
6271
r#"
63-
Could not find file with path: {:?}
72+
Could not find file with path: {}
6473
Hint: file paths in the GraphQLQuery attribute are relative to the project root (location of the Cargo.toml). Example: query_path = "src/my_query.graphql".
6574
"#,
66-
path
75+
path.display()
6776
))
6877
})?;
6978
file.read_to_string(&mut out)?;
@@ -88,29 +97,52 @@ fn impl_gql_query(input: &syn::DeriveInput) -> Result<TokenStream, failure::Erro
8897
.unwrap_or(deprecation::DeprecationStrategy::Warn);
8998

9099
// We need to qualify the query with the path to the crate it is part of
91-
let query_path = format!("{}/{}", cargo_manifest_dir, query_path);
92-
let query_string = read_file(&query_path)?;
93-
let query = graphql_parser::parse_query(&query_string)?;
100+
let query_path = ::std::path::Path::new(&cargo_manifest_dir).join(query_path);
101+
// Check the query cache.
102+
let (query_string, query) = {
103+
let mut lock = QUERY_CACHE.lock().expect("query cache is poisoned");
104+
match lock.entry(query_path) {
105+
::std::collections::hash_map::Entry::Occupied(o) => o.get().clone(),
106+
::std::collections::hash_map::Entry::Vacant(v) => {
107+
let query_string = read_file(v.key())?;
108+
let query = graphql_parser::parse_query(&query_string)?;
109+
v.insert((query_string, query)).clone()
110+
},
111+
}
112+
};
94113

95114
// We need to qualify the schema with the path to the crate it is part of
96115
let schema_path = ::std::path::Path::new(&cargo_manifest_dir).join(schema_path);
97-
let schema_string = read_file(&schema_path)?;
98-
99-
let extension = schema_path
100-
.extension()
101-
.and_then(|e| e.to_str())
102-
.unwrap_or("INVALID");
103-
104-
let schema = match extension {
105-
"graphql" | "gql" => {
106-
let s = graphql_parser::schema::parse_schema(&schema_string)?;
107-
schema::Schema::from(s)
108-
}
109-
"json" => {
110-
let parsed: FullResponse<introspection_response::IntrospectionResponse> = ::serde_json::from_str(&schema_string)?;
111-
schema::Schema::from(parsed.data)
116+
// Check the schema cache.
117+
let schema = {
118+
let mut lock = SCHEMA_CACHE.lock().expect("schema cache is poisoned");
119+
match lock.entry(schema_path) {
120+
::std::collections::hash_map::Entry::Occupied(o) => o.get().clone(),
121+
::std::collections::hash_map::Entry::Vacant(v) => {
122+
let schema_string = read_file(v.key())?;
123+
let schema = {
124+
let extension = v
125+
.key()
126+
.extension()
127+
.and_then(|e| e.to_str())
128+
.unwrap_or("INVALID");
129+
130+
match extension {
131+
"graphql" | "gql" => {
132+
let s = graphql_parser::schema::parse_schema(&schema_string)?;
133+
schema::Schema::from(s)
134+
}
135+
"json" => {
136+
let parsed: FullResponse<introspection_response::IntrospectionResponse> = ::serde_json::from_str(&schema_string)?;
137+
schema::Schema::from(parsed.data)
138+
}
139+
extension => panic!("Unsupported extension for the GraphQL schema: {} (only .json and .graphql are supported)", extension)
140+
}
141+
};
142+
143+
v.insert(schema).clone()
144+
},
112145
}
113-
extension => panic!("Unsupported extension for the GraphQL schema: {} (only .json and .graphql are supported)", extension)
114146
};
115147

116148
let module_name = Ident::new(&input.ident.to_string().to_snake_case(), Span::call_site());

graphql_query_derive/src/objects.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use selection::*;
99
use shared::{field_impls_for_selection, response_fields_for_selection};
1010
use std::borrow::Cow;
1111

12-
#[derive(Debug, PartialEq)]
12+
#[derive(Debug, Clone, PartialEq)]
1313
pub struct GqlObject {
1414
pub description: Option<String>,
1515
pub fields: Vec<GqlObjectField>,

graphql_query_derive/src/scalars.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use proc_macro2;
22

3-
#[derive(Debug, PartialEq, PartialOrd, Ord, Eq)]
3+
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq)]
44
pub struct Scalar {
55
pub name: String,
66
pub description: Option<String>,

0 commit comments

Comments
 (0)