1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! The application a cluster replicates
use async_trait;
use AppData;
use Deserialize;
use Serialize;
use DeserializeOwned;
/// The application: request/response types, state, and one method of business logic
///
/// The implementing type IS the application state - a struct holding your data. The framework
/// derives snapshots from it via serde: a snapshot is the serialized state, installing one
/// replaces the state with the deserialized bytes. That makes whole-state serialization the
/// scope of this crate; it serves the coordination/metadata class of app whose state fits in
/// memory (ZooKeeper snapshots the same way). An app whose snapshot is a streamed checkpoint
/// of something larger builds on openraft directly.
///
/// # Example (KV store)
///
/// ```
/// use std::collections::BTreeMap;
///
/// use async_trait::async_trait;
/// use ezraft::EzApp;
/// use serde::Deserialize;
/// use serde::Serialize;
///
/// #[derive(Serialize, Deserialize, Debug, Clone, derive_more::Display)]
/// enum Request {
/// #[display("Set({key})")]
/// Set { key: String, value: String },
/// }
///
/// #[derive(Serialize, Deserialize)]
/// struct Response {
/// value: Option<String>,
/// }
///
/// #[derive(Default, Serialize, Deserialize)]
/// struct KvApp {
/// data: BTreeMap<String, String>,
/// }
///
/// #[async_trait]
/// impl EzApp for KvApp {
/// type Request = Request;
/// type Response = Response;
///
/// async fn apply(&mut self, req: Request) -> Response {
/// match req {
/// // The replaced value, if any: the caller learns what was there
/// // without a second round trip.
/// Request::Set { key, value } => Response {
/// value: self.data.insert(key, value),
/// },
/// }
/// }
///
/// fn read(&self, key: &str) -> Option<serde_json::Value> {
/// self.data.get(key).map(|v| serde_json::Value::String(v.clone()))
/// }
/// }
/// ```