summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanto Cariotti <santo@dcariotti.me>2024-08-20 21:11:43 +0200
committerSanto Cariotti <santo@dcariotti.me>2024-08-20 21:11:43 +0200
commitc2b09dbb88591d9695c1cd2227c5d559b4a8e775 (patch)
tree8773ae641ea61c90024c3e7b5dd184dbf6a3cbab
parent3c8b004d6ecb6764cd5bc935aaeaf884040320ab (diff)
Add state for database
-rw-r--r--Cargo.lock16
-rw-r--r--Cargo.toml2
-rw-r--r--src/db.rs19
-rw-r--r--src/errors.rs1
-rw-r--r--src/graphql.rs47
-rw-r--r--src/main.rs22
-rw-r--r--src/state.rs7
7 files changed, 72 insertions, 42 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d89368d..16b9947 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -363,10 +363,10 @@ dependencies = [
"futures-util",
"lazy_static",
"postgis",
- "postgres",
"serde",
"serde_json",
"tokio",
+ "tokio-postgres",
"tower-http",
"tracing",
"tracing-subscriber",
@@ -1165,20 +1165,6 @@ dependencies = [
]
[[package]]
-name = "postgres"
-version = "0.19.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c9ec84ab55b0f9e418675de50052d494ba893fd28c65769a6e68fcdacbee2b8"
-dependencies = [
- "bytes",
- "fallible-iterator",
- "futures-util",
- "log",
- "tokio",
- "tokio-postgres",
-]
-
-[[package]]
name = "postgres-protocol"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index cc0473d..50f662d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,7 +10,6 @@ axum = "0.7.5"
config = "0.14.0"
futures-util = "0.3.30"
postgis = "0.9.0"
-postgres = "0.19.8"
serde_json = "1.0.125"
tokio = { version = "1.38.1", features = ["rt"] }
tracing = "0.1.40"
@@ -18,3 +17,4 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
tower-http = { version = "0.5.2", features = ["trace", "compression-br", "propagate-header", "sensitive-headers"] }
lazy_static = "1.5.0"
serde = { version = "1.0.208", features = ["derive"] }
+tokio-postgres = "0.7.11"
diff --git a/src/db.rs b/src/db.rs
new file mode 100644
index 0000000..b74550b
--- /dev/null
+++ b/src/db.rs
@@ -0,0 +1,19 @@
+use crate::errors::AppError;
+
+use tokio_postgres::{Client, NoTls};
+
+/// Setup database connection. Get variable `DATABASE_URL` from the environment.
+pub async fn setup() -> Result<Client, AppError> {
+ let database_url = &crate::config::CONFIG.database_url;
+
+ let (client, connection) = tokio_postgres::connect(database_url, NoTls).await.unwrap();
+
+ // Spawn a new task to run the connection to the database
+ tokio::spawn(async move {
+ if let Err(e) = connection.await {
+ eprintln!("Database connection error: {}", e);
+ }
+ });
+
+ Ok(client)
+}
diff --git a/src/errors.rs b/src/errors.rs
index e0a70b5..fafe0b0 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -6,6 +6,7 @@ use axum::{
use serde_json::json;
/// All errors raised by the web app
+#[derive(Debug)]
pub enum AppError {
/// Database error
Database,
diff --git a/src/graphql.rs b/src/graphql.rs
index 12b6db3..2843156 100644
--- a/src/graphql.rs
+++ b/src/graphql.rs
@@ -1,14 +1,11 @@
-use async_graphql::{
- http::GraphiQLSource, Context, EmptyMutation, EmptySubscription, Object, Schema,
-};
-use async_graphql_axum::GraphQL;
-use axum::{
- response::{self, IntoResponse},
- routing::get,
- Router,
-};
+use std::sync::Arc;
-struct Query;
+use async_graphql::{Context, EmptyMutation, EmptySubscription, Object, Schema};
+use async_graphql_axum::{GraphQLRequest, GraphQLResponse};
+
+// use crate::state::AppState;
+
+pub struct Query;
#[Object]
impl Query {
@@ -23,6 +20,19 @@ impl Query {
#[graphql(desc = "First value")] a: i32,
#[graphql(desc = "Second value")] b: Option<i32>,
) -> i32 {
+ // let state = ctx.data::<AppState>().unwrap();
+ // let client = &*state.client;
+ //
+ // // Perform a database query
+ // let rows = client
+ // .query("SELECT owner FROM payment", &[])
+ // .await
+ // .unwrap();
+ // for row in rows {
+ // let owner: String = row.get(0);
+ // println!("{owner}");
+ // }
+
match b {
Some(x) => a + x,
None => a,
@@ -30,16 +40,9 @@ impl Query {
}
}
-pub async fn graphiql() -> impl IntoResponse {
- response::Html(
- GraphiQLSource::build()
- .endpoint("/")
- .subscription_endpoint("/ws")
- .finish(),
- )
-}
-
-pub fn create_route() -> Router {
- let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
- Router::new().route("/", get(graphiql).post_service(GraphQL::new(schema)))
+pub async fn graphql_handler(
+ schema: Arc<Schema<Query, EmptyMutation, EmptySubscription>>,
+ req: GraphQLRequest,
+) -> GraphQLResponse {
+ schema.execute(req.into_inner()).await.into()
}
diff --git a/src/main.rs b/src/main.rs
index 8643d71..7ef7ee6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,14 +1,18 @@
mod config;
+mod db;
mod errors;
mod graphql;
mod logger;
mod routes;
-use std::{net::SocketAddr, time::Duration};
+mod state;
+use std::{net::SocketAddr, sync::Arc, time::Duration};
use crate::config::CONFIG;
+use async_graphql::{EmptyMutation, EmptySubscription, Schema};
use axum::{
http::{header, Request},
- Router,
+ routing::post,
+ Extension, Router,
};
use tokio::net::TcpListener;
use tower_http::{
@@ -21,10 +25,19 @@ use tracing::Span;
/// Create the app: setup everything and returns a `Router`
async fn create_app() -> Router {
logger::setup();
- // let _ = db::setup().await;
+ let dbclient = db::setup().await.unwrap();
+ let state = state::AppState {
+ client: Arc::new(dbclient),
+ };
+ let schema = Schema::build(graphql::Query, EmptyMutation, EmptySubscription)
+ .data(state.clone())
+ .finish();
Router::new()
- .nest("/graphql", graphql::create_route())
+ .route(
+ "/graphql",
+ post(move |req| graphql::graphql_handler(schema.clone().into(), req)),
+ )
.fallback(crate::routes::page_404)
// Mark the `Authorization` request header as sensitive so it doesn't
// show in logs.
@@ -43,6 +56,7 @@ async fn create_app() -> Router {
},
),
)
+ .layer(Extension(state))
}
#[tokio::main(flavor = "current_thread")]
diff --git a/src/state.rs b/src/state.rs
new file mode 100644
index 0000000..d4719b9
--- /dev/null
+++ b/src/state.rs
@@ -0,0 +1,7 @@
+use std::sync::Arc;
+
+use tokio_postgres::Client;
+#[derive(Clone)]
+pub struct AppState {
+ pub client: Arc<Client>,
+}