2023-07-29 06:32:15 +03:00
|
|
|
# nim-raft-consesnsus
|
|
|
|
# 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-07-29 06:10:45 +03:00
|
|
|
# RAFT Node Public Types.
|
|
|
|
# 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
|
|
|
|
|
|
|
|
export results, UUID
|
2023-07-29 12:20:47 +03:00
|
|
|
|
2023-07-29 06:10:45 +03:00
|
|
|
type
|
|
|
|
# RAFT Node basic definitions
|
|
|
|
Blob* = seq[byte]
|
|
|
|
|
|
|
|
RAFTNodeState* = enum
|
|
|
|
UNKNOWN = 0,
|
|
|
|
FOLLOWER = 1,
|
|
|
|
LEADER = 2
|
|
|
|
|
2023-08-06 19:25:21 +03:00
|
|
|
RAFTNodeId* = UUID # UUID uniquely identifying every RAFT Node
|
2023-07-29 06:10:45 +03:00
|
|
|
RAFTNodePeers* = seq[RAFTNodeId] # List of RAFT Node Peers IDs
|
|
|
|
RAFTNodeTerm* = uint64 # RAFT Node Term Type
|
|
|
|
RAFTLogIndex* = uint64 # RAFT Node Log Index Type
|
|
|
|
|
|
|
|
# RAFT Node State Machine basic definitions
|
2023-08-06 19:25:21 +03:00
|
|
|
RAFTNodeStateMachineState* = object # State Machine State
|
2023-07-29 06:10:45 +03:00
|
|
|
RAFTNodeStateMachine* = 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: RAFTNodeStateMachineState
|
|
|
|
|
|
|
|
# RAFT Node Persistent Storage basic definition
|
|
|
|
RAFTNodePersistentStorage* = ref object # Should be some kind of Persistent Transactional Store Wrapper
|
|
|
|
|
2023-07-29 06:17:48 +03:00
|
|
|
# Basic modules (algos) definitions
|
2023-07-29 07:23:31 +03:00
|
|
|
RAFTNodeAccessCallback = proc: RAFTNode {.nimcall, gcsafe.} # This should be implementes as a closure holding the RAFTNode
|
2023-07-29 07:03:20 +03:00
|
|
|
RAFTConsensusModule* = object of RootObj
|
|
|
|
state_transitions_fsm: seq[byte] # I plan to use nim.fsm https://github.com/ba0f3/fsm.nim
|
|
|
|
raft_node_access_callback: RAFTNodeAccessCallback
|
2023-07-29 06:17:48 +03:00
|
|
|
|
2023-07-29 07:03:20 +03:00
|
|
|
RAFTLogCompactionModule* = object of RootObj
|
|
|
|
raft_node_access_callback: RAFTNodeAccessCallback
|
2023-08-06 06:27:34 +03:00
|
|
|
|
2023-07-29 07:03:20 +03:00
|
|
|
RAFTMembershipChangeModule* = object of RootObj
|
|
|
|
raft_node_access_callback: RAFTNodeAccessCallback
|
2023-07-29 06:17:48 +03:00
|
|
|
|
2023-07-29 15:54:41 +03:00
|
|
|
# Callback for sending messages out of this RAFT Node
|
2023-08-06 19:25:21 +03:00
|
|
|
RAFTMessageId* = UUID # UUID assigned to every RAFT Node Message,
|
2023-07-29 15:54:41 +03:00
|
|
|
# so it can be matched with it's coresponding response etc.
|
|
|
|
|
|
|
|
RAFTMessageSendCallback* = proc (raft_message: 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* = ref object # Abstarct RAFT Node Log entry containing opaque binary data (Blob)
|
|
|
|
term*: RAFTNodeTerm
|
|
|
|
data*: Blob
|
|
|
|
|
2023-08-06 03:39:05 +03:00
|
|
|
RAFTNodeLog* = ref object # Needs more elaborate definition. Probably this will be a RocksDB/MDBX/SQLite Store Wrapper etc.
|
|
|
|
log_data*: seq[RAFTNodeLogEntry] # RAFT Node Log Data
|
2023-08-06 06:27:34 +03:00
|
|
|
|
2023-08-06 03:39:05 +03:00
|
|
|
# Base typoe for RAFT message objects
|
2023-07-29 15:54:41 +03:00
|
|
|
RAFTMessageBase* = ref object of RootObj # Base Type for RAFT Node Messages
|
|
|
|
msg_id*: RAFTMessageId # Message UUID
|
|
|
|
sender_id*: RAFTNodeId # Sender RAFT Node ID
|
|
|
|
sender_term*: RAFTNodeTerm # Sender RAFT Node Term
|
|
|
|
peers*: RAFTNodePeers # List of RAFT Node IDs, which should receive this message
|
|
|
|
|
2023-07-29 06:10:45 +03:00
|
|
|
# RAFT Node Object definitions
|
|
|
|
RAFTNode* = object
|
2023-07-29 12:20:47 +03:00
|
|
|
# Timers
|
2023-07-29 15:54:41 +03:00
|
|
|
voting_timout: uint64
|
|
|
|
heart_beat_timeout: uint64
|
2023-07-29 12:20:47 +03:00
|
|
|
# etc. timers
|
|
|
|
|
|
|
|
# Mtx definitions go here
|
|
|
|
raft_state_mutex: Lock
|
|
|
|
raft_log_mutex: Lock
|
|
|
|
raft_comm_mutex_receive_msg: Lock
|
|
|
|
raft_comm_mutex_client_response: Lock
|
2023-07-29 06:10:45 +03:00
|
|
|
|
2023-07-29 15:54:41 +03:00
|
|
|
# Modules (Algos)
|
2023-07-29 06:17:48 +03:00
|
|
|
consensus_module: RAFTConsensusModule
|
2023-07-29 07:03:20 +03:00
|
|
|
log_compaction_module: RAFTLogCompactionModule
|
2023-07-29 06:17:48 +03:00
|
|
|
membership_change_module: RAFTMembershipChangeModule
|
|
|
|
|
|
|
|
# Misc
|
2023-07-29 06:10:45 +03:00
|
|
|
msg_send_callback: RAFTMessageSendCallback
|
|
|
|
persistent_storage: RAFTNodePersistentStorage
|
|
|
|
|
2023-07-29 12:24:53 +03:00
|
|
|
# Persistent state
|
2023-07-29 06:10:45 +03:00
|
|
|
id: RAFTNodeId # This RAFT Node ID
|
|
|
|
state: RAFTNodeState # This RAFT Node State
|
|
|
|
current_term: RAFTNodeTerm # Latest term this RAFT Node has seen (initialized to 0 on first boot, increases monotonically)
|
|
|
|
log: RAFTNodeLog # This RAFT Node Log
|
|
|
|
voted_for: RAFTNodeId # Candidate RAFTNodeId that received vote in current term (or nil/zero if none)
|
|
|
|
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
|
|
|
|
state_machine: RAFTNodeStateMachine # Not sure for now putting it here. I assume that persisting the State Machine's state is enough
|
|
|
|
# to consider it 'persisted'
|
2023-08-06 06:27:34 +03:00
|
|
|
|
2023-07-29 06:10:45 +03:00
|
|
|
# Volatile state
|
|
|
|
commit_index: RAFTLogIndex # Index of highest log entry known to be committed (initialized to 0, increases monotonically)
|
|
|
|
last_applied: RAFTLogIndex # Index of highest log entry applied to state machine (initialized to 0, increases monotonically)
|
|
|
|
current_leader_id: RAFTNodeId # Current RAFT Node Leader ID (used to redirect Client Requests in case this RAFT Node is not the leader)
|
2023-08-06 06:27:34 +03:00
|
|
|
|
2023-07-29 06:10:45 +03:00
|
|
|
# Volatile state on leaders
|
|
|
|
next_index: 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)
|
|
|
|
match_index: seq[RAFTLogIndex] # For each peer RAFT Node, index of highest log entry known to be replicated on Node
|
|
|
|
# (initialized to 0, increases monotonically)
|
2023-07-29 12:20:47 +03:00
|
|
|
|