This commit is contained in:
Raycho Mukelov 2023-10-28 20:13:51 +03:00
parent 27458fe0e1
commit 6ac8558633
2 changed files with 30 additions and 24 deletions

View File

@ -9,53 +9,57 @@
import std/tables import std/tables
import std/rlocks import std/rlocks
import types
type type
# Define callback to use with Terminals # Define callback to use with Terminals. Node states are updated/read in-place in the node object
ConsensusFSMCallbackType*[NodeType] = proc(node: NodeType) {.gcsafe.} ConsensusFSMCallbackType*[NodeType] = proc(node: NodeType) {.gcsafe.}
# Define Non-Terminals as a (unique) tuples of the internal state and a sequence of callbacks # Define Non-Terminals as a (unique) tuples of the internal state and a sequence of callbacks
NonTerminalSymbol*[NodeType, NodeStates] = (NodeStates, seq[ConsensusFSMCallbackType[NodeType]]) NonTerminalSymbol*[NodeType] = (NodeType, seq[ConsensusFSMCallbackType[NodeType]])
# Define loose conditions computed from our NodeType # Define loose conditions computed from our NodeType (Truth Table)
Condition*[NodeType] = proc(node: NodeType): bool LogicalFunctionCondition*[EventType, NodeTytpe, RaftMessageBase] = proc(e: EventType, n: NodeTytpe, msg: Option[RaftMessageBase]): bool
# Define Terminals as a tuple of a Event and (Hash) Table of sequences of (loose) conditions and their respective values computed from NodeType (Truth Table) # Define Terminals as a tuple of a Event and a sequence of logical functions (conditions) and their respective values computed from NodeType, NodeTytpe and RaftMessageBase
TerminalSymbol*[NodeType, EventType] = (EventType, (seq[Condition[NodeType]], seq[bool])) # (kind of Truth Table)
TerminalSymbol*[EventType, NodeType, RaftMessageBase] = (EventType, seq[LogicalFunctionCondition[EventType, NodeType, Option[RaftMessageBase]]])
# Define State Transition Rules LUT of the form ( NonTerminal -> Terminal ) -> NonTerminal ) # Define State Transition Rules LUT of the form ( NonTerminal -> Terminal ) -> NonTerminal )
StateTransitionsRulesLUT*[NodeType, EventType, NodeStates] = Table[ StateTransitionsRulesLUT*[NodeType, EventType, RaftMessageBase] = Table[
(NonTerminalSymbol[NodeType, NodeStates], TerminalSymbol[NodeType, EventType]), (NonTerminalSymbol[NodeType], TerminalSymbol[NodeType, EventType, RaftMessageBase]),
NonTerminalSymbol[NodeType, NodeStates]] NonTerminalSymbol[NodeType]]
# FSM type definition # FSM type definition
ConsensusFSM*[NodeType, EventType, NodeStates] = ref object ConsensusFSM*[NodeType, EventType, BaseRaftMessage] = ref object
mtx: RLock mtx: RLock
state: NonTerminalSymbol[NodeType, NodeStates] state: NonTerminalSymbol[NodeType]
stateTransitionsLUT: StateTransitionsRulesLUT[NodeType, EventType, NodeStates] stateTransitionsLUT: StateTransitionsRulesLUT[NodeType, EventType, RaftMessageBase]
# FSM type constructor # FSM type constructor
proc new*[NodeType, EventType, NodeStates](T: type ConsensusFSM[NodeType, EventType, NodeStates], proc new*[NodeType, EventType, NodeStates](T: type ConsensusFSM[NodeType, EventType, RaftMessageBase],
lut: StateTransitionsRulesLUT[NodeType, EventType, NodeStates], lut: StateTransitionsRulesLUT[NodeType, EventType, RaftMessageBase],
startSymbol: NonTerminalSymbol[NodeType, NodeStates] startSymbol: NonTerminalSymbol[NodeType]
): T = ): T =
result = new(ConsensusFSM[NodeType, EventType, NodeStates]) result = new(ConsensusFSM[NodeType, EventType, NodeStates])
initRLock(result.mtx) initRLock(result.mtx)
result.state = startSymbol result.state = startSymbol
result.stateTransitionsLUT = lut result.stateTransitionsLUT = lut
proc computeFSMInputRobustLogic[NodeType, EventType](node: NodeType, event: EventType, rawInput: TerminalSymbol[NodeType, EventType]): proc computeFSMLogicFunctionsPermutationValue[NonTerminalSymbol, EventType, RaftMessageBase](nts: NonTerminalSymbol, rawInput: TerminalSymbol, msg: Option[RaftMessageBase]): TerminalSymbol =
TerminalSymbol[NodeType, EventType] =
var var
robustLogicEventTerminal = rawInput[1] logicFunctionsConds = rawInput[1]
let f = robustLogicEventTerminal[0] let e = rawInput[0]
robustLogicEventTerminal[1] = f(node) for f in nts[2]:
rawInput[1] = robustLogicEventTerminal f = f(nts[1], e, msg)
rawInput[1] = logicFunctionsConds
result = rawInput result = rawInput
proc consensusFSMAdvance[NodeType, EventType, NodeStates](fsm: ConsensusFSM[NodeType, EventType, NodeStates], node: NodeType, event: EventType, proc consensusFSMAdvance[NodeType, EventType](fsm: ConsensusFSM[NodeType, EventType, RaftMessageBase], node: NodeType, event: EventType,
rawInput: TerminalSymbol[NodeType, EventType]): NonTerminalSymbol[NodeType, NodeStates] = rawInput: TerminalSymbol[EventType, NodeType, RaftMessageBase]): NonTerminalSymbol[NodeType] =
withRLock(): withRLock():
var var
input = computeFSMInputRobustLogic(node, event, rawInput) input = computeFSMLogicFunctionsPermutationValue(node, event, rawInput)
fsm.state = fsm.stateTransitionsLUT[(fsm.state, input)] fsm.state = fsm.stateTransitionsLUT[(fsm.state, input)]
result = fsm.state result = fsm.state

View File

@ -172,6 +172,8 @@ proc raftNodeSendHeartBeat*[SmCommandType, SmStateType](node: RaftNode[SmCommand
if successCnt >= (node.peers.len div 2 + node.peers.len mod 2): if successCnt >= (node.peers.len div 2 + node.peers.len mod 2):
node.hrtBtSuccess = true node.hrtBtSuccess = true
else:
node.hrtBtSuccess = false
raftNodeScheduleHeartBeat(node) raftNodeScheduleHeartBeat(node)