diff --git a/codegen/src/shuttle_main.rs b/codegen/src/shuttle_main.rs index 8387dd7577..e427096210 100644 --- a/codegen/src/shuttle_main.rs +++ b/codegen/src/shuttle_main.rs @@ -262,7 +262,7 @@ impl ToTokens for LoaderAndRunner { let loader_runner = quote! { async fn __loader( #factory_ident: ::shuttle_runtime::ResourceFactory, - ) -> ::std::result::Result<::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, ::shuttle_runtime::Error> { + ) -> ::std::result::Result<::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, ::shuttle_runtime::BoxDynError> { use ::shuttle_runtime::__internals::Context; #extra_imports @@ -447,7 +447,7 @@ mod tests { let expected = quote! { async fn __loader( _factory: ::shuttle_runtime::ResourceFactory, - ) -> ::std::result::Result<::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, ::shuttle_runtime::Error> { + ) -> ::std::result::Result<::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, ::shuttle_runtime::BoxDynError> { use ::shuttle_runtime::__internals::Context; let mut inputs = Vec::new(); Ok(inputs) @@ -494,7 +494,7 @@ mod tests { let expected = quote! { async fn __loader( factory: ::shuttle_runtime::ResourceFactory, - ) -> ::std::result::Result<::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, ::shuttle_runtime::Error> { + ) -> ::std::result::Result<::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, ::shuttle_runtime::BoxDynError> { use ::shuttle_runtime::__internals::Context; use ::shuttle_runtime::{ResourceFactory, IntoResource, ResourceInputBuilder}; let mut inputs = Vec::new(); @@ -578,7 +578,7 @@ mod tests { let expected = quote! { async fn __loader( factory: ::shuttle_runtime::ResourceFactory, - ) -> ::std::result::Result<::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, ::shuttle_runtime::Error> { + ) -> ::std::result::Result<::std::vec::Vec<::std::vec::Vec<::core::primitive::u8>>, ::shuttle_runtime::BoxDynError> { use ::shuttle_runtime::__internals::Context; use ::shuttle_runtime::{ResourceFactory, IntoResource, ResourceInputBuilder}; let __vars = ::std::collections::HashMap::from_iter( diff --git a/examples b/examples index 01a552be52..530f70e9c6 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 01a552be52c3f4d57d666714adba64d8c8463b6f +Subproject commit 530f70e9c6fcc6c15848f5bea4e4c4db19f3ca4e diff --git a/resources/aws-rds/src/lib.rs b/resources/aws-rds/src/lib.rs index 151085b203..872a1d113a 100644 --- a/resources/aws-rds/src/lib.rs +++ b/resources/aws-rds/src/lib.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use serde::{Deserialize, Serialize}; use shuttle_service::{ resource::{ProvisionResourceRequest, ResourceType}, - DatabaseResource, DbInput, Environment, Error, IntoResource, ResourceFactory, + DatabaseResource, DbInput, Environment, IntoResource, ResourceFactory, ResourceInputBuilder, }; @@ -61,7 +61,7 @@ macro_rules! aws_engine { type Input = MaybeRequest; type Output = OutputWrapper; - async fn build(self, factory: &ResourceFactory) -> Result { + async fn build(self, factory: &ResourceFactory) -> Result { let md = factory.get_metadata(); Ok(match md.env { Environment::Deployment => MaybeRequest::Request(ProvisionResourceRequest { @@ -94,7 +94,7 @@ pub struct OutputWrapper(DatabaseResource); #[async_trait] impl IntoResource for OutputWrapper { - async fn into_resource(self) -> Result { + async fn into_resource(self) -> Result { Ok(match self.0 { DatabaseResource::ConnectionString(s) => s, DatabaseResource::Info(info) => info.connection_string(true), @@ -111,26 +111,24 @@ mod _diesel_async { #[cfg(feature = "postgres")] #[async_trait] impl IntoResource for OutputWrapper { - async fn into_resource(self) -> Result { + async fn into_resource(self) -> Result { 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)?) + .await?) } } #[cfg(any(feature = "mysql", feature = "mariadb"))] #[async_trait] impl IntoResource for OutputWrapper { - async fn into_resource(self) -> Result { + async fn into_resource(self) -> Result { use diesel_async::{AsyncConnection, AsyncMysqlConnection}; let connection_string: String = self.into_resource().await.unwrap(); Ok(AsyncMysqlConnection::establish(&connection_string) - .await - .map_err(shuttle_service::error::CustomError::new)?) + .await?) } } } @@ -144,15 +142,14 @@ mod _diesel_async_bb8 { impl IntoResource> for OutputWrapper { async fn into_resource( self, - ) -> Result, Error> { + ) -> Result, shuttle_service::BoxDynError> { 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)?) + .await?) } } @@ -161,15 +158,14 @@ mod _diesel_async_bb8 { impl IntoResource> for OutputWrapper { async fn into_resource( self, - ) -> Result, Error> { + ) -> Result, shuttle_service::BoxDynError> { 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)?) + .await?) } } } @@ -183,7 +179,7 @@ mod _diesel_async_deadpool { impl IntoResource> for OutputWrapper { async fn into_resource( self, - ) -> Result, Error> { + ) -> Result, shuttle_service::BoxDynError> { let connection_string: String = self.into_resource().await.unwrap(); Ok( @@ -191,8 +187,7 @@ mod _diesel_async_deadpool { connection_string, )) .max_size(MAX_CONNECTIONS as usize) - .build() - .map_err(shuttle_service::error::CustomError::new)?, + .build()?, ) } } @@ -202,7 +197,7 @@ mod _diesel_async_deadpool { impl IntoResource> for OutputWrapper { async fn into_resource( self, - ) -> Result, Error> { + ) -> Result, shuttle_service::BoxDynError> { let connection_string: String = self.into_resource().await.unwrap(); Ok( @@ -210,8 +205,7 @@ mod _diesel_async_deadpool { connection_string, )) .max_size(MAX_CONNECTIONS as usize) - .build() - .map_err(shuttle_service::error::CustomError::new)?, + .build()?, ) } } @@ -224,30 +218,28 @@ mod _sqlx { #[cfg(feature = "postgres")] #[async_trait] impl IntoResource for OutputWrapper { - async fn into_resource(self) -> Result { + async fn into_resource(self) -> Result { let connection_string: String = self.into_resource().await.unwrap(); Ok(sqlx::postgres::PgPoolOptions::new() .min_connections(MIN_CONNECTIONS) .max_connections(MAX_CONNECTIONS) .connect(&connection_string) - .await - .map_err(shuttle_service::error::CustomError::new)?) + .await?) } } #[cfg(any(feature = "mysql", feature = "mariadb"))] #[async_trait] impl IntoResource for OutputWrapper { - async fn into_resource(self) -> Result { + async fn into_resource(self) -> Result { let connection_string: String = self.into_resource().await.unwrap(); Ok(sqlx::mysql::MySqlPoolOptions::new() .min_connections(MIN_CONNECTIONS) .max_connections(MAX_CONNECTIONS) .connect(&connection_string) - .await - .map_err(shuttle_service::error::CustomError::new)?) + .await?) } } } diff --git a/resources/openai/src/lib.rs b/resources/openai/src/lib.rs index e97de879ab..441fb7c53e 100644 --- a/resources/openai/src/lib.rs +++ b/resources/openai/src/lib.rs @@ -2,7 +2,7 @@ use async_openai::config::OpenAIConfig; use async_openai::Client; use async_trait::async_trait; use serde::{Deserialize, Serialize}; -use shuttle_service::{CustomError, Error, IntoResource, ResourceFactory, ResourceInputBuilder}; +use shuttle_service::{IntoResource, ResourceFactory, ResourceInputBuilder}; pub use async_openai; @@ -46,10 +46,10 @@ impl ResourceInputBuilder for OpenAI { type Input = Config; type Output = Config; - async fn build(self, _factory: &ResourceFactory) -> Result { + async fn build(self, _factory: &ResourceFactory) -> Result { let api_key = self .api_key - .ok_or(Error::Custom(CustomError::msg("Open AI API key required")))?; + .ok_or(CustomError::msg("Open AI API key required"))?; let config = Config { api_base: self.api_base, api_key, @@ -62,7 +62,7 @@ impl ResourceInputBuilder for OpenAI { #[async_trait] impl IntoResource> for Config { - async fn into_resource(self) -> Result, Error> { + async fn into_resource(self) -> Result, shuttle_service::BoxDynError> { let mut openai_config = OpenAIConfig::new().with_api_key(self.api_key); if let Some(api_base) = self.api_base { openai_config = openai_config.with_api_base(api_base) diff --git a/resources/opendal/src/lib.rs b/resources/opendal/src/lib.rs index eca5ed6eb9..d4bf36a8f4 100644 --- a/resources/opendal/src/lib.rs +++ b/resources/opendal/src/lib.rs @@ -4,10 +4,7 @@ use std::str::FromStr; use async_trait::async_trait; use opendal::{Operator, Scheme}; use serde::{Deserialize, Serialize}; -use shuttle_service::{ - error::{CustomError, Error as ShuttleError}, - IntoResource, ResourceFactory, ResourceInputBuilder, -}; +use shuttle_service::{IntoResource, ResourceFactory, ResourceInputBuilder}; #[derive(Serialize)] pub struct Opendal { @@ -35,21 +32,12 @@ pub struct OpendalOutput { cfg: HashMap, } -pub struct Error(opendal::Error); - -impl From for shuttle_service::Error { - fn from(error: Error) -> Self { - let msg = format!("Failed to build opendal resource: {:?}", error.0); - ShuttleError::Custom(CustomError::msg(msg)) - } -} - #[async_trait] impl ResourceInputBuilder for Opendal { type Input = OpendalOutput; type Output = OpendalOutput; - async fn build(self, factory: &ResourceFactory) -> Result { + async fn build(self, factory: &ResourceFactory) -> Result { Ok(OpendalOutput { scheme: self.scheme, cfg: factory @@ -63,10 +51,10 @@ impl ResourceInputBuilder for Opendal { #[async_trait] impl IntoResource for OpendalOutput { - async fn into_resource(self) -> Result { - let scheme = Scheme::from_str(&self.scheme).map_err(Error)?; + async fn into_resource(self) -> Result { + let scheme = Scheme::from_str(&self.scheme)?; - Ok(Operator::via_iter(scheme, self.cfg).map_err(Error)?) + Ok(Operator::via_iter(scheme, self.cfg)?) } } diff --git a/resources/qdrant/src/lib.rs b/resources/qdrant/src/lib.rs index 8341819921..92dace49ae 100644 --- a/resources/qdrant/src/lib.rs +++ b/resources/qdrant/src/lib.rs @@ -1,7 +1,6 @@ use async_trait::async_trait; use serde::{Deserialize, Serialize}; use shuttle_service::{ - error::{CustomError, Error}, resource::{ProvisionResourceRequest, ResourceType}, ContainerRequest, ContainerResponse, Environment, IntoResource, ResourceFactory, ResourceInputBuilder, @@ -47,7 +46,7 @@ impl ResourceInputBuilder for Qdrant { // The response can be a provisioned container, depending on local/deployment and config. type Output = OutputWrapper; - async fn build(self, factory: &ResourceFactory) -> Result { + async fn build(self, factory: &ResourceFactory) -> Result { let md = factory.get_metadata(); match md.env { Environment::Deployment => match self.cloud_url { @@ -55,9 +54,9 @@ impl ResourceInputBuilder for Qdrant { url: cloud_url, api_key: self.api_key, })), - None => Err(Error::Custom(CustomError::msg( + None => Err(CustomError::msg( "missing `cloud_url` parameter", - ))), + )), }, Environment::Local => match self.local_url { Some(local_url) => Ok(MaybeRequest::NotRequest(QdrantClientConfigWrap { @@ -96,7 +95,7 @@ pub struct QdrantClientConfigWrap { #[async_trait] impl IntoResource for OutputWrapper { - async fn into_resource(self) -> Result { + async fn into_resource(self) -> Result { let config = match self { Self::Container(output) => QdrantClientConfigWrap { url: format!("http://localhost:{}", output.host_port), @@ -106,7 +105,6 @@ impl IntoResource for OutputWrapper { }; Ok(qdrant_client::config::QdrantConfig::from_url(&config.url) .api_key(config.api_key) - .build() - .map_err(|err| Error::Custom(err.into()))?) + .build()?) } } diff --git a/resources/shared-db/src/postgres.rs b/resources/shared-db/src/postgres.rs index 0949b521b9..a2f9ae3b94 100644 --- a/resources/shared-db/src/postgres.rs +++ b/resources/shared-db/src/postgres.rs @@ -2,7 +2,7 @@ use async_trait::async_trait; use serde::{Deserialize, Serialize}; use shuttle_service::{ resource::{ProvisionResourceRequest, ResourceType}, - DatabaseResource, DbInput, Environment, Error, IntoResource, ResourceFactory, + DatabaseResource, DbInput, Environment, IntoResource, ResourceFactory, ResourceInputBuilder, }; @@ -46,7 +46,7 @@ impl ResourceInputBuilder for Postgres { type Input = MaybeRequest; type Output = OutputWrapper; - async fn build(self, factory: &ResourceFactory) -> Result { + async fn build(self, factory: &ResourceFactory) -> Result { let md = factory.get_metadata(); Ok(match md.env { Environment::Deployment => MaybeRequest::Request(ProvisionResourceRequest { @@ -72,7 +72,7 @@ pub struct OutputWrapper(DatabaseResource); #[async_trait] impl IntoResource for OutputWrapper { - async fn into_resource(self) -> Result { + async fn into_resource(self) -> Result { Ok(match self.0 { DatabaseResource::ConnectionString(s) => s, DatabaseResource::Info(info) => info.connection_string(true), @@ -83,14 +83,13 @@ impl IntoResource for OutputWrapper { #[cfg(feature = "diesel-async")] #[async_trait] impl IntoResource for OutputWrapper { - async fn into_resource(self) -> Result { + async fn into_resource(self) -> Result { use diesel_async::{AsyncConnection, AsyncPgConnection}; let connection_string: String = self.into_resource().await?; Ok(AsyncPgConnection::establish(&connection_string) - .await - .map_err(shuttle_service::error::CustomError::new)?) + .await?) } } @@ -99,15 +98,14 @@ impl IntoResource for OutputWrapper { impl IntoResource> for OutputWrapper { async fn into_resource( self, - ) -> Result, Error> { + ) -> Result, shuttle_service::BoxDynError> { let connection_string: String = self.into_resource().await?; 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)?) + .await?) } } @@ -116,14 +114,13 @@ impl IntoResource> for OutputW impl IntoResource> for OutputWrapper { async fn into_resource( self, - ) -> Result, Error> { + ) -> Result, shuttle_service::BoxDynError> { let connection_string: String = self.into_resource().await?; Ok( diesel_deadpool::Pool::builder(AsyncDieselConnectionManager::new(connection_string)) .max_size(MAX_CONNECTIONS as usize) - .build() - .map_err(shuttle_service::error::CustomError::new)?, + .build()?, ) } } @@ -131,35 +128,32 @@ impl IntoResource> for Ou #[cfg(feature = "sqlx")] #[async_trait] impl IntoResource for OutputWrapper { - async fn into_resource(self) -> Result { + async fn into_resource(self) -> Result { let connection_string: String = self.into_resource().await?; Ok(sqlx::postgres::PgPoolOptions::new() .min_connections(MIN_CONNECTIONS) .max_connections(MAX_CONNECTIONS) .connect(&connection_string) - .await - .map_err(shuttle_service::error::CustomError::new)?) + .await?) } } #[cfg(feature = "opendal-postgres")] #[async_trait] impl IntoResource for OutputWrapper { - async fn into_resource(self) -> Result { + async fn into_resource(self) -> Result { let connection_string: String = self.into_resource().await?; let pool = sqlx::postgres::PgPoolOptions::new() .min_connections(MIN_CONNECTIONS) .max_connections(MAX_CONNECTIONS) .connect(&connection_string) - .await - .map_err(shuttle_service::error::CustomError::new)?; + .await?; sqlx::query( "CREATE TABLE IF NOT EXISTS opendal (key TEXT PRIMARY KEY, value BYTEA NOT NULL)", ) .execute(&pool) - .await - .map_err(shuttle_service::error::CustomError::new)?; + .await?; let config = opendal::services::Postgresql::default() .root("/") @@ -169,8 +163,7 @@ impl IntoResource for OutputWrapper { .key_field("key") // value field type in the table should be compatible with Rust's Vec like bytea .value_field("value"); - let op = opendal::Operator::new(config) - .map_err(shuttle_service::error::CustomError::new)? + let op = opendal::Operator::new(config)? .finish(); Ok(op) diff --git a/resources/turso/src/lib.rs b/resources/turso/src/lib.rs index 1cb3b58fe0..1459804823 100644 --- a/resources/turso/src/lib.rs +++ b/resources/turso/src/lib.rs @@ -1,10 +1,7 @@ use async_trait::async_trait; use libsql::{Builder, Database}; use serde::{Deserialize, Serialize}; -use shuttle_service::{ - error::{CustomError, Error as ShuttleError}, - Environment, IntoResource, ResourceFactory, ResourceInputBuilder, -}; +use shuttle_service::{Environment, IntoResource, ResourceFactory, ResourceInputBuilder}; use url::Url; #[derive(Serialize, Default)] @@ -43,14 +40,14 @@ pub enum Error { LocateLocalDB(std::io::Error), } -impl From for shuttle_service::Error { +impl From for shuttle_service::BoxDynError { fn from(error: Error) -> Self { let msg = match error { Error::UrlParseError(err) => format!("Failed to parse Turso Url: {}", err), Error::LocateLocalDB(err) => format!("Failed to get path to local db file: {}", err), }; - ShuttleError::Custom(CustomError::msg(msg)) + CustomError::msg(msg) } } @@ -77,17 +74,17 @@ impl ResourceInputBuilder for Turso { type Input = TursoOutput; type Output = TursoOutput; - async fn build(self, factory: &ResourceFactory) -> Result { + async fn build(self, factory: &ResourceFactory) -> Result { let md = factory.get_metadata(); match md.env { Environment::Deployment => { if self.addr.is_empty() { - Err(ShuttleError::Custom(CustomError::msg("missing addr"))) + Err(CustomError::msg("missing addr")) } else { if !self.addr.starts_with("libsql://") && !self.addr.starts_with("https://") { - return Err(ShuttleError::Custom(CustomError::msg( + return Err(CustomError::msg( "addr must start with either libsql:// or https://", - ))); + )); } self.output_from_addr(&self.addr, true).await } @@ -121,23 +118,21 @@ impl ResourceInputBuilder for Turso { #[async_trait] impl IntoResource for TursoOutput { - async fn into_resource(self) -> Result { - let database = if self.remote { + async fn into_resource(self) -> Result { + if self.remote { Builder::new_remote( self.conn_url.to_string(), self.token .clone() - .ok_or(ShuttleError::Custom(CustomError::msg( + .ok_or(CustomError::msg( "missing token for remote database", - )))?, + ))?, ) .build() .await } else { Builder::new_local(self.conn_url.to_string()).build().await - }; - - database.map_err(|err| ShuttleError::Custom(err.into())) + } } } diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 8d763ec7a5..4529738627 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -19,7 +19,7 @@ pub use async_trait::async_trait; pub use plugins::{Metadata, Secrets}; pub use shuttle_codegen::main; pub use shuttle_service::{ - CustomError, DbInput, DeploymentMetadata, Environment, Error, IntoResource, ResourceFactory, + BoxDynError, DbInput, DeploymentMetadata, Environment, IntoResource, ResourceFactory, ResourceInputBuilder, SecretStore, Service, }; pub use tokio; @@ -42,16 +42,16 @@ pub mod __internals { #[async_trait] pub trait Loader { - async fn load(self, factory: ResourceFactory) -> Result>, Error>; + async fn load(self, factory: ResourceFactory) -> Result>, BoxDynError>; } #[async_trait] impl Loader for F where F: FnOnce(ResourceFactory) -> O + Send, - O: Future>, Error>> + Send, + O: Future>, BoxDynError>> + Send, { - async fn load(self, factory: ResourceFactory) -> Result>, Error> { + async fn load(self, factory: ResourceFactory) -> Result>, BoxDynError> { self(factory).await } } @@ -60,19 +60,19 @@ pub mod __internals { pub trait Runner { type Service: Service; - async fn run(self, resources: Vec>) -> Result; + async fn run(self, resources: Vec>) -> Result; } #[async_trait] impl Runner for F where F: FnOnce(Vec>) -> O + Send, - O: Future> + Send, + O: Future> + Send, S: Service, { type Service = S; - async fn run(self, resources: Vec>) -> Result { + async fn run(self, resources: Vec>) -> Result { self(resources).await } } diff --git a/runtime/src/plugins.rs b/runtime/src/plugins.rs index 2a9a8fd43d..6a5b0712c1 100644 --- a/runtime/src/plugins.rs +++ b/runtime/src/plugins.rs @@ -2,7 +2,8 @@ use crate::async_trait; use serde::{Deserialize, Serialize}; use shuttle_service::{ resource::{ProvisionResourceRequest, ResourceType}, - DeploymentMetadata, Error, IntoResource, ResourceFactory, ResourceInputBuilder, SecretStore, + BoxDynError, DeploymentMetadata, IntoResource, ResourceFactory, ResourceInputBuilder, + SecretStore, }; /// ## Shuttle Metadata @@ -24,7 +25,7 @@ impl ResourceInputBuilder for Metadata { type Input = DeploymentMetadata; type Output = DeploymentMetadata; - async fn build(self, factory: &ResourceFactory) -> Result { + async fn build(self, factory: &ResourceFactory) -> Result { Ok(factory.get_metadata()) } } @@ -69,7 +70,7 @@ impl ResourceInputBuilder for Secrets { type Input = ProvisionResourceRequest; type Output = SecretsOutputWrapper; - async fn build(self, _factory: &ResourceFactory) -> Result { + async fn build(self, _factory: &ResourceFactory) -> Result { Ok(ProvisionResourceRequest { r#type: ResourceType::Secrets, config: serde_json::Value::Null, @@ -79,7 +80,7 @@ impl ResourceInputBuilder for Secrets { #[async_trait] impl IntoResource for SecretsOutputWrapper { - async fn into_resource(self) -> Result { + async fn into_resource(self) -> Result { Ok(self.0) } } diff --git a/service/src/error.rs b/service/src/error.rs deleted file mode 100644 index f38dd8e8cc..0000000000 --- a/service/src/error.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Types representing various errors that can occur in the process of building and deploying a service. - -/// An error that can occur in the process of building and deploying a service. -#[derive(Debug, thiserror::Error)] -pub enum Error { - /// An Input/Output error. - #[error("IO error: {0}")] - Io(#[from] std::io::Error), - /// An Error related to the database. - #[error("Database error: {0}")] - Database(String), - /// An error related to the build process. - #[error("Panic occurred in shuttle_service::main`: {0}")] - BuildPanic(String), - /// An error related to the bind process. - #[error("Panic occurred in `Service::bind`: {0}")] - BindPanic(String), - /// An error related to parsing the Secrets.toml file. - #[error("Failed to interpolate string. Is your Secrets.toml correct?")] - StringInterpolation(#[from] strfmt::FmtError), - #[error(transparent)] - Custom(#[from] CustomError), -} - -/// Type alias for an `anyhow::Error`. -pub type CustomError = anyhow::Error; diff --git a/service/src/lib.rs b/service/src/lib.rs index 4c610dcc98..6cadd21373 100644 --- a/service/src/lib.rs +++ b/service/src/lib.rs @@ -14,9 +14,7 @@ pub use shuttle_common::{ ContainerRequest, ContainerResponse, DatabaseInfo, DatabaseResource, DbInput, }; -pub use crate::error::{CustomError, Error}; - -pub mod error; +pub type BoxDynError = Box; /// Allows implementing plugins for the Shuttle main function. /// @@ -49,7 +47,7 @@ pub trait ResourceInputBuilder: Default { type Output: Serialize + DeserializeOwned; /// Construct this resource config. The [`ResourceFactory`] provides access to secrets and metadata. - async fn build(self, factory: &ResourceFactory) -> Result; + async fn build(self, factory: &ResourceFactory) -> Result; } /// A factory for getting metadata when building resources @@ -92,13 +90,13 @@ pub trait IntoResource: Serialize + DeserializeOwned { /// Initialize any logic for creating the final resource of type `R` from the base resource. /// /// Example: turn a connection string into a connection pool. - async fn into_resource(self) -> Result; + async fn into_resource(self) -> Result; } // Base impl for [`ResourceInputBuilder::Output`] types that don't need to convert into anything else #[async_trait] impl IntoResource for R { - async fn into_resource(self) -> Result { + async fn into_resource(self) -> Result { Ok(self) } } @@ -113,5 +111,5 @@ pub trait Service: Send { /// /// The passed [`SocketAddr`] receives proxied HTTP traffic from your Shuttle subdomain (or custom domain). /// Binding to the address is only relevant if this service is an HTTP server. - async fn bind(mut self, addr: SocketAddr) -> Result<(), error::Error>; + async fn bind(mut self, addr: SocketAddr) -> Result<(), BoxDynError>; } diff --git a/services/shuttle-actix-web/src/lib.rs b/services/shuttle-actix-web/src/lib.rs index 1cb61a5942..08c2f27d5c 100644 --- a/services/shuttle-actix-web/src/lib.rs +++ b/services/shuttle-actix-web/src/lib.rs @@ -13,7 +13,7 @@ impl shuttle_runtime::Service for ActixWebService where F: FnOnce(&mut actix_web::web::ServiceConfig) + Send + Clone + 'static, { - async fn bind(mut self, addr: SocketAddr) -> Result<(), shuttle_runtime::Error> { + async fn bind(mut self, addr: SocketAddr) -> Result<(), shuttle_runtime::BoxDynError> { // Start a worker for each cpu, but no more than 4. let worker_count = num_cpus::get().min(4); @@ -23,7 +23,7 @@ where .bind(addr)? .run(); - server.await.map_err(shuttle_runtime::CustomError::new)?; + server.await?; Ok(()) } @@ -39,4 +39,4 @@ where } #[doc = include_str!("../README.md")] -pub type ShuttleActixWeb = Result, shuttle_runtime::Error>; +pub type ShuttleActixWeb = Result, shuttle_runtime::BoxDynError>; diff --git a/services/shuttle-axum/src/lib.rs b/services/shuttle-axum/src/lib.rs index a517df1ccb..efcdb08322 100644 --- a/services/shuttle-axum/src/lib.rs +++ b/services/shuttle-axum/src/lib.rs @@ -1,5 +1,4 @@ #![doc = include_str!("../README.md")] -use shuttle_runtime::{CustomError, Error}; use std::net::SocketAddr; #[cfg(feature = "axum")] @@ -17,27 +16,19 @@ pub struct AxumService(pub Router); #[shuttle_runtime::async_trait] impl shuttle_runtime::Service for AxumService { - /// Takes the router that is returned by the user in their [shuttle_runtime::main] function - /// and binds to an address passed in by shuttle. - async fn bind(mut self, addr: SocketAddr) -> Result<(), Error> { + async fn bind(mut self, addr: SocketAddr) -> Result<(), shuttle_runtime::BoxDynError> { #[cfg(feature = "axum")] axum::serve( - shuttle_runtime::tokio::net::TcpListener::bind(addr) - .await - .map_err(CustomError::new)?, + shuttle_runtime::tokio::net::TcpListener::bind(addr).await?, self.0, ) - .await - .map_err(CustomError::new)?; + .await?; #[cfg(feature = "axum-0-7")] axum_0_7::serve( - shuttle_runtime::tokio::net::TcpListener::bind(addr) - .await - .map_err(CustomError::new)?, + shuttle_runtime::tokio::net::TcpListener::bind(addr).await?, self.0, ) - .await - .map_err(CustomError::new)?; + .await?; Ok(()) } @@ -50,4 +41,4 @@ impl From for AxumService { } #[doc = include_str!("../README.md")] -pub type ShuttleAxum = Result; +pub type ShuttleAxum = Result; diff --git a/services/shuttle-poem/src/lib.rs b/services/shuttle-poem/src/lib.rs index af10bc3ce8..227bd703f1 100644 --- a/services/shuttle-poem/src/lib.rs +++ b/services/shuttle-poem/src/lib.rs @@ -10,11 +10,13 @@ impl shuttle_runtime::Service for PoemService where T: poem::Endpoint + Send + 'static, { - async fn bind(mut self, addr: std::net::SocketAddr) -> Result<(), shuttle_runtime::Error> { + async fn bind( + mut self, + addr: std::net::SocketAddr, + ) -> Result<(), shuttle_runtime::BoxDynError> { poem::Server::new(poem::listener::TcpListener::bind(addr)) .run(self.0) - .await - .map_err(shuttle_runtime::CustomError::new)?; + .await?; Ok(()) } @@ -30,4 +32,4 @@ where } #[doc = include_str!("../README.md")] -pub type ShuttlePoem = Result, shuttle_runtime::Error>; +pub type ShuttlePoem = Result, shuttle_runtime::BoxDynError>; diff --git a/services/shuttle-rama/src/lib.rs b/services/shuttle-rama/src/lib.rs index 651af56fbc..949415805e 100644 --- a/services/shuttle-rama/src/lib.rs +++ b/services/shuttle-rama/src/lib.rs @@ -6,7 +6,7 @@ use rama::{ http::{Request, server::HttpServer, service::web::response::IntoResponse}, tcp::server::TcpListener, }; -use shuttle_runtime::{CustomError, Error, tokio}; +use shuttle_runtime::tokio; use std::{convert::Infallible, fmt, net::SocketAddr}; /// A wrapper type for [`Service`] so we can implement [`shuttle_runtime::Service`] for it. @@ -102,11 +102,10 @@ where { /// Takes the service that is returned by the user in their [shuttle_runtime::main] function /// and binds to an address passed in by shuttle. - async fn bind(self, addr: SocketAddr) -> Result<(), Error> { + async fn bind(self, addr: SocketAddr) -> Result<(), shuttle_runtime::BoxDynError> { TcpListener::build_with_state(self.state) .bind(addr) - .await - .map_err(|err| Error::BindPanic(err.to_string()))? + .await? .serve(self.svc.0) .await; Ok(()) @@ -122,21 +121,20 @@ where { /// Takes the service that is returned by the user in their [shuttle_runtime::main] function /// and binds to an address passed in by shuttle. - async fn bind(self, addr: SocketAddr) -> Result<(), Error> { + async fn bind(self, addr: SocketAddr) -> Result<(), shuttle_runtime::BoxDynError> { // shuttle only supports h1 between load balancer <=> web service, // h2 is terminated by shuttle's load balancer HttpServer::http1() .listen_with_state(self.state, addr, self.svc.0) - .await - .map_err(|err| CustomError::new(OpaqueError::from_boxed(err)))?; + .await?; Ok(()) } } #[doc = include_str!("../README.md")] -pub type ShuttleRamaTransport = Result, State>, Error>; +pub type ShuttleRamaTransport = + Result, State>, shuttle_runtime::BoxDynError>; #[doc = include_str!("../README.md")] -pub type ShuttleRamaApplication = Result, State>, Error>; - -pub use shuttle_runtime::{Error as ShuttleError, Service as ShuttleService}; +pub type ShuttleRamaApplication = + Result, State>, shuttle_runtime::BoxDynError>; diff --git a/services/shuttle-rocket/src/lib.rs b/services/shuttle-rocket/src/lib.rs index 358288c4e2..8323d74b4f 100644 --- a/services/shuttle-rocket/src/lib.rs +++ b/services/shuttle-rocket/src/lib.rs @@ -8,9 +8,7 @@ pub struct RocketService(pub rocket::Rocket); #[shuttle_runtime::async_trait] impl shuttle_runtime::Service for RocketService { - /// Takes the router that is returned by the user in their [shuttle_runtime::main] function - /// and binds to an address passed in by shuttle. - async fn bind(mut self, addr: SocketAddr) -> Result<(), shuttle_runtime::Error> { + async fn bind(mut self, addr: SocketAddr) -> Result<(), shuttle_runtime::BoxDynError> { let shutdown = rocket::config::Shutdown { ctrlc: false, ..rocket::config::Shutdown::default() @@ -25,12 +23,7 @@ impl shuttle_runtime::Service for RocketService { .merge((rocket::Config::LOG_LEVEL, rocket::config::LogLevel::Off)) .merge((rocket::Config::SHUTDOWN, shutdown)); - let _rocket = self - .0 - .configure(config) - .launch() - .await - .map_err(shuttle_runtime::CustomError::new)?; + let _rocket = self.0.configure(config).launch().await?; Ok(()) } @@ -43,4 +36,4 @@ impl From> for RocketService { } #[doc = include_str!("../README.md")] -pub type ShuttleRocket = Result; +pub type ShuttleRocket = Result; diff --git a/services/shuttle-salvo/src/lib.rs b/services/shuttle-salvo/src/lib.rs index 10ae3334cc..725b64ca24 100644 --- a/services/shuttle-salvo/src/lib.rs +++ b/services/shuttle-salvo/src/lib.rs @@ -1,6 +1,5 @@ #![doc = include_str!("../README.md")] use salvo::Listener; -use shuttle_runtime::Error; use std::net::SocketAddr; pub use salvo; @@ -10,9 +9,7 @@ pub struct SalvoService(pub salvo::Router); #[shuttle_runtime::async_trait] impl shuttle_runtime::Service for SalvoService { - /// Takes the router that is returned by the user in their [shuttle_runtime::main] function - /// and binds to an address passed in by shuttle. - async fn bind(mut self, addr: SocketAddr) -> Result<(), Error> { + async fn bind(mut self, addr: SocketAddr) -> Result<(), shuttle_runtime::BoxDynError> { let listener = salvo::conn::TcpListener::new(addr).bind().await; salvo::Server::new(listener).serve(self.0).await; @@ -28,4 +25,4 @@ impl From for SalvoService { } #[doc = include_str!("../README.md")] -pub type ShuttleSalvo = Result; +pub type ShuttleSalvo = Result; diff --git a/services/shuttle-serenity/src/lib.rs b/services/shuttle-serenity/src/lib.rs index b89eeb4560..1a1f14a2e3 100644 --- a/services/shuttle-serenity/src/lib.rs +++ b/services/shuttle-serenity/src/lib.rs @@ -1,5 +1,4 @@ #![doc = include_str!("../README.md")] -use shuttle_runtime::{CustomError, Error}; use std::net::SocketAddr; #[cfg(feature = "serenity")] @@ -17,10 +16,8 @@ pub struct SerenityService(pub Client); #[shuttle_runtime::async_trait] impl shuttle_runtime::Service for SerenityService { - /// Takes the client that is returned by the user in their [shuttle_runtime::main] function - /// and starts it. - async fn bind(mut self, _addr: SocketAddr) -> Result<(), Error> { - self.0.start_autosharded().await.map_err(CustomError::new)?; + async fn bind(mut self, _addr: SocketAddr) -> Result<(), shuttle_runtime::BoxDynError> { + self.0.start_autosharded().await?; Ok(()) } @@ -33,4 +30,4 @@ impl From for SerenityService { } #[doc = include_str!("../README.md")] -pub type ShuttleSerenity = Result; +pub type ShuttleSerenity = Result; diff --git a/services/shuttle-thruster/src/lib.rs b/services/shuttle-thruster/src/lib.rs index c972bb4284..1525521cb4 100644 --- a/services/shuttle-thruster/src/lib.rs +++ b/services/shuttle-thruster/src/lib.rs @@ -1,5 +1,4 @@ #![doc = include_str!("../README.md")] -use shuttle_runtime::Error; use std::net::SocketAddr; pub use thruster; @@ -12,9 +11,7 @@ impl shuttle_runtime::Service for ThrusterService where T: thruster::ThrusterServer + Send + 'static, { - /// Takes the server that is returned by the user in their [shuttle_runtime::main] function - /// and binds to an address passed in by shuttle. - async fn bind(mut self, addr: SocketAddr) -> Result<(), Error> { + async fn bind(mut self, addr: SocketAddr) -> Result<(), shuttle_runtime::BoxDynError> { self.0.build(&addr.ip().to_string(), addr.port()).await; Ok(()) @@ -31,4 +28,4 @@ where } #[doc = include_str!("../README.md")] -pub type ShuttleThruster = Result, Error>; +pub type ShuttleThruster = Result, shuttle_runtime::BoxDynError>; diff --git a/services/shuttle-tide/src/lib.rs b/services/shuttle-tide/src/lib.rs index fe758aa24c..de530d1cbc 100644 --- a/services/shuttle-tide/src/lib.rs +++ b/services/shuttle-tide/src/lib.rs @@ -1,5 +1,4 @@ #![doc = include_str!("../README.md")] -use shuttle_runtime::{CustomError, Error}; use std::net::SocketAddr; pub use tide; @@ -12,10 +11,8 @@ impl shuttle_runtime::Service for TideService where T: Clone + Send + Sync + 'static, { - /// Takes the router that is returned by the user in their [shuttle_runtime::main] function - /// and binds to an address passed in by shuttle. - async fn bind(mut self, addr: SocketAddr) -> Result<(), Error> { - self.0.listen(addr).await.map_err(CustomError::new)?; + async fn bind(mut self, addr: SocketAddr) -> Result<(), shuttle_runtime::BoxDynError> { + self.0.listen(addr).await?; Ok(()) } @@ -28,4 +25,4 @@ impl From> for TideService { } #[doc = include_str!("../README.md")] -pub type ShuttleTide = Result, Error>; +pub type ShuttleTide = Result, shuttle_runtime::BoxDynError>; diff --git a/services/shuttle-tower/src/lib.rs b/services/shuttle-tower/src/lib.rs index b20483a0a1..4c9aeab9ee 100644 --- a/services/shuttle-tower/src/lib.rs +++ b/services/shuttle-tower/src/lib.rs @@ -1,5 +1,4 @@ #![doc = include_str!("../README.md")] -use shuttle_runtime::{CustomError, Error}; use std::net::SocketAddr; pub use tower; @@ -18,14 +17,9 @@ where T::Error: std::error::Error + Send + Sync, T::Future: std::future::Future + Send + Sync, { - /// Takes the service that is returned by the user in their [shuttle_runtime::main] function - /// and binds to an address passed in by shuttle. - async fn bind(mut self, addr: SocketAddr) -> Result<(), Error> { + async fn bind(mut self, addr: SocketAddr) -> Result<(), shuttle_runtime::BoxDynError> { let shared = tower::make::Shared::new(self.0); - hyper::Server::bind(&addr) - .serve(shared) - .await - .map_err(CustomError::new)?; + hyper::Server::bind(&addr).serve(shared).await?; Ok(()) } @@ -47,4 +41,4 @@ where } #[doc = include_str!("../README.md")] -pub type ShuttleTower = Result, Error>; +pub type ShuttleTower = Result, shuttle_runtime::BoxDynError>; diff --git a/services/shuttle-warp/src/lib.rs b/services/shuttle-warp/src/lib.rs index 6faef130ef..d675a8cac5 100644 --- a/services/shuttle-warp/src/lib.rs +++ b/services/shuttle-warp/src/lib.rs @@ -1,5 +1,4 @@ #![doc = include_str!("../README.md")] -use shuttle_runtime::Error; use std::net::SocketAddr; use std::ops::Deref; @@ -14,9 +13,7 @@ where T: Send + Sync + Clone + 'static + warp::Filter, T::Extract: warp::reply::Reply, { - /// Takes the router that is returned by the user in their [shuttle_runtime::main] function - /// and binds to an address passed in by shuttle. - async fn bind(mut self, addr: SocketAddr) -> Result<(), Error> { + async fn bind(mut self, addr: SocketAddr) -> Result<(), shuttle_runtime::BoxDynError> { warp::serve((*self).clone()).run(addr).await; Ok(()) } @@ -41,4 +38,5 @@ impl Deref for WarpService { } #[doc = include_str!("../README.md")] -pub type ShuttleWarp = Result>, Error>; +pub type ShuttleWarp = + Result>, shuttle_runtime::BoxDynError>;