Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
chrislearn committed Jan 16, 2025
1 parent 5fd2563 commit 908a940
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 9 deletions.
3 changes: 2 additions & 1 deletion template/_base/Cargo.toml.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ rust-version = "1.80"
readme = "./README.md"

[dependencies]
anyhow = "1.0.79",
anyhow = "1.0.79"
figment = "0.10.8"
jsonwebtoken = "9.2.0"
once_cell = "1.19.0"
rust-embed = "8.0.0"
Expand Down
1 change: 1 addition & 0 deletions template/_base/src/config.rs.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use serde::Deserialize;
use std::{fs::File, io::Read, path::Path};


pub static CONFIG: OnceLock<ServerConfig> = OnceLock::new();

#[derive(Clone, Debug, Deserialize)]
pub struct ServerConfig {
Expand Down
42 changes: 34 additions & 8 deletions template/_base/src/main.rs.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,61 @@ mod db;
mod dtos;
mod services;
mod utils;
{% if db_type == "mongodb" %}
mod entities;
{% endif %}
{% if db_lib == "diesel" %}
mod schema;
{% endif %}
mod hoops;
mod routers;

use config::ServerConfig;

pub fn config() -> &'static ServerConfig {
&*crate::config::CONFIG
}

#[tokio::main]
async fn main() {

if let Err(e) = dotenv() {
println!("dotenv error: {:?}", e);
}

let raw_config = Figment::new()
.merge(Toml::file(Env::var("PALPO_CONFIG").as_deref().unwrap_or("palpo.toml")))
.merge(Env::prefixed("PALPO_").global());
.merge(Toml::file(Env::var("APP_CONFIG").as_deref().unwrap_or("config.toml")))
.merge(Env::prefixed("APP_").global());


let conf = match raw_config.extract::<ServerConfig>() {
let config = match raw_config.extract::<ServerConfig>() {
Ok(s) => s,
Err(e) => {
eprintln!("It looks like your config is invalid. The following error occurred: {e}");
std::process::exit(1);
}
};

{% if db_lib == "diesel" %}
let thread_pool = Arc::new(ScheduledThreadPool::new(conf.db.helper_threads));

let db_primary = {
let db_connection_config = ConnectionConfig {
statement_timeout: conf.db.statement_timeout,
};

let db_config = r2d2::Pool::builder()
.max_size(conf.db.pool_size)
.min_idle(conf.db.min_idle)
.connection_timeout(Duration::from_millis(conf.db.connection_timeout))
.connection_customizer(Box::new(db_connection_config))
.thread_pool(thread_pool.clone());

DieselPool::new(&conf.db.url, &conf.db, db_config).unwrap()
};
crate::db::DIESEL_POOL
.set(db_primary)
.expect("diesel pool should be set");
{% endif %}

crate::config::CONFIG.set(config).expect("config should be set");
crate::db::migrate();

//{{main_log_message}}
let _guard = clia_tracing_config::build()
.filter_level(&CFG.log.filter_level)
Expand Down
File renamed without changes.
82 changes: 82 additions & 0 deletions template/diesel/src/db/pool.rs.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@

use std::ops::Deref;
use std::time::Duration;

use diesel::prelude::*;
use diesel::r2d2::{self, ConnectionManager, CustomizeConnection, State};
use thiserror::Error;

use super::connection_url;
use crate::config::DbConfig;

pub type PgPool = r2d2::Pool<ConnectionManager<PgConnection>>;
pub type PgPooledConnection = r2d2::PooledConnection<ConnectionManager<PgConnection>>;

#[derive(Clone, Debug)]
pub struct DieselPool {
inner: PgPool,
}

impl DieselPool {
pub(crate) fn new(
url: &String,
config: &DbConfig,
r2d2_config: r2d2::Builder<ConnectionManager<PgConnection>>,
) -> Result<DieselPool, PoolError> {
let manager = ConnectionManager::new(connection_url(config, url));

let pool = DieselPool {
inner: r2d2_config.build_unchecked(manager),
};
match pool.wait_until_healthy(Duration::from_secs(5)) {
Ok(()) => {}
Err(PoolError::UnhealthyPool) => {}
Err(err) => return Err(err),
}

Ok(pool)
}

pub fn new_background_worker(inner: r2d2::Pool<ConnectionManager<PgConnection>>) -> Self {
Self { inner }
}

pub fn get(&self) -> Result<PgPooledConnection, PoolError> {
Ok(self.inner.get()?)
}

pub fn state(&self) -> State {
self.inner.state()
}

#[instrument(skip_all)]
pub fn wait_until_healthy(&self, timeout: Duration) -> Result<(), PoolError> {
match self.inner.get_timeout(timeout) {
Ok(_) => Ok(()),
Err(_) if !self.is_healthy() => Err(PoolError::UnhealthyPool),
Err(err) => Err(PoolError::R2D2(err)),
}
}

fn is_healthy(&self) -> bool {
self.state().connections > 0
}
}

impl Deref for DieselPool {
type Target = PgPool;

fn deref(&self) -> &Self::Target {
&self.inner
}
}

#[derive(Debug, Error)]
pub enum PoolError {
#[error(transparent)]
R2D2(#[from] r2d2::PoolError),
#[error("unhealthy database pool")]
UnhealthyPool,
#[error("Failed to lock test database connection")]
TestConnectionUnavailable,
}

0 comments on commit 908a940

Please sign in to comment.