Skip to content

Commit b61ca14

Browse files
committed
Pass the executor immutably through resolution
The executor is now using internal mutability through RwLock to make it thread-safe.
1 parent cd33093 commit b61ca14

File tree

16 files changed

+55
-51
lines changed

16 files changed

+55
-51
lines changed

src/executor.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::HashMap;
22
use std::marker::PhantomData;
3+
use std::sync::RwLock;
34

45
use ::GraphQLError;
56
use ast::{InputValue, ToInputValue, Document, Selection, Fragment, Definition, Type, FromInputValue, OperationType};
@@ -41,7 +42,7 @@ pub struct Executor<'a, CtxT> where CtxT: 'a {
4142
current_selection_set: Option<Vec<Selection>>,
4243
schema: &'a SchemaType,
4344
context: &'a CtxT,
44-
errors: &'a mut Vec<ExecutionError>,
45+
errors: &'a RwLock<Vec<ExecutionError>>,
4546
field_path: FieldPath<'a>,
4647
}
4748

@@ -81,7 +82,7 @@ impl<T> IntoFieldResult<T> for FieldResult<T> {
8182

8283
impl<'a, CtxT> Executor<'a, CtxT> {
8384
/// Resolve a single arbitrary value into an `ExecutionResult`
84-
pub fn resolve<T: GraphQLType<CtxT>>(&mut self, value: &T) -> ExecutionResult {
85+
pub fn resolve<T: GraphQLType<CtxT>>(&self, value: &T) -> ExecutionResult {
8586
Ok(value.resolve(
8687
match self.current_selection_set {
8788
Some(ref sel) => Some(sel.clone()),
@@ -93,7 +94,7 @@ impl<'a, CtxT> Executor<'a, CtxT> {
9394
/// Resolve a single arbitrary value into a return value
9495
///
9596
/// If the field fails to resolve, `null` will be returned.
96-
pub fn resolve_into_value<T: GraphQLType<CtxT>>(&mut self, value: &T) -> Value {
97+
pub fn resolve_into_value<T: GraphQLType<CtxT>>(&self, value: &T) -> Value {
9798
match self.resolve(value) {
9899
Ok(v) => v,
99100
Err(e) => {
@@ -108,7 +109,7 @@ impl<'a, CtxT> Executor<'a, CtxT> {
108109
///
109110
/// This can be used to connect different types, e.g. from different Rust
110111
/// libraries, that require different context types.
111-
pub fn replaced_context<'b, NewCtxT>(&'b mut self, ctx: &'b NewCtxT) -> Executor<'b, NewCtxT> {
112+
pub fn replaced_context<'b, NewCtxT>(&'b self, ctx: &'b NewCtxT) -> Executor<'b, NewCtxT> {
112113
Executor {
113114
fragments: self.fragments,
114115
variables: self.variables,
@@ -122,7 +123,7 @@ impl<'a, CtxT> Executor<'a, CtxT> {
122123

123124
#[doc(hidden)]
124125
pub fn sub_executor(
125-
&mut self,
126+
&self,
126127
field_name: Option<String>,
127128
location: SourcePosition,
128129
selection_set: Option<Vec<Selection>>,
@@ -167,11 +168,13 @@ impl<'a, CtxT> Executor<'a, CtxT> {
167168
}
168169

169170
/// Add an error to the execution engine
170-
pub fn push_error(&mut self, error: String, location: SourcePosition) {
171+
pub fn push_error(&self, error: String, location: SourcePosition) {
171172
let mut path = Vec::new();
172173
self.field_path.construct_path(&mut path);
173174

174-
self.errors.push(ExecutionError {
175+
let mut errors = self.errors.write().unwrap();
176+
177+
errors.push(ExecutionError {
175178
location: location,
176179
path: path,
177180
message: error,
@@ -261,17 +264,17 @@ pub fn execute_validated_query<'a, QueryT, MutationT, CtxT>(
261264
None => return Err(GraphQLError::UnknownOperationName),
262265
};
263266

264-
let mut errors = Vec::new();
267+
let errors = RwLock::new(Vec::new());
265268
let value;
266269

267270
{
268-
let mut executor = Executor {
271+
let executor = Executor {
269272
fragments: &fragments.into_iter().map(|f| (f.item.name.item.clone(), f.item)).collect(),
270273
variables: variables,
271274
current_selection_set: Some(op.item.selection_set),
272275
schema: &root_node.schema,
273276
context: context,
274-
errors: &mut errors,
277+
errors: &errors,
275278
field_path: FieldPath::Root(op.start),
276279
};
277280

@@ -281,6 +284,7 @@ pub fn execute_validated_query<'a, QueryT, MutationT, CtxT>(
281284
};
282285
}
283286

287+
let mut errors = errors.into_inner().unwrap();
284288
errors.sort();
285289

286290
Ok((value, errors))

src/executor_tests/executor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ mod threads_context_correctly {
167167
struct Schema;
168168

169169
graphql_object!(Schema: String |&self| {
170-
field a(&mut executor) -> String { executor.context().clone() }
170+
field a(&executor) -> String { executor.context().clone() }
171171
});
172172

173173
#[test]

src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ graphql_object!(User: Database |&self| {
6767
//
6868
// In this example, the context is used to convert the friend_ids array
6969
// into actual User objects.
70-
field friends(&mut executor) -> Vec<&User> {
70+
field friends(&executor) -> Vec<&User> {
7171
self.friend_ids.iter()
7272
.filter_map(|id| executor.context().users.get(id))
7373
.collect()
@@ -79,7 +79,7 @@ graphql_object!(User: Database |&self| {
7979
graphql_object!(QueryRoot: Database |&self| {
8080
8181
// Arguments work just like they do on functions.
82-
field user(&mut executor, id: String) -> Option<&User> {
82+
field user(&executor, id: String) -> Option<&User> {
8383
executor.context().users.get(&id)
8484
}
8585
});
@@ -121,15 +121,15 @@ use juniper::iron_handlers::GraphQLHandler;
121121
# Ok(&self.name)
122122
# }
123123
#
124-
# field friends(&mut executor) -> FieldResult<Vec<&User>> {
124+
# field friends(&executor) -> FieldResult<Vec<&User>> {
125125
# Ok(self.friend_ids.iter()
126126
# .filter_map(|id| executor.context().users.get(id))
127127
# .collect())
128128
# }
129129
# });
130130
#
131131
# graphql_object!(QueryRoot: Database |&self| {
132-
# field user(&mut executor, id: String) -> FieldResult<Option<&User>> {
132+
# field user(&executor, id: String) -> FieldResult<Option<&User>> {
133133
# Ok(executor.context().users.get(&id))
134134
# }
135135
# });

src/macros/args.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ macro_rules! __graphql__args {
1515

1616
(
1717
@assign_arg_vars,
18-
$args:ident, $executorvar:ident, &mut $exec:ident $($rest:tt)*
18+
$args:ident, $executorvar:ident, &$exec:ident $($rest:tt)*
1919
) => {
20-
let __graphql__args!(@as_pattern, $exec) = &mut $executorvar;
20+
let __graphql__args!(@as_pattern, $exec) = &$executorvar;
2121
__graphql__args!(@assign_arg_vars, $args, $executorvar, $($rest)*);
2222
};
2323

@@ -59,7 +59,7 @@ macro_rules! __graphql__args {
5959

6060
(
6161
@apply_args,
62-
$reg:expr, $base:expr, ( &mut executor $( $rest:tt )* )
62+
$reg:expr, $base:expr, ( &executor $( $rest:tt )* )
6363
) => {
6464
__graphql__args!(
6565
@apply_args,

src/macros/enums.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ macro_rules! graphql_enum {
8181
.into_meta()
8282
}
8383

84-
fn resolve(&self, _: Option<Vec<$crate::Selection>>, _: &mut $crate::Executor<CtxT>) -> $crate::Value {
84+
fn resolve(&self, _: Option<Vec<$crate::Selection>>, _: &$crate::Executor<CtxT>) -> $crate::Value {
8585
match self {
8686
$(
8787
&graphql_enum!(@as_pattern, $eval) =>

src/macros/interface.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ macro_rules! graphql_interface {
249249

250250
#[allow(unused_variables)]
251251
#[allow(unused_mut)]
252-
fn resolve_field(&$mainself, field: &str, args: &$crate::Arguments, mut executor: &mut $crate::Executor<$ctxt>) -> $crate::ExecutionResult {
252+
fn resolve_field(&$mainself, field: &str, args: &$crate::Arguments, mut executor: &$crate::Executor<$ctxt>) -> $crate::ExecutionResult {
253253
__graphql__build_field_matches!(
254254
($outname, $mainself, field, args, executor),
255255
(),
@@ -267,7 +267,7 @@ macro_rules! graphql_interface {
267267
&$mainself,
268268
type_name: &str,
269269
_: Option<Vec<$crate::Selection>>,
270-
executor: &mut $crate::Executor<$ctxt>,
270+
executor: &$crate::Executor<$ctxt>,
271271
)
272272
-> $crate::ExecutionResult
273273
{

src/macros/object.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,15 @@ string as documentation on the field.
194194
### Field arguments
195195
196196
```text
197-
&mut executor
197+
&executor
198198
arg_name: ArgType
199199
arg_name = default_value: ArgType
200200
arg_name: ArgType as "Argument description"
201201
arg_name = default_value: ArgType as "Argument description"
202202
```
203203
204204
Field arguments can take many forms. If the field needs access to the executor
205-
or context, it can take an [Executor][1] instance by specifying `&mut executor`
205+
or context, it can take an [Executor][1] instance by specifying `&executor`
206206
as the first argument.
207207
208208
The other cases are similar to regular Rust arguments, with two additions:
@@ -382,7 +382,7 @@ macro_rules! graphql_object {
382382
&$mainself,
383383
field: &str,
384384
args: &$crate::Arguments,
385-
mut executor: &mut $crate::Executor<$ctxt>
385+
executor: &$crate::Executor<$ctxt>
386386
)
387387
-> $crate::ExecutionResult
388388
{

src/macros/scalar.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ macro_rules! graphql_scalar {
7676
fn resolve(
7777
&$resolve_selfvar,
7878
_: Option<Vec<$crate::Selection>>,
79-
_: &mut $crate::Executor<CtxT>) -> $crate::Value {
79+
_: &$crate::Executor<CtxT>) -> $crate::Value {
8080
$resolve_body
8181
}
8282
}

src/macros/tests/args.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ Syntax to validate:
2020

2121
graphql_object!(Root: () |&self| {
2222
field simple() -> i64 { 0 }
23-
field exec_arg(&mut executor) -> i64 { 0 }
24-
field exec_arg_and_more(&mut executor, arg: i64) -> i64 { 0 }
23+
field exec_arg(&executor) -> i64 { 0 }
24+
field exec_arg_and_more(&executor, arg: i64) -> i64 { 0 }
2525

2626
field single_arg(arg: i64) -> i64 { 0 }
2727
field multi_args(

src/macros/union.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ macro_rules! graphql_union {
136136
&$mainself,
137137
type_name: &str,
138138
_: Option<Vec<$crate::Selection>>,
139-
executor: &mut $crate::Executor<$ctxt>,
139+
executor: &$crate::Executor<$ctxt>,
140140
)
141141
-> $crate::ExecutionResult
142142
{

0 commit comments

Comments
 (0)