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

Commit

Permalink
Upgrade to Shuttle v0.39 (#12)
Browse files Browse the repository at this point in the history
* Upgrade to shuttle v0.39

* Fix stuff

* fmt
  • Loading branch information
aumetra committed Feb 20, 2024
1 parent 4f49a12 commit 5981710
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 36 deletions.
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()))
}
}

0 comments on commit 5981710

Please sign in to comment.