#状态机 #恢复 #持久化 #步进 #能力 #程序 #调试

step-machine

通过持久化和恢复功能运行您的 CLI 程序作为状态机

3 个不稳定版本

0.2.0 2021 年 8 月 26 日
0.1.1 2021 年 8 月 21 日
0.1.0 2021 年 8 月 21 日

#2017算法

每月 29 次下载

MIT/Apache

12KB
147

version-badge docs-badge license-badge

step-machine

将您的 CLI 程序作为具有持久化和恢复功能的状态机运行。当此类程序出错时,您将有机会改变外部世界(创建缺失的文件夹、更改文件权限等)并从中断的地方继续程序。

用法

让我们抛两个硬币并确保它们都落在同一面。我们用我们机器的两个状态来表示这种行为。步进逻辑在 State::next() 方法中实现,这些方法返回下一个状态或 None 表示最后一个步骤(完整代码在 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)
    }
}

然后我们这样启动我们的机器

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

我们用第一步初始化 Engine。然后如果进程被中断(例如,由于错误),则恢复之前的状态。然后我们丢弃可能出现的错误并运行所有步骤直到完成。

现在我们来运行它

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

这次我们运气不好,程序出现了错误。让我们再试一次

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

注意,由于 restore() 的作用,我们的机器从中断的地方继续运行,并知道第一枚硬币落在正面。

依赖项

~0.7–1.5MB
~34K SLoC