Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sequential Composition

Sequential composition chains steps where output flows from one to the next.

The .then() Combinator

#![allow(unused)]
fn main() {
let workflow = step_a.then(step_b);
}

The output type of step_a must match the input type of step_b.

Example

#![allow(unused)]
fn main() {
use naaf_core::Step;

// A: String → Code
let generate = Step::builder(GenerateCode)
    .validate(SyntaxCheck)
    .build();

// B: Code → TestResults
let test = Step::builder(RunTests)
    .validate(TestResultsCheck)
    .build();

// C: TestResults → FinalOutput
let format = Step::builder(FormatOutput)
    .validate(FinalCheck)
    .build();

// Chain: String → Code → TestResults → FinalOutput
let pipeline = generate.then(test).then(format);

let output = pipeline.run(&runtime, &"build a counter".to_string()).await?;
}

Type Conversion

Use Materialiser for type conversion:

#![allow(unused)]
fn main() {
use naaf_core::Materialiser;

// A returns Code, B expects PathBuf
let generate_and_save = Step::builder(GenerateCode)
    .materialise(WriteToFile)
    .validate(FileCheck)
    .build();

// B expects PathBuf, A returns String - types match now
let pipeline = generate_and_save.then(run_tests);
}

Short-circuit Evaluation

The pipeline stops on first error:

#![allow(unused)]
fn main() {
let result = pipeline.run(&runtime, &input).await;

match result {
    Ok(output) => println!("Success: {:?}", output),
    Err(e) => {
        // Execution stopped at the failing step
        eprintln!("Pipeline failed: {:?}", e);
    }
}
}

With Retry

Each step in the pipeline can have its own retry policy:

#![allow(unused)]
fn main() {
use naaf_core::RetryPolicy;

let pipeline = Step::builder(GenerateCode)  // No retry
    .validate(SyntaxCheck)
    .build()
    .then(
        Step::builder(RunTests)  // With retry
            .validate(TestCheck)
            .repair_with(TestRepairer)
            .retry_policy(RetryPolicy::new(3))
            .build()
    );
}

See Also