Skip to main content

Crate apalis

Crate apalis 

Source
Expand description

apalis

Simple and extensible multithreaded background task and messages processing library for Rust


Β§Features

  • Simple, predictable task handling - Task handlers are just async functions, with a macro-free API
  • Robust task execution - Built-in retries, rate limiting, timeouts, idempotency, and error handling
  • Multiple storage backends - Redis, PostgreSQL, SQLite, and in-memory storage
  • Advanced task management - Prioritization, scheduling, metadata, and result tracking
  • Scalable by design - Distributed backends with configurable concurrency and multi-threaded execution
  • Lightweight and lazy - Like a Future, workers do nothing until polled or woken: no busy-waiting
  • Familiar dependency injection - Similar to popular frameworks like actix and axum
  • Runtime agnostic - Works with tokio, async-std, and other async runtimes
  • Production ready - Built-in monitoring, metrics, graceful shutdown, and comprehensive error reporting
  • Extensible middleware - Take full advantage of the tower ecosystem of services and utilities
  • Optional web interface - Manage and monitor tasks through a web UI

Β§Crate ecosystem

Β§Message queues

CrateExamplesFeatures
apalis-amqp Crates.iobasicπŸ” πŸ“… πŸ”’ πŸ“‘ πŸ‘·
apalis-nats Crates.ioexamplesπŸ” πŸ“… πŸ”’ πŸ“‘ πŸ‘·
apalis-rsmq Crates.ioexamplesπŸ” πŸ“… πŸ”’ πŸ“‘ πŸ‘·

Β§Persistence backends

CrateExamplesFeatures
apalis-redis Crates.iobasicπŸ” πŸ“… πŸ”’ πŸ“‘ πŸ‘· ⏯️
apalis-sqlite Crates.iobasicπŸ” πŸ“… πŸ”’ πŸ“‘ πŸ‘· ⏯️
apalis-postgres Crates.iobasicπŸ” πŸ“… πŸ”’ πŸ“‘ πŸ‘· ⏯️
apalis-mysql Crates.iobasicπŸ” πŸ“… πŸ”’ πŸ“‘ πŸ‘· ⏯️
apalis-pgmq Crates.ioexamplesπŸ” πŸ“… πŸ”’ πŸ“‘ πŸ‘· ⏯️

Β§Scheduling

CrateExamplesFeatures
apalis-cron Crates.ioexamplesπŸ” πŸ“…

Β§Core & tooling

CrateExamplesFeatures
apalisexamplesπŸ” πŸ“… πŸ”’ πŸ“‘ πŸ‘·
apalis-core:πŸ” πŸ“…
apalis-workflowrepositoryπŸ” πŸ“… πŸ”’
apalis-boardexamplesπŸ” πŸ“… πŸ”’ πŸ“‘ πŸ‘·
apalis-board-apiaxum actixπŸ” πŸ“… πŸ”’ πŸ“‘ πŸ‘·

Β§Feature legend

  • πŸ” Retries: automatically retry failed tasks.
  • πŸ“… Scheduling: delayed or scheduled execution.
  • πŸ”’ Unique jobs: deduplication or idempotency.
  • ⏯️ Resumable jobs: resume interrupted jobs or workflows.
  • πŸ” Task leases: time-limited task ownership, visibility timeouts, or orphan recovery.
  • πŸ“‘ Pubsub / realtime: event-driven notifications or realtime updates.
  • πŸ‘· Worker management: worker discovery, monitoring, lifecycle, or management APIs.

Β§Getting Started

To get started, just add to Cargo.toml

[dependencies]
apalis = { version = "1.0.0" }
# apalis-redis = { version = "1.0.0" } # Use redis/sqlite/postgres etc

Β§Usage

use apalis::prelude::*;
use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize, Clone)]
struct Email {
    to: String,
}

/// A function called for every task
async fn send_email(task: Email, data: Data<usize>) {
  // execute task
}


#[tokio::main]
async fn main() {
    let mut storage = MemoryStorage::new();
     storage
        .push(Email {
            to: "test@example.com".to_string(),
        })
        .await
        .expect("Could not add tasks");

    WorkerBuilder::new("email-worker")
      .backend(storage)
      .concurrency(2)
      .parallelize(tokio::spawn)
      .data(0usize)
      .build(send_email)
      .run()
      .await;
}

Β§Workflows

  • apalis has first class support for sequential, dag and conditional workflows.
use apalis::prelude::*;
use apalis_workflow::*;
use std::time::Duration;
use apalis_file_storage::JsonStorage;;

#[tokio::main]
async fn main() {
   let workflow = SteppedFlow::new("odd-numbers-workflow")
       .delay_for(Duration::from_millis(1000))
       .and_then(|a: usize| async move { Ok::<_, BoxDynError>((0..a).collect::<Vec<_>>()) })
       .filter_map(|x| async move { if x % 2 != 0 { Some(x) } else { None } })
       .and_then(|a: Vec<usize>| async move {
           println!("Sum: {}", a.iter().sum::<usize>());
           Ok::<_, BoxDynError>(())
        });

   let mut in_memory = JsonStorage::new_temp().unwrap();

   in_memory.push_start(10).await.unwrap();

   let worker = WorkerBuilder::new("rango-tango")
       .backend(in_memory)
       .on_event(|ctx, ev| {
           println!("On Event = {:?}", ev);
       })
       .build(workflow);
   worker.run().await.unwrap();
}

For more functionality like fold, filter_map and other combinators checkout the docs

Β§How apalis works

Here is a basic example of how the core parts integrate

sequenceDiagram
    participant App
    participant Worker
    participant Backend

    App->>+Backend: Add task to queue
    Backend-->>+Worker: Job data
    Worker->>+Backend: Update task status to 'Running'
    Worker->>+App: Started task
    loop task execution
        Worker-->>-App: Report task progress
    end
    Worker->>+Backend: Update task status to 'completed'

Β§Observability

With the web UI, you can manage your jobs through a simple interface. Check out this working example to see how it works.

Workers Screenshot

Β§Integrations

  • zino: Next-generation framework for composable applications in Rust.
  • spring-rs: Application framework written in Rust, inspired by Java’s SpringBoot

Β§Projects using apalis

  • Ryot: A self hosted platform for tracking various facets of your life - media, fitness etc.
  • Hyprnote: Local-first AI Notepad for Private Meetings
  • oxy: A framework for building SQL agents and automations for analytics.
  • OpenZeppelin Relayer: OpenZeppelin relayer service
  • Summarizer: Podcast summarizer
  • Universal Inbox: Universal Inbox is a solution that centralizes all your notifications and tasks in one place to create a unique inbox.
  • Hatsu: Self-hosted and fully-automated ActivityPub bridge for static sites.
  • Stamon: A lightweight self-hosted status monitoring tool
  • Gq: open-source filtering tool for JSON and YAML files

Β§External examples

Β§Resources

Β§Thanks to

  • tower - Tower is a library of modular and reusable components for building robust networking clients and servers.
  • redis-rs - Redis library for rust
  • sqlx - The Rust SQL Toolkit
  • cron - A cron expression parser and schedule explorer

Β§Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Β§Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Β§Contributors

See also the list of contributors who participated in this project.

Β§License

This project is licensed under the MIT License - see the LICENSE.md file for details

Β§Feature flags

  • tracing (enabled by default) β€” Support Tracing πŸ‘€
  • sentry β€” Support for Sentry exception and performance monitoring
  • prometheus β€” Support Prometheus metrics
  • opentelemetry β€” Support OpenTelemetry metrics
  • retry (enabled by default) β€” Support direct retrying tasks
  • timeout (enabled by default) β€” Support timeouts on tasks
  • limit (enabled by default) β€” πŸ’ͺ Limit the amount of tasks
  • filter β€” Support filtering tasks based on a predicate
  • catch-panic (enabled by default) β€” Captures panics in executions and convert them to errors
  • config (enabled by default) β€” Allow running workers using configuration
  • task-context β€” Enables tracking of tasks
  • shared β€” Enables cloning backends that dont implement clone
  • full β€” All available features

ModulesΒ§

configconfig
Worker configuration utilities allowing easier worker decoration
layers
Inbuilt middleware build on top of tower’s Layer
prelude
A β€œprelude” of common imports