@@ -59,14 +59,13 @@ struct User {
5959// Assign Database as the context type for User
6060#[graphql_object(context = Database )]
6161impl User {
62- // 3. Inject the context by specifying an argument
62+ // Inject the context by specifying an argument
6363 // with the context type.
6464 // Note:
6565 // - the type must be a reference
6666 // - the name of the argument SHOULD be `context`
6767 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
7069 self . friend_ids. iter ()
7170 . map (| id | context . users. get (id ). expect (" Could not find user with ID" ))
7271 . collect ()
@@ -87,4 +86,55 @@ impl User {
8786You only get an immutable reference to the context, so if you want to affect
8887change to the execution, you'll need to use [ interior
8988mutability] ( 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