From 3489e83cfabd775fc6c54dbba0339c642b69be85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oddbj=C3=B8rn=20Gr=C3=B8dem?= <29732646+oddgrd@users.noreply.github.com> Date: Mon, 6 Mar 2023 08:17:02 +0000 Subject: [PATCH] Feature: remove tokio runtime from all resources (#680) * feat: remove runtime from resources * fix: compile errors, comments * fix: remove comment --- resources/aws-rds/Cargo.toml | 1 - resources/aws-rds/src/lib.rs | 17 +++++---------- resources/persist/Cargo.toml | 1 - resources/persist/src/lib.rs | 2 -- resources/shared-db/Cargo.toml | 1 - resources/shared-db/src/lib.rs | 35 ++++++------------------------ resources/static-folder/Cargo.toml | 1 - resources/static-folder/src/lib.rs | 22 ++++--------------- service/src/lib.rs | 3 --- service/src/persist.rs | 7 +----- 10 files changed, 17 insertions(+), 73 deletions(-) diff --git a/resources/aws-rds/Cargo.toml b/resources/aws-rds/Cargo.toml index bcf5652c1..0dfec8369 100644 --- a/resources/aws-rds/Cargo.toml +++ b/resources/aws-rds/Cargo.toml @@ -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"] diff --git a/resources/aws-rds/src/lib.rs b/resources/aws-rds/src/lib.rs index 6b6165228..dec92c198 100644 --- a/resources/aws-rds/src/lib.rs +++ b/resources/aws-rds/src/lib.rs @@ -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) => { @@ -24,22 +23,16 @@ 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 - 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) diff --git a/resources/persist/Cargo.toml b/resources/persist/Cargo.toml index 7686a44c1..82e0559e6 100644 --- a/resources/persist/Cargo.toml +++ b/resources/persist/Cargo.toml @@ -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"] } diff --git a/resources/persist/src/lib.rs b/resources/persist/src/lib.rs index f6fd8e8a4..84d3ce458 100644 --- a/resources/persist/src/lib.rs +++ b/resources/persist/src/lib.rs @@ -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 { @@ -74,7 +73,6 @@ impl ResourceBuilder for Persist { async fn build( self, factory: &mut dyn Factory, - _runtime: &Runtime, ) -> Result { Ok(PersistInstance { service_name: factory.get_service_name(), diff --git a/resources/shared-db/Cargo.toml b/resources/shared-db/Cargo.toml index 611d5126a..0cbf266eb 100644 --- a/resources/shared-db/Cargo.toml +++ b/resources/shared-db/Cargo.toml @@ -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"] diff --git a/resources/shared-db/src/lib.rs b/resources/shared-db/src/lib.rs index c65069c75..fb3fd15a3 100644 --- a/resources/shared-db/src/lib.rs +++ b/resources/shared-db/src/lib.rs @@ -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}; @@ -16,26 +14,16 @@ impl ResourceBuilder for Postgres { Self {} } - async fn build( - self, - factory: &mut dyn Factory, - runtime: &Runtime, - ) -> Result { + async fn build(self, factory: &mut dyn Factory) -> Result { 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) @@ -53,11 +41,7 @@ impl ResourceBuilder for MongoDb { Self {} } - async fn build( - self, - factory: &mut dyn Factory, - runtime: &Runtime, - ) -> Result { + async fn build(self, factory: &mut dyn Factory) -> Result { let connection_string = factory .get_db_connection_string(database::Type::Shared(database::SharedEngine::MongoDb)) .await @@ -69,12 +53,7 @@ impl ResourceBuilder 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 diff --git a/resources/static-folder/Cargo.toml b/resources/static-folder/Cargo.toml index bd44daee7..cade0556f 100644 --- a/resources/static-folder/Cargo.toml +++ b/resources/static-folder/Cargo.toml @@ -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" diff --git a/resources/static-folder/src/lib.rs b/resources/static-folder/src/lib.rs index 259288dd9..524ffe80f 100644 --- a/resources/static-folder/src/lib.rs +++ b/resources/static-folder/src/lib.rs @@ -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` @@ -33,11 +32,7 @@ impl<'a> ResourceBuilder for StaticFolder<'a> { Self { folder: "static" } } - async fn build( - self, - factory: &mut dyn Factory, - _runtime: &Runtime, - ) -> Result { + async fn build(self, factory: &mut dyn Factory) -> Result { let folder = Path::new(self.folder); // Prevent users from users from reading anything outside of their crate's build folder @@ -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, @@ -185,8 +179,6 @@ mod tests { "Hello, test!", "expected file content to match" ); - - runtime.shutdown_background(); } #[tokio::test] @@ -194,15 +186,12 @@ mod tests { 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] @@ -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(); } } diff --git a/service/src/lib.rs b/service/src/lib.rs index d65961515..7b1b55597 100644 --- a/service/src/lib.rs +++ b/service/src/lib.rs @@ -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: /// ``` @@ -371,7 +369,6 @@ pub trait Factory: Send + Sync { /// async fn build( /// self, /// factory: &mut dyn Factory, -/// _runtime: &Runtime, /// ) -> Result { /// Ok(Resource { name: self.name }) /// } diff --git a/service/src/persist.rs b/service/src/persist.rs index 6b7510158..adeebc263 100644 --- a/service/src/persist.rs +++ b/service/src/persist.rs @@ -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 { @@ -70,11 +69,7 @@ impl ResourceBuilder for Persist { Self {} } - async fn build( - self, - factory: &mut dyn Factory, - _runtime: &Runtime, - ) -> Result { + async fn build(self, factory: &mut dyn Factory) -> Result { Ok(PersistInstance { service_name: factory.get_service_name(), })