Skip to main content

Crate boson_macros

Crate boson_macros 

Source
Expand description

Proc macros for Boson background work.

This crate exposes [task], an attribute macro that turns an async function into a Boson task with:

  • a typed params struct (<FnName>Params),
  • a typed enqueue handle (<TaskName>::send_with),
  • and link-time registration (see Mode 1 / Mode 2 on the boson crate for worker vs enqueue-host boot).

§Define a task

use boson_core::ExecutionContext;

#[boson::task(name = "notify_user")]
pub async fn notify_user(
    ctx: Box<dyn ExecutionContext>,
    user_id: String,
    message: String,
) -> boson_core::Result<()> {
    tracing::info!(actor = ctx.label(), %user_id, %message);
    Ok(())
}

The first parameter must be Box<dyn ExecutionContext>. How that context is built from actor_json is configured when the worker boots — see ExecutionContext and BosonBuilder.

§Enqueue work

After any process that will call send_with has called configure (Mode 1 embedded or Mode 2 enqueue-only host):

let job_id = NotifyUser::send_with(
    serde_json::json!({"System": {"operation": "notify"}}),
    NotifyUserParams {
        user_id: "user:123".into(),
        message: "Welcome!".into(),
    },
).await?;

Pass the same actor_json shape you would use with Boson::enqueue. The worker that runs the job must have discovered the task via auto_registry (and linked the crate that defines it).

§Project setup (once per crate)

  • Depend — add this crate plus quark, boson-runtime, boson-core, serde, and serde_json to the crate that owns the handler (see README).
  • Link — when the handler lives in a library crate, make that crate a dependency of the worker binary so inventory entries are linked (for example use my_worker as _; in main).

§Boot once (not per task)

Worker / enqueue-host boot (BosonBuilder, auto_registry, configure, identity factory) is not repeated for each new task. See the boson crate Getting started and the task_macro example.

§Generated items

For a task function notify_user with task name "notify_user", the macro generates:

ItemPurpose
NotifyUserParamsSerde payload struct for task arguments
NotifyUserHandle type with send_with(actor_json, params)
__notify_user_implOriginal function body (internal)

Registration for worker dispatch is emitted at compile time; boot-time collection is described on TaskRegistry and in the boson crate Mode 1 / Mode 2 sections.

Task handle names are derived from the task name (dots become underscores, PascalCase). Params struct names are derived from the function name.

§Macro attributes

name is required and must be the first attribute. Additional policy fields seed the initial TaskConfig on first enqueue (runtime admin may override later):

AttributeDefaultMeaning
name(required)Registry key and enqueue target
priority1Default priority (lower = higher priority)
pool"global"Worker pool name
idempotency_mode(inherit)"lwt" or "none" (override runtime default)
max_attempts3Default retry max attempts
base_delay_ms1000Retry base delay in milliseconds
backoff_multiplier2.0Retry backoff multiplier
max_delay_ms30000Retry max delay cap in milliseconds
max_in_flight100Default max in-flight jobs (0 = unlimited)
max_enqueue_per_second50Default enqueue rate limit (0 = unlimited)
#[boson::task(
    name = "process_order",
    priority = 10,
    pool = "checkout",
    max_in_flight = 200,
)]
async fn process_order(ctx: Box<dyn ExecutionContext>, order_id: String) -> boson_core::Result<()> {
    Ok(())
}

§Contract

The annotated function must:

  • be async
  • accept Box<dyn ExecutionContext> as the first argument
  • return Result<()> (for example boson_core::Result<()>)
  • include name = "..." as the first macro attribute

Free functions only — methods with &self are rejected at compile time.

Attribute Macros§

task
Marks an async function as a Boson task.