This commit is contained in:
Raycho Mukelov 2023-10-28 21:04:34 +03:00
parent f3c8ad4b78
commit 7201783eea
1 changed files with 19 additions and 6 deletions

View File

@ -13,15 +13,25 @@ import types
type type
EventType = enum
# Node events
NodeStart, NodeStop, NodeTick, NodeStepDown, NodeStepDownToCandidate, NodeStepDownToFollower, NodeStepDownToLeader,
NodeStepDownToShutdown, VotingTimeout, ElectionTimeout, HeartbeatTimeout, HeartbeatReceived, HeartbeatSent, AppendEntriesReceived,
AppendEntriesSent, RequestVoteReceived, RequestVoteSent, RequestVoteGranted, RequestVoteDenied, ClientRequestReceived,
ClientRequestSent, ClientRequestProcessed, ClientRequestFailed, ClientRequestTimeout, ClientRequestRetry, ClientRequestRetryExhausted,
AddNewNode, RemoveNode, NodeShutdown, NodeShutdownComplete, NodeShutdownFailed, NodeShutdownTimeout, NodeShutdownRetry
# Define callback to use with Terminals. Node states are updated/read in-place in the node object # 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] = (NodeType, seq[ConsensusFSMCallbackType[NodeType]]) NonTerminalSymbol*[NodeType] = (NodeType, seq[ConsensusFSMCallbackType[NodeType]])
# Define loose conditions computed from our NodeType (Truth Table) # Define loose conditions computed from our NodeType (Truth Table)
LogicalFunctionConditionValueType* = bool
LogicalFunctionCondition*[EventType, NodeTytpe, RaftMessageBase] = proc(e: EventType, n: NodeTytpe, msg: Option[RaftMessageBase]): bool LogicalFunctionCondition*[EventType, NodeTytpe, RaftMessageBase] = proc(e: EventType, n: NodeTytpe, msg: Option[RaftMessageBase]): bool
LogicalFunctionConditionsLUT*[EventType, NodeType, RaftMessageBase] = Table[(EventType, NodeType), LogicalFunctionCondition[EventType, NodeType, Option[RaftMessageBase]]]
# 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 # 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
# (kind of Truth Table) # (kind of Truth Table)
TerminalSymbol*[EventType, NodeType, RaftMessageBase] = (EventType, seq[LogicalFunctionCondition[EventType, NodeType, Option[RaftMessageBase]]]) TerminalSymbol*[EventType, NodeType, RaftMessageBase] = (EventType, seq[LogicalFunctionConditionValueType])
# 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, RaftMessageBase] = Table[ StateTransitionsRulesLUT*[NodeType, EventType, RaftMessageBase] = Table[
(NonTerminalSymbol[NodeType], TerminalSymbol[NodeType, EventType, RaftMessageBase]), (NonTerminalSymbol[NodeType], TerminalSymbol[NodeType, EventType, RaftMessageBase]),
@ -32,6 +42,7 @@ type
mtx: RLock mtx: RLock
state: NonTerminalSymbol[NodeType] state: NonTerminalSymbol[NodeType]
stateTransitionsLUT: StateTransitionsRulesLUT[NodeType, EventType, RaftMessageBase] stateTransitionsLUT: StateTransitionsRulesLUT[NodeType, EventType, RaftMessageBase]
logicalFunctionsLut: LogicalFunctionConditionsLUT[EventType, NodeType, RaftMessageBase]
# FSM type constructor # FSM type constructor
proc new*[NodeType, EventType, NodeStates](T: type ConsensusFSM[NodeType, EventType, RaftMessageBase], proc new*[NodeType, EventType, NodeStates](T: type ConsensusFSM[NodeType, EventType, RaftMessageBase],
@ -43,11 +54,13 @@ proc new*[NodeType, EventType, NodeStates](T: type ConsensusFSM[NodeType, EventT
result.state = startSymbol result.state = startSymbol
result.stateTransitionsLUT = lut result.stateTransitionsLUT = lut
proc computeFSMLogicFunctionsPermutationValue[NonTerminalSymbol, EventType, RaftMessageBase](nts: NonTerminalSymbol, rawInput: TerminalSymbol, msg: Option[RaftMessageBase]): TerminalSymbol = proc computeFSMLogicFunctionsPermutationValue[NonTerminalSymbol, NodeType, EventType, RaftMessageBase](
fsm: ConsensusFSM[NodeType, EventType, RaftMessageBase],
nts: NonTerminalSymbol, rawInput: TerminalSymbol, msg: Option[RaftMessageBase]): TerminalSymbol =
let
e = rawInput[0]
var var
logicFunctionsConds = rawInput[1] logicFunctionsConds = fsm.logicalFunctionsLut[(e, NodeType)]
let e = rawInput[0]
for f in nts[2]: for f in nts[2]:
f = f(nts[1], e, msg) f = f(nts[1], e, msg)
@ -59,7 +72,7 @@ proc consensusFSMAdvance[NodeType, EventType](fsm: ConsensusFSM[NodeType, EventT
rawInput: TerminalSymbol[EventType, NodeType, RaftMessageBase]): NonTerminalSymbol[NodeType] = rawInput: TerminalSymbol[EventType, NodeType, RaftMessageBase]): NonTerminalSymbol[NodeType] =
withRLock(): withRLock():
var var
input = computeFSMLogicFunctionsPermutationValue(node, event, rawInput) input = computeFSMLogicFunctionsPermutationValue(fsm, node, event, rawInput)
fsm.state = fsm.stateTransitionsLUT[(fsm.state, input)] fsm.state = fsm.stateTransitionsLUT[(fsm.state, input)]
result = fsm.state result = fsm.state