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

Feature: remove tokio runtime from all resources #680

Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 0 additions & 1 deletion resources/aws-rds/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ async-trait = "0.1.56"
paste = "1.0.7"
shuttle-service = { path = "../../service", version = "0.8.0", default-features = false }
sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls"] }
tokio = { version = "1.19.2", features = ["rt"] }

[features]
postgres = ["sqlx/postgres"]
Expand Down
16 changes: 5 additions & 11 deletions resources/aws-rds/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use shuttle_service::{
error::CustomError,
Factory, ResourceBuilder,
};
use tokio::runtime::Runtime;

macro_rules! aws_engine {
($feature:expr, $pool_path:path, $options_path:path, $struct_ident:ident) => {
Expand All @@ -24,22 +23,17 @@ macro_rules! aws_engine {
Self {}
}

async fn build(self, factory: &mut dyn Factory, runtime: &Runtime) -> Result<$pool_path, shuttle_service::Error> {
async fn build(self, factory: &mut dyn Factory) -> Result<$pool_path, shuttle_service::Error> {
let connection_string = factory
.get_db_connection_string(Type::AwsRds(AwsRdsEngine::$struct_ident))
.await?;

// A sqlx Pool cannot cross runtime boundaries, so make sure to create the Pool on the service end
oddgrd marked this conversation as resolved.
Show resolved Hide resolved
let pool = runtime
.spawn(async move {
$options_path::new()
.min_connections(1)
.max_connections(5)
.connect(&connection_string)
.await
})
let pool = $options_path::new()
.min_connections(1)
.max_connections(5)
.connect(&connection_string)
.await
.map_err(CustomError::new)?
.map_err(CustomError::new)?;

Ok(pool)
Expand Down
1 change: 0 additions & 1 deletion resources/persist/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,3 @@ serde = { version = "1.0.0", features = ["derive"] }
shuttle-common = { path = "../../common", version = "0.8.0", default-features = false }
shuttle-service = { path = "../../service", version = "0.8.0", default-features = false }
thiserror = "1.0.32"
tokio = { version = "1.19.2", features = ["rt"] }
2 changes: 0 additions & 2 deletions resources/persist/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use std::io::BufReader;
use std::io::BufWriter;
use std::path::PathBuf;
use thiserror::Error;
use tokio::runtime::Runtime;

#[derive(Error, Debug)]
pub enum PersistError {
Expand Down Expand Up @@ -74,7 +73,6 @@ impl ResourceBuilder<PersistInstance> for Persist {
async fn build(
self,
factory: &mut dyn Factory,
_runtime: &Runtime,
) -> Result<PersistInstance, shuttle_service::Error> {
Ok(PersistInstance {
service_name: factory.get_service_name(),
Expand Down
1 change: 0 additions & 1 deletion resources/shared-db/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ async-trait = "0.1.56"
mongodb = { version = "2.3.0", optional = true }
shuttle-service = { path = "../../service", version = "0.8.0", default-features = false }
sqlx = { version = "0.6.2", features = ["runtime-tokio-native-tls"], optional = true }
tokio = { version = "1.19.2", features = ["rt"] }

[features]
postgres = ["sqlx/postgres"]
35 changes: 7 additions & 28 deletions resources/shared-db/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#![doc = include_str!("../README.md")]

use tokio::runtime::Runtime;

use async_trait::async_trait;
use shuttle_service::{database, error::CustomError, Error, Factory, ResourceBuilder};

Expand All @@ -16,26 +14,16 @@ impl ResourceBuilder<sqlx::PgPool> for Postgres {
Self {}
}

async fn build(
self,
factory: &mut dyn Factory,
runtime: &Runtime,
) -> Result<sqlx::PgPool, Error> {
async fn build(self, factory: &mut dyn Factory) -> Result<sqlx::PgPool, Error> {
let connection_string = factory
.get_db_connection_string(database::Type::Shared(database::SharedEngine::Postgres))
.await?;

// A sqlx Pool cannot cross runtime boundaries, so make sure to create the Pool on the service end
let pool = runtime
.spawn(async move {
sqlx::postgres::PgPoolOptions::new()
.min_connections(1)
.max_connections(5)
.connect(&connection_string)
.await
})
let pool = sqlx::postgres::PgPoolOptions::new()
.min_connections(1)
.max_connections(5)
.connect(&connection_string)
.await
.map_err(CustomError::new)?
.map_err(CustomError::new)?;

Ok(pool)
Expand All @@ -53,11 +41,7 @@ impl ResourceBuilder<mongodb::Database> for MongoDb {
Self {}
}

async fn build(
self,
factory: &mut dyn Factory,
runtime: &Runtime,
) -> Result<mongodb::Database, crate::Error> {
async fn build(self, factory: &mut dyn Factory) -> Result<mongodb::Database, crate::Error> {
let connection_string = factory
.get_db_connection_string(database::Type::Shared(database::SharedEngine::MongoDb))
.await
Expand All @@ -69,12 +53,7 @@ impl ResourceBuilder<mongodb::Database> for MongoDb {
client_options.min_pool_size = Some(1);
client_options.max_pool_size = Some(5);

// A mongodb client cannot cross runtime boundaries, so make sure to create the client on the service end
let client = runtime
.spawn(async move { mongodb::Client::with_options(client_options) })
.await
.map_err(CustomError::new)?
.map_err(CustomError::new)?;
let client = mongodb::Client::with_options(client_options).map_err(CustomError::new)?;

// Return a handle to the database defined at the end of the connection string, which is the users provisioned
// database
Expand Down
1 change: 0 additions & 1 deletion resources/static-folder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ keywords = ["shuttle-service", "static-folder"]
[dependencies]
async-trait = "0.1.56"
shuttle-service = { path = "../../service", version = "0.8.0", default-features = false }
tokio = { version = "1.19.2", features = ["rt"] }

[dev-dependencies]
tempdir = "0.3.7"
Expand Down
22 changes: 4 additions & 18 deletions resources/static-folder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use std::{
fs::rename,
path::{Path, PathBuf},
};
use tokio::runtime::Runtime;

pub struct StaticFolder<'a> {
/// The folder to reach at runtime. Defaults to `static`
Expand All @@ -33,11 +32,7 @@ impl<'a> ResourceBuilder<PathBuf> for StaticFolder<'a> {
Self { folder: "static" }
}

async fn build(
self,
factory: &mut dyn Factory,
_runtime: &Runtime,
) -> Result<PathBuf, shuttle_service::Error> {
async fn build(self, factory: &mut dyn Factory) -> Result<PathBuf, shuttle_service::Error> {
let folder = Path::new(self.folder);

// Prevent users from users from reading anything outside of their crate's build folder
Expand Down Expand Up @@ -171,8 +166,7 @@ mod tests {
// Call plugin
let static_folder = StaticFolder::new();

let runtime = tokio::runtime::Runtime::new().unwrap();
let actual_folder = static_folder.build(&mut factory, &runtime).await.unwrap();
let actual_folder = static_folder.build(&mut factory).await.unwrap();

assert_eq!(
actual_folder,
Expand All @@ -185,24 +179,19 @@ mod tests {
"Hello, test!",
"expected file content to match"
);

runtime.shutdown_background();
}

#[tokio::test]
#[should_panic(expected = "Cannot use an absolute path for a static folder")]
async fn cannot_use_absolute_path() {
let mut factory = MockFactory::new();
let static_folder = StaticFolder::new();
let runtime = tokio::runtime::Runtime::new().unwrap();

let _ = static_folder
.folder("/etc")
.build(&mut factory, &runtime)
.build(&mut factory)
.await
.unwrap();

runtime.shutdown_background();
}

#[tokio::test]
Expand All @@ -217,13 +206,10 @@ mod tests {
// Call plugin
let static_folder = StaticFolder::new();

let runtime = tokio::runtime::Runtime::new().unwrap();
let _ = static_folder
.folder("../escape")
.build(&mut factory, &runtime)
.build(&mut factory)
.await
.unwrap();

runtime.shutdown_background();
}
}
3 changes: 0 additions & 3 deletions service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,6 @@ pub trait Factory: Send + Sync {
/// You may want to create your own managed resource by implementing this trait for some builder `B` to construct resource `T`. [`Factory`] can be used to provision resources
/// on shuttle's servers if your resource will need any.
///
/// The biggest thing to look out for is that your resource object might panic when it crosses the boundary between the shuttle's backend runtime and the runtime
/// of services. These resources should be created on the passed in `runtime` for this trait to prevent these panics.
///
/// Your resource will be available on a [shuttle_service::main][main] function as follow:
/// ```
Expand Down Expand Up @@ -371,7 +369,6 @@ pub trait Factory: Send + Sync {
/// async fn build(
/// self,
/// factory: &mut dyn Factory,
/// _runtime: &Runtime,
/// ) -> Result<Resource, shuttle_service::Error> {
/// Ok(Resource { name: self.name })
/// }
Expand Down
7 changes: 1 addition & 6 deletions service/src/persist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use std::io::BufReader;
use std::io::BufWriter;
use std::path::PathBuf;
use thiserror::Error;
use tokio::runtime::Runtime;

#[derive(Error, Debug)]
pub enum PersistError {
Expand Down Expand Up @@ -70,11 +69,7 @@ impl ResourceBuilder<PersistInstance> for Persist {
Self {}
}

async fn build(
self,
factory: &mut dyn Factory,
_runtime: &Runtime,
) -> Result<PersistInstance, crate::Error> {
async fn build(self, factory: &mut dyn Factory) -> Result<PersistInstance, crate::Error> {
Ok(PersistInstance {
service_name: factory.get_service_name(),
})
Expand Down