#bpmn #process #process-flow

snurr

Read BPMN 2.0 files and run the process flow

20 releases (10 breaking)

Uses new Rust 2024

0.13.0 Sep 20, 2025
0.11.0 Jun 1, 2025
0.7.0 Nov 6, 2024

#1 in #bpmn

Download history 31/week @ 2025-08-09 25/week @ 2025-08-16 128/week @ 2025-08-23 42/week @ 2025-08-30 12/week @ 2025-09-06 11/week @ 2025-09-13 150/week @ 2025-09-20 91/week @ 2025-09-27 52/week @ 2025-10-04 45/week @ 2025-10-11 17/week @ 2025-10-18

1,109 downloads per month

MIT license

88KB
2K SLoC

Snurr

Build Status

Snurr can run the process flow from a Business Process Model and Notation (BPMN) 2.0 file created by https://demo.bpmn.io/new.

  • Add your own behavior with Rust code from a small API. The wiring is already setup from the file.
  • Easy to update the BPMN diagram with new Task and Gateways without the need to refactor your old code.
  • The BPMN file is the actual design. Forget outdated documentation.
  • Scaffold the initial BPMN diagram so you don't have to do the boilerplate code.
  • Contains no database.
  • Single or multithreaded (opt in)

Read the Snurr documentation and explore the tests folder for more examples.

NOTE: To view or edit BPMN files in your project you can use the BPMN Editor plugin in VS Code.

Tasks

Example

BPMN diagram used in example.

BPMN example

Usage

[dependencies]
snurr = "0.13"
log = "0.4"
pretty_env_logger = "0.5"
use snurr::Process;

extern crate pretty_env_logger;

#[derive(Debug, Default)]
struct Counter {
    count: u32,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    pretty_env_logger::init();

    let bpmn = Process::<Counter>::new("examples/example.bpmn")?
        .task("Count 1", |input| {
            input.lock().unwrap().count += 1;
            None
        })
        .exclusive("equal to 3", |input| {
            match input.lock().unwrap().count {
                3 => "YES",
                _ => "NO",
            }
            .into()
        })
        .build()?;

    let counter = bpmn.run(Counter::default())?;
    println!("Count: {}", counter.count);
    Ok(())
}

Output

If RUST_LOG=info is set when running example

 INFO  snurr::process::engine > Start: Begin process
 INFO  snurr::process::engine > SequenceFlow: count
 INFO  snurr::process::engine > Task: Count 1
 INFO  snurr::process::engine > SequenceFlow: control
 INFO  snurr::process::engine > Exclusive: equal to 3
 INFO  snurr::process::engine > SequenceFlow: NO
 INFO  snurr::process::engine > Task: Count 1
 INFO  snurr::process::engine > SequenceFlow: control
 INFO  snurr::process::engine > Exclusive: equal to 3
 INFO  snurr::process::engine > SequenceFlow: NO
 INFO  snurr::process::engine > Task: Count 1
 INFO  snurr::process::engine > SequenceFlow: control
 INFO  snurr::process::engine > Exclusive: equal to 3
 INFO  snurr::process::engine > SequenceFlow: YES
 INFO  snurr::process::engine > End: End process
Count: 3

Prepared sample

Run or copy the simple.rs in the examples folder

RUST_LOG=info cargo run --example simple

Dependencies

~1.5–2.4MB
~43K SLoC