Run your Rust CLI programs as state machines with persistence and recovery abilities

Overview

version-badge docs-badge license-badge

step-machine

Run your CLI programs as state machines with persistence and recovery abilities. When such a program breaks you'll have opportunity to change the external world (create a missing folder, change a file permissions or something) and continue the program from the step it was interrupted on.

Usage

Let's toss two coins and make sure they both landed on the same side. We express the behaviour as two states of our machine. Step logic is implemented in State::next() methods which return the next state or None for the last step (the full code is in examples/coin.rs).

#[derive(Debug, Serialize, Deserialize, From)]
enum Machine {
    FirstToss(FirstToss),
    SecondToss(SecondToss),
}

#[derive(Debug, Serialize, Deserialize)]
struct FirstToss;
impl FirstToss {
    fn next(self) -> StepResult {
        let first_coin = Coin::toss();
        println!("First coin: {:?}", first_coin);
        Ok(Some(SecondToss { first_coin }.into()))
    }
}

#[derive(Debug, Serialize, Deserialize)]
struct SecondToss {
    first_coin: Coin,
}
impl SecondToss {
    fn next(self) -> StepResult {
        let second_coin = Coin::toss();
        println!("Second coin: {:?}", second_coin);
        ensure!(second_coin == self.first_coin, "Coins landed differently");
        println!("Coins match");
        Ok(None)
    }
}

Then we start our machine like this:

let init_state = FirstToss.into();
let mut engine = Engine::<Machine>::new(init_state)?.restore()?;
engine.drop_error()?;
engine.run()?;

We initialize the Engine with the first step. Then we restore the previous state if the process was interrupted (e.g. by an error). Then we drop a possible error and run all the steps to completion.

Let's run it now:

$ cargo run --example coin
First coin: Heads
Second coin: Tails
Error: Coins landed differently

We weren't lucky this time and the program resulted in an error. Let's run it again:

$ cargo run --example coin
Second coin: Heads
Coins match

Notice that, thanks to the restore(), our machine run from the step it was interrupted, knowing about the first coin landed on heads.

You might also like...
CLI application to run clang-format on a set of files specified using globs in a JSON configuration file.
CLI application to run clang-format on a set of files specified using globs in a JSON configuration file.

run_clang_format CLI application for running clang-format for an existing .clang-format file on a set of files, specified using globs in a .json confi

A run-codes cli front end with some extra features

run-cli Run-cli A run-codes cli front end with some extra features Report Bug · Request Feature Table of Contents About The Project Built With Getting

CLI application to run clang-tidy on a set of files specified using globs in a JSON configuration file.
CLI application to run clang-tidy on a set of files specified using globs in a JSON configuration file.

run-clang-tidy CLI application for running clang-tidy for an existing .clang-tidy file on a set of files, specified using globs in a .json configurati

I'm currently learning Rust and these are my first programs with this language

learning-Rust I follow the Rust by example official doc for learning That is also available in 'doc pdf' alongside another great rust learning sheet I

A simple, opinionated way to run containers for tests in your Rust project.

rustainers rustainers is a simple, opinionated way to run containers for tests. TLDR More information about this crate can be found in the crate docum

🕺 Run React code snippets/components from your command-line without config

Run React code snippets/components from your command-line without config.

Run the right version of python, in the right environment, for your project

rpy Do you deal with lots of virtual python environments? rpy is for you! Before rpy: ~/dev/prj$ env PYTHONPATH=src/py path/to/my/interpreter src/py/m

Experimental extension that brings OpenAI API to your PostgreSQL to run queries in human language.

Postgres ChatGPT Experimental PostgreSQL extension that enables the use of OpenAI GPT API inside PostgreSQL, allowing for queries to be written usi

Animated app icons in your Dock that can run an arbitrary shell script when clicked.
Animated app icons in your Dock that can run an arbitrary shell script when clicked.

Live App Icon for Mac Animated app icons in your Dock that can run an arbitrary shell script when clicked. Requirements macOS 13 (Ventura) or higher X

Owner
Imbolc
Imbolc
Rustato: A powerful, thread-safe global state management library for Rust applications, offering type-safe, reactive state handling with an easy-to-use macro-based API.

Rustato State Manager A generical thread-safe global state manager for Rust Introduction • Features • Installation • Usage • Advanced Usage • Api Refe

BiteCraft 8 Sep 16, 2024
Share clipboard between machines on your local network.

Clipshare Do you ever have to work on multiple machines? Do you ever used your Github™ Gists just to send some text between then? Clipshare is here to

Rodrigo Navarro 39 Jun 19, 2023
A visual canvas and virtual machine for writing assembly to build cool things. Create machines and connect them together.

Visual Assembly Canvas A highly visual assembly editor, infinite canvas for wiring blocks and machines together, bytecode virtual machine runnable nat

Phoomparin Mano 31 Oct 11, 2023
A visual canvas and virtual machine for writing assembly to build cool things. Create machines and connect them together.

Visual Assembly Canvas A highly visual assembly editor, infinite canvas for wiring blocks and machines together, bytecode virtual machine runnable nat

Phoomparin Mano 32 Oct 11, 2023
A slightly smart clipboard tool - leverage the filesystem to persist across machines after shutdown.

clipd A slightly smart clipboard using the filesystem under ~/.clipd to persist after shutdown. cowsay "clipd is great" | clipd copy clipd paste ____

null 5 Aug 9, 2022
Send files between machines - no installation required!

skicka.pwy.io:99 Skicka (from Swedish send) allows to send files between machines - no installation required! Transmitting a file is as easy as piping

Patryk Wychowaniec 55 Jul 12, 2023
A lightweight terminal tool to manage processes in Unix machines.

TTV v0.0.1 TTV (term-task-viewer) is a lightweight tool to view and manage active processes in Unix machines. It provides an easy interface with vim-l

Caio Ishikawa 9 Aug 29, 2023
This is the data collector that gets your system's state and sends it to the backend

⚡ Installation Linux curl -s https://raw.githubusercontent.com/xornet-cloud/Reporter/main/scripts/install.sh | sudo bash Windows Invoke-Command -Scrip

Xornet 18 Sep 3, 2022
Recompile Rust faster. Good for your flow state.

plonk Plonk is a development-time build tool for Rust projects. cargo install cargo-plonk # fn main() { # lib::say_hello(); # } $ cargo build -p exam

Divy Srivastava 16 Dec 12, 2023
koyo is a cli tool that lets you run commands as another user. It is similar to doas or sudo.

koyo is a cli tool that lets you run commands as another user. It is similar to doas or sudo.

null 3 Nov 27, 2021