2023-08-09 10:17:03 +03:00
# nim-raft
2023-07-29 06:32:15 +03:00
# 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-09 11:44:15 +03:00
# Raft Node Public Types.
2023-07-29 06:10:45 +03:00
# I guess that at some point these can be moved to a separate file called raft_consensus_types.nim for example
2023-07-29 12:20:47 +03:00
import std / locks
2023-08-06 19:25:21 +03:00
import stew / results
import eth / keyfile
2023-08-06 19:33:30 +03:00
export results
2023-07-29 12:20:47 +03:00
2023-07-29 06:10:45 +03:00
type
2023-08-09 12:20:06 +03:00
# Raft Node basic definitions
Blob * = seq [ byte ]
RaftNodeState * = enum
UNKNOWN = 0 ,
FOLLOWER = 1 ,
LEADER = 2
RaftNodeId * = UUID # UUID uniquely identifying every Raft Node
RaftNodePeers * = seq [ RaftNodeId ] # List of Raft Node Peers IDs
RaftNodeTerm * = uint64 # Raft Node Term Type
RaftLogIndex * = uint64 # Raft Node Log Index Type
# Raft Node Abstract State Machine type
RaftNodeStateMachine * [ LogEntryDataType , SmStateType ] = ref object # Some probably opaque State Machine Impelementation to be used by the Raft Node
# providing at minimum operations for initialization, querying the current state
# and RaftNodeLogEntry application
state : SmStateType
# Raft Node Persistent Storage basic definition
RaftNodePersistentStorage * = ref object # Should be some kind of Persistent Transactional Store Wrapper
# Basic modules (algos) definitions
RaftNodeAccessCallback [ LogEntryDataType ] = proc : RaftNode [ LogEntryDataType ] {. nimcall , gcsafe . } # This should be implementes as a closure holding the RaftNode
RaftConsensusModule * [ LogEntryDataType ] = object of RootObj
stateTransitionsFsm : seq [ byte ] # I plan to use nim.fsm https://github.com/ba0f3/fsm.nim
raftNodeAccessCallback : RaftNodeAccessCallback [ LogEntryDataType ]
RaftLogCompactionModule * [ LogEntryDataType ] = object of RootObj
raftNodeAccessCallback : RaftNodeAccessCallback [ LogEntryDataType ]
RaftMembershipChangeModule * [ LogEntryDataType ] = object of RootObj
raftNodeAccessCallback : RaftNodeAccessCallback [ LogEntryDataType ]
# Callback for sending messages out of this Raft Node
RaftMessageId * = UUID # UUID assigned to every Raft Node Message,
# so it can be matched with it's corresponding response etc.
RaftMessageSendCallback * = proc ( raftMessage : RaftMessageBase ) {. nimcall , gcsafe . } # Callback for Sending Raft Node Messages
# out of this Raft Node. Can be used for broadcasting
# (a Heart-Beat for example)
# Raft Node basic Log definitions
RaftNodeLogEntry * [ LogEntryDataType ] = ref object # Abstarct Raft Node Log entry containing opaque binary data (Blob etc.)
term * : RaftNodeTerm
data * : LogEntryDataType
RaftNodeLog * [ LogEntryDataType ] = ref object # Needs more elaborate definition.
# Probably this will be a RocksDB/MDBX/SQLite Store Wrapper etc.
logData * : seq [ RaftNodeLogEntry [ LogEntryDataType ] ] # Raft Node Log Data
# Base type for Raft message objects
RaftMessageBase * = ref object of RootObj # Base Type for Raft Node Messages
msgId * : RaftMessageId # Message UUID
senderId * : RaftNodeId # Sender Raft Node ID
senderTerm * : RaftNodeTerm # Sender Raft Node Term
peers * : RaftNodePeers # List of Raft Node IDs, which should receive this message
# Raft Node Object type
RaftNode * [ LogEntryDataType , SmStateType ] = ref object
# Timers
votingTimout : uint64
heartBeatTimeout : uint64
# etc. timers
# Mtx definitions go here
raftStateMutex : Lock
raftLogMutex : Lock
raftCommMutexReceiveMsg : Lock
raftCommMutexClientResponse : Lock
# Modules (Algos)
consensusModule : RaftConsensusModule [ LogEntryDataType ]
logCompactionModule : RaftLogCompactionModule [ LogEntryDataType ]
membershipChangeModule : RaftMembershipChangeModule [ LogEntryDataType ]
# Misc
msgSendCallback : RaftMessageSendCallback
persistentStorage : RaftNodePersistentStorage
# Persistent state
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)
log : RaftNodeLog [ LogEntryDataType ] # This Raft Node Log
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
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
stateMachine : RaftNodeStateMachine [ LogEntryDataType , SmStateType ] # Not sure for now putting it here. I assume that persisting the State Machine's
# state is enough to consider it 'persisted'
# Volatile state
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)
# Volatile state on leaders
nextIndex : seq [ 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 : seq [ RaftLogIndex ] # For each peer Raft Node, index of highest log entry known to be replicated on Node
# (initialized to 0, increases monotonically)