Skip to content
This repository has been archived by the owner on Apr 3, 2024. It is now read-only.

Upgrade to Shuttle v0.39 #12

Merged
merged 3 commits into from
Feb 20, 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
43 changes: 43 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Check

on:
pull_request:
push:
branches: main

env:
CARGO_TERM_COLOR: always

jobs:
formatting:
runs-on: "ubuntu-latest"
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "stable"
components: rustfmt
- run: cargo fmt --check

check:
runs-on: "ubuntu-latest"
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "stable"
- uses: taiki-e/install-action@cargo-hack
- uses: Swatinem/rust-cache@v2
- run: cargo hack check --feature-powerset

test:
runs-on: "ubuntu-latest"
needs: check
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "stable"
- uses: taiki-e/install-action@cargo-hack
- uses: Swatinem/rust-cache@v2
- run: cargo hack test --feature-powerset --skip debug_trace
12 changes: 8 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ version = "0.1.0"
edition = "2021"

[dependencies]
async-trait = "0.1.71"
diesel-async = { version = "0.4.1", features = ["postgres", "deadpool"] }
serde = { version = "1.0.171", features = ["derive"] }
shuttle-service = { version = "0.36.0", default-features = false }
async-trait = "0.1.77"
diesel-async = { version = "0.4.1", features = ["postgres"] }
serde = { version = "1.0.197", features = ["derive"] }
shuttle-service = { version = "0.39.0", default-features = false }

[features]
bb8 = ["diesel-async/bb8"]
deadpool = ["diesel-async/deadpool"]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# shuttle-diesel-async

`diesel-async` resource for Shuttle services exporting a compatible crate for migrations.
`diesel-async` resource for Shuttle services

## License

Expand Down
101 changes: 70 additions & 31 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
use async_trait::async_trait;
use diesel_async::{
pooled_connection::{deadpool::Pool, AsyncDieselConnectionManager},
AsyncPgConnection,
};
use serde::Serialize;
use diesel_async::{AsyncConnection, AsyncPgConnection};
use serde::{Deserialize, Serialize};
use shuttle_service::{
database::{SharedEngine, Type as DatabaseType},
DbInput, DbOutput, Factory, ResourceBuilder, Type,
resource::Type,
DatabaseResource, DbInput, Factory, IntoResource, ResourceBuilder,
};

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

#[cfg(feature = "bb8")]
use diesel_async::pooled_connection::bb8;

#[cfg(feature = "deadpool")]
use diesel_async::pooled_connection::deadpool;

pub use diesel_async;

#[cfg(any(feature = "bb8", feature = "deadpool"))]
const MAX_POOL_SIZE: usize = 5;

#[derive(Default, Serialize)]
#[derive(Deserialize, Serialize)]
#[serde(transparent)]
pub struct Wrapper(DatabaseResource);

#[derive(Default)]
pub struct Postgres {
#[serde(flatten)]
db_input: DbInput,
}

Expand All @@ -29,52 +40,80 @@ impl Postgres {
}
}

fn get_connection_string(db_output: &DbOutput) -> String {
#[inline]
#[cfg(any(feature = "bb8", feature = "deadpool"))]
fn get_pool_manager(
db_output: &DatabaseResource,
) -> AsyncDieselConnectionManager<AsyncPgConnection> {
AsyncDieselConnectionManager::new(get_connection_string(db_output))
}

#[inline]
fn get_connection_string(db_output: &DatabaseResource) -> String {
match db_output {
DbOutput::Info(ref info) => info.connection_string_private(),
DbOutput::Local(ref local) => local.clone(),
DatabaseResource::ConnectionString(conn_str) => conn_str.clone(),
DatabaseResource::Info(info) => info.connection_string_shuttle(),
}
}

#[async_trait]
impl ResourceBuilder<Pool<AsyncPgConnection>> for Postgres {
impl ResourceBuilder for Postgres {
const TYPE: Type = Type::Database(DatabaseType::Shared(SharedEngine::Postgres));

type Config = Self;
type Output = DbOutput;

fn new() -> Self {
Self::default()
}
type Config = DbInput;
type Output = Wrapper;

fn config(&self) -> &Self::Config {
self
&self.db_input
}

async fn output(
self,
factory: &mut dyn Factory,
) -> Result<Self::Output, shuttle_service::Error> {
let db_output = if let Some(local_uri) = self.db_input.local_uri {
DbOutput::Local(local_uri)
let resource = if let Some(local_uri) = self.db_input.local_uri {
DatabaseResource::ConnectionString(local_uri)
} else {
let conn_data = factory
let conn_info = factory
.get_db_connection(DatabaseType::Shared(SharedEngine::Postgres))
.await?;
DbOutput::Info(conn_data)
DatabaseResource::Info(conn_info)
};

Ok(db_output)
Ok(Wrapper(resource))
}
}

#[async_trait]
impl IntoResource<AsyncPgConnection> for Wrapper {
async fn into_resource(self) -> Result<AsyncPgConnection, shuttle_service::Error> {
AsyncPgConnection::establish(&get_connection_string(&self.0))
.await
.map_err(|err| shuttle_service::Error::Database(err.to_string()))
}
}

#[async_trait]
#[cfg(feature = "bb8")]
impl IntoResource<bb8::Pool<AsyncPgConnection>> for Wrapper {
async fn into_resource(self) -> Result<bb8::Pool<AsyncPgConnection>, shuttle_service::Error> {
bb8::Pool::builder()
.max_size(MAX_POOL_SIZE as u32)
.build(get_pool_manager(&self.0))
.await
.map_err(|err| shuttle_service::Error::Database(err.to_string()))
}
}

async fn build(
db_output: &Self::Output,
) -> Result<Pool<AsyncPgConnection>, shuttle_service::Error> {
let conn_string = get_connection_string(db_output);
let config = AsyncDieselConnectionManager::new(conn_string);
Pool::builder(config)
#[async_trait]
#[cfg(feature = "deadpool")]
impl IntoResource<deadpool::Pool<AsyncPgConnection>> for Wrapper {
async fn into_resource(
self,
) -> Result<deadpool::Pool<AsyncPgConnection>, shuttle_service::Error> {
deadpool::Pool::builder(get_pool_manager(&self.0))
.max_size(MAX_POOL_SIZE)
.build()
.map_err(|err| shuttle_service::Error::Custom(err.into()))
.map_err(|err| shuttle_service::Error::Database(err.to_string()))
}
}
Loading