Skip to content

Commit

Permalink
Change: Add default value to declare_raft_types
Browse files Browse the repository at this point in the history
Types used in `declare_raft_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<Self>`
- `SnapshotData`: `Cursor<Vec<u8>>`
- `AsyncRuntime`: `::openraft::TokioRuntime`

Note that **The types must be specified in the exact order**:
`D`, `R`, `NodeId`, `Node`, `Entry`, `SnapshotData`, `AsyncRuntime`.

For example, to declare with only `D`, `R` and `Entry` types:
```rust,ignore
openraft::declare_raft_types!(
   pub TypeConfig:
       D = ClientRequest,
       R = ClientResponse,
       Entry = MyEntry,
);
```

Type `NodeId`, `Node`, `SnapshotData` and `AsyncRuntime` will be filled
with default values mentioned above.

Or one can just use the default types for all:
```rust,ignore
openraft::declare_raft_types!(pub TypeConfig);
```

Upgrade tip:

Ensures types declared in `declare_raft_types` are in the correct order
  • Loading branch information
drmingdrmer committed Mar 29, 2024
1 parent 1d7a5ed commit 8f0cc16
Show file tree
Hide file tree
Showing 15 changed files with 186 additions and 64 deletions.
4 changes: 0 additions & 4 deletions cluster_benchmark/tests/benchmark/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ openraft::declare_raft_types!(
pub TypeConfig:
D = ClientRequest,
R = ClientResponse,
NodeId = NodeId,
Node = (),
Entry = Entry<TypeConfig>,
SnapshotData = Cursor<Vec<u8>>,
AsyncRuntime = TokioRuntime
);

#[derive(Debug)]
Expand Down
6 changes: 0 additions & 6 deletions examples/raft-kv-memstore-generic-snapshot-data/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -27,13 +25,9 @@ openraft::declare_raft_types!(
pub TypeConfig:
D = Request,
R = Response,
NodeId = NodeId,
Node = BasicNode,
Entry = openraft::Entry<TypeConfig>,
// 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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -16,7 +17,6 @@ use openraft::Vote;

use crate::router::Router;
use crate::typ;
use crate::BasicNode;
use crate::NodeId;
use crate::TypeConfig;

Expand Down
6 changes: 0 additions & 6 deletions examples/raft-kv-memstore-opendal-snapshot-data/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -27,12 +25,8 @@ openraft::declare_raft_types!(
pub TypeConfig:
D = Request,
R = Response,
NodeId = NodeId,
Node = BasicNode,
Entry = openraft::Entry<TypeConfig>,
// In this example, snapshot is a path pointing to a file stored in shared storage.
SnapshotData = String,
AsyncRuntime = TokioRuntime
);

pub type LogStore = store::LogStore;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -16,7 +17,6 @@ use openraft::Vote;

use crate::router::Router;
use crate::typ;
use crate::BasicNode;
use crate::NodeId;
use crate::TypeConfig;

Expand Down
6 changes: 0 additions & 6 deletions examples/raft-kv-memstore-singlethreaded/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -51,10 +49,6 @@ openraft::declare_raft_types!(
D = Request,
R = Response,
NodeId = NodeId,
Node = BasicNode,
Entry = openraft::Entry<TypeConfig>,
SnapshotData = Cursor<Vec<u8>>,
AsyncRuntime = TokioRuntime
);

pub type LogStore = store::LogStore;
Expand Down
2 changes: 1 addition & 1 deletion examples/raft-kv-memstore-singlethreaded/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
7 changes: 0 additions & 7 deletions examples/raft-kv-memstore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -32,11 +30,6 @@ openraft::declare_raft_types!(
pub TypeConfig:
D = Request,
R = Response,
NodeId = NodeId,
Node = BasicNode,
Entry = openraft::Entry<TypeConfig>,
SnapshotData = Cursor<Vec<u8>>,
AsyncRuntime = TokioRuntime,
);

pub type LogStore = store::LogStore;
Expand Down
5 changes: 0 additions & 5 deletions examples/raft-kv-rocksdb/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -44,11 +43,7 @@ openraft::declare_raft_types!(
pub TypeConfig:
D = Request,
R = Response,
NodeId = NodeId,
Node = Node,
Entry = openraft::Entry<TypeConfig>,
SnapshotData = SnapshotData,
AsyncRuntime = TokioRuntime
);

pub mod typ {
Expand Down
6 changes: 3 additions & 3 deletions openraft/src/engine/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ where C: RaftTypeConfig
DeleteConflictLog { since: LogId<C::NodeId> },

// 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<C> },

Expand Down Expand Up @@ -212,7 +212,7 @@ where NID: NodeId
#[allow(dead_code)]
Applied { log_id: Option<LogId<NID>> },

/// 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 },
}
Expand Down
51 changes: 51 additions & 0 deletions openraft/src/raft/declare_raft_types_test.rs
Original file line number Diff line number Diff line change
@@ -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<Self>,
SnapshotData = Cursor<Vec<u8>>,
AsyncRuntime = TokioRuntime,
);

declare_raft_types!(
WithoutD:
R = (),
NodeId = u64,
Node = (),
Entry = crate::Entry<Self>,
SnapshotData = Cursor<Vec<u8>>,
AsyncRuntime = TokioRuntime,
);

declare_raft_types!(
WithoutR:
D = (),
NodeId = u64,
Node = (),
Entry = crate::Entry<Self>,
SnapshotData = Cursor<Vec<u8>>,
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);
134 changes: 129 additions & 5 deletions openraft/src/raft/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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<Self>`
/// - `SnapshotData`: `Cursor<Vec<u8>>`
/// - `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<Self>;
$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<Vec<u8>>;
$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.
Expand Down
Loading

0 comments on commit 8f0cc16

Please sign in to comment.