added database_pool crate, for pool handling and migrations
This commit is contained in:
parent
27d02a0d5c
commit
f60eb616d3
11 changed files with 197 additions and 0 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,3 +1,6 @@
|
||||||
|
# database
|
||||||
|
/database
|
||||||
|
|
||||||
# rust
|
# rust
|
||||||
/target
|
/target
|
||||||
|
|
||||||
|
|
|
||||||
42
Cargo.lock
generated
42
Cargo.lock
generated
|
|
@ -300,6 +300,21 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23"
|
||||||
|
dependencies = [
|
||||||
|
"crc-catalog",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc-catalog"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-queue"
|
name = "crossbeam-queue"
|
||||||
version = "0.3.8"
|
version = "0.3.8"
|
||||||
|
|
@ -383,6 +398,21 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "database"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"sqlx",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "database_pool"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"sqlx",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deunicode"
|
name = "deunicode"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
|
@ -444,6 +474,9 @@ name = "either"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
|
|
@ -485,6 +518,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||||
name = "ezidam"
|
name = "ezidam"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"database_pool",
|
||||||
"infer",
|
"infer",
|
||||||
"rocket",
|
"rocket",
|
||||||
"rocket_db_pools",
|
"rocket_db_pools",
|
||||||
|
|
@ -2058,6 +2092,8 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
"chrono",
|
||||||
|
"crc",
|
||||||
"crossbeam-queue",
|
"crossbeam-queue",
|
||||||
"either",
|
"either",
|
||||||
"event-listener",
|
"event-listener",
|
||||||
|
|
@ -2079,6 +2115,8 @@ dependencies = [
|
||||||
"paste",
|
"paste",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rustls",
|
"rustls",
|
||||||
|
"serde",
|
||||||
|
"sha2",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"sqlformat",
|
"sqlformat",
|
||||||
"sqlx-rt",
|
"sqlx-rt",
|
||||||
|
|
@ -2099,9 +2137,13 @@ dependencies = [
|
||||||
"dotenv",
|
"dotenv",
|
||||||
"either",
|
"either",
|
||||||
"heck",
|
"heck",
|
||||||
|
"hex",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"sqlx-rt",
|
"sqlx-rt",
|
||||||
"syn",
|
"syn",
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,8 @@
|
||||||
members = [
|
members = [
|
||||||
"crates/*"
|
"crates/*"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
thiserror = "1"
|
||||||
|
chrono = "0.4.23"
|
||||||
|
sqlx = "0.5.13"
|
||||||
8
crates/database_pool/Cargo.toml
Normal file
8
crates/database_pool/Cargo.toml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "database_pool"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies.sqlx]
|
||||||
|
workspace = true
|
||||||
|
features = ["sqlite", "migrate", "runtime-tokio-rustls"]
|
||||||
50
crates/database_pool/src/lib.rs
Normal file
50
crates/database_pool/src/lib.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
//! # Initialize database pool connection
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! use database_pool::Pool;
|
||||||
|
//!
|
||||||
|
//! # async fn get_database() {
|
||||||
|
//! let database = Pool::init("/path/to/database.sqlite").await.expect("Failed to init pool");
|
||||||
|
//!
|
||||||
|
//! // Close pool
|
||||||
|
//! database.close().await;
|
||||||
|
//! # }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! # Run migrations to pool
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! use database_pool::Pool;
|
||||||
|
//! use database_pool::run_migrations;
|
||||||
|
//!
|
||||||
|
//! # async fn migrations() {
|
||||||
|
//! # let database = Pool::init("/path/to/database.sqlite").await.unwrap();
|
||||||
|
//! run_migrations(&database.pool).await.expect("Failed to run migrations");
|
||||||
|
//! # }
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! # Run transaction on database
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! use database_pool::Pool;
|
||||||
|
//!
|
||||||
|
//! # async fn run_transaction() {
|
||||||
|
//! # let database = Pool::init("/path/to/database.sqlite").await.unwrap();
|
||||||
|
//! // Start transaction
|
||||||
|
//! let mut transaction = database.pool.begin().await.expect("Failed to start transaction");
|
||||||
|
//!
|
||||||
|
//! // Run functions requiring database
|
||||||
|
//!
|
||||||
|
//! // Commit transaction
|
||||||
|
//! transaction.commit().await.expect("Failed to commit transaction");
|
||||||
|
//!
|
||||||
|
//! // Do what you need :)
|
||||||
|
//!
|
||||||
|
//! # }
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
mod migrations;
|
||||||
|
mod pool;
|
||||||
|
|
||||||
|
pub use migrations::run_migrations;
|
||||||
|
pub use pool::Pool;
|
||||||
15
crates/database_pool/src/migrations.rs
Normal file
15
crates/database_pool/src/migrations.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
use sqlx::migrate::MigrateError;
|
||||||
|
use sqlx::{Pool, Sqlite};
|
||||||
|
|
||||||
|
pub async fn run_migrations(pool: &Pool<Sqlite>) -> Result<(), MigrateError> {
|
||||||
|
match sqlx::migrate!("../database").run(pool).await {
|
||||||
|
Ok(ok) => {
|
||||||
|
println!("Migrations are OK");
|
||||||
|
Ok(ok)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Failed to run migrations!");
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
crates/database_pool/src/pool.rs
Normal file
29
crates/database_pool/src/pool.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
use sqlx::sqlite::SqlitePoolOptions;
|
||||||
|
use sqlx::{Error, Pool as SqlxPool, Sqlite};
|
||||||
|
|
||||||
|
pub struct Pool {
|
||||||
|
url: String,
|
||||||
|
pub pool: SqlxPool<Sqlite>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pool {
|
||||||
|
/// Initializes a new connection pool to database
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `url` - Path to SQLite database, must be full path
|
||||||
|
pub async fn init(url: impl Into<String>) -> Result<Self, Error> {
|
||||||
|
let url = url.into();
|
||||||
|
let pool = SqlitePoolOptions::new().connect(&url).await?;
|
||||||
|
|
||||||
|
println!("SQLite pool established for `{url}`");
|
||||||
|
|
||||||
|
Ok(Self { url, pool })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Close connection pool to database
|
||||||
|
pub async fn close(&self) {
|
||||||
|
self.pool.close().await;
|
||||||
|
println!("SQLite pool closed for `{}`", self.url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,3 +8,6 @@ rocket = "0.5.0-rc.2"
|
||||||
rocket_db_pools = { version = "0.1.0-rc.2", features = ["sqlx_sqlite"] }
|
rocket_db_pools = { version = "0.1.0-rc.2", features = ["sqlx_sqlite"] }
|
||||||
rocket_dyn_templates = { version = "0.1.0-rc.2", features = ["tera"] }
|
rocket_dyn_templates = { version = "0.1.0-rc.2", features = ["tera"] }
|
||||||
infer = { version = "0.12.0", default-features = false }
|
infer = { version = "0.12.0", default-features = false }
|
||||||
|
|
||||||
|
# local crates
|
||||||
|
database_pool = { path = "../database_pool" }
|
||||||
2
crates/ezidam/Rocket.toml
Normal file
2
crates/ezidam/Rocket.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
[default.databases.ezidam]
|
||||||
|
url = "../../database/ezidam.sqlite"
|
||||||
36
crates/ezidam/src/database.rs
Normal file
36
crates/ezidam/src/database.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
use database_pool::run_migrations;
|
||||||
|
use rocket::fairing::AdHoc;
|
||||||
|
use rocket::{error, fairing, info, Build, Rocket};
|
||||||
|
use rocket_db_pools::{sqlx, Database as RocketDatabase};
|
||||||
|
|
||||||
|
#[derive(RocketDatabase)]
|
||||||
|
#[database("ezidam")]
|
||||||
|
pub struct Database(sqlx::SqlitePool);
|
||||||
|
|
||||||
|
impl Database {
|
||||||
|
pub fn rocket(rocket_builder: Rocket<Build>) -> Rocket<Build> {
|
||||||
|
rocket_builder
|
||||||
|
// Init
|
||||||
|
.attach(Self::init())
|
||||||
|
// SQL Migrations
|
||||||
|
.attach(AdHoc::try_on_ignite("SQL Startup", Self::startup))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn startup(rocket: Rocket<Build>) -> fairing::Result {
|
||||||
|
let Some(db) = Self::fetch(&rocket) else {
|
||||||
|
error!("Failed to get database");
|
||||||
|
return Err(rocket);
|
||||||
|
};
|
||||||
|
|
||||||
|
match run_migrations(&db.0).await {
|
||||||
|
Ok(()) => {
|
||||||
|
info!("Migrations ran successfully");
|
||||||
|
Ok(rocket)
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Failed to run migrations: {}", e);
|
||||||
|
Err(rocket)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod database;
|
||||||
mod shutdown;
|
mod shutdown;
|
||||||
|
|
||||||
// see for using rocket with main function https://github.com/intellij-rust/intellij-rust/issues/5975#issuecomment-920620289
|
// see for using rocket with main function https://github.com/intellij-rust/intellij-rust/issues/5975#issuecomment-920620289
|
||||||
|
|
@ -6,6 +7,9 @@ async fn main() -> std::result::Result<(), rocket::Error> {
|
||||||
// Build server
|
// Build server
|
||||||
let rocket_builder = rocket::build();
|
let rocket_builder = rocket::build();
|
||||||
|
|
||||||
|
// Database
|
||||||
|
let rocket_builder = database::Database::rocket(rocket_builder);
|
||||||
|
|
||||||
// Shutdown
|
// Shutdown
|
||||||
let rocket_builder = shutdown::shutdown(rocket_builder);
|
let rocket_builder = shutdown::shutdown(rocket_builder);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue