From d60e5eb9207d010b83721001d9330056320df3c4 Mon Sep 17 00:00:00 2001 From: Jake Hillion Date: Thu, 21 Jul 2022 12:55:31 +0100 Subject: [PATCH 1/2] added users table --- .gitignore | 2 + Cargo.lock | 45 +++++++++++++++++++ Cargo.toml | 1 + diesel.toml | 5 +++ migrations/.gitkeep | 0 .../down.sql | 6 +++ .../up.sql | 36 +++++++++++++++ .../2022-07-21-115312_create_users/down.sql | 3 ++ .../2022-07-21-115312_create_users/up.sql | 6 +++ src/schema.rs | 6 +++ 10 files changed, 110 insertions(+) create mode 100644 diesel.toml create mode 100644 migrations/.gitkeep create mode 100644 migrations/00000000000000_diesel_initial_setup/down.sql create mode 100644 migrations/00000000000000_diesel_initial_setup/up.sql create mode 100644 migrations/2022-07-21-115312_create_users/down.sql create mode 100644 migrations/2022-07-21-115312_create_users/up.sql create mode 100644 src/schema.rs diff --git a/.gitignore b/.gitignore index ea8c4bf..3d62c7b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +.env + diff --git a/Cargo.lock b/Cargo.lock index 004ffa2..ae1526c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -374,6 +374,12 @@ version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "cache-padded" version = "1.2.0" @@ -523,6 +529,29 @@ dependencies = [ "cipher", ] +[[package]] +name = "diesel" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b28135ecf6b7d446b43e27e225622a038cc4e2930a1022f51cdb97ada19b8e4d" +dependencies = [ + "bitflags", + "byteorder", + "diesel_derives", + "pq-sys", +] + +[[package]] +name = "diesel_derives" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "digest" version = "0.9.0" @@ -859,6 +888,7 @@ name = "inventory-system" version = "0.1.0" dependencies = [ "async-std", + "diesel", "env_logger", "log", "rust-embed", @@ -1045,6 +1075,15 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +[[package]] +name = "pq-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b845d6d8ec554f972a2c5298aad68953fd64e7441e846075450b44656a016d1" +dependencies = [ + "vcpkg", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -1668,6 +1707,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index b53e48e..a502a92 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,5 +12,6 @@ env_logger = "0.9" async-std = "1" tide = "0.16.0" +diesel = { version = "1.4", features = ["postgres"] } rust-embed = { version = "6.2.0", features = ["interpolate-folder-path"]} diff --git a/diesel.toml b/diesel.toml new file mode 100644 index 0000000..92267c8 --- /dev/null +++ b/diesel.toml @@ -0,0 +1,5 @@ +# For documentation on how to configure this file, +# see diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "src/schema.rs" diff --git a/migrations/.gitkeep b/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/migrations/00000000000000_diesel_initial_setup/down.sql b/migrations/00000000000000_diesel_initial_setup/down.sql new file mode 100644 index 0000000..a9f5260 --- /dev/null +++ b/migrations/00000000000000_diesel_initial_setup/down.sql @@ -0,0 +1,6 @@ +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + +DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass); +DROP FUNCTION IF EXISTS diesel_set_updated_at(); diff --git a/migrations/00000000000000_diesel_initial_setup/up.sql b/migrations/00000000000000_diesel_initial_setup/up.sql new file mode 100644 index 0000000..d68895b --- /dev/null +++ b/migrations/00000000000000_diesel_initial_setup/up.sql @@ -0,0 +1,36 @@ +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + + + + +-- Sets up a trigger for the given table to automatically set a column called +-- `updated_at` whenever the row is modified (unless `updated_at` was included +-- in the modified columns) +-- +-- # Example +-- +-- ```sql +-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW()); +-- +-- SELECT diesel_manage_updated_at('users'); +-- ``` +CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ +BEGIN + EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s + FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl); +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ +BEGIN + IF ( + NEW IS DISTINCT FROM OLD AND + NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at + ) THEN + NEW.updated_at := current_timestamp; + END IF; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; diff --git a/migrations/2022-07-21-115312_create_users/down.sql b/migrations/2022-07-21-115312_create_users/down.sql new file mode 100644 index 0000000..f9bd3a3 --- /dev/null +++ b/migrations/2022-07-21-115312_create_users/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` + +DROP TABLE IF EXISTS users; diff --git a/migrations/2022-07-21-115312_create_users/up.sql b/migrations/2022-07-21-115312_create_users/up.sql new file mode 100644 index 0000000..05aef01 --- /dev/null +++ b/migrations/2022-07-21-115312_create_users/up.sql @@ -0,0 +1,6 @@ +-- Your SQL goes here + +CREATE TABLE users ( + id UUID PRIMARY KEY NOT NULL DEFAULT gen_random_uuid(), + nickname VARCHAR NOT NULL +); diff --git a/src/schema.rs b/src/schema.rs new file mode 100644 index 0000000..ba98e14 --- /dev/null +++ b/src/schema.rs @@ -0,0 +1,6 @@ +table! { + users (id) { + id -> Uuid, + nickname -> Varchar, + } +} -- 2.47.0 From 69d81446cb5984510e621c0da48cfb15d454a623 Mon Sep 17 00:00:00 2001 From: Jake Hillion Date: Fri, 22 Jul 2022 23:12:24 +0100 Subject: [PATCH 2/2] added diesel connection --- Cargo.lock | 142 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 +- build.rs | 3 + diesel.toml | 2 +- src/api.rs | 14 +++- src/db/error.rs | 10 +++ src/db/mod.rs | 24 +++++++ src/{ => db}/schema.rs | 0 src/main.rs | 15 ++++- 9 files changed, 208 insertions(+), 6 deletions(-) create mode 100644 build.rs create mode 100644 src/db/error.rs create mode 100644 src/db/mod.rs rename src/{ => db}/schema.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index ae1526c..694a124 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -539,6 +539,7 @@ dependencies = [ "byteorder", "diesel_derives", "pq-sys", + "r2d2", ] [[package]] @@ -552,6 +553,16 @@ dependencies = [ "syn", ] +[[package]] +name = "diesel_migrations" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c" +dependencies = [ + "migrations_internals", + "migrations_macros", +] + [[package]] name = "digest" version = "0.9.0" @@ -889,9 +900,11 @@ version = "0.1.0" dependencies = [ "async-std", "diesel", + "diesel_migrations", "env_logger", "log", "rust-embed", + "thiserror", "tide", ] @@ -931,6 +944,16 @@ version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.17" @@ -954,6 +977,27 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "migrations_internals" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b4fc84e4af020b837029e017966f86a1c2d5e83e64b589963d5047525995860" +dependencies = [ + "diesel", +] + +[[package]] +name = "migrations_macros" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c" +dependencies = [ + "migrations_internals", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -1001,6 +1045,29 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -1108,6 +1175,17 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r2d2" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" +dependencies = [ + "log", + "parking_lot", + "scheduled-thread-pool", +] + [[package]] name = "rand" version = "0.7.3" @@ -1281,6 +1359,21 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scheduled-thread-pool" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf" +dependencies = [ + "parking_lot", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "semver" version = "0.9.0" @@ -1433,6 +1526,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" + [[package]] name = "socket2" version = "0.4.4" @@ -1871,3 +1970,46 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/Cargo.toml b/Cargo.toml index a502a92..b6f300e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,10 +8,12 @@ edition = "2021" [dependencies] log = "0.4" env_logger = "0.9" +thiserror = "1" async-std = "1" tide = "0.16.0" -diesel = { version = "1.4", features = ["postgres"] } +diesel = { version = "1.4", features = ["postgres", "r2d2"] } +diesel_migrations = "1.4" rust-embed = { version = "6.2.0", features = ["interpolate-folder-path"]} diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..b8a52dd --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + println!("cargo:rerun-if-changed=migrations/"); +} diff --git a/diesel.toml b/diesel.toml index 92267c8..71215db 100644 --- a/diesel.toml +++ b/diesel.toml @@ -2,4 +2,4 @@ # see diesel.rs/guides/configuring-diesel-cli [print_schema] -file = "src/schema.rs" +file = "src/db/schema.rs" diff --git a/src/api.rs b/src/api.rs index 907eec1..747fb56 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,6 +1,16 @@ -pub fn serve() -> tide::Server<()> { - let mut app = tide::new(); +use std::sync::Arc; +use diesel::pg::PgConnection; +use diesel::r2d2::{ConnectionManager, Pool}; + +pub struct State { + _db: Pool>, +} + +pub fn serve(db: Pool>) -> tide::Server> { + let state = Arc::new(State { _db: db }); + + let mut app = tide::with_state(state); app.at("/hello").get(|_| async { Ok("Hello, Jake!") }); app diff --git a/src/db/error.rs b/src/db/error.rs new file mode 100644 index 0000000..4ed0b54 --- /dev/null +++ b/src/db/error.rs @@ -0,0 +1,10 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error("database pool failure: {0}")] + Pool(#[from] diesel::r2d2::PoolError), + + #[error("database migration failed: {0}")] + Migration(#[from] diesel::migration::RunMigrationsError), +} diff --git a/src/db/mod.rs b/src/db/mod.rs new file mode 100644 index 0000000..629f804 --- /dev/null +++ b/src/db/mod.rs @@ -0,0 +1,24 @@ +use log::info; + +mod error; +pub mod schema; + +use crate::embedded_migrations; +pub use error::Error; + +use std::env; + +use diesel::pg::PgConnection; +use diesel::r2d2::{ConnectionManager, Pool}; + +pub(super) fn new() -> Result>, Error> { + let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); + + let pool = Pool::new(ConnectionManager::new(database_url))?; + + info!("starting db migrations..."); + embedded_migrations::run(&pool.get()?)?; + info!("db migrations complete"); + + Ok(pool) +} diff --git a/src/schema.rs b/src/db/schema.rs similarity index 100% rename from src/schema.rs rename to src/db/schema.rs diff --git a/src/main.rs b/src/main.rs index 3c3da6e..8df6fed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ mod api; +mod db; mod react; use api::serve as serve_api; @@ -7,13 +8,23 @@ use react::serve as serve_react; use async_std::task; use std::io; +#[macro_use] +extern crate diesel; + +// embed diesel migrations +#[macro_use] +extern crate diesel_migrations; + +embed_migrations!(); + fn main() -> Result<(), io::Error> { let env = env_logger::Env::new().filter_or("LOG", "info"); env_logger::init_from_env(env); - let mut app = tide::new(); + let db = db::new().unwrap(); - app.at("/_api").nest(serve_api()); + let mut app = tide::new(); + app.at("/_api").nest(serve_api(db)); app.at("/").nest(serve_react()); task::block_on(app.listen("127.0.0.1:8080")) -- 2.47.0