2023-05-26 00:42:35 +05:30
|
|
|
/*
|
|
|
|
* mCaptcha - A proof of work based DoS protection system
|
|
|
|
* Copyright © 2023 Aravinth Manivannan <realravinth@batsense.net>
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as
|
|
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Affero General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2023-05-24 21:22:14 +05:30
|
|
|
#![allow(clippy::uninlined_format_args)]
|
|
|
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
use actix_web::middleware;
|
|
|
|
use actix_web::middleware::Logger;
|
|
|
|
use actix_web::web::Data;
|
|
|
|
use actix_web::App;
|
|
|
|
use actix_web::HttpServer;
|
|
|
|
use openraft::BasicNode;
|
|
|
|
use openraft::Config;
|
|
|
|
use openraft::Raft;
|
|
|
|
|
2023-05-27 10:28:52 +05:30
|
|
|
use crate::app::DcacheApp;
|
2023-05-24 21:22:14 +05:30
|
|
|
use crate::network::api;
|
|
|
|
use crate::network::management;
|
|
|
|
use crate::network::raft;
|
2023-05-27 10:28:52 +05:30
|
|
|
use crate::network::raft_network_impl::DcacheNetwork;
|
|
|
|
use crate::store::DcacheRequest;
|
|
|
|
use crate::store::DcacheResponse;
|
|
|
|
use crate::store::DcacheStore;
|
2023-05-24 21:22:14 +05:30
|
|
|
|
|
|
|
pub mod app;
|
|
|
|
pub mod client;
|
|
|
|
pub mod network;
|
|
|
|
pub mod store;
|
|
|
|
|
2023-05-27 10:28:52 +05:30
|
|
|
pub type DcacheNodeId = u64;
|
2023-05-24 21:22:14 +05:30
|
|
|
|
|
|
|
openraft::declare_raft_types!(
|
|
|
|
/// Declare the type configuration for example K/V store.
|
2023-05-27 10:28:52 +05:30
|
|
|
pub DcacheTypeConfig: D = DcacheRequest, R = DcacheResponse, NodeId = DcacheNodeId, Node = BasicNode
|
2023-05-24 21:22:14 +05:30
|
|
|
);
|
|
|
|
|
2023-05-27 10:28:52 +05:30
|
|
|
pub type DcacheRaft = Raft<DcacheTypeConfig, DcacheNetwork, Arc<DcacheStore>>;
|
2023-05-24 21:22:14 +05:30
|
|
|
|
|
|
|
pub mod typ {
|
|
|
|
use openraft::BasicNode;
|
|
|
|
|
2023-05-27 10:28:52 +05:30
|
|
|
use crate::DcacheNodeId;
|
|
|
|
use crate::DcacheTypeConfig;
|
2023-05-24 21:22:14 +05:30
|
|
|
|
|
|
|
pub type RaftError<E = openraft::error::Infallible> =
|
2023-05-27 10:28:52 +05:30
|
|
|
openraft::error::RaftError<DcacheNodeId, E>;
|
2023-05-24 21:22:14 +05:30
|
|
|
pub type RPCError<E = openraft::error::Infallible> =
|
2023-05-27 10:28:52 +05:30
|
|
|
openraft::error::RPCError<DcacheNodeId, BasicNode, RaftError<E>>;
|
2023-05-24 21:22:14 +05:30
|
|
|
|
2023-05-27 10:28:52 +05:30
|
|
|
pub type ClientWriteError = openraft::error::ClientWriteError<DcacheNodeId, BasicNode>;
|
|
|
|
pub type CheckIsLeaderError = openraft::error::CheckIsLeaderError<DcacheNodeId, BasicNode>;
|
|
|
|
pub type ForwardToLeader = openraft::error::ForwardToLeader<DcacheNodeId, BasicNode>;
|
|
|
|
pub type InitializeError = openraft::error::InitializeError<DcacheNodeId, BasicNode>;
|
2023-05-24 21:22:14 +05:30
|
|
|
|
2023-05-27 10:28:52 +05:30
|
|
|
pub type ClientWriteResponse = openraft::raft::ClientWriteResponse<DcacheTypeConfig>;
|
2023-05-24 21:22:14 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn start_example_raft_node(
|
2023-05-27 10:28:52 +05:30
|
|
|
node_id: DcacheNodeId,
|
2023-05-24 21:22:14 +05:30
|
|
|
http_addr: String,
|
|
|
|
) -> std::io::Result<()> {
|
|
|
|
// Create a configuration for the raft instance.
|
|
|
|
let config = Config {
|
|
|
|
heartbeat_interval: 500,
|
|
|
|
election_timeout_min: 1500,
|
|
|
|
election_timeout_max: 3000,
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
|
|
|
|
let salt = "foobar12".into();
|
|
|
|
#[cfg(release)]
|
|
|
|
todo!("set salt");
|
|
|
|
|
|
|
|
let config = Arc::new(config.validate().unwrap());
|
|
|
|
|
|
|
|
// Create a instance of where the Raft data will be stored.
|
2023-05-27 10:28:52 +05:30
|
|
|
let store = Arc::new(DcacheStore::new(salt));
|
2023-05-24 21:22:14 +05:30
|
|
|
|
|
|
|
// Create the network layer that will connect and communicate the raft instances and
|
|
|
|
// will be used in conjunction with the store created above.
|
2023-05-27 10:28:52 +05:30
|
|
|
let network = DcacheNetwork {};
|
2023-05-24 21:22:14 +05:30
|
|
|
|
|
|
|
// Create a local raft instance.
|
|
|
|
let raft = Raft::new(node_id, config.clone(), network, store.clone())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Create an application that will store all the instances created above, this will
|
|
|
|
// be later used on the actix-web services.
|
2023-05-27 10:28:52 +05:30
|
|
|
let app = Data::new(DcacheApp {
|
2023-05-24 21:22:14 +05:30
|
|
|
id: node_id,
|
|
|
|
addr: http_addr.clone(),
|
|
|
|
raft,
|
|
|
|
store,
|
|
|
|
config,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Start the actix-web server.
|
|
|
|
let server = HttpServer::new(move || {
|
|
|
|
App::new()
|
|
|
|
.wrap(Logger::default())
|
|
|
|
.wrap(Logger::new("%a %{User-Agent}i"))
|
|
|
|
.wrap(middleware::Compress::default())
|
|
|
|
.app_data(app.clone())
|
|
|
|
// raft internal RPC
|
|
|
|
.service(raft::append)
|
|
|
|
.service(raft::snapshot)
|
|
|
|
.service(raft::vote)
|
|
|
|
// admin API
|
|
|
|
.service(management::init)
|
|
|
|
.service(management::add_learner)
|
|
|
|
.service(management::change_membership)
|
|
|
|
.service(management::metrics)
|
|
|
|
// application API
|
|
|
|
.service(api::write)
|
|
|
|
// .service(api::read)
|
|
|
|
// .service(api::consistent_read)
|
|
|
|
});
|
|
|
|
|
|
|
|
let x = server.bind(http_addr)?;
|
|
|
|
|
|
|
|
x.run().await
|
|
|
|
}
|