use std::sync::Arc; use diesel::r2d2::{ConnectionManager, Pool}; use diesel::SqliteConnection; use minijinja_autoreload::AutoReloader; use thiserror::Error; use crate::handler::internal_server_error; use crate::prelude::*; pub type ConnectionPool = Pool>; pub type PooledConnection = diesel::r2d2::PooledConnection>; #[derive(Clone)] pub struct Provider { pub db_pool: ConnectionPool, template_loader: Arc, } #[derive(Error, Debug)] pub enum ProviderError { #[error("Error while using the connection pool: {0}")] R2D2Error(#[from] diesel::r2d2::PoolError), } impl Provider { pub fn new(db: ConnectionPool, template_loader: AutoReloader) -> Provider { Provider { db_pool: db, template_loader: Arc::new(template_loader), } } pub fn db_conn(&self) -> Result { let conn = self.db_pool.get()?; Ok(conn) } pub fn render(&self, path: &str, data: T) -> anyhow::Result { // TODO: more graceful handling of the potential errors here; this should not // use anyhow let env = self.template_loader.acquire_env().unwrap(); let template = env.get_template(path)?; let rendered = template.render(data)?; Ok(rendered) } pub fn render_resp(&self, path: &str, data: T) -> Response { let rendered = self.render(path, data); match rendered { Ok(rendered) => Html(rendered).into_response(), Err(err) => { error!(?err, "error while rendering template"); internal_server_error() } } } }