diff options
Diffstat (limited to 'rust/src/server.rs')
-rw-r--r-- | rust/src/server.rs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/rust/src/server.rs b/rust/src/server.rs new file mode 100644 index 00000000..70e667be --- /dev/null +++ b/rust/src/server.rs @@ -0,0 +1,81 @@ +//! API endpoint handlers + +use crate::auth::*; +use crate::errors::*; +use chrono; +use diesel; +use diesel::pg::PgConnection; +use diesel::r2d2::ConnectionManager; +use dotenv::dotenv; +use rand::Rng; +use std::process::Command; +use std::{env, thread, time}; + +#[cfg(feature = "postgres")] +embed_migrations!("../migrations/"); + +pub type ConnectionPool = diesel::r2d2::Pool<ConnectionManager<diesel::pg::PgConnection>>; + +pub type DbConn = + diesel::r2d2::PooledConnection<diesel::r2d2::ConnectionManager<diesel::PgConnection>>; + +/// Instantiate a new API server with a pooled database connection +pub fn database_worker_pool() -> Result<ConnectionPool> { + dotenv().ok(); + let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); + let manager = ConnectionManager::<PgConnection>::new(database_url); + let pool = diesel::r2d2::Pool::builder() + .build(manager) + .expect("Failed to create database pool."); + Ok(pool) +} + +#[derive(Clone)] +pub struct Server { + pub db_pool: ConnectionPool, + pub auth_confectionary: AuthConfectionary, +} + +/// Instantiate a new API server with a pooled database connection +pub fn create_server() -> Result<Server> { + dotenv().ok(); + let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); + let manager = ConnectionManager::<PgConnection>::new(database_url); + let pool = diesel::r2d2::Pool::builder() + .build(manager) + .expect("Failed to create database pool."); + let confectionary = env_confectionary()?; + Ok(Server { + db_pool: pool, + auth_confectionary: confectionary, + }) +} + +/// Generates a server for testing. Calls an external bash script to generate a random postgres +/// database, which will be unique to this process but common across threads and connections. The +/// database will automagically get cleaned up (deleted) after 60 seconds. +/// Currently, start times are staggered by up to 200ms to prevent internal postgres concurrency +/// errors; if this fails run the tests serially (one at a time), which is slower but more robust. +/// CI should run tests serially. +pub fn create_test_server() -> Result<Server> { + dotenv().ok(); + // sleep a bit so we don't have thundering herd collisions, resuliting in + // "pg_extension_name_index" or "pg_proc_proname_args_nsp_index" or "pg_type_typname_nsp_index" + // duplicate key violations. + thread::sleep(time::Duration::from_millis( + rand::thread_rng().gen_range(0, 200), + )); + let pg_tmp = Command::new("./tests/pg_tmp.sh") + .output() + .expect("run ./tests/pg_tmp.sh to get temporary postgres DB"); + let database_url = String::from_utf8_lossy(&pg_tmp.stdout).to_string(); + env::set_var("DATABASE_URL", database_url); + + let mut server = create_server()?; + server.auth_confectionary = AuthConfectionary::new_dummy(); + let conn = server.db_pool.get().expect("db_pool error"); + + // run migrations; this is a fresh/bare database + diesel_migrations::run_pending_migrations(&conn).unwrap(); + Ok(server) +} |