nim-raft/raft/types.nim

155 lines
7.7 KiB
Nim
Raw Normal View History

# nim-raft
# Copyright (c) 2023 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
# at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.
2023-08-14 20:49:21 +00:00
# Raft Node Public Types
import std/locks
2023-08-14 20:49:21 +00:00
import options
import stew/results
2023-08-29 09:20:40 +00:00
import uuids
2023-08-31 20:52:52 +00:00
export results, options, locks, uuids
2023-08-14 20:49:21 +00:00
type
RaftNodeState* = enum
2023-08-14 20:49:21 +00:00
rnsUnknown = 0,
rnsFollower = 1,
rnsCandidate = 2
rnsLeader = 3
2023-08-25 09:00:40 +00:00
RaftNodeId* = UUID # uuid4 uniquely identifying every Raft Node
RaftNodeTerm* = uint64 # Raft Node Term Type
RaftLogIndex* = uint64 # Raft Node Log Index Type
2023-08-14 20:49:21 +00:00
RaftNodePeer* = object # Raft Node Peer object
id*: RaftNodeId
nextIndex*: RaftLogIndex # For each peer Raft Node, index of the next log entry to send to that Node
# (initialized to leader last log index + 1)
matchIndex*: RaftLogIndex # For each peer Raft Node, index of highest log entry known to be replicated on Node
# (initialized to 0, increases monotonically)
hasVoted*: bool # Indicates if this peer have voted for this Raft Node During Election
canVote*: bool # Indicates if this peer can vote
RaftNodePeers* = seq[RaftNodePeer] # List of Raft Node Peers
# Raft Node Abstract State Machine type
2023-08-31 12:03:07 +00:00
RaftNodeStateMachine*[SmCommandType, SmStateType] = ref object # Some opaque State Machine Impelementation to be used by the Raft Node
2023-08-14 20:49:21 +00:00
# providing at minimum operations for initialization, querying the current state
# and RaftNodeLogEntry (SmCommandType) application
2023-08-31 12:03:07 +00:00
state*: ref SmStateType
# Raft Node Persistent Storage basic definition
2023-08-14 20:49:21 +00:00
RaftNodePersistentStorage*[SmCommandType, SmStateType] = object # Should be some kind of Persistent Transactional Store Wrapper
# Basic modules (algos) definitions
2023-08-14 20:49:21 +00:00
RaftNodeAccessCallback[SmCommandType, SmStateType] = proc: RaftNode[SmCommandType, SmStateType] {.nimcall, gcsafe.} # This should be implementes as a closure holding the RaftNode
2023-08-14 20:49:21 +00:00
RaftConsensusModule*[SmCommandType, SmStateType] = object of RootObj
stateTransitionsFsm: seq[byte] # I plan to use nim.fsm https://github.com/ba0f3/fsm.nim
gatheredVotesCount: int
2023-08-14 20:49:21 +00:00
raftNodeAccessCallback: RaftNodeAccessCallback[SmCommandType, SmStateType]
2023-08-14 20:49:21 +00:00
RaftLogCompactionModule*[SmCommandType, SmStateType] = object of RootObj
raftNodeAccessCallback: RaftNodeAccessCallback[SmCommandType, SmStateType]
2023-08-14 20:49:21 +00:00
RaftMembershipChangeModule*[SmCommandType, SmStateType] = object of RootObj
raftNodeAccessCallback: RaftNodeAccessCallback[SmCommandType, SmStateType]
# Callback for sending messages out of this Raft Node
2023-08-25 09:00:40 +00:00
RaftMessageId* = UUID # UUID assigned to every Raft Node Message,
2023-08-14 20:49:21 +00:00
# so it can be matched with it's corresponding response etc.
2023-08-14 20:49:21 +00:00
RaftMessageBase* = ref object of RootObj # Base Type for Raft Protocol Messages
msgId*: RaftMessageId # Message UUID
senderId*: RaftNodeId # Sender Raft Node ID
2023-08-31 20:52:52 +00:00
receiverId*: RaftNodeId # Receiver Raft Node ID
senderTerm*: RaftNodeTerm # Sender Raft Node Term
2023-08-14 20:49:21 +00:00
2023-08-31 20:52:52 +00:00
RaftMessageResponseBase* = ref object of RootObj
msgId*: RaftMessageId # Original Message ID
senderId*: RaftNodeId # Sender Raft Node ID
respondentId: RaftNodeId # Responding RaftNodeId
senderTerm*: RaftNodeTerm # Sender Raft Node Term
RaftMessageSendCallback* = proc (raftMessage: RaftMessageBase): RaftMessageResponseBase {.gcsafe.} # Callback for Sending Raft Node Messages
# out of this Raft Node.
2023-08-14 20:49:21 +00:00
# For later use when adding/removing new nodes (dynamic configuration chganges)
RaftNodeConfiguration* = object
# Raft Node Log definition
LogEntryType* = enum
etUnknown = 0,
etConfiguration = 1,
etData = 2,
etNoOp = 3
RaftNodeLogEntry*[SmCommandType] = object # Abstarct Raft Node Log entry containing opaque binary data (Blob etc.)
term*: RaftNodeTerm
index*: RaftLogIndex
entryType*: LogEntryType # Type of entry - data to append, configuration or no op etc.
data*: Option[SmCommandType] # Entry data (State Machine Command) - this is mutually exclusive with configuration
# depending on entryType field
2023-08-31 14:05:41 +00:00
configuration*: Option[RaftNodeConfiguration] # Node configuration
2023-08-14 20:49:21 +00:00
RaftNodeLog*[SmCommandType] = object # Needs more elaborate definition.
2023-08-14 20:49:21 +00:00
# Probably this will be a RocksDB/MDBX/SQLite Store Wrapper etc.
logData*: seq[RaftNodeLogEntry[SmCommandType]] # Raft Node Log Data
# Timer types
2023-08-25 09:00:40 +00:00
RaftTimer* = ref object
mtx*: Lock
canceled*: bool
expired*: bool
timeout*: int
2023-08-25 09:00:40 +00:00
oneshot*: bool
2023-08-25 09:00:40 +00:00
RaftTimerCallback* = proc (timer: RaftTimer) {.nimcall, gcsafe.} # Pass any function wrapped in a closure
# Raft Node Object type
2023-08-31 14:05:41 +00:00
RaftNode*[SmCommandType, SmStateType] = ref object
# Timers
requestVotesTimeout: int
heartBeatTimeout: int
appendEntriesTimeout: int
requestVotesTimer: RaftTimer
heartBeatTimer: RaftTimer
appendEntriesTimer: RaftTimer
2023-08-14 20:49:21 +00:00
# Mtx definition(s) go here
2023-08-31 20:52:52 +00:00
raftStateMutex*: Lock
# Modules (Algos)
2023-08-14 20:49:21 +00:00
consensusModule: RaftConsensusModule[SmCommandType, SmStateType]
logCompactionModule: RaftLogCompactionModule[SmCommandType, SmStateType]
membershipChangeModule: RaftMembershipChangeModule[SmCommandType, SmStateType]
# Misc
2023-08-31 20:52:52 +00:00
msgSendCallback*: RaftMessageSendCallback
2023-08-14 20:49:21 +00:00
persistentStorage: RaftNodePersistentStorage[SmCommandType, SmStateType]
# Persistent state
2023-08-31 20:52:52 +00:00
id*: RaftNodeId # This Raft Node ID
state*: RaftNodeState # This Raft Node State
currentTerm*: RaftNodeTerm # Latest term this Raft Node has seen (initialized to 0 on first boot, increases monotonically)
votedFor*: RaftNodeId # Candidate RaftNodeId that received vote in current term (or nil/zero if none),
# also used to redirect Client Requests in case this Raft Node is not the leader
2023-08-14 20:49:21 +00:00
log: RaftNodeLog[SmCommandType] # This Raft Node Log
2023-08-31 20:52:52 +00:00
stateMachine*: RaftNodeStateMachine[SmCommandType, SmStateType] # Not sure for now putting it here. I assume that persisting the State Machine's
2023-08-14 20:49:21 +00:00
# state is enough to consider it 'persisted'
2023-08-31 20:52:52 +00:00
peers*: RaftNodePeers # This Raft Node Peers IDs. I am not sure if this must be persistent or volatile but making it persistent
# makes sense for the moment
2023-08-14 20:49:21 +00:00
# Volatile state
2023-08-31 20:52:52 +00:00
commitIndex*: RaftLogIndex # Index of highest log entry known to be committed (initialized to 0, increases monotonically)
lastApplied*: RaftLogIndex # Index of highest log entry applied to state machine (initialized to 0, increases monotonically)
2023-08-14 20:49:21 +00:00
currentLeaderId: RaftNodeId # The ID of the cirrent leader Raft Node or 0/nil if None is leader (election is in progress etc.)