pub trait ResourceBuilder<T> {
    type Config: Serialize;
    type Output: Serialize + DeserializeOwned;

    const TYPE: Type;

    // Required methods
    fn new() -> Self;
    fn config(&self) -> &Self::Config;
    fn output<'life0, 'async_trait>(
        self,
        factory: &'life0 mut dyn Factory
    ) -> Pin<Box<dyn Future<Output = Result<Self::Output, Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;
    fn build<'life0, 'async_trait>(
        build_data: &'life0 Self::Output
    ) -> Pin<Box<dyn Future<Output = Result<T, Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;
}
Expand description

Used to get resources of type T from factories.

This is mainly meant for consumption by our code generator and should generally not be called by users.

Creating your own managed resource

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.

Your resource will be available on a shuttle_runtime::main function as follow:

#[shuttle_runtime::main]
async fn my_service([custom_resource_crate::namespace::B] custom_resource: T)
    -> shuttle_axum::ShuttleAxum {}

Here custom_resource_crate::namespace is the crate and namespace to a builder B that implements ResourceBuilder to create resource T.

Example

pub struct Builder {
    name: String,
}

pub struct Resource {
    name: String,
}

impl Builder {
    /// Name to give resource
    pub fn name(self, name: &str) -> Self {
        self.name = name.to_string();

        self
    }
}

#[async_trait]
impl ResourceBuilder<Resource> for Builder {
    const TYPE: Type = Type::Custom;

    type Config = Self;

    type Output = String;

    fn new() -> Self {
        Self {
            name: String::new(),
        }
    }

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


    async fn output(self, factory: &mut dyn Factory) -> Result<Self::Output, shuttle_service::Error> {
        Ok(self.name)
    }

    async fn build(build_data: &Self::Output) -> Result<Resource, shuttle_service::Error> {
        Ok(Resource { name: build_data })
    }
}

Then using this resource in a service:

#[shuttle_runtime::main]
async fn my_service(
    [custom_resource_crate::Builder(name = "John")] resource: custom_resource_crate::Resource
)
    -> shuttle_axum::ShuttleAxum {}

Required Associated Types§

source

type Config: Serialize

The internal config being constructed by this builder. This will be used to find cached Self::Output.

source

type Output: Serialize + DeserializeOwned

The output type used to build this resource later

Required Associated Constants§

source

const TYPE: Type

The type of resource this creates

Required Methods§

source

fn new() -> Self

Create a new instance of this resource builder

source

fn config(&self) -> &Self::Config

Get the internal config state of the builder

If the exact same config was returned by a previous deployement that used this resource, then Self::output() will not be called to get the builder output again. Rather the output state of the previous deployment will be passed to Self::build().

source

fn output<'life0, 'async_trait>( self, factory: &'life0 mut dyn Factory ) -> Pin<Box<dyn Future<Output = Result<Self::Output, Error>> + Send + 'async_trait>>where Self: 'async_trait, 'life0: 'async_trait,

Get the config output of this builder

This method is where the actual resource provisioning should take place and is expected to take the longest. It can at times even take minutes. That is why the output of this method is cached and calling this method can be skipped as explained in Self::config().

source

fn build<'life0, 'async_trait>( build_data: &'life0 Self::Output ) -> Pin<Box<dyn Future<Output = Result<T, Error>> + Send + 'async_trait>>where Self: 'async_trait, 'life0: 'async_trait,

Build this resource from its config output

Implementors§