task

Attribute Macro task 

Source
#[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 Input and Output types from the run() signature
  • Automatically implements the Task trait
  • 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