diff --git a/src/server/database.rs b/src/server/database.rs new file mode 100644 index 0000000..38b53f0 --- /dev/null +++ b/src/server/database.rs @@ -0,0 +1,40 @@ +use diesel_async::{ + AsyncMigrationHarness, AsyncPgConnection, + pooled_connection::{AsyncDieselConnectionManager, deadpool::Pool}, +}; +use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations}; + +use crate::util::error::{Contextualize, Error, ErrorType}; + +pub const DB_MIGRATIONS: EmbeddedMigrations = embed_migrations!(); + +pub type DbPool = Pool; + +/// Connect to the database using the given URI, and perform migrations +pub async fn setup>(database_uri: S) -> Result { + let pool_manager = AsyncDieselConnectionManager::::new(database_uri); + + let pool = Pool::builder(pool_manager) + .build() + // At time of writing only the `NoRuntimeSpecified` error is possible from the builder, + // which should only occur when configuring timeouts without a `Runtime` + .map_err(|e| ErrorType::Database(e.to_string())) + .err_context("Error creating pool for database connections")?; + + tracing::debug!("Establishing connection to database for migrations..."); + + let migration_conn = pool + .get() + .await + .map_err(|e| ErrorType::Database(e.to_string())) + .err_context("Failed to get connection to database")?; + + tracing::debug!("Running migrations..."); + + AsyncMigrationHarness::new(migration_conn) + .run_pending_migrations(DB_MIGRATIONS) + .map_err(|e| ErrorType::Database(e.to_string())) + .err_context("Failed to run pending database migrations")?; + + Ok(pool) +} diff --git a/src/server/mod.rs b/src/server/mod.rs index aa12a48..550751f 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,4 +1,5 @@ pub mod config; +pub mod database; pub mod main; pub use main::main;