1use axum::Router;
12use axum::body::Bytes;
13use axum::extract::State;
14use axum::routing::post;
15use openraft::BasicNode;
16use openraft::error::{InstallSnapshotError, NetworkError, RPCError, RaftError, RemoteError};
17use openraft::network::{RPCOption, RaftNetwork, RaftNetworkFactory};
18use openraft::raft::{
19 AppendEntriesRequest, AppendEntriesResponse, InstallSnapshotRequest, InstallSnapshotResponse,
20 VoteRequest, VoteResponse,
21};
22use serde::{Deserialize, Serialize};
23
24use crate::cmd::{Cmd, CmdResult};
25use crate::raft::{MocraRaft, Node, NodeId, TypeConfig};
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct JoinRequest {
30 pub node_id: NodeId,
31 pub addr: String,
32}
33
34pub fn raft_router(raft: MocraRaft) -> Router {
39 Router::new()
40 .route("/raft/append", post(append))
41 .route("/raft/vote", post(vote))
42 .route("/raft/snapshot", post(snapshot))
43 .route("/cluster/join", post(join))
44 .route("/cluster/write", post(cluster_write))
45 .with_state(raft)
46}
47
48async fn cluster_write(State(raft): State<MocraRaft>, body: Bytes) -> Vec<u8> {
54 let cmd: Cmd = match rmp_serde::from_slice(&body) {
55 Ok(c) => c,
56 Err(e) => {
57 let out: Result<CmdResult, String> = Err(format!("decode cmd: {e}"));
58 return rmp_serde::to_vec(&out).unwrap_or_default();
59 }
60 };
61 let out: Result<CmdResult, String> = raft
62 .client_write(cmd)
63 .await
64 .map(|r| r.data)
65 .map_err(|e| e.to_string());
66 rmp_serde::to_vec(&out).unwrap_or_default()
67}
68
69async fn join(State(raft): State<MocraRaft>, body: Bytes) -> Vec<u8> {
74 let req: JoinRequest = match rmp_serde::from_slice(&body) {
75 Ok(r) => r,
76 Err(_) => return Vec::new(),
77 };
78 let res = raft
79 .add_learner(req.node_id, BasicNode::new(req.addr), true)
80 .await;
81 let out: Result<(), String> = res.map(|_| ()).map_err(|e| e.to_string());
82 rmp_serde::to_vec(&out).unwrap_or_default()
83}
84
85async fn append(State(raft): State<MocraRaft>, body: Bytes) -> Vec<u8> {
86 let req: AppendEntriesRequest<TypeConfig> = match rmp_serde::from_slice(&body) {
87 Ok(r) => r,
88 Err(_) => return Vec::new(),
89 };
90 let res = raft.append_entries(req).await;
91 rmp_serde::to_vec(&res).unwrap_or_default()
92}
93
94async fn vote(State(raft): State<MocraRaft>, body: Bytes) -> Vec<u8> {
95 let req: VoteRequest<NodeId> = match rmp_serde::from_slice(&body) {
96 Ok(r) => r,
97 Err(_) => return Vec::new(),
98 };
99 let res = raft.vote(req).await;
100 rmp_serde::to_vec(&res).unwrap_or_default()
101}
102
103async fn snapshot(State(raft): State<MocraRaft>, body: Bytes) -> Vec<u8> {
104 let req: InstallSnapshotRequest<TypeConfig> = match rmp_serde::from_slice(&body) {
105 Ok(r) => r,
106 Err(_) => return Vec::new(),
107 };
108 let res = raft.install_snapshot(req).await;
109 rmp_serde::to_vec(&res).unwrap_or_default()
110}
111
112#[derive(Clone)]
116pub struct HttpNetwork {
117 client: reqwest::Client,
118}
119
120impl HttpNetwork {
121 pub fn new() -> Self {
122 Self {
123 client: reqwest::Client::new(),
124 }
125 }
126}
127
128impl Default for HttpNetwork {
129 fn default() -> Self {
130 Self::new()
131 }
132}
133
134pub struct HttpConnection {
136 client: reqwest::Client,
137 target: NodeId,
138 addr: String,
139}
140
141impl HttpConnection {
142 async fn post(&self, path: &str, body: Vec<u8>) -> Result<Vec<u8>, NetworkError> {
145 let url = format!("http://{}{}", self.addr, path);
146 let resp = self
147 .client
148 .post(url)
149 .body(body)
150 .send()
151 .await
152 .map_err(|e| NetworkError::new(&e))?;
153 let bytes = resp.bytes().await.map_err(|e| NetworkError::new(&e))?;
154 Ok(bytes.to_vec())
155 }
156}
157
158impl RaftNetworkFactory<TypeConfig> for HttpNetwork {
159 type Network = HttpConnection;
160
161 async fn new_client(&mut self, target: NodeId, node: &Node) -> Self::Network {
162 HttpConnection {
163 client: self.client.clone(),
164 target,
165 addr: node.addr.clone(),
166 }
167 }
168}
169
170impl RaftNetwork<TypeConfig> for HttpConnection {
171 async fn append_entries(
172 &mut self,
173 req: AppendEntriesRequest<TypeConfig>,
174 _option: RPCOption,
175 ) -> Result<AppendEntriesResponse<NodeId>, RPCError<NodeId, Node, RaftError<NodeId>>> {
176 let body = rmp_serde::to_vec(&req).map_err(|e| RPCError::Network(NetworkError::new(&e)))?;
177 let bytes = self
178 .post("/raft/append", body)
179 .await
180 .map_err(RPCError::Network)?;
181 let res: Result<AppendEntriesResponse<NodeId>, RaftError<NodeId>> =
182 rmp_serde::from_slice(&bytes).map_err(|e| RPCError::Network(NetworkError::new(&e)))?;
183 res.map_err(|e| RPCError::RemoteError(RemoteError::new(self.target, e)))
184 }
185
186 async fn vote(
187 &mut self,
188 req: VoteRequest<NodeId>,
189 _option: RPCOption,
190 ) -> Result<VoteResponse<NodeId>, RPCError<NodeId, Node, RaftError<NodeId>>> {
191 let body = rmp_serde::to_vec(&req).map_err(|e| RPCError::Network(NetworkError::new(&e)))?;
192 let bytes = self
193 .post("/raft/vote", body)
194 .await
195 .map_err(RPCError::Network)?;
196 let res: Result<VoteResponse<NodeId>, RaftError<NodeId>> =
197 rmp_serde::from_slice(&bytes).map_err(|e| RPCError::Network(NetworkError::new(&e)))?;
198 res.map_err(|e| RPCError::RemoteError(RemoteError::new(self.target, e)))
199 }
200
201 async fn install_snapshot(
202 &mut self,
203 req: InstallSnapshotRequest<TypeConfig>,
204 _option: RPCOption,
205 ) -> Result<
206 InstallSnapshotResponse<NodeId>,
207 RPCError<NodeId, Node, RaftError<NodeId, InstallSnapshotError>>,
208 > {
209 let body = rmp_serde::to_vec(&req).map_err(|e| RPCError::Network(NetworkError::new(&e)))?;
210 let bytes = self
211 .post("/raft/snapshot", body)
212 .await
213 .map_err(RPCError::Network)?;
214 let res: Result<InstallSnapshotResponse<NodeId>, RaftError<NodeId, InstallSnapshotError>> =
215 rmp_serde::from_slice(&bytes).map_err(|e| RPCError::Network(NetworkError::new(&e)))?;
216 res.map_err(|e| RPCError::RemoteError(RemoteError::new(self.target, e)))
217 }
218}