Add database module
This commit is contained in:
parent
e91fd0f2bf
commit
c4c5ef0027
7 changed files with 185 additions and 72 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
@ -775,6 +775,7 @@ name = "dpts"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dpts-csv",
|
"dpts-csv",
|
||||||
|
"dpts-database",
|
||||||
"dpts-entity",
|
"dpts-entity",
|
||||||
"dpts-error",
|
"dpts-error",
|
||||||
"dpts-migration",
|
"dpts-migration",
|
||||||
|
@ -800,6 +801,21 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dpts-database"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"async-graphql",
|
||||||
|
"axum",
|
||||||
|
"chrono",
|
||||||
|
"dotenv",
|
||||||
|
"dpts-entity",
|
||||||
|
"dpts-migration",
|
||||||
|
"log",
|
||||||
|
"sea-orm",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dpts-entity"
|
name = "dpts-entity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -808,6 +824,7 @@ dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"chrono",
|
"chrono",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
|
"dpts-database",
|
||||||
"dpts-migration",
|
"dpts-migration",
|
||||||
"log",
|
"log",
|
||||||
"sea-orm",
|
"sea-orm",
|
||||||
|
|
|
@ -10,6 +10,7 @@ dpts-csv = { workspace = true }
|
||||||
dpts-entity = { workspace = true }
|
dpts-entity = { workspace = true }
|
||||||
dpts-error = { workspace = true }
|
dpts-error = { workspace = true }
|
||||||
dpts-migration = { workspace = true }
|
dpts-migration = { workspace = true }
|
||||||
|
dpts-database = { workspace = true }
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [".", "dpts-*"]
|
members = [".", "dpts-*"]
|
||||||
|
@ -17,13 +18,14 @@ members = [".", "dpts-*"]
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
dpts = { path = "." }
|
dpts = { path = "." }
|
||||||
dpts-csv = { path = "dpts-csv" }
|
dpts-csv = { path = "dpts-csv" }
|
||||||
|
dpts-database = { path = "dpts-database" }
|
||||||
dpts-entity = { path = "dpts-entity" }
|
dpts-entity = { path = "dpts-entity" }
|
||||||
dpts-error = { path = "dpts-error" }
|
dpts-error = { path = "dpts-error" }
|
||||||
dpts-migration = {path = "dpts-migration"}
|
dpts-migration = {path = "dpts-migration"}
|
||||||
chrono = {version = "0.4", features = ["serde"]}
|
chrono = {version = "0.4", features = ["serde"]}
|
||||||
clap = "4.5"
|
clap = "4.5"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
serde = "1.0.219"
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
31
dpts-database/Cargo.toml
Normal file
31
dpts-database/Cargo.toml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
[package]
|
||||||
|
name = "dpts-database"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
test = []
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
dpts-entity = { workspace = true }
|
||||||
|
dpts-migration = { workspace = true }
|
||||||
|
async-graphql = {version = "7.0", features = ["chrono"]}
|
||||||
|
axum = "0.8"
|
||||||
|
chrono = {workspace = true}
|
||||||
|
dotenv = {workspace = true}
|
||||||
|
log = "0.4.27"
|
||||||
|
tokio = "1.44.2"
|
||||||
|
|
||||||
|
[dependencies.sea-orm]
|
||||||
|
version = "1.1"
|
||||||
|
features = [
|
||||||
|
"macros",
|
||||||
|
"debug-print",
|
||||||
|
"runtime-tokio-native-tls",
|
||||||
|
"sqlx-sqlite",
|
||||||
|
"with-chrono",
|
||||||
|
]
|
||||||
|
default-features = false
|
123
dpts-database/src/connection.rs
Normal file
123
dpts-database/src/connection.rs
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
use sea_orm::{entity::*, query::*, ConnectOptions, Database, DatabaseConnection};
|
||||||
|
use dpts_migration::{Migrator, MigratorTrait};
|
||||||
|
|
||||||
|
|
||||||
|
use tokio::sync::OnceCell;
|
||||||
|
|
||||||
|
pub struct OnceDatabaseConnection {
|
||||||
|
inner: OnceCell<DatabaseConnection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OnceDatabaseConnection {
|
||||||
|
const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: OnceCell::const_new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn get(&self) -> Option<&DatabaseConnection> {
|
||||||
|
self.inner.get()
|
||||||
|
}
|
||||||
|
pub async fn get_or_init<F, T>(&self, f: F) -> &DatabaseConnection where
|
||||||
|
F: FnOnce() -> T,
|
||||||
|
T: Future<Output = DatabaseConnection>
|
||||||
|
{
|
||||||
|
self.inner.get_or_init(f).await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub async fn init_test(&self) {
|
||||||
|
self.get_or_init( || async {
|
||||||
|
let mut opt = ConnectOptions::new("sqlite::memory:");
|
||||||
|
opt.max_connections(100)
|
||||||
|
.min_connections(5)
|
||||||
|
.connect_timeout(Duration::from_secs(8))
|
||||||
|
.acquire_timeout(Duration::from_secs(8))
|
||||||
|
.idle_timeout(Duration::from_secs(8))
|
||||||
|
.max_lifetime(Duration::from_secs(8))
|
||||||
|
.sqlx_logging(true)
|
||||||
|
.sqlx_logging_level(log::LevelFilter::Info);
|
||||||
|
//.set_schema_search_path("my_schema"); // Setting default PostgreSQL schema
|
||||||
|
let db = Database::connect(opt).await.unwrap();
|
||||||
|
Migrator::fresh(&db).await.unwrap();
|
||||||
|
db
|
||||||
|
}).await;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static DATABASE_CONNECTION: OnceDatabaseConnection = OnceDatabaseConnection::new();
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
|
use chrono::{offset, FixedOffset, Local, TimeZone};
|
||||||
|
use sea_orm::{entity::*, query::*, ConnectOptions, Database};
|
||||||
|
use dpts_migration::{Migrator, MigratorTrait};
|
||||||
|
use dpts_entity::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn check_database_connection() {
|
||||||
|
DATABASE_CONNECTION.init_test().await;
|
||||||
|
let db = DATABASE_CONNECTION.get().unwrap();
|
||||||
|
assert!(db.ping().await.is_ok());
|
||||||
|
}
|
||||||
|
#[tokio::test]
|
||||||
|
async fn check_insert_entity() {
|
||||||
|
DATABASE_CONNECTION.init_test().await;
|
||||||
|
let db = DATABASE_CONNECTION.get().unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
let local_date_time = Local::now();
|
||||||
|
let offset_date_time = local_date_time.with_timezone(local_date_time.offset());
|
||||||
|
|
||||||
|
let user = UserActiveModel{
|
||||||
|
login_name: Set("admin".to_owned()),
|
||||||
|
password_hash: Set("admin".to_owned()),
|
||||||
|
created_at: Set(offset_date_time),
|
||||||
|
updated_at: Set(offset_date_time),
|
||||||
|
..Default::default()
|
||||||
|
}.insert(db)
|
||||||
|
.await.unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
let record_tag = RecordTagActiveModel{
|
||||||
|
user_id: Set(user.id),
|
||||||
|
name: Set("test".to_owned()),
|
||||||
|
..Default::default()
|
||||||
|
}.insert(db)
|
||||||
|
.await.unwrap();
|
||||||
|
|
||||||
|
let record_header = RecordHeaderActiveModel{
|
||||||
|
user_id: Set(user.id),
|
||||||
|
created_at: Set(offset_date_time),
|
||||||
|
updated_at: Set(offset_date_time),
|
||||||
|
recorded_at: Set(offset_date_time),
|
||||||
|
comment: Set("".to_owned()),
|
||||||
|
..Default::default()
|
||||||
|
}.insert(db)
|
||||||
|
.await.unwrap();
|
||||||
|
|
||||||
|
RecordDetailActiveModel {
|
||||||
|
record_header_id: Set(record_header.id),
|
||||||
|
record_tag_id: Set(record_tag.id),
|
||||||
|
count: Set(1),
|
||||||
|
..Default::default()
|
||||||
|
}.insert(db)
|
||||||
|
.await.unwrap();
|
||||||
|
RecordDetailActiveModel {
|
||||||
|
record_header_id: Set(record_header.id),
|
||||||
|
record_tag_id: Set(record_tag.id),
|
||||||
|
count: Set(2),
|
||||||
|
..Default::default()
|
||||||
|
}.insert(db)
|
||||||
|
.await.unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
Migrator::reset(db).await.unwrap();
|
||||||
|
db.clone().close().await.unwrap();
|
||||||
|
}
|
||||||
|
}
|
7
dpts-database/src/lib.rs
Normal file
7
dpts-database/src/lib.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
mod connection;
|
||||||
|
|
||||||
|
pub use connection::*;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ axum = "0.8"
|
||||||
chrono = {workspace = true}
|
chrono = {workspace = true}
|
||||||
dotenv = {workspace = true}
|
dotenv = {workspace = true}
|
||||||
log = "0.4.27"
|
log = "0.4.27"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { workspace = true }
|
||||||
tokio = "1.44.2"
|
tokio = "1.44.2"
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
|
@ -25,3 +25,6 @@ features = [
|
||||||
"with-chrono",
|
"with-chrono",
|
||||||
]
|
]
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
dpts-database = { workspace = true, features = ["test"] }
|
|
@ -1,70 +0,0 @@
|
||||||
use std::time::Duration;
|
|
||||||
use chrono::{offset, FixedOffset, Local, TimeZone};
|
|
||||||
use sea_orm::{entity::*, query::*, ConnectOptions, Database};
|
|
||||||
use dpts_migration::{Migrator, MigratorTrait};
|
|
||||||
use dpts_entity::*;
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn main() {
|
|
||||||
let mut opt = ConnectOptions::new("sqlite::memory:");
|
|
||||||
opt.max_connections(100)
|
|
||||||
.min_connections(5)
|
|
||||||
.connect_timeout(Duration::from_secs(8))
|
|
||||||
.acquire_timeout(Duration::from_secs(8))
|
|
||||||
.idle_timeout(Duration::from_secs(8))
|
|
||||||
.max_lifetime(Duration::from_secs(8))
|
|
||||||
.sqlx_logging(true)
|
|
||||||
.sqlx_logging_level(log::LevelFilter::Info);
|
|
||||||
//.set_schema_search_path("my_schema"); // Setting default PostgreSQL schema
|
|
||||||
let db= Database::connect(opt).await.unwrap();
|
|
||||||
Migrator::fresh(&db).await.unwrap();
|
|
||||||
|
|
||||||
let local_date_time = Local::now();
|
|
||||||
let offset_date_time = local_date_time.with_timezone(local_date_time.offset());
|
|
||||||
|
|
||||||
let user = UserActiveModel{
|
|
||||||
login_name: Set("admin".to_owned()),
|
|
||||||
password_hash: Set("admin".to_owned()),
|
|
||||||
created_at: Set(offset_date_time),
|
|
||||||
updated_at: Set(offset_date_time),
|
|
||||||
..Default::default()
|
|
||||||
}.insert(&db)
|
|
||||||
.await.unwrap();
|
|
||||||
|
|
||||||
|
|
||||||
let record_tag = RecordTagActiveModel{
|
|
||||||
user_id: Set(user.id),
|
|
||||||
name: Set("test".to_owned()),
|
|
||||||
..Default::default()
|
|
||||||
}.insert(&db)
|
|
||||||
.await.unwrap();
|
|
||||||
|
|
||||||
let record_header = RecordHeaderActiveModel{
|
|
||||||
user_id: Set(user.id),
|
|
||||||
created_at: Set(offset_date_time),
|
|
||||||
updated_at: Set(offset_date_time),
|
|
||||||
recorded_at: Set(offset_date_time),
|
|
||||||
comment: Set("".to_owned()),
|
|
||||||
..Default::default()
|
|
||||||
}.insert(&db)
|
|
||||||
.await.unwrap();
|
|
||||||
|
|
||||||
RecordDetailActiveModel {
|
|
||||||
record_header_id: Set(record_header.id),
|
|
||||||
record_tag_id: Set(record_tag.id),
|
|
||||||
count: Set(1),
|
|
||||||
..Default::default()
|
|
||||||
}.insert(&db)
|
|
||||||
.await.unwrap();
|
|
||||||
RecordDetailActiveModel {
|
|
||||||
record_header_id: Set(record_header.id),
|
|
||||||
record_tag_id: Set(record_tag.id),
|
|
||||||
count: Set(2),
|
|
||||||
..Default::default()
|
|
||||||
}.insert(&db)
|
|
||||||
.await.unwrap();
|
|
||||||
|
|
||||||
|
|
||||||
Migrator::reset(&db).await.unwrap();
|
|
||||||
db.close().await.unwrap();
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue