7 个不稳定版本
0.3.0 | 2024 年 5 月 5 日 |
---|---|
0.2.2 | 2022 年 9 月 18 日 |
0.2.0 | 2022 年 8 月 21 日 |
0.1.4 | 2022 年 5 月 21 日 |
0.0.1 | 2021 年 2 月 17 日 |
#33 在 WebSocket
74 每月下载量
在 3 crates 中使用
47KB
1K SLoC
Aper
Aper 是一个用于使用 状态机 进行数据同步的 Rust 库。Aper 提供了将常见数据结构以状态机形式表示的机制,以及一个与传输无关的协议,用于在网络中保持状态机的多个实例同步。
使用案例包括在共享状态上运行的实时多人应用、希望增量双向共享状态更新的客户端-服务器应用以及多人回合制游戏。
什么是状态机?
对于 Aper 而言,状态机简单地是一个实现 StateMachine
并具有以下属性的 struct
或 enum
- 它定义了一个
StateMachine::Transition
类型,通过该类型可以描述状态的所有可能变化。这通常是有用的,尽管不是必需的,该类型是一个enum
类型。 - 它定义了一个
StateMachine::Conflict
类型,用于描述在应用一个在应用时无效的转换时可能发生的冲突。对于简单类型,其中冲突是不可能的,您可以使用NeverConflict
来实现这一点。 - 所有状态更新都是确定性的:如果您克隆一个
StateMachine
和一个Transition
,将克隆的转换应用到克隆的状态的结果必须与将原始转换应用到原始状态的结果相同。
以下是一个实现计数器的示例 StateMachine
use aper::{StateMachine, NeverConflict};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
struct Counter { value: i64 }
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
enum CounterTransition {
Reset,
Increment(i64),
Decrement(i64),
}
impl StateMachine for Counter {
type Transition = CounterTransition;
type Conflict = NeverConflict;
fn apply(&self, event: &CounterTransition) -> Result<Counter, NeverConflict> {
match event {
CounterTransition::Reset => Ok(Counter {value: 0}),
CounterTransition::Increment(amount) => Ok(Counter {value: self.value + amount}),
CounterTransition::Decrement(amount) => Ok(Counter {value: self.value - amount}),
}
}
}
为什么不使用 CRDT?
无冲突复制数据类型 是一种表示在同伴之间共享数据的方式,非常巧妙。为了避免需要中心“真相之源”,CRDTs 需要更新操作(即状态转换)是 交换律 的。这使得它们可以表示许多常见的数据结构,但无法表示任意复杂的更新逻辑。通过依赖于中心权威,状态机方法允许你实现具有任意更新逻辑的数据结构,例如在两个数据结构之间原子地移动值,或者棋盘游戏的规则。
Aper 正在快速发展。请将此视为技术预览。 请参阅 1.0 版本的待解决问题列表
依赖项
~1.7–2.6MB
~57K SLoC