#![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; use crate::app::ExampleApp; use crate::network::api; use crate::network::management; use crate::network::raft; use crate::network::raft_network_impl::ExampleNetwork; use crate::store::ExampleRequest; use crate::store::ExampleResponse; use crate::store::ExampleStore; pub mod app; pub mod client; pub mod network; pub mod store; pub type ExampleNodeId = u64; openraft::declare_raft_types!( /// Declare the type configuration for example K/V store. pub ExampleTypeConfig: D = ExampleRequest, R = ExampleResponse, NodeId = ExampleNodeId, Node = BasicNode ); pub type ExampleRaft = Raft>; pub mod typ { use openraft::BasicNode; use crate::ExampleNodeId; use crate::ExampleTypeConfig; pub type RaftError = openraft::error::RaftError; pub type RPCError = openraft::error::RPCError>; pub type ClientWriteError = openraft::error::ClientWriteError; pub type CheckIsLeaderError = openraft::error::CheckIsLeaderError; pub type ForwardToLeader = openraft::error::ForwardToLeader; pub type InitializeError = openraft::error::InitializeError; pub type ClientWriteResponse = openraft::raft::ClientWriteResponse; } pub async fn start_example_raft_node( node_id: ExampleNodeId, 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. let store = Arc::new(ExampleStore::new(salt)); // Create the network layer that will connect and communicate the raft instances and // will be used in conjunction with the store created above. let network = ExampleNetwork {}; // 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. let app = Data::new(ExampleApp { 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 }