@@ -59,14 +59,13 @@ struct User {
59
59
// Assign Database as the context type for User
60
60
#[graphql_object(context = Database )]
61
61
impl User {
62
- // 3. Inject the context by specifying an argument
62
+ // Inject the context by specifying an argument
63
63
// with the context type.
64
64
// Note:
65
65
// - the type must be a reference
66
66
// - the name of the argument SHOULD be `context`
67
67
fn friends <'db >(& self , context : & 'db Database ) -> Vec <& 'db User > {
68
-
69
- // 5. Use the database to lookup users
68
+ // Use the database to lookup users
70
69
self . friend_ids. iter ()
71
70
. map (| id | context . users. get (id ). expect (" Could not find user with ID" ))
72
71
. collect ()
@@ -87,4 +86,55 @@ impl User {
87
86
You only get an immutable reference to the context, so if you want to affect
88
87
change to the execution, you'll need to use [ interior
89
88
mutability] ( https://doc.rust-lang.org/book/first-edition/mutability.html#interior-vs-exterior-mutability )
90
- using e.g. ` RwLock ` or ` RefCell ` .
89
+ using e.g. ` RwLock ` or ` RefCell ` . \
90
+ If you are using async runtime like ` tokio ` for mutable references you will need to use a corresponding async version of RwLock:
91
+ ``` rust
92
+ # extern crate juniper;
93
+ # use std :: collections :: HashMap ;
94
+ # use juniper :: graphql_object;
95
+ # use tokio :: sync :: RwLock ;
96
+ #
97
+ // This struct represents our context.
98
+ struct Database {
99
+ requested_count : HashMap <i32 , i32 >,
100
+ }
101
+
102
+ // Mark the Database as a valid context type for Juniper
103
+ impl juniper :: Context for Database {}
104
+
105
+ struct User {
106
+ id : i32 ,
107
+ name : String ,
108
+ times_requested : i32 ,
109
+ }
110
+
111
+ // Assign Database as the context type for User and envelope it in RwLock
112
+ #[graphql_object(context = RwLock <Database >)]
113
+ impl User {
114
+ // Inject the context by specifying an argument
115
+ // with the context type.
116
+ // Note:
117
+ // - the type must be a reference
118
+ // - the name of the argument SHOULD be `context`
119
+ fn times_requested <'db >(& self , context : & 'db RwLock <Database >) -> Vec <& 'db User > {
120
+ // Acquire a mutable reference and await if async RwLock is used,
121
+ // which is neccessary if context consists async operations
122
+ // like querying remote databases
123
+ // If context is immutable use .read() on RwLock
124
+ let mut context = context . write (). await ;
125
+ // Preform a mutable operation
126
+ context . requested_count. entry (0 ). and_modify (| e | { * e += 1 }). or_insert (1 )
127
+ }
128
+
129
+ fn name (& self ) -> & str {
130
+ self . name. as_str ()
131
+ }
132
+
133
+ fn id (& self ) -> i32 {
134
+ self . id
135
+ }
136
+ }
137
+ #
138
+ # fn main () { }
139
+ ```
140
+ Replace ` tokio::sync::RwLock ` with ` std::sync::RwLock ` if async runtime is not intended
0 commit comments