Skip to main content

BackgroundTasks

Struct BackgroundTasks 

Source
pub struct BackgroundTasks { /* private fields */ }
Expand description

Background task queue for running tasks after response is sent.

Tasks are executed in the order they are added, after the response has been sent to the client. This is useful for:

  • Sending emails
  • Writing to external logs
  • Triggering webhooks
  • Updating caches

§Example

use fastapi_core::extract::BackgroundTasks;

async fn handler(mut tasks: BackgroundTasks) -> &'static str {
    tasks.add_task(|| async {
        // Send notification email
        send_email("user@example.com", "Welcome!").await;
    });
    "Response sent, email will be sent in background"
}

§Note

Background tasks run after the response is sent but before the request context is fully cleaned up. They share the same cancellation context as the request, so long-running tasks should check for cancellation.

Implementations§

Source§

impl BackgroundTasks

Source

pub fn new() -> Self

Create a new empty task queue.

Source

pub fn add_task<F, Fut>(&mut self, task: F)
where F: FnOnce() -> Fut + Send + 'static, Fut: Future<Output = ()> + Send + 'static,

Add a background task.

The task will be executed after the response is sent.

Source

pub fn add_sync_task<F>(&mut self, task: F)
where F: FnOnce() + Send + 'static,

Add a synchronous background task.

The task will be executed after the response is sent.

Source

pub fn take_tasks( &mut self, ) -> Vec<Box<dyn FnOnce() -> Pin<Box<dyn Future<Output = ()> + Send>> + Send>>

Take all tasks from the queue.

Source

pub fn is_empty(&self) -> bool

Returns true if there are no tasks.

Source

pub fn len(&self) -> usize

Returns the number of tasks.

Source

pub async fn execute_all(self)

Execute all tasks sequentially.

This is called by the framework after the response is sent. Tasks run in the order they were added (FIFO).

§Error Handling

This method does NOT provide error isolation. If a task panics, subsequent tasks will not run. For panic isolation, use Self::execute_with_panic_isolation() instead.

Since tasks run after the response is sent, panics do not affect the HTTP response that was already delivered to the client.

§Example
let response = app.handle(&ctx, &mut request).await;
// Send response to client...
if let Some(tasks) = App::take_background_tasks(&mut request) {
    tasks.execute_all().await;
}
Source

pub async fn execute_with_context(self, ctx: &RequestContext)

Execute all tasks with cancellation support via RequestContext.

This version checks for cancellation between tasks and respects the request’s cancellation state. Use this when you want background tasks to be cancelled along with the request.

§Arguments
  • ctx - The request context for cancellation checking
§Cancellation Behavior
  • Checks ctx.is_cancelled() before starting each task
  • If cancelled, remaining tasks are skipped
  • Already-running tasks complete before the check
  • Logs the number of skipped tasks
§Integration with asupersync

Background tasks run in the same region as the request. When the region is cancelled (client disconnect, timeout, etc.), subsequent tasks will be skipped. This ensures proper structured concurrency.

§Example
let response = app.handle(&ctx, &mut request).await;
// Send response to client...
if let Some(tasks) = App::take_background_tasks(&mut request) {
    tasks.execute_with_context(&ctx).await;
}
Source

pub async fn execute_with_panic_isolation(self)

Execute tasks with per-task panic isolation using catch_unwind.

This version catches panics that occur when calling the task closure (i.e., when creating the future), allowing subsequent tasks to continue.

§What Is Caught vs. Not Caught
// CAUGHT: Panic in closure before returning future
tasks.add_task(|| {
    panic!("this is caught");
    async {}  // never reached
});

// NOT CAUGHT: Panic inside async block (during .await)
tasks.add_task(|| async {
    panic!("this is NOT caught - propagates and stops remaining tasks");
});

Due to Rust’s async limitation, panics inside the async task body cannot be caught without additional crate dependencies (like futures).

For most use cases where task code is well-behaved, execute_all() or execute_with_context() is sufficient.

Source

pub fn into_inner(self) -> BackgroundTasksInner

Get the inner storage for request extensions.

Trait Implementations§

Source§

impl Clone for BackgroundTasks

Source§

fn clone(&self) -> BackgroundTasks

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for BackgroundTasks

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for BackgroundTasks

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl FromRequest for BackgroundTasks

Source§

type Error = Infallible

Error type when extraction fails.
Source§

async fn from_request( _ctx: &RequestContext, req: &mut Request, ) -> Result<Self, Self::Error>

Extract a value from the request. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, _span: NoopSpan) -> Self

Instruments this future with a span (no-op when disabled).
Source§

fn in_current_span(self) -> Self

Instruments this future with the current span (no-op when disabled).
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ResponseProduces<T> for T