diff --git a/cluster_benchmark/tests/benchmark/store.rs b/cluster_benchmark/tests/benchmark/store.rs index 4d3859f27..4418d0f5c 100644 --- a/cluster_benchmark/tests/benchmark/store.rs +++ b/cluster_benchmark/tests/benchmark/store.rs @@ -43,11 +43,7 @@ openraft::declare_raft_types!( pub TypeConfig: D = ClientRequest, R = ClientResponse, - NodeId = NodeId, Node = (), - Entry = Entry, - SnapshotData = Cursor>, - AsyncRuntime = TokioRuntime ); #[derive(Debug)] diff --git a/examples/raft-kv-memstore-generic-snapshot-data/src/lib.rs b/examples/raft-kv-memstore-generic-snapshot-data/src/lib.rs index b3e79435e..a4b358382 100644 --- a/examples/raft-kv-memstore-generic-snapshot-data/src/lib.rs +++ b/examples/raft-kv-memstore-generic-snapshot-data/src/lib.rs @@ -3,9 +3,7 @@ use std::sync::Arc; -use openraft::BasicNode; use openraft::Config; -use openraft::TokioRuntime; use crate::app::App; use crate::router::Router; @@ -27,13 +25,9 @@ openraft::declare_raft_types!( pub TypeConfig: D = Request, R = Response, - NodeId = NodeId, - Node = BasicNode, - Entry = openraft::Entry, // In this example, snapshot is just a copy of the state machine. // And it can be any type. SnapshotData = StateMachineData, - AsyncRuntime = TokioRuntime ); pub type LogStore = store::LogStore; diff --git a/examples/raft-kv-memstore-generic-snapshot-data/src/network.rs b/examples/raft-kv-memstore-generic-snapshot-data/src/network.rs index 55534f3f2..75343a811 100644 --- a/examples/raft-kv-memstore-generic-snapshot-data/src/network.rs +++ b/examples/raft-kv-memstore-generic-snapshot-data/src/network.rs @@ -8,6 +8,7 @@ use openraft::raft::AppendEntriesResponse; use openraft::raft::SnapshotResponse; use openraft::raft::VoteRequest; use openraft::raft::VoteResponse; +use openraft::BasicNode; use openraft::OptionalSend; use openraft::RaftNetwork; use openraft::RaftNetworkFactory; @@ -16,7 +17,6 @@ use openraft::Vote; use crate::router::Router; use crate::typ; -use crate::BasicNode; use crate::NodeId; use crate::TypeConfig; diff --git a/examples/raft-kv-memstore-opendal-snapshot-data/src/lib.rs b/examples/raft-kv-memstore-opendal-snapshot-data/src/lib.rs index 290492278..2d480c525 100644 --- a/examples/raft-kv-memstore-opendal-snapshot-data/src/lib.rs +++ b/examples/raft-kv-memstore-opendal-snapshot-data/src/lib.rs @@ -4,9 +4,7 @@ use std::sync::Arc; use opendal::Operator; -use openraft::BasicNode; use openraft::Config; -use openraft::TokioRuntime; use crate::app::App; use crate::router::Router; @@ -27,12 +25,8 @@ openraft::declare_raft_types!( pub TypeConfig: D = Request, R = Response, - NodeId = NodeId, - Node = BasicNode, - Entry = openraft::Entry, // In this example, snapshot is a path pointing to a file stored in shared storage. SnapshotData = String, - AsyncRuntime = TokioRuntime ); pub type LogStore = store::LogStore; diff --git a/examples/raft-kv-memstore-opendal-snapshot-data/src/network.rs b/examples/raft-kv-memstore-opendal-snapshot-data/src/network.rs index 55534f3f2..75343a811 100644 --- a/examples/raft-kv-memstore-opendal-snapshot-data/src/network.rs +++ b/examples/raft-kv-memstore-opendal-snapshot-data/src/network.rs @@ -8,6 +8,7 @@ use openraft::raft::AppendEntriesResponse; use openraft::raft::SnapshotResponse; use openraft::raft::VoteRequest; use openraft::raft::VoteResponse; +use openraft::BasicNode; use openraft::OptionalSend; use openraft::RaftNetwork; use openraft::RaftNetworkFactory; @@ -16,7 +17,6 @@ use openraft::Vote; use crate::router::Router; use crate::typ; -use crate::BasicNode; use crate::NodeId; use crate::TypeConfig; diff --git a/examples/raft-kv-memstore-singlethreaded/src/lib.rs b/examples/raft-kv-memstore-singlethreaded/src/lib.rs index 18e6df8da..836d5ed13 100644 --- a/examples/raft-kv-memstore-singlethreaded/src/lib.rs +++ b/examples/raft-kv-memstore-singlethreaded/src/lib.rs @@ -6,9 +6,7 @@ use std::marker::PhantomData; use std::rc::Rc; use std::sync::Arc; -use openraft::BasicNode; use openraft::Config; -use openraft::TokioRuntime; use crate::app::App; use crate::router::Router; @@ -51,10 +49,6 @@ openraft::declare_raft_types!( D = Request, R = Response, NodeId = NodeId, - Node = BasicNode, - Entry = openraft::Entry, - SnapshotData = Cursor>, - AsyncRuntime = TokioRuntime ); pub type LogStore = store::LogStore; diff --git a/examples/raft-kv-memstore-singlethreaded/src/network.rs b/examples/raft-kv-memstore-singlethreaded/src/network.rs index cf0e1808b..efbb51a9d 100644 --- a/examples/raft-kv-memstore-singlethreaded/src/network.rs +++ b/examples/raft-kv-memstore-singlethreaded/src/network.rs @@ -7,12 +7,12 @@ use openraft::raft::InstallSnapshotRequest; use openraft::raft::InstallSnapshotResponse; use openraft::raft::VoteRequest; use openraft::raft::VoteResponse; +use openraft::BasicNode; use openraft::RaftNetwork; use openraft::RaftNetworkFactory; use crate::router::Router; use crate::typ; -use crate::BasicNode; use crate::NodeId; use crate::TypeConfig; diff --git a/examples/raft-kv-memstore/src/lib.rs b/examples/raft-kv-memstore/src/lib.rs index 5956979c8..66d19ecf2 100644 --- a/examples/raft-kv-memstore/src/lib.rs +++ b/examples/raft-kv-memstore/src/lib.rs @@ -8,9 +8,7 @@ use actix_web::middleware; use actix_web::middleware::Logger; use actix_web::web::Data; use actix_web::HttpServer; -use openraft::BasicNode; use openraft::Config; -use openraft::TokioRuntime; use crate::app::App; use crate::network::api; @@ -32,11 +30,6 @@ openraft::declare_raft_types!( pub TypeConfig: D = Request, R = Response, - NodeId = NodeId, - Node = BasicNode, - Entry = openraft::Entry, - SnapshotData = Cursor>, - AsyncRuntime = TokioRuntime, ); pub type LogStore = store::LogStore; diff --git a/examples/raft-kv-rocksdb/src/lib.rs b/examples/raft-kv-rocksdb/src/lib.rs index 776a948ef..f5ef0208a 100644 --- a/examples/raft-kv-rocksdb/src/lib.rs +++ b/examples/raft-kv-rocksdb/src/lib.rs @@ -7,7 +7,6 @@ use std::path::Path; use std::sync::Arc; use openraft::Config; -use openraft::TokioRuntime; use tokio::net::TcpListener; use tokio::task; @@ -44,11 +43,7 @@ openraft::declare_raft_types!( pub TypeConfig: D = Request, R = Response, - NodeId = NodeId, Node = Node, - Entry = openraft::Entry, - SnapshotData = SnapshotData, - AsyncRuntime = TokioRuntime ); pub mod typ { diff --git a/openraft/src/engine/command.rs b/openraft/src/engine/command.rs index 2e6856323..ced1768b8 100644 --- a/openraft/src/engine/command.rs +++ b/openraft/src/engine/command.rs @@ -89,9 +89,9 @@ where C: RaftTypeConfig DeleteConflictLog { since: LogId }, // TODO(1): current it is only used to replace BuildSnapshot, InstallSnapshot, CancelSnapshot. - /// A command send to state machine worker [`worker::Worker`]. + /// A command send to state machine worker [`sm::worker::Worker`]. /// - /// The runtime(`RaftCore`) will just forward this command to [`worker::Worker`]. + /// The runtime(`RaftCore`) will just forward this command to [`sm::worker::Worker`]. /// The response will be sent back in a `RaftMsg::StateMachine` message to `RaftCore`. StateMachine { command: sm::Command }, @@ -212,7 +212,7 @@ where NID: NodeId #[allow(dead_code)] Applied { log_id: Option> }, - /// Wait until a [`worker::Worker`] command is finished. + /// Wait until a [`sm::worker::Worker`] command is finished. #[allow(dead_code)] StateMachineCommand { command_seq: sm::CommandSeq }, } diff --git a/openraft/src/raft/declare_raft_types_test.rs b/openraft/src/raft/declare_raft_types_test.rs new file mode 100644 index 000000000..b33c0cbdd --- /dev/null +++ b/openraft/src/raft/declare_raft_types_test.rs @@ -0,0 +1,51 @@ +//! Test the `declare_raft_types` macro with default values + +use std::io::Cursor; + +use crate::declare_raft_types; +use crate::TokioRuntime; + +declare_raft_types!( + All: + D = (), + R = (), + NodeId = u64, + Node = (), + Entry = crate::Entry, + SnapshotData = Cursor>, + AsyncRuntime = TokioRuntime, +); + +declare_raft_types!( + WithoutD: + R = (), + NodeId = u64, + Node = (), + Entry = crate::Entry, + SnapshotData = Cursor>, + AsyncRuntime = TokioRuntime, +); + +declare_raft_types!( + WithoutR: + D = (), + NodeId = u64, + Node = (), + Entry = crate::Entry, + SnapshotData = Cursor>, + AsyncRuntime = TokioRuntime, +); + +// This raise an compile error: +// > error: Type not in its expected position : NodeId = u64, D = (), types must present +// > in this order : D, R, NodeId, Node, Entry, SnapshotData, AsyncRuntime +// declare_raft_types!( +// Foo: +// Node = (), +// NodeId = u64, +// D = (), +// ); + +declare_raft_types!(EmptyWithColon:); + +declare_raft_types!(Empty); diff --git a/openraft/src/raft/mod.rs b/openraft/src/raft/mod.rs index dc9a445b6..3a20dc216 100644 --- a/openraft/src/raft/mod.rs +++ b/openraft/src/raft/mod.rs @@ -1,5 +1,6 @@ //! Public Raft interface and data types. +#[cfg(test)] mod declare_raft_types_test; mod external_request; mod message; mod raft_inner; @@ -99,21 +100,144 @@ use crate::Vote; /// AsyncRuntime = openraft::TokioRuntime, /// ); /// ``` +/// +/// **The types must be specified in the exact order**: +/// `D`, `R`, `NodeId`, `Node`, `Entry`, `SnapshotData`, `AsyncRuntime`. +/// +/// Types can be omitted, in which case the default type will be used. +/// The default values for each type are: +/// - `D`: `String` +/// - `R`: `String` +/// - `NodeId`: `u64` +/// - `Node`: `::openraft::BasicNode` +/// - `Entry`: `::openraft::Entry` +/// - `SnapshotData`: `Cursor>` +/// - `AsyncRuntime`: `::openraft::TokioRuntime` +/// +/// For example, to declare with only `D` and `R` types: +/// ```ignore +/// openraft::declare_raft_types!( +/// pub TypeConfig: +/// D = ClientRequest, +/// R = ClientResponse, +/// ); +/// ``` +/// +/// Or just use the default type config: +/// ```ignore +/// openraft::declare_raft_types!(pub TypeConfig); +/// ``` #[macro_export] macro_rules! declare_raft_types { - ( $(#[$outer:meta])* $visibility:vis $id:ident: $($(#[$inner:meta])* $type_id:ident = $type:ty),+ $(,)? ) => { + // Add a trailing colon to `declare_raft_types(MyType)`, + // Make it the standard form: `declare_raft_types(MyType:)`. + ($(#[$outer:meta])* $visibility:vis $id:ident) => { + $crate::declare_raft_types!($(#[$outer])* $visibility $id:); + }; + + // The main entry of this macro + ($(#[$outer:meta])* $visibility:vis $id:ident: $($(#[$inner:meta])* $type_id:ident = $type:ty),* $(,)? ) => { $(#[$outer])* #[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] $visibility struct $id {} impl $crate::RaftTypeConfig for $id { - $( - $(#[$inner])* - type $type_id = $type; - )+ + $crate::declare_raft_types!(@F_0, $($(#[$inner])* $type_id = $type,)* @T); } }; + + // Add explicit type D + (@F_0, $(#[$meta:meta])* D=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + $(#[$meta])* + type D = $t; + $crate::declare_raft_types!(@F_1, $($(#[$inner])* $type_id = $type,)* @T); + }; + + // Add default type D + (@F_0, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + type D = String; + $crate::declare_raft_types!(@F_1, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_1, $(#[$meta:meta])* R=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + $(#[$meta])* + type R = $t; + $crate::declare_raft_types!(@F_2, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_1, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + type R = String; + $crate::declare_raft_types!(@F_2, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_2, $(#[$meta:meta])* NodeId=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + $(#[$meta])* + type NodeId = $t; + $crate::declare_raft_types!(@F_3, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_2, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + type NodeId = u64; + $crate::declare_raft_types!(@F_3, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_3, $(#[$meta:meta])* Node=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + $(#[$meta])* + type Node = $t; + $crate::declare_raft_types!(@F_4, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_3, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + type Node = $crate::BasicNode; + $crate::declare_raft_types!(@F_4, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_4, $(#[$meta:meta])* Entry=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + $(#[$meta])* + type Entry = $t; + $crate::declare_raft_types!(@F_5, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_4, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + type Entry = $crate::Entry; + $crate::declare_raft_types!(@F_5, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_5, $(#[$meta:meta])* SnapshotData=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + $(#[$meta])* + type SnapshotData = $t; + $crate::declare_raft_types!(@F_6, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_5, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + type SnapshotData = Cursor>; + $crate::declare_raft_types!(@F_6, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_6, $(#[$meta:meta])* AsyncRuntime=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + $(#[$meta])* + type AsyncRuntime = $t; + $crate::declare_raft_types!(@F_7, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_6, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { + type AsyncRuntime = $crate::TokioRuntime; + $crate::declare_raft_types!(@F_7, $($(#[$inner])* $type_id = $type,)* @T); + }; + + (@F_7, @T ) => {}; + + // Match any non-captured items to raise compile error + (@F_7, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T ) => { + compile_error!( + stringify!( + Type not in its expected position: + $($type_id=$type,)* + types must present in this order: D, R, NodeId, Node, Entry, SnapshotData, AsyncRuntime + ) + ); + }; } /// The Raft API. diff --git a/stores/memstore/src/lib.rs b/stores/memstore/src/lib.rs index 7a9abc100..57f1e4b76 100644 --- a/stores/memstore/src/lib.rs +++ b/stores/memstore/src/lib.rs @@ -28,7 +28,6 @@ use openraft::SnapshotMeta; use openraft::StorageError; use openraft::StorageIOError; use openraft::StoredMembership; -use openraft::TokioRuntime; use openraft::Vote; use serde::Deserialize; use serde::Serialize; @@ -79,11 +78,7 @@ openraft::declare_raft_types!( pub TypeConfig: D = ClientRequest, R = ClientResponse, - NodeId = MemNodeId, Node = (), - Entry = Entry, - SnapshotData = Cursor>, - AsyncRuntime = TokioRuntime ); /// The application snapshot type which the `MemStore` works with. diff --git a/stores/rocksstore/src/lib.rs b/stores/rocksstore/src/lib.rs index 8cd57a2ff..a070c71e1 100644 --- a/stores/rocksstore/src/lib.rs +++ b/stores/rocksstore/src/lib.rs @@ -25,7 +25,6 @@ use openraft::storage::RaftLogStorage; use openraft::storage::RaftStateMachine; use openraft::storage::Snapshot; use openraft::AnyError; -use openraft::BasicNode; use openraft::Entry; use openraft::EntryPayload; use openraft::ErrorVerb; @@ -38,7 +37,6 @@ use openraft::SnapshotMeta; use openraft::StorageError; use openraft::StorageIOError; use openraft::StoredMembership; -use openraft::TokioRuntime; use openraft::Vote; use rand::Rng; use rocksdb::ColumnFamily; @@ -56,11 +54,6 @@ openraft::declare_raft_types!( pub TypeConfig: D = RocksRequest, R = RocksResponse, - NodeId = RocksNodeId, - Node = BasicNode, - Entry = Entry, - SnapshotData = Cursor>, - AsyncRuntime = TokioRuntime ); /** diff --git a/stores/sledstore/src/lib.rs b/stores/sledstore/src/lib.rs index 24785b063..6bce2f250 100644 --- a/stores/sledstore/src/lib.rs +++ b/stores/sledstore/src/lib.rs @@ -21,7 +21,6 @@ use openraft::storage::RaftLogStorage; use openraft::storage::RaftStateMachine; use openraft::storage::Snapshot; use openraft::AnyError; -use openraft::BasicNode; use openraft::Entry; use openraft::EntryPayload; use openraft::LogId; @@ -33,7 +32,6 @@ use openraft::SnapshotMeta; use openraft::StorageError; use openraft::StorageIOError; use openraft::StoredMembership; -use openraft::TokioRuntime; use openraft::Vote; use serde::Deserialize; use serde::Serialize; @@ -46,11 +44,6 @@ openraft::declare_raft_types!( pub TypeConfig: D = ExampleRequest, R = ExampleResponse, - NodeId = ExampleNodeId, - Node = BasicNode, - Entry = Entry, - SnapshotData = Cursor>, - AsyncRuntime = TokioRuntime ); /**