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
bosoncrate 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, andserde_jsonto 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 _;inmain).
§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:
| Item | Purpose |
|---|---|
NotifyUserParams | Serde payload struct for task arguments |
NotifyUser | Handle type with send_with(actor_json, params) |
__notify_user_impl | Original 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):
| Attribute | Default | Meaning |
|---|---|---|
name | (required) | Registry key and enqueue target |
priority | 1 | Default priority (lower = higher priority) |
pool | "global" | Worker pool name |
idempotency_mode | (inherit) | "lwt" or "none" (override runtime default) |
max_attempts | 3 | Default retry max attempts |
base_delay_ms | 1000 | Retry base delay in milliseconds |
backoff_multiplier | 2.0 | Retry backoff multiplier |
max_delay_ms | 30000 | Retry max delay cap in milliseconds |
max_in_flight | 100 | Default max in-flight jobs (0 = unlimited) |
max_enqueue_per_second | 50 | Default 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 exampleboson_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.