Skip to content

Commit b0742a7

Browse files
committed
graphql_query_derive: cache parsing of schema and query files
Fixes #110.
1 parent 7cf660e commit b0742a7

File tree

2 files changed

+51
-18
lines changed

2 files changed

+51
-18
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/lib.rs

Lines changed: 50 additions & 18 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);
@@ -89,28 +98,51 @@ fn impl_gql_query(input: &syn::DeriveInput) -> Result<TokenStream, failure::Erro
8998

9099
// We need to qualify the query with the path to the crate it is part of
91100
let query_path = ::std::path::Path::new(&cargo_manifest_dir).join(query_path);
92-
let query_string = read_file(&query_path)?;
93-
let query = graphql_parser::parse_query(&query_string)?;
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());

0 commit comments

Comments
 (0)