transient

Attribute Macro transient 

#[transient]
Expand description

Define a transient constructor.

Transient constructors are invoked each time a new instance of their output type is needed, even within the same request. The created instances are not cached.

Check out #[singleton] and #[request_scoped] if you need to define constructors with different lifecycles.

§Example

use pavex::methods;

pub struct TemporaryBuffer {
    data: Vec<u8>,
}

#[methods]
impl TemporaryBuffer {
    #[transient]
    pub fn new() -> Self {
        Self {
            data: Vec::with_capacity(1024),
        }
    }
}

TemporaryBuffer::new will be called each time a new instance of TemporaryBuffer is needed, even within the same request.

§Guide

Check out the “Dependency injection” section of Pavex’s guide for a thorough introduction to dependency injection in Pavex applications.

§Registration

You can register a transient constructor with your application in two ways:

The #[transient] macro generates a constant that you can use to refer to the constructor when invoking Blueprint::constructor.

§Arguments

The sections below provide an exhaustive list of all the arguments and flags supported by the transient macro:

NameKindRequired
idArgumentNo
clone_if_necessaryFlagNo
never_cloneFlagNo
allowArgumentNo

§id

By default, Pavex generates a constant named after your type and method (converted to UPPER_SNAKE_CASE) that you use when registering the constructor.

The id argument allows you to customize the name of the generated constant.

§Example

Using the default generated identifier:

use pavex::{methods, Blueprint};

pub struct TokenGenerator {
    // [...]
}

#[methods]
impl TokenGenerator {
    #[transient]
    pub fn new() -> Self {
        Self {
            // [...]
        }
    }
}

let mut bp = Blueprint::new();
// The generated constant is named `TOKEN_GENERATOR_NEW`
bp.constructor(TOKEN_GENERATOR_NEW);

Using a custom identifier:

use pavex::{methods, Blueprint};

pub struct TokenGenerator {
    // [...]
}

#[methods]
impl TokenGenerator {
    #[transient(id = "TOKEN_CONSTRUCTOR")]
    //           👆 Custom identifier
    pub fn new() -> Self {
        Self {
            // [...]
        }
    }
}

let mut bp = Blueprint::new();
// Use the custom identifier when registering
bp.constructor(TOKEN_CONSTRUCTOR);

§clone_if_necessary

By default, Pavex will not clone the output of transient constructors. The clone_if_necessary flag allows Pavex to invoke .clone() on the output if it helps satisfy Rust’s borrow checker.

The constructed type must implement the Clone trait.

This flag is mutually exclusive with never_clone.

§Example

use pavex::{transient, methods};
use uuid::Uuid;

#[derive(Clone)]
pub struct InstanceId {
    value: Uuid,
}

#[methods]
impl InstanceId {
    #[transient(clone_if_necessary)]
    //           👆 Allow cloning when needed
    pub fn new() -> Self {
        Self {
            value: uuid::Uuid::new_v4(),
        }
    }
}

§never_clone

The never_clone flag explicitly prevents Pavex from cloning the output of this constructor. This is the default behavior for transient constructors, so this flag is typically used for clarity and explicitness.

This flag is mutually exclusive with clone_if_necessary.

§Example

use pavex::methods;

pub struct TempFile {
    // Contains non-cloneable resources
    handle: std::fs::File,
}

#[methods]
impl TempFile {
    #[transient(never_clone)]
    //           👆 Explicitly prevent cloning (default behavior)
    pub fn new() -> std::io::Result<Self> {
        Ok(Self {
            handle: std::fs::File::create_new("temp.tmp")?,
        })
    }
}

Pavex will report an error during the code-generation phase if cloning is required but forbidden.

§allow

The allow argument can be used to suppress specific warnings.

Currently, only one value is supported:

  • unused: Suppress warnings if this constructor is registered but never used

§Example

use pavex::methods;

pub struct TraceId {
    // [...]
}

#[methods]
impl TraceId {
    #[transient(allow(unused))]
    //           👆 Don't warn if unused
    pub fn new() -> Self {
        Self {
            // [...]
        }
    }
}