Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add diesel-async support for shuttle-aws-rds #1808

Merged
merged 3 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions resources/aws-rds/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ keywords = ["shuttle-service", "rds"]

[dependencies]
async-trait = "0.1.56"
diesel-async = { version = "0.4.1", optional = true }
paste = "1.0.7"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Expand All @@ -19,9 +20,14 @@ sqlx = { version = "0.7.1", optional = true }
default = []

# Database
postgres = ["sqlx?/postgres"]
mysql = ["sqlx?/mysql"]
mariadb = ["sqlx?/mysql"]
postgres = ["sqlx?/postgres", "diesel-async?/postgres"]
mysql = ["sqlx?/mysql", "diesel-async?/mysql"]
mariadb = ["sqlx?/mysql", "diesel-async?/mysql"]

# Databases with diesel-async support
diesel-async = ["dep:diesel-async"]
diesel-async-bb8 = [ "diesel-async", "diesel-async/bb8" ]
diesel-async-deadpool = [ "diesel-async", "diesel-async/deadpool" ]

# Add an sqlx Pool as a resource output type
sqlx = ["dep:sqlx", "sqlx/runtime-tokio", "sqlx/tls-rustls"]
Expand Down
136 changes: 132 additions & 4 deletions resources/aws-rds/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ use shuttle_service::{
DatabaseResource, DbInput, Error, IntoResource, ResourceFactory, ResourceInputBuilder,
};

#[cfg(any(feature = "diesel-async-bb8", feature = "diesel-async-deadpool"))]
use diesel_async::pooled_connection::AsyncDieselConnectionManager;

#[cfg(feature = "diesel-async-bb8")]
use diesel_async::pooled_connection::bb8 as diesel_bb8;

#[cfg(feature = "diesel-async-deadpool")]
use diesel_async::pooled_connection::deadpool as diesel_deadpool;

#[allow(dead_code)]
const MIN_CONNECTIONS: u32 = 1;
#[allow(dead_code)]
const MAX_CONNECTIONS: u32 = 5;

macro_rules! aws_engine {
($feature:expr, $struct_ident:ident) => {
paste::paste! {
Expand Down Expand Up @@ -76,6 +90,120 @@ impl IntoResource<String> for OutputWrapper {
}

// If these were done in the main macro above, this would produce two conflicting `impl IntoResource<sqlx::MySqlPool>`

#[cfg(feature = "diesel_async")]
mod _diesel_async {
use super::*;

#[cfg(feature = "postgres")]
#[async_trait]
impl IntoResource<diesel_async::AsyncPgConnection> for OutputWrapper {
async fn into_resource(self) -> Result<diesel_async::AsyncPgConnection, Error> {
use diesel_async::{AsyncConnection, AsyncPgConnection};

let connection_string: String = self.into_resource().await.unwrap();
Ok(AsyncPgConnection::establish(&connection_string)
.await
.map_err(shuttle_service::error::CustomError::new)?)
}
}

#[cfg(any(feature = "mysql", feature = "mariadb"))]
#[async_trait]
impl IntoResource<diesel_async::AsyncMysqlConnection> for OutputWrapper {
async fn into_resource(self) -> Result<diesel_async::AsyncMysqlConnection, Error> {
use diesel_async::{AsyncConnection, AsyncPgConnection};

let connection_string: String = self.into_resource().await.unwrap();
Ok(AsyncPgConnection::establish(&connection_string)
.await
.map_err(shuttle_service::error::CustomError::new)?)
}
}
}

#[cfg(feature = "diesel-async-bb8")]
mod _diesel_async_bb8 {
use super::*;

#[cfg(feature = "postgres")]
#[async_trait]
impl IntoResource<diesel_bb8::Pool<diesel_async::AsyncPgConnection>> for OutputWrapper {
async fn into_resource(
self,
) -> Result<diesel_bb8::Pool<diesel_async::AsyncPgConnection>, Error> {
let connection_string: String = self.into_resource().await.unwrap();

Ok(diesel_bb8::Pool::builder()
.min_idle(Some(MIN_CONNECTIONS))
.max_size(MAX_CONNECTIONS)
.build(AsyncDieselConnectionManager::new(connection_string))
.await
.map_err(shuttle_service::error::CustomError::new)?)
}
}

#[cfg(any(feature = "mysql", feature = "mariadb"))]
#[async_trait]
impl IntoResource<diesel_bb8::Pool<diesel_async::AsyncMysqlConnection>> for OutputWrapper {
async fn into_resource(
self,
) -> Result<diesel_bb8::Pool<diesel_async::AsyncMysqlConnection>, Error> {
let connection_string: String = self.into_resource().await.unwrap();

Ok(diesel_bb8::Pool::builder()
.min_idle(Some(MIN_CONNECTIONS))
.max_size(MAX_CONNECTIONS)
.build(AsyncDieselConnectionManager::new(connection_string))
.await
.map_err(shuttle_service::error::CustomError::new)?)
}
}
}

#[cfg(feature = "diesel-async-deadpool")]
mod _diesel_async_deadpool {
use super::*;

#[cfg(feature = "postgres")]
#[async_trait]
impl IntoResource<diesel_deadpool::Pool<diesel_async::AsyncPgConnection>> for OutputWrapper {
async fn into_resource(
self,
) -> Result<diesel_deadpool::Pool<diesel_async::AsyncPgConnection>, Error> {
let connection_string: String = self.into_resource().await.unwrap();

Ok(
diesel_deadpool::Pool::builder(AsyncDieselConnectionManager::new(
connection_string,
))
.max_size(MAX_CONNECTIONS as usize)
.build()
.map_err(shuttle_service::error::CustomError::new)?,
)
}
}

#[cfg(any(feature = "mysql", feature = "mariadb"))]
#[async_trait]
impl IntoResource<diesel_deadpool::Pool<diesel_async::AsyncMysqlConnection>> for OutputWrapper {
async fn into_resource(
self,
) -> Result<diesel_deadpool::Pool<diesel_async::AsyncMysqlConnection>, Error> {
let connection_string: String = self.into_resource().await.unwrap();

Ok(
diesel_deadpool::Pool::builder(AsyncDieselConnectionManager::new(
connection_string,
))
.max_size(MAX_CONNECTIONS as usize)
.build()
.map_err(shuttle_service::error::CustomError::new)?,
)
}
}
}

#[cfg(feature = "sqlx")]
mod _sqlx {
use super::*;
Expand All @@ -87,8 +215,8 @@ mod _sqlx {
let connection_string: String = self.into_resource().await.unwrap();

Ok(sqlx::postgres::PgPoolOptions::new()
.min_connections(1)
.max_connections(5)
.min_connections(MIN_CONNECTIONS)
.max_connections(MAX_CONNECTIONS)
.connect(&connection_string)
.await
.map_err(shuttle_service::error::CustomError::new)?)
Expand All @@ -102,8 +230,8 @@ mod _sqlx {
let connection_string: String = self.into_resource().await.unwrap();

Ok(sqlx::mysql::MySqlPoolOptions::new()
.min_connections(1)
.max_connections(5)
.min_connections(MIN_CONNECTIONS)
.max_connections(MAX_CONNECTIONS)
.connect(&connection_string)
.await
.map_err(shuttle_service::error::CustomError::new)?)
Expand Down