Skip to content

Commit

Permalink
✨ introducing... graphql! (#2)
Browse files Browse the repository at this point in the history
* ✨ multi-id queries & id splitting! Nextup: Queries

* ✨ optional query params

* ⚗️ persons query now exists

* ⚗️ cults query now exists, and people and cults exist within each other

* ♻️ shimmied the bits around
  • Loading branch information
jayy-lmao authored and James Holman committed Jan 23, 2020
1 parent 1f01493 commit f0c584f
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 70 deletions.
10 changes: 8 additions & 2 deletions api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
postgres = "0.15.2"
actix-web = "1.0.7"
serde = { version = "1.0.101", features = ["derive"] }
dotenv = "0.9.0"
env_logger = "0.6"
futures = "0.1"
juniper = "0.13.1"
postgres = "0.15.2"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"

[[bin]]
name = "readspacer-api"
Expand Down
71 changes: 42 additions & 29 deletions api/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,52 @@
use actix_web::{web, App, HttpServer, Responder};
#[macro_use]
extern crate juniper;

mod db;
mod schema;
mod models;
mod resolvers;
mod types;
mod db;

fn greet() -> impl Responder {
"Yo there"
use actix_web::{web, App, Error, HttpResponse, HttpServer};
use futures::future::Future;
use juniper::http::GraphQLRequest;
use juniper::http::playground::playground_source;
use std::io;
use std::sync::Arc;
use crate::schema::{create_schema, Schema};

fn graphql(
st: web::Data<Arc<Schema>>,
data: web::Json<GraphQLRequest>,
) -> impl Future<Item = HttpResponse, Error = Error> {
web::block(move || {
let res = data.execute(&st, &());
Ok::<_, serde_json::error::Error>(serde_json::to_string(&res)?)
})
.map_err(Error::from)
.and_then(|user| {
Ok(HttpResponse::Ok()
.content_type("application/json")
.body(user))
})
}

fn playground() -> HttpResponse {
let html = playground_source("http://localhost:8000/graphql");
HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(html)
}

fn main() {
println!("Server starting...");
HttpServer::new(|| {
App::new()
.service(web::resource("/hello").route(web::get().to(greet)))
.service(
web::resource("/some_persons").route(web::get().to(resolvers::person::get_some_person)),
)
.service(
web::resource("/persons").route(web::get().to(resolvers::person::get_person_list)),
)
.service(
web::resource("/persons/{person_id}")
.route(web::get().to(resolvers::person::get_person)),
)
// .route(web::post().to(create_person)))
// .route(web::delete().to(delete_person))
// .route(web::put().to(update_person)))
.service(
web::resource("/cults/{cult_id}").route(web::get().to(resolvers::cult::get_cult)),
)
.service(web::resource("/cults").route(web::get().to(resolvers::cult::get_cult_list)))
fn main() -> io::Result<()> {
let schema = std::sync::Arc::new(create_schema());
HttpServer::new(move || {
App::new().data(schema.clone()).service(
web::resource("/graphql")
.route(web::post().to_async(graphql))
.route(web::get().to(playground)),
)
})
.bind("0.0.0.0:8000")
.unwrap()
.bind("0.0.0.0:8000")?
.run()
.unwrap();
}
45 changes: 36 additions & 9 deletions api/src/models/person.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
extern crate postgres;
use crate::db::get_db_conn;
use crate::types::Person;
use crate::db::get_db_conn;

pub fn get_person_all(vec: &mut Vec<Person>) {
let conn = get_db_conn();
for row in &conn
.query("SELECT person_id, person_name FROM persons", &[])
.query("SELECT person_id, person_name, cult FROM persons", &[])
.unwrap()
{
let person = Person {
Expand All @@ -19,19 +19,28 @@ pub fn get_person_all(vec: &mut Vec<Person>) {

pub fn get_person_by_ids(vec: &mut Vec<Person>, ids: Vec<i32>) {
//TODO: In desperate need of refactor, or else ye shall face the n+1 problem!!

for id in ids.iter() {
get_person_by_id(vec, *id);
};
let conn = get_db_conn();
for row in &conn
.query(
"SELECT person_id, person_name, cult FROM persons WHERE person_id = ANY($1)",
&[&ids],
)
.unwrap()
{
let person = Person {
person_id: row.get(0),
person_name: row.get(1),
cult: row.get(2),
};
vec.push(person);
}
}

pub fn get_person_by_id(vec: &mut Vec<Person>, id: i32) {
// let pg_connection_string = env::var("DATABASE_URI").expect("need a db uri");
// let conn = Connection::connect(&pg_connection_string[..], TlsMode::None).unwrap();
let conn = get_db_conn();
for row in &conn
.query(
"SELECT person_id, person_name, cult FROM persons WHERE person_id = $1",
"select person_id, person_name, cult from persons where person_id = $1",
&[&id],
)
.unwrap()
Expand All @@ -44,3 +53,21 @@ pub fn get_person_by_id(vec: &mut Vec<Person>, id: i32) {
vec.push(person);
}
}

pub fn get_person_by_cult(vec: &mut Vec<Person>, cult: i32) {
let conn = get_db_conn();
for row in &conn
.query(
"select person_id, person_name, cult from persons where cult = $1",
&[&cult],
)
.unwrap()
{
let person = Person {
person_id: row.get(0),
person_name: row.get(1),
cult: row.get(2),
};
vec.push(person);
}
}
28 changes: 16 additions & 12 deletions api/src/resolvers/cult.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
use actix_web::{web, Responder};
use crate::types::{Cult, Person};
use crate::models::person:: get_person_by_cult;

use crate::{models, types::Cult};
#[juniper::object(description = "A real human CULT")]
impl Cult {
pub fn id(&self) -> i32 {
self.id
}

pub fn get_cult_list() -> impl Responder {
let mut vec: Vec<Cult> = Vec::new();
models::cult::get_cult_all(&mut vec);
web::Json(vec)
}
pub fn name(&self) -> &str {
self.name.as_str()
}

pub fn get_cult(info: web::Path<i32>) -> impl Responder {
let mut vec: Vec<Cult> = Vec::new();
models::cult::get_cult_by_id(&mut vec, info.into_inner());
web::Json(vec)
}
pub fn members(&self) -> Vec<Person> {
let mut vec: Vec<Person> = Vec::new();
get_person_by_cult(&mut vec, self.id);
vec
}
}
39 changes: 21 additions & 18 deletions api/src/resolvers/person.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
use actix_web::{web, Responder};
use crate::types::{Cult, Person};
use crate::models::{
cult::get_cult_by_id,
};

use crate::{models, types::Person};
#[juniper::object(description = "A real human bean")]
impl Person {
pub fn id(&self) -> i32 {
self.person_id
}

pub fn get_person_list() -> impl Responder {
let mut vec: Vec<Person> = Vec::new();
models::person::get_person_all(&mut vec);
web::Json(vec)
}
pub fn name(&self) -> &str {
self.person_name.as_str()
}

pub fn get_some_person() -> impl Responder {
let mut vec: Vec<Person> = Vec::new();
models::person::get_person_by_ids(&mut vec, vec![1,2,3]);
web::Json(vec)
}

pub fn get_person(info: web::Path<i32>) -> impl Responder {
let mut vec: Vec<Person> = Vec::new();
models::person::get_person_by_id(&mut vec, info.into_inner());
web::Json(vec)
}
pub fn cult(&self) -> Vec<Cult> {
let mut vec: Vec<Cult> = Vec::new();
match self.cult {
Some(cult_id) => get_cult_by_id(&mut vec, cult_id),
None => (),
}
vec
}
}
29 changes: 29 additions & 0 deletions api/src/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use juniper::{EmptyMutation, RootNode};

use crate::models::{
cult::get_cult_all,
person::get_person_all,
};
use crate::types::{Cult, Person};
pub struct QueryRoot;

#[juniper::object]
impl QueryRoot {
fn persons() -> Vec<Person> {
let mut vec: Vec<Person> = Vec::new();
get_person_all(&mut vec);
vec
}

fn cults() -> Vec<Cult> {
let mut vec: Vec<Cult> = Vec::new();
get_cult_all(&mut vec);
vec
}
}

pub type Schema = RootNode<'static, QueryRoot, EmptyMutation<()>>;

pub fn create_schema() -> Schema {
Schema::new(QueryRoot {}, EmptyMutation::new())
}
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ services:
image: postgres:12
mem_limit: 1536MB
mem_reservation: 1G
command: ["postgres", "-c", "log_statement=all", "-c", "log_destination=stderr"]
environment:
POSTGRES_USER: jayylmao
POSTGRES_PASSWORD: yeetus
Expand Down

0 comments on commit f0c584f

Please sign in to comment.