#[task]Expand description
Attribute macro to automatically implement the Task trait.
Apply this to an impl block containing a run() method (sync or async). The macro:
- Derives
InputandOutputtypes from therun()signature - Automatically implements the
Tasktrait - Supports both sync and async run methods
- Supports stateless (no self) and stateful (&self, &mut self) tasks
- Handles various input patterns (no inputs, single input, multiple inputs)
§Task Patterns
The #[task] macro supports three patterns based on state requirements:
§1. Stateless Tasks (No State)
Unit structs for pure computations. Use no self parameter:
ⓘ
use dagx::{task, Task};
struct Add;
#[task]
impl Add {
async fn run(a: &i32, b: &i32) -> i32 {
a + b // Pure function, no state
}
}§2. Read-Only State Tasks
Tasks that read configuration or constant data. Use &self:
ⓘ
use dagx::{task, Task};
struct Multiplier {
factor: i32,
}
#[task]
impl Multiplier {
async fn run(&self, input: &i32) -> i32 {
input * self.factor // Read-only access
}
}§3. Mutable State Tasks
Tasks that accumulate or modify state. Use &mut self:
ⓘ
use dagx::{task, Task};
struct Counter {
count: i32,
}
#[task]
impl Counter {
async fn run(&mut self, increment: &i32) -> i32 {
self.count += increment; // Modifies state
self.count
}
}§Input Patterns
§No Inputs (Source Tasks)
ⓘ
use dagx::{task, Task};
struct LoadData {
value: i32,
}
#[task]
impl LoadData {
async fn run(&mut self) -> i32 {
self.value
}
}
```ignore
# Single Input
```ignore
use dagx::{task, Task};
struct Double;
#[task]
impl Double {
async fn run(&mut self, input: &i32) -> i32 {
input * 2
}
}
```ignore
# Multiple Inputs (up to 8)
```ignore
use dagx::{task, Task};
struct Combine;
#[task]
impl Combine {
async fn run(&mut self, a: &i32, b: &String, c: &bool) -> String {
format!("{}: {} ({})", b, a, c)
}
}
```ignore
- The impl block must contain exactly one `async fn run()` method
- The `run()` method can be stateless (no self parameter) or stateful (`&mut self`)
- All input parameters must be references (e.g., `&i32`, not `i32`)
- The macro requires `Task` to be in scope: `use dagx::Task;`
- For stateless tasks, the struct must implement `Default` (e.g., unit structs)
The macro transforms your implementation into a full `Task` trait implementation.
For stateless tasks (no self parameter):
```ignore
// Your code:
#[task]
impl Add {
async fn run(a: &i32, b: &i32) -> i32 {
a + b
}
}
// Generated:
impl Task for Add {
type Input = (i32, i32);
type Output = i32;
async fn run(&mut self, input: Self::Input) -> Self::Output {
let (a, b) = input;
Self::run_impl(&a, &b).await
}
}
impl Add {
#[inline]
async fn run_impl(a: &i32, b: &i32) -> i32 {
a + b
}
}
```ignore
For stateful tasks (with &mut self):
```ignore
// Your code:
#[task]
impl Counter {
async fn run(&mut self, inc: &i32) -> i32 {
self.count += inc;
self.count
}
}
// Generated:
impl Task for Counter {
type Input = i32;
type Output = i32;
async fn run(&mut self, input: Self::Input) -> Self::Output {
let inc = input;
self.run_impl(&inc).await
}
}
impl Counter {
async fn run_impl(&mut self, inc: &i32) -> i32 {
self.count += inc;
self.count
}
}
```ignore