-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Raft consensus algorithm
--   
--   Please see the README on GitHub at
--   <a>https://github.com/adjoint-io/raft#readme</a>
@package libraft
@version 0.1.1.0

module Control.Concurrent.STM.Timer
data Timer m
waitTimer :: MonadConc m => Timer m -> m ()

-- | Starting a timer will only work if the timer is currently stopped
startTimer :: MonadConc m => Timer m -> m ()
resetTimer :: MonadConc m => Timer m -> m ()
newTimer :: MonadConc m => Natural -> m (Timer m)

-- | Create a new timer with the given random seed and range of timer
--   timeouts.
newTimerRange :: MonadConc m => Int -> (Natural, Natural) -> m (Timer m)

module Raft.Types

-- | Unique identifier of a Raft node
type NodeId = ByteString
type NodeIds = Set NodeId

-- | Unique identifier of a client
newtype ClientId
ClientId :: NodeId -> ClientId

-- | Unique identifier of a leader
newtype LeaderId
LeaderId :: NodeId -> LeaderId
[unLeaderId] :: LeaderId -> NodeId

-- | Representation of monotonic election terms
newtype Term
Term :: Natural -> Term

-- | Initial term. Terms start at 0
term0 :: Term
incrTerm :: Term -> Term
prevTerm :: Term -> Term

-- | Representation of monotonic indices
newtype Index
Index :: Natural -> Index

-- | Initial index. Indeces start at 0
index0 :: Index
incrIndex :: Index -> Index

-- | Decrement index. If the given index is 0, return the given index
decrIndexWithDefault0 :: Index -> Index
instance Data.Serialize.Serialize Raft.Types.Index
instance GHC.Generics.Generic Raft.Types.Index
instance GHC.Real.Real Raft.Types.Index
instance GHC.Real.Integral Raft.Types.Index
instance GHC.Num.Num Raft.Types.Index
instance GHC.Enum.Enum Raft.Types.Index
instance GHC.Classes.Ord Raft.Types.Index
instance GHC.Classes.Eq Raft.Types.Index
instance GHC.Show.Show Raft.Types.Index
instance Data.Serialize.Serialize Raft.Types.Term
instance GHC.Generics.Generic Raft.Types.Term
instance GHC.Enum.Enum Raft.Types.Term
instance GHC.Classes.Ord Raft.Types.Term
instance GHC.Classes.Eq Raft.Types.Term
instance GHC.Show.Show Raft.Types.Term
instance Data.Serialize.Serialize Raft.Types.LeaderId
instance GHC.Generics.Generic Raft.Types.LeaderId
instance GHC.Classes.Eq Raft.Types.LeaderId
instance GHC.Show.Show Raft.Types.LeaderId
instance Data.Serialize.Serialize Raft.Types.ClientId
instance GHC.Generics.Generic Raft.Types.ClientId
instance GHC.Classes.Ord Raft.Types.ClientId
instance GHC.Classes.Eq Raft.Types.ClientId
instance GHC.Show.Show Raft.Types.ClientId

module Raft.Persistent

-- | Provides an interface to read and write the persistent state to disk.
class Monad m => RaftPersist m where {
    type family RaftPersistError m;
}
readPersistentState :: (RaftPersist m, Exception (RaftPersistError m)) => m (Either (RaftPersistError m) PersistentState)
writePersistentState :: (RaftPersist m, Exception (RaftPersistError m)) => PersistentState -> m (Either (RaftPersistError m) ())

-- | Persistent state that all Raft nodes maintain, regardless of node
--   state.
data PersistentState
PersistentState :: Term -> Maybe NodeId -> PersistentState

-- | Last term server has seen
[currentTerm] :: PersistentState -> Term

-- | Candidate id that received vote in current term
[votedFor] :: PersistentState -> Maybe NodeId

-- | A node initiates its persistent state with term 0 and with its vote
--   blank
initPersistentState :: PersistentState
instance Data.Serialize.Serialize Raft.Persistent.PersistentState
instance GHC.Generics.Generic Raft.Persistent.PersistentState
instance GHC.Show.Show Raft.Persistent.PersistentState

module Raft.Log
data EntryIssuer
ClientIssuer :: ClientId -> EntryIssuer
LeaderIssuer :: LeaderId -> EntryIssuer
data EntryValue v
EntryValue :: v -> EntryValue v

-- | Used as a first committed entry of a new term
NoValue :: EntryValue v

-- | Representation of an entry in the replicated log
data Entry v
Entry :: Index -> Term -> EntryValue v -> EntryIssuer -> Entry v

-- | Index of entry in the log
[entryIndex] :: Entry v -> Index

-- | Term when entry was received by leader
[entryTerm] :: Entry v -> Term

-- | Command to update state machine
[entryValue] :: Entry v -> EntryValue v

-- | Id of the client that issued the command
[entryIssuer] :: Entry v -> EntryIssuer
type Entries v = Seq (Entry v)

-- | Provides an interface for nodes to write log entries to storage.
class Monad m => RaftWriteLog m v where {
    type family RaftWriteLogError m;
}

-- | Write the given log entries to storage
writeLogEntries :: (RaftWriteLog m v, Exception (RaftWriteLogError m)) => Entries v -> m (Either (RaftWriteLogError m) ())
data DeleteSuccess v
DeleteSuccess :: DeleteSuccess v

-- | Provides an interface for nodes to delete log entries from storage.
class Monad m => RaftDeleteLog m v where {
    type family RaftDeleteLogError m;
}

-- | Delete log entries from a given index; e.g. 'deleteLogEntriesFrom 7'
--   should delete every log entry with an index &gt;= 7.
deleteLogEntriesFrom :: (RaftDeleteLog m v, Exception (RaftDeleteLogError m)) => Index -> m (Either (RaftDeleteLogError m) (DeleteSuccess v))

-- | Provides an interface for nodes to read log entries from storage.
class Monad m => RaftReadLog m v where {
    type family RaftReadLogError m;
}

-- | Read the log at a given index
readLogEntry :: (RaftReadLog m v, Exception (RaftReadLogError m)) => Index -> m (Either (RaftReadLogError m) (Maybe (Entry v)))

-- | Read log entries from a specific index onwards, including the specific
--   index
readLogEntriesFrom :: (RaftReadLog m v, Exception (RaftReadLogError m)) => Index -> m (Either (RaftReadLogError m) (Entries v))

-- | Read the last log entry in the log
readLastLogEntry :: (RaftReadLog m v, Exception (RaftReadLogError m)) => m (Either (RaftReadLogError m) (Maybe (Entry v)))

-- | Read log entries from a specific index onwards, including the specific
--   index
readLogEntriesFrom :: (RaftReadLog m v, Exception (RaftReadLogError m)) => Index -> m (Either (RaftReadLogError m) (Entries v))
type RaftLog m v = (RaftReadLog m v, RaftWriteLog m v, RaftDeleteLog m v)
type RaftLogExceptions m = (Exception (RaftReadLogError m), Exception (RaftWriteLogError m), Exception (RaftDeleteLogError m))

-- | Representation of possible errors that come from reading, writing or
--   deleting logs from the persistent storage
data RaftLogError m
RaftLogReadError :: RaftReadLogError m -> RaftLogError m
RaftLogWriteError :: RaftWriteLogError m -> RaftLogError m
RaftLogDeleteError :: RaftDeleteLogError m -> RaftLogError m
updateLog :: forall m v. (RaftDeleteLog m v, Exception (RaftDeleteLogError m), RaftWriteLog m v, Exception (RaftWriteLogError m)) => Entries v -> m (Either (RaftLogError m) ())
instance Data.Serialize.Serialize v => Data.Serialize.Serialize (Raft.Log.Entry v)
instance GHC.Generics.Generic (Raft.Log.Entry v)
instance GHC.Show.Show v => GHC.Show.Show (Raft.Log.Entry v)
instance Data.Serialize.Serialize v => Data.Serialize.Serialize (Raft.Log.EntryValue v)
instance GHC.Generics.Generic (Raft.Log.EntryValue v)
instance GHC.Show.Show v => GHC.Show.Show (Raft.Log.EntryValue v)
instance Data.Serialize.Serialize Raft.Log.EntryIssuer
instance GHC.Generics.Generic Raft.Log.EntryIssuer
instance GHC.Show.Show Raft.Log.EntryIssuer

module Raft.RPC

-- | Interface for nodes to send messages to one another. E.g.
--   Control.Concurrent.Chan, Network.Socket, etc.
class RaftSendRPC m v
sendRPC :: RaftSendRPC m v => NodeId -> RPCMessage v -> m ()

-- | Interface for nodes to receive messages from one another
class Show (RaftRecvRPCError m v) => RaftRecvRPC m v where {
    type family RaftRecvRPCError m v;
}
receiveRPC :: RaftRecvRPC m v => m (Either (RaftRecvRPCError m v) (RPCMessage v))

-- | Representation of a message sent between nodes
data RPCMessage v
RPCMessage :: NodeId -> RPC v -> RPCMessage v
[sender] :: RPCMessage v -> NodeId
[rpc] :: RPCMessage v -> RPC v
data RPC v
AppendEntriesRPC :: AppendEntries v -> RPC v
AppendEntriesResponseRPC :: AppendEntriesResponse -> RPC v
RequestVoteRPC :: RequestVote -> RPC v
RequestVoteResponseRPC :: RequestVoteResponse -> RPC v
class RPCType a v
toRPC :: RPCType a v => a -> RPC v
rpcTerm :: RPC v -> Term
data NoEntriesSpec
FromInconsistency :: NoEntriesSpec
FromHeartbeat :: NoEntriesSpec
FromClientReadReq :: Int -> NoEntriesSpec
data EntriesSpec v
FromIndex :: Index -> EntriesSpec v
FromNewLeader :: Entry v -> EntriesSpec v
FromClientWriteReq :: Entry v -> EntriesSpec v
NoEntries :: NoEntriesSpec -> EntriesSpec v

-- | The data used to construct an AppendEntries value, snapshotted from
--   the node state at the time the AppendEntries val should be created.
data AppendEntriesData v
AppendEntriesData :: Term -> Index -> EntriesSpec v -> AppendEntriesData v
[aedTerm] :: AppendEntriesData v -> Term
[aedLeaderCommit] :: AppendEntriesData v -> Index
[aedEntriesSpec] :: AppendEntriesData v -> EntriesSpec v

-- | Representation of a message sent from a leader to its peers
data AppendEntries v
AppendEntries :: Term -> LeaderId -> Index -> Term -> Entries v -> Index -> Maybe Int -> AppendEntries v

-- | Leader's term
[aeTerm] :: AppendEntries v -> Term

-- | Leader's identifier so that followers can redirect clients
[aeLeaderId] :: AppendEntries v -> LeaderId

-- | Index of log entry immediately preceding new ones
[aePrevLogIndex] :: AppendEntries v -> Index

-- | Term of aePrevLogIndex entry
[aePrevLogTerm] :: AppendEntries v -> Term

-- | Log entries to store (empty for heartbeat)
[aeEntries] :: AppendEntries v -> Entries v

-- | Leader's commit index
[aeLeaderCommit] :: AppendEntries v -> Index

-- | which read request the message corresponds to
[aeReadRequest] :: AppendEntries v -> Maybe Int

-- | Representation of the response from a follower to an AppendEntries
--   message
data AppendEntriesResponse
AppendEntriesResponse :: Term -> Bool -> Maybe Int -> AppendEntriesResponse

-- | current term for leader to update itself
[aerTerm] :: AppendEntriesResponse -> Term

-- | true if follower contained entry matching aePrevLogIndex and
--   aePrevLogTerm
[aerSuccess] :: AppendEntriesResponse -> Bool

-- | which read request the response corresponds to
[aerReadRequest] :: AppendEntriesResponse -> Maybe Int

-- | Representation of the message sent by candidates to their peers to
--   request their vote
data RequestVote
RequestVote :: Term -> NodeId -> Index -> Term -> RequestVote

-- | candidates term
[rvTerm] :: RequestVote -> Term

-- | candidate requesting vote
[rvCandidateId] :: RequestVote -> NodeId

-- | index of candidate's last log entry
[rvLastLogIndex] :: RequestVote -> Index

-- | term of candidate's last log entry
[rvLastLogTerm] :: RequestVote -> Term

-- | Representation of a response to a RequestVote message
data RequestVoteResponse
RequestVoteResponse :: Term -> Bool -> RequestVoteResponse

-- | current term for candidate to update itself
[rvrTerm] :: RequestVoteResponse -> Term

-- | true means candidate recieved vote
[rvrVoteGranted] :: RequestVoteResponse -> Bool
instance Data.Serialize.Serialize v => Data.Serialize.Serialize (Raft.RPC.RPCMessage v)
instance GHC.Generics.Generic (Raft.RPC.RPCMessage v)
instance GHC.Show.Show v => GHC.Show.Show (Raft.RPC.RPCMessage v)
instance Data.Serialize.Serialize v => Data.Serialize.Serialize (Raft.RPC.RPC v)
instance GHC.Generics.Generic (Raft.RPC.RPC v)
instance GHC.Show.Show v => GHC.Show.Show (Raft.RPC.RPC v)
instance Data.Serialize.Serialize Raft.RPC.RequestVoteResponse
instance GHC.Generics.Generic Raft.RPC.RequestVoteResponse
instance GHC.Show.Show Raft.RPC.RequestVoteResponse
instance Data.Serialize.Serialize Raft.RPC.RequestVote
instance GHC.Generics.Generic Raft.RPC.RequestVote
instance GHC.Show.Show Raft.RPC.RequestVote
instance Data.Serialize.Serialize Raft.RPC.AppendEntriesResponse
instance GHC.Generics.Generic Raft.RPC.AppendEntriesResponse
instance GHC.Show.Show Raft.RPC.AppendEntriesResponse
instance Data.Serialize.Serialize v => Data.Serialize.Serialize (Raft.RPC.AppendEntries v)
instance GHC.Generics.Generic (Raft.RPC.AppendEntries v)
instance GHC.Show.Show v => GHC.Show.Show (Raft.RPC.AppendEntries v)
instance GHC.Show.Show v => GHC.Show.Show (Raft.RPC.AppendEntriesData v)
instance GHC.Show.Show v => GHC.Show.Show (Raft.RPC.EntriesSpec v)
instance GHC.Show.Show Raft.RPC.NoEntriesSpec
instance Raft.RPC.RPCType (Raft.RPC.AppendEntries v) v
instance Raft.RPC.RPCType Raft.RPC.AppendEntriesResponse v
instance Raft.RPC.RPCType Raft.RPC.RequestVote v
instance Raft.RPC.RPCType Raft.RPC.RequestVoteResponse v

module Raft.NodeState
data Mode
Follower :: Mode
Candidate :: Mode
Leader :: Mode

-- | All valid state transitions of a Raft node
data Transition (init :: Mode) (res :: Mode)
[StartElection] :: Transition  'Follower  'Candidate
[HigherTermFoundFollower] :: Transition  'Follower  'Follower
[RestartElection] :: Transition  'Candidate  'Candidate
[DiscoverLeader] :: Transition  'Candidate  'Follower
[HigherTermFoundCandidate] :: Transition  'Candidate  'Follower
[BecomeLeader] :: Transition  'Candidate  'Leader
[SendHeartbeat] :: Transition  'Leader  'Leader
[DiscoverNewLeader] :: Transition  'Leader  'Follower
[HigherTermFoundLeader] :: Transition  'Leader  'Follower
[Noop] :: Transition init init

-- | Existential type hiding the result type of a transition
data ResultState init
[ResultState] :: Transition init res -> NodeState res -> ResultState init
followerResultState :: Transition init  'Follower -> FollowerState -> ResultState init
candidateResultState :: Transition init  'Candidate -> CandidateState -> ResultState init
leaderResultState :: Transition init  'Leader -> LeaderState -> ResultState init

-- | Existential type hiding the internal node state
data RaftNodeState
[RaftNodeState] :: {unRaftNodeState :: NodeState s} -> RaftNodeState
nodeMode :: RaftNodeState -> Mode

-- | A node in Raft begins as a follower
initRaftNodeState :: RaftNodeState

-- | The volatile state of a Raft Node
data NodeState (a :: Mode)
[NodeFollowerState] :: FollowerState -> NodeState  'Follower
[NodeCandidateState] :: CandidateState -> NodeState  'Candidate
[NodeLeaderState] :: LeaderState -> NodeState  'Leader

-- | Representation of the current leader in the cluster. The system is
--   considered to be unavailable if there is no leader
data CurrentLeader
CurrentLeader :: LeaderId -> CurrentLeader
NoLeader :: CurrentLeader
data FollowerState
FollowerState :: CurrentLeader -> Index -> Index -> (Index, Term) -> Maybe Term -> FollowerState

-- | Id of the current leader
[fsCurrentLeader] :: FollowerState -> CurrentLeader

-- | Index of highest log entry known to be committed
[fsCommitIndex] :: FollowerState -> Index

-- | Index of highest log entry applied to state machine
[fsLastApplied] :: FollowerState -> Index

-- | Index and term of the last log entry in the node's log
[fsLastLogEntryData] :: FollowerState -> (Index, Term)

-- | The term of the log entry specified in and AppendEntriesRPC
[fsTermAtAEPrevIndex] :: FollowerState -> Maybe Term
data CandidateState
CandidateState :: Index -> Index -> NodeIds -> (Index, Term) -> CandidateState

-- | Index of highest log entry known to be committed
[csCommitIndex] :: CandidateState -> Index

-- | Index of highest log entry applied to state machine
[csLastApplied] :: CandidateState -> Index

-- | Votes from other nodes in the raft network
[csVotes] :: CandidateState -> NodeIds

-- | Index and term of the last log entry in the node's log
[csLastLogEntryData] :: CandidateState -> (Index, Term)
type ClientReadReqs = Map Int (ClientId, Int)
data LeaderState
LeaderState :: Index -> Index -> Map NodeId Index -> Map NodeId Index -> (Index, Term, Maybe EntryIssuer) -> Int -> ClientReadReqs -> LeaderState

-- | Index of highest log entry known to be committed
[lsCommitIndex] :: LeaderState -> Index

-- | Index of highest log entry applied to state machine
[lsLastApplied] :: LeaderState -> Index

-- | For each server, index of the next log entry to send to that server
[lsNextIndex] :: LeaderState -> Map NodeId Index

-- | For each server, index of highest log entry known to be replicated on
--   server
[lsMatchIndex] :: LeaderState -> Map NodeId Index

-- | Index, term, and client id of the last log entry in the node's log.
--   The only time `Maybe ClientId` will be Nothing is at the initial term.
[lsLastLogEntryData] :: LeaderState -> (Index, Term, Maybe EntryIssuer)

-- | Number of read requests handled this term
[lsReadReqsHandled] :: LeaderState -> Int

-- | The number of successful responses received regarding a specific read
--   request heartbeat.
[lsReadRequest] :: LeaderState -> ClientReadReqs

-- | Update the last log entry in the node's log
setLastLogEntryData :: NodeState ns -> Entries v -> NodeState ns

-- | Get the last applied index and the commit index of the last log entry
--   in the node's log
getLastLogEntryData :: NodeState ns -> (Index, Term)

-- | Get the index of highest log entry applied to state machine and the
--   index of highest log entry known to be committed
getLastAppliedAndCommitIndex :: NodeState ns -> (Index, Index)

-- | Check if node is in a follower state
isFollower :: NodeState s -> Bool

-- | Check if node is in a candidate state
isCandidate :: NodeState s -> Bool

-- | Check if node is in a leader state
isLeader :: NodeState s -> Bool
instance GHC.Show.Show Raft.NodeState.LeaderState
instance GHC.Show.Show Raft.NodeState.CandidateState
instance GHC.Show.Show Raft.NodeState.FollowerState
instance GHC.Generics.Generic Raft.NodeState.CurrentLeader
instance GHC.Classes.Eq Raft.NodeState.CurrentLeader
instance GHC.Show.Show Raft.NodeState.CurrentLeader
instance GHC.Show.Show Raft.NodeState.Mode
instance GHC.Show.Show (Raft.NodeState.Transition init res)
instance GHC.Show.Show (Raft.NodeState.ResultState init)
instance GHC.Show.Show Raft.NodeState.RaftNodeState
instance GHC.Show.Show (Raft.NodeState.NodeState v)
instance Data.Serialize.Serialize Raft.NodeState.CurrentLeader

module Raft.Logging

-- | Representation of the logs' destination
data LogDest
LogFile :: FilePath -> LogDest
LogStdout :: LogDest
NoLogs :: LogDest

-- | Representation of the severity of the logs
data Severity
Info :: Severity
Debug :: Severity
Critical :: Severity
data LogMsg
LogMsg :: Maybe UTCTime -> Severity -> LogMsgData -> LogMsg
[mTime] :: LogMsg -> Maybe UTCTime
[severity] :: LogMsg -> Severity
[logMsgData] :: LogMsg -> LogMsgData
data LogMsgData
LogMsgData :: NodeId -> Mode -> Text -> LogMsgData
[logMsgNodeId] :: LogMsgData -> NodeId
[logMsgNodeState] :: LogMsgData -> Mode
[logMsg] :: LogMsgData -> Text
logMsgToText :: LogMsg -> Text
logMsgDataToText :: LogMsgData -> Text
class Monad m => RaftLogger m
loggerNodeId :: RaftLogger m => m NodeId
loggerNodeState :: RaftLogger m => m RaftNodeState
mkLogMsgData :: RaftLogger m => Text -> m LogMsgData
logToDest :: MonadIO m => LogDest -> LogMsg -> m ()
logToStdout :: MonadIO m => LogMsg -> m ()
logToFile :: MonadIO m => FilePath -> LogMsg -> m ()
logWithSeverityIO :: (RaftLogger m, MonadIO m) => Severity -> LogDest -> Text -> m ()
logInfoIO :: (RaftLogger m, MonadIO m) => LogDest -> Text -> m ()
logDebugIO :: (RaftLogger m, MonadIO m) => LogDest -> Text -> m ()
logCriticalIO :: (RaftLogger m, MonadIO m) => LogDest -> Text -> m ()
newtype RaftLoggerT m a
RaftLoggerT :: StateT [LogMsg] m a -> RaftLoggerT m a
[unRaftLoggerT] :: RaftLoggerT m a -> StateT [LogMsg] m a
runRaftLoggerT :: Monad m => RaftLoggerT m a -> m (a, [LogMsg])
type RaftLoggerM = RaftLoggerT Identity
runRaftLoggerM :: RaftLoggerM a -> (a, [LogMsg])
logWithSeverity :: RaftLogger m => Severity -> Text -> RaftLoggerT m ()
logInfo :: RaftLogger m => Text -> RaftLoggerT m ()
logDebug :: RaftLogger m => Text -> RaftLoggerT m ()
logCritical :: RaftLogger m => Text -> RaftLoggerT m ()
instance Control.Monad.Trans.Class.MonadTrans Raft.Logging.RaftLoggerT
instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState [Raft.Logging.LogMsg] (Raft.Logging.RaftLoggerT m)
instance GHC.Base.Monad m => GHC.Base.Monad (Raft.Logging.RaftLoggerT m)
instance GHC.Base.Monad m => GHC.Base.Applicative (Raft.Logging.RaftLoggerT m)
instance GHC.Base.Functor m => GHC.Base.Functor (Raft.Logging.RaftLoggerT m)
instance GHC.Show.Show Raft.Logging.LogMsgData
instance GHC.Show.Show Raft.Logging.Severity
instance Raft.Logging.RaftLogger m => Raft.Logging.RaftLogger (Raft.Logging.RaftLoggerT m)

module Raft.Config

-- | Configuration of a node in the cluster
data NodeConfig
NodeConfig :: NodeId -> NodeIds -> (Natural, Natural) -> Natural -> NodeConfig

-- | Node id of the running node
[configNodeId] :: NodeConfig -> NodeId

-- | Set of all other node ids in the cluster
[configNodeIds] :: NodeConfig -> NodeIds

-- | Range of times an election timeout can take
[configElectionTimeout] :: NodeConfig -> (Natural, Natural)

-- | Heartbeat timeout timer
[configHeartbeatTimeout] :: NodeConfig -> Natural
instance GHC.Show.Show Raft.Config.NodeConfig

module Raft.Client

-- | Interface for Raft nodes to send messages to clients
class RaftSendClient m sm
sendClient :: RaftSendClient m sm => ClientId -> ClientResponse sm -> m ()

-- | Interface for Raft nodes to receive messages from clients
class Show (RaftRecvClientError m v) => RaftRecvClient m v where {
    type family RaftRecvClientError m v;
}
receiveClient :: RaftRecvClient m v => m (Either (RaftRecvClientError m v) (ClientRequest v))

-- | Representation of a client request coupled with the client id
data ClientRequest v
ClientRequest :: ClientId -> ClientReq v -> ClientRequest v

-- | Representation of a client request
data ClientReq v

-- | Request the latest state of the state machine
ClientReadReq :: ClientReq v

-- | Write a command
ClientWriteReq :: v -> ClientReq v

-- | Representation of a client response
data ClientResponse s

-- | Respond with the latest state of the state machine.
ClientReadResponse :: ClientReadResp s -> ClientResponse s

-- | Respond with the index of the entry appended to the log
ClientWriteResponse :: ClientWriteResp -> ClientResponse s

-- | Respond with the node id of the current leader
ClientRedirectResponse :: ClientRedirResp -> ClientResponse s

-- | Representation of a read response to a client The <tt>s</tt> stands
--   for the "current" state of the state machine
newtype ClientReadResp s
ClientReadResp :: s -> ClientReadResp s

-- | Representation of a write response to a client
data ClientWriteResp

-- | Index of the entry appended to the log due to the previous client
--   request
ClientWriteResp :: Index -> ClientWriteResp

-- | Representation of a redirect response to a client
data ClientRedirResp
ClientRedirResp :: CurrentLeader -> ClientRedirResp
instance GHC.Generics.Generic (Raft.Client.ClientResponse s)
instance GHC.Show.Show s => GHC.Show.Show (Raft.Client.ClientResponse s)
instance GHC.Generics.Generic Raft.Client.ClientRedirResp
instance GHC.Show.Show Raft.Client.ClientRedirResp
instance GHC.Generics.Generic Raft.Client.ClientWriteResp
instance GHC.Show.Show Raft.Client.ClientWriteResp
instance GHC.Generics.Generic (Raft.Client.ClientReadResp s)
instance GHC.Show.Show s => GHC.Show.Show (Raft.Client.ClientReadResp s)
instance GHC.Generics.Generic (Raft.Client.ClientRequest v)
instance GHC.Show.Show v => GHC.Show.Show (Raft.Client.ClientRequest v)
instance GHC.Generics.Generic (Raft.Client.ClientReq v)
instance GHC.Show.Show v => GHC.Show.Show (Raft.Client.ClientReq v)
instance Data.Serialize.Serialize s => Data.Serialize.Serialize (Raft.Client.ClientResponse s)
instance Data.Serialize.Serialize Raft.Client.ClientRedirResp
instance Data.Serialize.Serialize Raft.Client.ClientWriteResp
instance Data.Serialize.Serialize s => Data.Serialize.Serialize (Raft.Client.ClientReadResp s)
instance Data.Serialize.Serialize v => Data.Serialize.Serialize (Raft.Client.ClientRequest v)
instance Data.Serialize.Serialize v => Data.Serialize.Serialize (Raft.Client.ClientReq v)

module Raft.Event

-- | Representation of events a raft node can send and receive
data Event v
MessageEvent :: MessageEvent v -> Event v
TimeoutEvent :: Timeout -> Event v

-- | Representation of timeouts
data Timeout

-- | Timeout after which a follower will become candidate
ElectionTimeout :: Timeout

-- | Timeout after which a leader will send AppendEntries RPC to all peers
HeartbeatTimeout :: Timeout

-- | Representation of message events to a node
data MessageEvent v

-- | Incoming event from a peer
RPCMessageEvent :: RPCMessage v -> MessageEvent v

-- | Incoming event from a client
ClientRequestEvent :: ClientRequest v -> MessageEvent v
instance GHC.Show.Show v => GHC.Show.Show (Raft.Event.Event v)
instance GHC.Generics.Generic (Raft.Event.MessageEvent v)
instance GHC.Show.Show v => GHC.Show.Show (Raft.Event.MessageEvent v)
instance GHC.Show.Show Raft.Event.Timeout
instance Data.Serialize.Serialize v => Data.Serialize.Serialize (Raft.Event.MessageEvent v)

module Raft.Action
data Action sm v

-- | Send a message to a specific node id
SendRPC :: NodeId -> SendRPCAction v -> Action sm v

-- | Send a unique message to specific nodes in parallel
SendRPCs :: Map NodeId (SendRPCAction v) -> Action sm v

-- | Broadcast the same message to all nodes
BroadcastRPC :: NodeIds -> SendRPCAction v -> Action sm v

-- | Append entries to the replicated log
AppendLogEntries :: Entries v -> Action sm v

-- | Respond to client after a client request
RespondToClient :: ClientId -> ClientResponse sm -> Action sm v

-- | Reset a timeout timer
ResetTimeoutTimer :: Timeout -> Action sm v
data SendRPCAction v
SendAppendEntriesRPC :: AppendEntriesData v -> SendRPCAction v
SendAppendEntriesResponseRPC :: AppendEntriesResponse -> SendRPCAction v
SendRequestVoteRPC :: RequestVote -> SendRPCAction v
SendRequestVoteResponseRPC :: RequestVoteResponse -> SendRPCAction v
instance (GHC.Show.Show v, GHC.Show.Show sm) => GHC.Show.Show (Raft.Action.Action sm v)
instance GHC.Show.Show v => GHC.Show.Show (Raft.Action.SendRPCAction v)

module Raft.Monad

-- | Interface to handle commands in the underlying state machine.
--   Functional dependency permitting only a single state machine command
--   to be defined to update the state machine.
class RSMP sm v | sm -> v where {
    data family RSMPError sm v;
    type family RSMPCtx sm v = ctx | ctx -> sm v;
}
applyCmdRSMP :: RSMP sm v => RSMPCtx sm v -> sm -> v -> Either (RSMPError sm v) sm
class (Monad m, RSMP sm v) => RSM sm v m | m sm -> v
validateCmd :: RSM sm v m => v -> m (Either (RSMPError sm v) ())
askRSMPCtx :: RSM sm v m => m (RSMPCtx sm v)
applyEntryRSM :: RSM sm v m => sm -> Entry v -> m (Either (RSMPError sm v) sm)
tellAction :: Action sm v -> TransitionM sm v ()
tellActions :: [Action sm v] -> TransitionM sm v ()
data TransitionEnv sm
TransitionEnv :: NodeConfig -> sm -> RaftNodeState -> TransitionEnv sm
[nodeConfig] :: TransitionEnv sm -> NodeConfig
[stateMachine] :: TransitionEnv sm -> sm
[nodeState] :: TransitionEnv sm -> RaftNodeState
newtype TransitionM sm v a
TransitionM :: RaftLoggerT (RWS (TransitionEnv sm) [Action sm v] PersistentState) a -> TransitionM sm v a
[unTransitionM] :: TransitionM sm v a -> RaftLoggerT (RWS (TransitionEnv sm) [Action sm v] PersistentState) a
runTransitionM :: TransitionEnv sm -> PersistentState -> TransitionM sm v a -> ((a, [LogMsg]), PersistentState, [Action sm v])
askNodeId :: TransitionM sm v NodeId
type RPCHandler ns sm r v = RPCType r v => NodeState ns -> NodeId -> r -> TransitionM sm v (ResultState ns)
type TimeoutHandler ns sm v = NodeState ns -> Timeout -> TransitionM sm v (ResultState ns)
type ClientReqHandler ns sm v = NodeState ns -> ClientRequest v -> TransitionM sm v (ResultState ns)
broadcast :: SendRPCAction v -> TransitionM sm v ()
send :: NodeId -> SendRPCAction v -> TransitionM sm v ()

-- | Resets the election timeout.
resetElectionTimeout :: TransitionM sm v ()
resetHeartbeatTimeout :: TransitionM sm v ()
redirectClientToLeader :: ClientId -> CurrentLeader -> TransitionM sm v ()
respondClientRead :: ClientId -> TransitionM sm v ()
appendLogEntries :: Show v => Seq (Entry v) -> TransitionM sm v ()
startElection :: Index -> Index -> (Index, Term) -> TransitionM sm v CandidateState
logInfo :: () => Text -> TransitionM sm v ()
logDebug :: () => Text -> TransitionM sm v ()
instance GHC.Base.Monad (Raft.Monad.TransitionM sm v)
instance GHC.Base.Applicative (Raft.Monad.TransitionM sm v)
instance GHC.Base.Functor (Raft.Monad.TransitionM sm v)
instance Control.Monad.Writer.Class.MonadWriter [Raft.Action.Action sm v] (Raft.Monad.TransitionM sm v)
instance Control.Monad.Reader.Class.MonadReader (Raft.Monad.TransitionEnv sm) (Raft.Monad.TransitionM sm v)
instance Control.Monad.State.Class.MonadState Raft.Persistent.PersistentState (Raft.Monad.TransitionM sm v)
instance Raft.Logging.RaftLogger (Control.Monad.Trans.RWS.Lazy.RWS (Raft.Monad.TransitionEnv sm) [Raft.Action.Action sm v] Raft.Persistent.PersistentState)

module Raft.Leader

-- | Leaders should not respond to <a>AppendEntries</a> messages.
handleAppendEntries :: RPCHandler  'Leader sm (AppendEntries v) v
handleAppendEntriesResponse :: forall sm v. Show v => RPCHandler  'Leader sm AppendEntriesResponse v

-- | Leaders should not respond to <a>RequestVote</a> messages.
handleRequestVote :: RPCHandler  'Leader sm RequestVote v

-- | Leaders should not respond to <a>RequestVoteResponse</a> messages.
handleRequestVoteResponse :: RPCHandler  'Leader sm RequestVoteResponse v
handleTimeout :: Show v => TimeoutHandler  'Leader sm v

-- | The leader handles all client requests, responding with the current
--   state machine on a client read, and appending an entry to the log on a
--   valid client write.
handleClientRequest :: Show v => ClientReqHandler  'Leader sm v

module Raft.Follower

-- | Handle AppendEntries RPC message from Leader Sections 5.2 and 5.3 of
--   Raft Paper &amp; Figure 2: Receiver Implementation
--   
--   Note: see <a>PersistentState</a> datatype for discussion about not
--   keeping the entire log in memory.
handleAppendEntries :: forall v sm. Show v => RPCHandler  'Follower sm (AppendEntries v) v

-- | Followers should not respond to <a>AppendEntriesResponse</a> messages.
handleAppendEntriesResponse :: RPCHandler  'Follower sm AppendEntriesResponse v
handleRequestVote :: RPCHandler  'Follower sm RequestVote v

-- | Followers should not respond to <a>RequestVoteResponse</a> messages.
handleRequestVoteResponse :: RPCHandler  'Follower sm RequestVoteResponse v

-- | Follower converts to Candidate if handling ElectionTimeout
handleTimeout :: TimeoutHandler  'Follower sm v

-- | When a client handles a client request, it redirects the client to the
--   current leader by responding with the current leader id, if it knows
--   of one.
handleClientRequest :: ClientReqHandler  'Follower sm v

module Raft.Candidate
handleAppendEntries :: RPCHandler  'Candidate sm (AppendEntries v) v

-- | Candidates should not respond to <a>AppendEntriesResponse</a>
--   messages.
handleAppendEntriesResponse :: RPCHandler  'Candidate sm AppendEntriesResponse v
handleRequestVote :: RPCHandler  'Candidate sm RequestVote v

-- | Candidates should not respond to <a>RequestVoteResponse</a> messages.
handleRequestVoteResponse :: forall sm v. Show v => RPCHandler  'Candidate sm RequestVoteResponse v
handleTimeout :: TimeoutHandler  'Candidate sm v

-- | When candidates handle a client request, they respond with NoLeader,
--   as the very reason they are candidate is because there is no leader.
--   This is done instead of simply not responding such that the client can
--   know that the node is live but that there is an election taking place.
handleClientRequest :: ClientReqHandler  'Candidate sm v

module Raft.Handle

-- | Main entry point for handling events
handleEvent :: forall sm v. (RSMP sm v, Show v) => RaftNodeState -> TransitionEnv sm -> PersistentState -> Event v -> (RaftNodeState, PersistentState, [Action sm v], [LogMsg])
data RaftHandler ns sm v
RaftHandler :: RPCHandler ns sm (AppendEntries v) v -> RPCHandler ns sm AppendEntriesResponse v -> RPCHandler ns sm RequestVote v -> RPCHandler ns sm RequestVoteResponse v -> TimeoutHandler ns sm v -> ClientReqHandler ns sm v -> RaftHandler ns sm v
[handleAppendEntries] :: RaftHandler ns sm v -> RPCHandler ns sm (AppendEntries v) v
[handleAppendEntriesResponse] :: RaftHandler ns sm v -> RPCHandler ns sm AppendEntriesResponse v
[handleRequestVote] :: RaftHandler ns sm v -> RPCHandler ns sm RequestVote v
[handleRequestVoteResponse] :: RaftHandler ns sm v -> RPCHandler ns sm RequestVoteResponse v
[handleTimeout] :: RaftHandler ns sm v -> TimeoutHandler ns sm v
[handleClientRequest] :: RaftHandler ns sm v -> ClientReqHandler ns sm v
followerRaftHandler :: Show v => RaftHandler  'Follower sm v
candidateRaftHandler :: Show v => RaftHandler  'Candidate sm v
leaderRaftHandler :: Show v => RaftHandler  'Leader sm v
mkRaftHandler :: forall ns sm v. Show v => NodeState ns -> RaftHandler ns sm v
handleEvent' :: forall ns sm v. (RSMP sm v, Show v) => NodeState ns -> TransitionEnv sm -> PersistentState -> Event v -> ((ResultState ns, [LogMsg]), PersistentState, [Action sm v])

module Raft

-- | Interface to handle commands in the underlying state machine.
--   Functional dependency permitting only a single state machine command
--   to be defined to update the state machine.
class RSMP sm v | sm -> v where {
    data family RSMPError sm v;
    type family RSMPCtx sm v = ctx | ctx -> sm v;
}
applyCmdRSMP :: RSMP sm v => RSMPCtx sm v -> sm -> v -> Either (RSMPError sm v) sm
class (Monad m, RSMP sm v) => RSM sm v m | m sm -> v
validateCmd :: RSM sm v m => v -> m (Either (RSMPError sm v) ())
askRSMPCtx :: RSM sm v m => m (RSMPCtx sm v)

-- | Interface for nodes to send messages to one another. E.g.
--   Control.Concurrent.Chan, Network.Socket, etc.
class RaftSendRPC m v
sendRPC :: RaftSendRPC m v => NodeId -> RPCMessage v -> m ()

-- | Interface for nodes to receive messages from one another
class Show (RaftRecvRPCError m v) => RaftRecvRPC m v where {
    type family RaftRecvRPCError m v;
}
receiveRPC :: RaftRecvRPC m v => m (Either (RaftRecvRPCError m v) (RPCMessage v))

-- | Interface for Raft nodes to send messages to clients
class RaftSendClient m sm
sendClient :: RaftSendClient m sm => ClientId -> ClientResponse sm -> m ()

-- | Interface for Raft nodes to receive messages from clients
class Show (RaftRecvClientError m v) => RaftRecvClient m v where {
    type family RaftRecvClientError m v;
}
receiveClient :: RaftRecvClient m v => m (Either (RaftRecvClientError m v) (ClientRequest v))

-- | Provides an interface to read and write the persistent state to disk.
class Monad m => RaftPersist m where {
    type family RaftPersistError m;
}
readPersistentState :: (RaftPersist m, Exception (RaftPersistError m)) => m (Either (RaftPersistError m) PersistentState)
writePersistentState :: (RaftPersist m, Exception (RaftPersistError m)) => PersistentState -> m (Either (RaftPersistError m) ())
type EventChan m v = TChan (STM m) (Event v)

-- | The raft server environment composed of the concurrent variables used
--   in the effectful raft layer.
data RaftEnv v m
RaftEnv :: EventChan m v -> m () -> m () -> NodeConfig -> LogDest -> RaftEnv v m
[eventChan] :: RaftEnv v m -> EventChan m v
[resetElectionTimer] :: RaftEnv v m -> m ()
[resetHeartbeatTimer] :: RaftEnv v m -> m ()
[raftNodeConfig] :: RaftEnv v m -> NodeConfig
[raftNodeLogDest] :: RaftEnv v m -> LogDest

-- | Run timers, RPC and client request handlers and start event loop. It
--   should run forever
runRaftNode :: (Show v, Show sm, Show (Action sm v), MonadIO m, MonadConc m, MonadFail m, RSM sm v m, Show (RSMPError sm v), RaftSendRPC m v, RaftRecvRPC m v, RaftSendClient m sm, RaftRecvClient m v, RaftLog m v, RaftLogExceptions m, RaftPersist m, Exception (RaftPersistError m)) => NodeConfig -> LogDest -> Int -> sm -> m ()
runRaftT :: MonadConc m => RaftNodeState -> RaftEnv v m -> RaftT v m () -> m ()
handleEventLoop :: forall sm v m. (Show v, Show sm, Show (Action sm v), MonadIO m, MonadConc m, MonadFail m, RSM sm v m, Show (RSMPError sm v), RaftPersist m, RaftSendRPC m v, RaftSendClient m sm, RaftLog m v, RaftLogExceptions m, RaftPersist m, Exception (RaftPersistError m)) => sm -> RaftT v m ()

-- | Representation of a client request coupled with the client id
data ClientRequest v
ClientRequest :: ClientId -> ClientReq v -> ClientRequest v

-- | Representation of a client request
data ClientReq v

-- | Request the latest state of the state machine
ClientReadReq :: ClientReq v

-- | Write a command
ClientWriteReq :: v -> ClientReq v

-- | Representation of a client response
data ClientResponse s

-- | Respond with the latest state of the state machine.
ClientReadResponse :: ClientReadResp s -> ClientResponse s

-- | Respond with the index of the entry appended to the log
ClientWriteResponse :: ClientWriteResp -> ClientResponse s

-- | Respond with the node id of the current leader
ClientRedirectResponse :: ClientRedirResp -> ClientResponse s

-- | Representation of a read response to a client The <tt>s</tt> stands
--   for the "current" state of the state machine
newtype ClientReadResp s
ClientReadResp :: s -> ClientReadResp s

-- | Representation of a write response to a client
data ClientWriteResp

-- | Index of the entry appended to the log due to the previous client
--   request
ClientWriteResp :: Index -> ClientWriteResp

-- | Representation of a redirect response to a client
data ClientRedirResp
ClientRedirResp :: CurrentLeader -> ClientRedirResp

-- | Configuration of a node in the cluster
data NodeConfig
NodeConfig :: NodeId -> NodeIds -> (Natural, Natural) -> Natural -> NodeConfig

-- | Node id of the running node
[configNodeId] :: NodeConfig -> NodeId

-- | Set of all other node ids in the cluster
[configNodeIds] :: NodeConfig -> NodeIds

-- | Range of times an election timeout can take
[configElectionTimeout] :: NodeConfig -> (Natural, Natural)

-- | Heartbeat timeout timer
[configHeartbeatTimeout] :: NodeConfig -> Natural

-- | Representation of events a raft node can send and receive
data Event v
MessageEvent :: MessageEvent v -> Event v
TimeoutEvent :: Timeout -> Event v

-- | Representation of timeouts
data Timeout

-- | Timeout after which a follower will become candidate
ElectionTimeout :: Timeout

-- | Timeout after which a leader will send AppendEntries RPC to all peers
HeartbeatTimeout :: Timeout

-- | Representation of message events to a node
data MessageEvent v

-- | Incoming event from a peer
RPCMessageEvent :: RPCMessage v -> MessageEvent v

-- | Incoming event from a client
ClientRequestEvent :: ClientRequest v -> MessageEvent v

-- | Representation of an entry in the replicated log
data Entry v
Entry :: Index -> Term -> EntryValue v -> EntryIssuer -> Entry v

-- | Index of entry in the log
[entryIndex] :: Entry v -> Index

-- | Term when entry was received by leader
[entryTerm] :: Entry v -> Term

-- | Command to update state machine
[entryValue] :: Entry v -> EntryValue v

-- | Id of the client that issued the command
[entryIssuer] :: Entry v -> EntryIssuer
type Entries v = Seq (Entry v)

-- | Provides an interface for nodes to write log entries to storage.
class Monad m => RaftWriteLog m v where {
    type family RaftWriteLogError m;
}

-- | Write the given log entries to storage
writeLogEntries :: (RaftWriteLog m v, Exception (RaftWriteLogError m)) => Entries v -> m (Either (RaftWriteLogError m) ())
data DeleteSuccess v
DeleteSuccess :: DeleteSuccess v

-- | Provides an interface for nodes to delete log entries from storage.
class Monad m => RaftDeleteLog m v where {
    type family RaftDeleteLogError m;
}

-- | Delete log entries from a given index; e.g. 'deleteLogEntriesFrom 7'
--   should delete every log entry with an index &gt;= 7.
deleteLogEntriesFrom :: (RaftDeleteLog m v, Exception (RaftDeleteLogError m)) => Index -> m (Either (RaftDeleteLogError m) (DeleteSuccess v))

-- | Provides an interface for nodes to read log entries from storage.
class Monad m => RaftReadLog m v where {
    type family RaftReadLogError m;
}

-- | Read the log at a given index
readLogEntry :: (RaftReadLog m v, Exception (RaftReadLogError m)) => Index -> m (Either (RaftReadLogError m) (Maybe (Entry v)))

-- | Read log entries from a specific index onwards, including the specific
--   index
readLogEntriesFrom :: (RaftReadLog m v, Exception (RaftReadLogError m)) => Index -> m (Either (RaftReadLogError m) (Entries v))

-- | Read the last log entry in the log
readLastLogEntry :: (RaftReadLog m v, Exception (RaftReadLogError m)) => m (Either (RaftReadLogError m) (Maybe (Entry v)))

-- | Read log entries from a specific index onwards, including the specific
--   index
readLogEntriesFrom :: (RaftReadLog m v, Exception (RaftReadLogError m)) => Index -> m (Either (RaftReadLogError m) (Entries v))
type RaftLog m v = (RaftReadLog m v, RaftWriteLog m v, RaftDeleteLog m v)

-- | Representation of possible errors that come from reading, writing or
--   deleting logs from the persistent storage
data RaftLogError m
RaftLogReadError :: RaftReadLogError m -> RaftLogError m
RaftLogWriteError :: RaftWriteLogError m -> RaftLogError m
RaftLogDeleteError :: RaftDeleteLogError m -> RaftLogError m
type RaftLogExceptions m = (Exception (RaftReadLogError m), Exception (RaftWriteLogError m), Exception (RaftDeleteLogError m))

-- | Representation of the logs' destination
data LogDest
LogFile :: FilePath -> LogDest
LogStdout :: LogDest
NoLogs :: LogDest

-- | Representation of the severity of the logs
data Severity
Info :: Severity
Debug :: Severity
Critical :: Severity
data Mode
Follower :: Mode
Candidate :: Mode
Leader :: Mode

-- | Existential type hiding the internal node state
data RaftNodeState
[RaftNodeState] :: {unRaftNodeState :: NodeState s} -> RaftNodeState

-- | The volatile state of a Raft Node
data NodeState (a :: Mode)
[NodeFollowerState] :: FollowerState -> NodeState  'Follower
[NodeCandidateState] :: CandidateState -> NodeState  'Candidate
[NodeLeaderState] :: LeaderState -> NodeState  'Leader

-- | Representation of the current leader in the cluster. The system is
--   considered to be unavailable if there is no leader
data CurrentLeader
CurrentLeader :: LeaderId -> CurrentLeader
NoLeader :: CurrentLeader
data FollowerState
FollowerState :: CurrentLeader -> Index -> Index -> (Index, Term) -> Maybe Term -> FollowerState

-- | Id of the current leader
[fsCurrentLeader] :: FollowerState -> CurrentLeader

-- | Index of highest log entry known to be committed
[fsCommitIndex] :: FollowerState -> Index

-- | Index of highest log entry applied to state machine
[fsLastApplied] :: FollowerState -> Index

-- | Index and term of the last log entry in the node's log
[fsLastLogEntryData] :: FollowerState -> (Index, Term)

-- | The term of the log entry specified in and AppendEntriesRPC
[fsTermAtAEPrevIndex] :: FollowerState -> Maybe Term
data CandidateState
CandidateState :: Index -> Index -> NodeIds -> (Index, Term) -> CandidateState

-- | Index of highest log entry known to be committed
[csCommitIndex] :: CandidateState -> Index

-- | Index of highest log entry applied to state machine
[csLastApplied] :: CandidateState -> Index

-- | Votes from other nodes in the raft network
[csVotes] :: CandidateState -> NodeIds

-- | Index and term of the last log entry in the node's log
[csLastLogEntryData] :: CandidateState -> (Index, Term)
data LeaderState
LeaderState :: Index -> Index -> Map NodeId Index -> Map NodeId Index -> (Index, Term, Maybe EntryIssuer) -> Int -> ClientReadReqs -> LeaderState

-- | Index of highest log entry known to be committed
[lsCommitIndex] :: LeaderState -> Index

-- | Index of highest log entry applied to state machine
[lsLastApplied] :: LeaderState -> Index

-- | For each server, index of the next log entry to send to that server
[lsNextIndex] :: LeaderState -> Map NodeId Index

-- | For each server, index of highest log entry known to be replicated on
--   server
[lsMatchIndex] :: LeaderState -> Map NodeId Index

-- | Index, term, and client id of the last log entry in the node's log.
--   The only time `Maybe ClientId` will be Nothing is at the initial term.
[lsLastLogEntryData] :: LeaderState -> (Index, Term, Maybe EntryIssuer)

-- | Number of read requests handled this term
[lsReadReqsHandled] :: LeaderState -> Int

-- | The number of successful responses received regarding a specific read
--   request heartbeat.
[lsReadRequest] :: LeaderState -> ClientReadReqs

-- | A node in Raft begins as a follower
initRaftNodeState :: RaftNodeState

-- | Check if node is in a follower state
isFollower :: NodeState s -> Bool

-- | Check if node is in a candidate state
isCandidate :: NodeState s -> Bool

-- | Check if node is in a leader state
isLeader :: NodeState s -> Bool

-- | Update the last log entry in the node's log
setLastLogEntryData :: NodeState ns -> Entries v -> NodeState ns

-- | Get the last applied index and the commit index of the last log entry
--   in the node's log
getLastLogEntryData :: NodeState ns -> (Index, Term)

-- | Get the index of highest log entry applied to state machine and the
--   index of highest log entry known to be committed
getLastAppliedAndCommitIndex :: NodeState ns -> (Index, Index)

-- | Persistent state that all Raft nodes maintain, regardless of node
--   state.
data PersistentState
PersistentState :: Term -> Maybe NodeId -> PersistentState

-- | Last term server has seen
[currentTerm] :: PersistentState -> Term

-- | Candidate id that received vote in current term
[votedFor] :: PersistentState -> Maybe NodeId

-- | A node initiates its persistent state with term 0 and with its vote
--   blank
initPersistentState :: PersistentState

-- | Unique identifier of a Raft node
type NodeId = ByteString
type NodeIds = Set NodeId

-- | Unique identifier of a client
newtype ClientId
ClientId :: NodeId -> ClientId

-- | Unique identifier of a leader
newtype LeaderId
LeaderId :: NodeId -> LeaderId
[unLeaderId] :: LeaderId -> NodeId

-- | Representation of monotonic election terms
newtype Term
Term :: Natural -> Term

-- | Representation of monotonic indices
newtype Index
Index :: Natural -> Index

-- | Initial term. Terms start at 0
term0 :: Term

-- | Initial index. Indeces start at 0
index0 :: Index
data RPC v
AppendEntriesRPC :: AppendEntries v -> RPC v
AppendEntriesResponseRPC :: AppendEntriesResponse -> RPC v
RequestVoteRPC :: RequestVote -> RPC v
RequestVoteResponseRPC :: RequestVoteResponse -> RPC v
class RPCType a v
toRPC :: RPCType a v => a -> RPC v

-- | Representation of a message sent between nodes
data RPCMessage v
RPCMessage :: NodeId -> RPC v -> RPCMessage v
[sender] :: RPCMessage v -> NodeId
[rpc] :: RPCMessage v -> RPC v

-- | Representation of a message sent from a leader to its peers
data AppendEntries v
AppendEntries :: Term -> LeaderId -> Index -> Term -> Entries v -> Index -> Maybe Int -> AppendEntries v

-- | Leader's term
[aeTerm] :: AppendEntries v -> Term

-- | Leader's identifier so that followers can redirect clients
[aeLeaderId] :: AppendEntries v -> LeaderId

-- | Index of log entry immediately preceding new ones
[aePrevLogIndex] :: AppendEntries v -> Index

-- | Term of aePrevLogIndex entry
[aePrevLogTerm] :: AppendEntries v -> Term

-- | Log entries to store (empty for heartbeat)
[aeEntries] :: AppendEntries v -> Entries v

-- | Leader's commit index
[aeLeaderCommit] :: AppendEntries v -> Index

-- | which read request the message corresponds to
[aeReadRequest] :: AppendEntries v -> Maybe Int

-- | Representation of the response from a follower to an AppendEntries
--   message
data AppendEntriesResponse
AppendEntriesResponse :: Term -> Bool -> Maybe Int -> AppendEntriesResponse

-- | current term for leader to update itself
[aerTerm] :: AppendEntriesResponse -> Term

-- | true if follower contained entry matching aePrevLogIndex and
--   aePrevLogTerm
[aerSuccess] :: AppendEntriesResponse -> Bool

-- | which read request the response corresponds to
[aerReadRequest] :: AppendEntriesResponse -> Maybe Int

-- | Representation of the message sent by candidates to their peers to
--   request their vote
data RequestVote
RequestVote :: Term -> NodeId -> Index -> Term -> RequestVote

-- | candidates term
[rvTerm] :: RequestVote -> Term

-- | candidate requesting vote
[rvCandidateId] :: RequestVote -> NodeId

-- | index of candidate's last log entry
[rvLastLogIndex] :: RequestVote -> Index

-- | term of candidate's last log entry
[rvLastLogTerm] :: RequestVote -> Term

-- | Representation of a response to a RequestVote message
data RequestVoteResponse
RequestVoteResponse :: Term -> Bool -> RequestVoteResponse

-- | current term for candidate to update itself
[rvrTerm] :: RequestVoteResponse -> Term

-- | true means candidate recieved vote
[rvrVoteGranted] :: RequestVoteResponse -> Bool

-- | The data used to construct an AppendEntries value, snapshotted from
--   the node state at the time the AppendEntries val should be created.
data AppendEntriesData v
AppendEntriesData :: Term -> Index -> EntriesSpec v -> AppendEntriesData v
[aedTerm] :: AppendEntriesData v -> Term
[aedLeaderCommit] :: AppendEntriesData v -> Index
[aedEntriesSpec] :: AppendEntriesData v -> EntriesSpec v
instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Raft.RaftT v m)
instance GHC.Base.MonadPlus m => GHC.Base.Alternative (Raft.RaftT v m)
instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Raft.RaftT v m)
instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState Raft.NodeState.RaftNodeState (Raft.RaftT v m)
instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (Raft.RaftEnv v m) (Raft.RaftT v m)
instance GHC.Base.Monad m => GHC.Base.Monad (Raft.RaftT v m)
instance GHC.Base.Monad m => GHC.Base.Applicative (Raft.RaftT v m)
instance GHC.Base.Functor m => GHC.Base.Functor (Raft.RaftT v m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Raft.RaftT v m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Raft.RaftT v m)
instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Raft.RaftT v m)
instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Raft.RaftT v m)
instance Control.Monad.Conc.Class.MonadConc m => Control.Monad.Conc.Class.MonadConc (Raft.RaftT v m)
instance Control.Monad.Trans.Class.MonadTrans (Raft.RaftT v)
instance GHC.Base.Monad m => Raft.Logging.RaftLogger (Raft.RaftT v m)

module Examples.Raft.FileStore
newtype NodeEnvError
NodeEnvError :: Text -> NodeEnvError
data NodeFileStoreEnv
NodeFileStoreEnv :: FilePath -> FilePath -> NodeFileStoreEnv
[nfsPersistentState] :: NodeFileStoreEnv -> FilePath
[nfsLogEntries] :: NodeFileStoreEnv -> FilePath
newtype RaftFileStoreT m a
RaftFileStoreT :: ReaderT NodeFileStoreEnv m a -> RaftFileStoreT m a
[unRaftFileStoreT] :: RaftFileStoreT m a -> ReaderT NodeFileStoreEnv m a
readLogEntries :: (MonadIO m, Serialize v) => RaftFileStoreT m (Either Text (Entries v))
instance Control.Monad.Trans.Class.MonadTrans Examples.Raft.FileStore.RaftFileStoreT
instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Examples.Raft.FileStore.RaftFileStoreT m)
instance GHC.Base.Alternative m => GHC.Base.Alternative (Examples.Raft.FileStore.RaftFileStoreT m)
instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader Examples.Raft.FileStore.NodeFileStoreEnv (Examples.Raft.FileStore.RaftFileStoreT m)
instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Examples.Raft.FileStore.RaftFileStoreT m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Examples.Raft.FileStore.RaftFileStoreT m)
instance GHC.Base.Monad m => GHC.Base.Monad (Examples.Raft.FileStore.RaftFileStoreT m)
instance GHC.Base.Applicative m => GHC.Base.Applicative (Examples.Raft.FileStore.RaftFileStoreT m)
instance GHC.Base.Functor m => GHC.Base.Functor (Examples.Raft.FileStore.RaftFileStoreT m)
instance GHC.Show.Show Examples.Raft.FileStore.NodeEnvError
instance Control.Monad.Conc.Class.MonadConc m => Control.Monad.Catch.MonadThrow (Examples.Raft.FileStore.RaftFileStoreT m)
instance Control.Monad.Conc.Class.MonadConc m => Control.Monad.Catch.MonadCatch (Examples.Raft.FileStore.RaftFileStoreT m)
instance Control.Monad.Conc.Class.MonadConc m => Control.Monad.Catch.MonadMask (Examples.Raft.FileStore.RaftFileStoreT m)
instance Control.Monad.Conc.Class.MonadConc m => Control.Monad.Conc.Class.MonadConc (Examples.Raft.FileStore.RaftFileStoreT m)
instance (Control.Monad.IO.Class.MonadIO m, Control.Monad.Conc.Class.MonadConc m, Data.Serialize.Serialize v) => Raft.Log.RaftWriteLog (Examples.Raft.FileStore.RaftFileStoreT m) v
instance (Control.Monad.IO.Class.MonadIO m, Control.Monad.Conc.Class.MonadConc m) => Raft.Persistent.RaftPersist (Examples.Raft.FileStore.RaftFileStoreT m)
instance (Control.Monad.IO.Class.MonadIO m, Control.Monad.Conc.Class.MonadConc m, Data.Serialize.Serialize v) => Raft.Log.RaftReadLog (Examples.Raft.FileStore.RaftFileStoreT m) v
instance (Control.Monad.IO.Class.MonadIO m, Control.Monad.Conc.Class.MonadConc m, Data.Serialize.Serialize v) => Raft.Log.RaftDeleteLog (Examples.Raft.FileStore.RaftFileStoreT m) v
instance GHC.Exception.Type.Exception Examples.Raft.FileStore.NodeEnvError

module Examples.Raft.Socket.Common

-- | Convert a host and a port to a valid NodeId
hostPortToNid :: (HostName, ServiceName) -> NodeId

-- | Retrieve the host and port from a valid NodeId
nidToHostPort :: NodeId -> (HostName, ServiceName)

-- | Get a free port number.
getFreePort :: IO ServiceName

module Examples.Raft.Socket.Node
data NodeSocketEnv v
NodeSocketEnv :: Socket -> TVar (STM IO) (Map NodeId Socket) -> TChan (STM IO) (RPCMessage v) -> TChan (STM IO) (ClientRequest v) -> NodeSocketEnv v
[nsSocket] :: NodeSocketEnv v -> Socket
[nsPeers] :: NodeSocketEnv v -> TVar (STM IO) (Map NodeId Socket)
[nsMsgQueue] :: NodeSocketEnv v -> TChan (STM IO) (RPCMessage v)
[nsClientReqQueue] :: NodeSocketEnv v -> TChan (STM IO) (ClientRequest v)
newtype RaftSocketT v m a
RaftSocketT :: ReaderT (NodeSocketEnv v) m a -> RaftSocketT v m a
[unRaftSocketT] :: RaftSocketT v m a -> ReaderT (NodeSocketEnv v) m a

-- | Handles connections failures by first trying to reconnect
retryConnection :: (Serialize v, MonadIO m, MonadConc m) => TVar (STM m) (Map NodeId Socket) -> NodeId -> Maybe Socket -> RPCMessage v -> SomeException -> m (Maybe Socket)
handleFailure :: (MonadIO m, MonadConc m) => TVar (STM m) (Map NodeId Socket) -> [NodeId] -> Maybe Socket -> SomeException -> m (Maybe Socket)
runRaftSocketT :: (MonadIO m, MonadConc m) => NodeSocketEnv v -> RaftSocketT v m a -> m a

-- | Recursively accept a connection. It keeps trying to accept connections
--   even when a node dies
acceptForkNode :: forall v m. (Serialize v, MonadIO m, MonadConc m) => RaftSocketT v m ()
newSock :: HostName -> ServiceName -> IO Socket
instance Control.Monad.Trans.Class.MonadTrans (Examples.Raft.Socket.Node.RaftSocketT v)
instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Examples.Raft.Socket.Node.RaftSocketT v m)
instance GHC.Base.Alternative m => GHC.Base.Alternative (Examples.Raft.Socket.Node.RaftSocketT v m)
instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (Examples.Raft.Socket.Node.NodeSocketEnv v) (Examples.Raft.Socket.Node.RaftSocketT v m)
instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Examples.Raft.Socket.Node.RaftSocketT v m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Examples.Raft.Socket.Node.RaftSocketT v m)
instance GHC.Base.Monad m => GHC.Base.Monad (Examples.Raft.Socket.Node.RaftSocketT v m)
instance GHC.Base.Applicative m => GHC.Base.Applicative (Examples.Raft.Socket.Node.RaftSocketT v m)
instance GHC.Base.Functor m => GHC.Base.Functor (Examples.Raft.Socket.Node.RaftSocketT v m)
instance Control.Monad.Conc.Class.MonadConc m => Control.Monad.Catch.MonadThrow (Examples.Raft.Socket.Node.RaftSocketT v m)
instance Control.Monad.Conc.Class.MonadConc m => Control.Monad.Catch.MonadCatch (Examples.Raft.Socket.Node.RaftSocketT v m)
instance Control.Monad.Conc.Class.MonadConc m => Control.Monad.Catch.MonadMask (Examples.Raft.Socket.Node.RaftSocketT v m)
instance Control.Monad.Conc.Class.MonadConc m => Control.Monad.Conc.Class.MonadConc (Examples.Raft.Socket.Node.RaftSocketT v m)
instance (Control.Monad.IO.Class.MonadIO m, Control.Monad.Conc.Class.MonadConc m, Data.Serialize.Serialize sm) => Raft.Client.RaftSendClient (Examples.Raft.Socket.Node.RaftSocketT v m) sm
instance (Control.Monad.IO.Class.MonadIO m, Control.Monad.Conc.Class.MonadConc m, Data.Serialize.Serialize v) => Raft.Client.RaftRecvClient (Examples.Raft.Socket.Node.RaftSocketT v m) v
instance (Control.Monad.IO.Class.MonadIO m, Control.Monad.Conc.Class.MonadConc m, Data.Serialize.Serialize v, GHC.Show.Show v) => Raft.RPC.RaftSendRPC (Examples.Raft.Socket.Node.RaftSocketT v m) v
instance (Control.Monad.IO.Class.MonadIO m, Control.Monad.Conc.Class.MonadConc m, GHC.Show.Show v) => Raft.RPC.RaftRecvRPC (Examples.Raft.Socket.Node.RaftSocketT v m) v

module Examples.Raft.Socket.Client
data ClientSocketEnv
ClientSocketEnv :: ServiceName -> HostName -> Socket -> ClientSocketEnv
[clientPort] :: ClientSocketEnv -> ServiceName
[clientHost] :: ClientSocketEnv -> HostName
[clientSocket] :: ClientSocketEnv -> Socket
newtype RaftSocketClientM a
RaftSocketClientM :: ReaderT ClientSocketEnv IO a -> RaftSocketClientM a
[unRaftSocketClientM] :: RaftSocketClientM a -> ReaderT ClientSocketEnv IO a
runRaftSocketClientM :: ClientSocketEnv -> RaftSocketClientM a -> IO a

-- | Randomly select a node from a set of nodes a send a message to it
selectRndNode :: NodeIds -> IO NodeId

-- | Randomly read the state of a random node
sendReadRndNode :: (Serialize sm, Serialize v) => Proxy v -> NodeIds -> RaftSocketClientM (Either [Char] (ClientResponse sm))

-- | Randomly write to a random node
sendWriteRndNode :: (Serialize v, Serialize sm) => v -> NodeIds -> RaftSocketClientM (Either [Char] (ClientResponse sm))

-- | Request the state of a node. It blocks until the node responds
sendRead :: forall v sm. (Serialize sm, Serialize v) => Proxy v -> NodeId -> RaftSocketClientM (Either [Char] (ClientResponse sm))

-- | Write to a node. It blocks until the node responds
sendWrite :: (Serialize v, Serialize sm) => v -> NodeId -> RaftSocketClientM (Either [Char] (ClientResponse sm))

-- | Accept a connection and return the client response synchronously
acceptClientConnections :: Serialize sm => RaftSocketClientM (Either [Char] (ClientResponse sm))
instance GHC.Base.MonadPlus Examples.Raft.Socket.Client.RaftSocketClientM
instance GHC.Base.Alternative Examples.Raft.Socket.Client.RaftSocketClientM
instance Control.Monad.Reader.Class.MonadReader Examples.Raft.Socket.Client.ClientSocketEnv Examples.Raft.Socket.Client.RaftSocketClientM
instance Control.Monad.IO.Class.MonadIO Examples.Raft.Socket.Client.RaftSocketClientM
instance GHC.Base.Monad Examples.Raft.Socket.Client.RaftSocketClientM
instance GHC.Base.Applicative Examples.Raft.Socket.Client.RaftSocketClientM
instance GHC.Base.Functor Examples.Raft.Socket.Client.RaftSocketClientM
instance GHC.Show.Show Examples.Raft.Socket.Client.ClientSocketEnv
