Skip to main content

nil_server_database/
lib.rs

1// Copyright (C) Call of Nil contributors
2// SPDX-License-Identifier: AGPL-3.0-only
3
4#![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}