This took most of today to get working.
GraphQL interface to a list of names.. to can query by id, and can add names. There's no dupe check, no remove/delete, not even a way to enumerate stored values. The trickiest part of the incrementing id for addPerson. Initially I reused some of the HashMap in a Mutex pattern to store u32s, well u8 at first but that doesn't cast to a juniper scalar type. I don't know why that didn't work. The incremented value didn't seem to persist in the hash.
This commit is contained in:
		
						commit
						b7211a77e4
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | /target | ||||||
							
								
								
									
										1760
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1760
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										11
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | [package] | ||||||
|  | name = "rust-graphql-example" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2018" | ||||||
|  | 
 | ||||||
|  | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
|  | juniper_rocket = "0.8.0" | ||||||
|  | juniper = "0.15.7" | ||||||
|  | rocket = "0.5.0-rc.1" | ||||||
							
								
								
									
										155
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,155 @@ | |||||||
|  | extern crate rocket; | ||||||
|  | 
 | ||||||
|  | use std::sync::{ atomic::AtomicUsize, atomic::Ordering, Mutex }; | ||||||
|  | use std::{ collections::HashMap }; | ||||||
|  | use juniper::{ EmptySubscription, RootNode, graphql_object, Context }; | ||||||
|  | use rocket::{ response::content, Rocket, State }; | ||||||
|  | 
 | ||||||
|  | #[derive(Clone)] | ||||||
|  | pub struct Person { | ||||||
|  |     id: String, | ||||||
|  |     name: String, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Person { | ||||||
|  |     pub fn new(id: String, name: String) -> Person { | ||||||
|  |         Person { id, name } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn name(&self) -> Option<&str> { | ||||||
|  |         Some(self.name.as_str()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[graphql_object(context = Database)] | ||||||
|  | impl Person { | ||||||
|  |     fn id(&self) -> &str { | ||||||
|  |         &self.id | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn name(&self) -> Option<&str> { | ||||||
|  |         Some(self.name.as_str()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Default)] | ||||||
|  | pub struct Database { | ||||||
|  |     people: Mutex<HashMap<String, Person>>, | ||||||
|  |     next_id: AtomicUsize, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Database { | ||||||
|  |     pub fn new() -> Database { | ||||||
|  |         let database = Database { | ||||||
|  |             people: Mutex::new(HashMap::new()), | ||||||
|  |             next_id: AtomicUsize::new(1), | ||||||
|  |         }; | ||||||
|  |         database | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_person(&self, id: &str) -> Option<Person> { | ||||||
|  |         let people = self.people.lock().expect("Couldn't lock people"); | ||||||
|  |         match people.get(id) { | ||||||
|  |             Some(person) => Some(person.to_owned()), | ||||||
|  |             None => None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn add_person(&self, person: Person) { | ||||||
|  |         self.people.lock().expect("Couldn't lock people").insert(person.id.to_owned(), person); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn new_id(&self) -> usize { | ||||||
|  |         self.next_id.fetch_add(1, Ordering::Relaxed) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn new_person(&self, name: String) -> Option<Person> { | ||||||
|  |         let person = Person { | ||||||
|  |             id: self.new_id().to_string(), | ||||||
|  |             name, | ||||||
|  |         }; | ||||||
|  |         self.people.lock().expect("lock people hashmap").insert(person.id.to_owned(), person.to_owned()); | ||||||
|  |         Some(person) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Context for Database {} | ||||||
|  | 
 | ||||||
|  | pub struct Query; | ||||||
|  | #[graphql_object(context = Database)] | ||||||
|  | impl Query { | ||||||
|  |     #[graphql(arguments(id(description = "id of the human")))] | ||||||
|  |     fn human(database: &Database, id: String) -> Option<Person> { | ||||||
|  |         database.get_person(&id) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct Mutations; | ||||||
|  | 
 | ||||||
|  | #[graphql_object(context = Database)] | ||||||
|  | impl Mutations { | ||||||
|  |     fn addHuman(database: &Database, id: String, name: String) -> Person { | ||||||
|  |         let new_guy = Person::new(id, name); | ||||||
|  |         database.add_person(new_guy.to_owned()); | ||||||
|  |         new_guy.to_owned() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn newId(database: &Database) -> i32 { | ||||||
|  |         database.new_id() as i32 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn newPerson(database: &Database, name: String) -> Option<Person> { | ||||||
|  |         database.new_person(name) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Schema = RootNode<'static, Query, Mutations, EmptySubscription<Database>>; | ||||||
|  | 
 | ||||||
|  | #[rocket::get("/")] | ||||||
|  | fn graphiql() -> content::Html<String> { | ||||||
|  |     juniper_rocket::graphiql_source("/graphql", None) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[rocket::get("/graphql?<request>")] | ||||||
|  | fn get_graphql_handler( | ||||||
|  |     context: &State<Database>, | ||||||
|  |     request: juniper_rocket::GraphQLRequest, | ||||||
|  |     schema: &State<Schema>, | ||||||
|  | ) -> juniper_rocket::GraphQLResponse { | ||||||
|  |     request.execute_sync(&*schema, &*context) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[rocket::post("/graphql", data = "<request>")] | ||||||
|  | fn post_graphql_handler( | ||||||
|  |     context: &State<Database>, | ||||||
|  |     request: juniper_rocket::GraphQLRequest, | ||||||
|  |     schema: &State<Schema>, | ||||||
|  | ) -> juniper_rocket::GraphQLResponse { | ||||||
|  |     request.execute_sync(&*schema, &*context) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[rocket::get("/rest/<id>")] | ||||||
|  | fn get_rest(id: String, context: &State<Database>) -> Option<String> { | ||||||
|  |     match context.get_person(&id) { | ||||||
|  |         None => None, | ||||||
|  |         Some(person) => Some(person.name().unwrap().to_string()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[rocket::main] | ||||||
|  | async fn main() { | ||||||
|  |     Rocket::build() | ||||||
|  |         .manage(Database::new()) | ||||||
|  |         .manage(Schema::new( | ||||||
|  |             Query, | ||||||
|  |             Mutations, | ||||||
|  |             EmptySubscription::<Database>::new(), | ||||||
|  |         )) | ||||||
|  |         .mount( | ||||||
|  |             "/", | ||||||
|  |             rocket::routes![graphiql, get_graphql_handler, post_graphql_handler, get_rest], | ||||||
|  |         ) | ||||||
|  |         .launch() | ||||||
|  |         .await | ||||||
|  |         .expect("server to launch"); | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Alex Wright
						Alex Wright