nil_server_database/
lib.rs1#![cfg_attr(docsrs, feature(doc_cfg))]
5#![doc(html_favicon_url = "https://nil.dev.br/favicon.png")]
6#![feature(
7 const_clone,
8 const_cmp,
9 const_convert,
10 const_trait_impl,
11 derive_const,
12 str_as_str
13)]
14
15pub mod error;
16mod r#impl;
17mod migration;
18pub mod model;
19mod schema;
20pub mod sql_types;
21
22use crate::error::Result;
23use crate::migration::run_pending_migrations;
24use diesel::{SqliteConnection, sql_query};
25use diesel_async::RunQueryDsl;
26use diesel_async::pooled_connection::AsyncDieselConnectionManager;
27use diesel_async::pooled_connection::deadpool::{Hook, HookError, Pool};
28use diesel_async::sync_connection_wrapper::SyncConnectionWrapper;
29use std::borrow::Cow;
30
31type Conn = SyncConnectionWrapper<SqliteConnection>;
32
33#[must_use]
34#[derive(Clone)]
35pub struct Database {
36 pool: Pool<Conn>,
37}
38
39impl Database {
40 pub fn new(url: &str) -> Result<Self> {
41 run_pending_migrations(url)?;
42 let manager = AsyncDieselConnectionManager::new(url);
43 let pool = Pool::builder(manager)
44 .max_size(4)
45 .post_create(Hook::async_fn(move |conn: &mut Conn, _| {
46 Box::pin(async move {
47 execute(conn, "PRAGMA journal_mode=WAL;").await?;
48 execute(conn, "PRAGMA synchronous=NORMAL;").await?;
49 execute(conn, "PRAGMA busy_timeout=5000;").await?;
50 execute(conn, "PRAGMA foreign_keys=ON;").await?;
51 Ok(())
52 })
53 }))
54 .build()?;
55
56 Ok(Self { pool })
57 }
58}
59
60#[doc(hidden)]
61#[macro_export]
62macro_rules! conn {
63 ($database:expr) => {
64 &mut *$database.pool.get().await?
65 };
66}
67
68async fn execute(conn: &mut Conn, query: &str) -> Result<(), HookError> {
69 sql_query(query)
70 .execute(conn)
71 .await
72 .map_err(|err| HookError::Message(Cow::Owned(err.to_string())))?;
73
74 Ok(())
75}