-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Raft consensus algorithm -- -- Please see the README on GitHub at -- https://github.com/adjoint-io/raft#readme @package libraft @version 0.4.1.0 module Control.Concurrent.STM.Timer data Timer -- | Create a new timer with the supplied timer action and timer length, newTimer :: Natural -> IO Timer -- | Create a new timer with the supplied timer action, random seed, and -- range from which the the timer will choose a random timer length at -- each start or reset. newTimerRange :: Int -> (Natural, Natural) -> IO Timer -- | Start the timer. If the timer is already running, the timer is not -- started. Returns True if the timer was succesfully started. startTimer :: Timer -> IO Bool -- | Resets the timer with a new random timeout. resetTimer :: Timer -> IO () -- | Wait for a timer to complete waitTimer :: Timer -> IO () 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 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 -- | Representation of monotonic election terms newtype Term Term :: Natural -> Term intToNatural :: Int -> Either [Char] Natural -- | 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 newtype SerialNum SerialNum :: Natural -> SerialNum instance Data.Serialize.Serialize Raft.Types.SerialNum instance GHC.Num.Num Raft.Types.SerialNum instance GHC.Enum.Enum Raft.Types.SerialNum instance GHC.Classes.Ord Raft.Types.SerialNum instance GHC.Classes.Eq Raft.Types.SerialNum instance GHC.Generics.Generic Raft.Types.SerialNum instance GHC.Read.Read Raft.Types.SerialNum instance GHC.Show.Show Raft.Types.SerialNum instance Data.Serialize.Serialize 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.Generics.Generic Raft.Types.Index instance GHC.Show.Show Raft.Types.Index instance Data.Serialize.Serialize 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 GHC.Generics.Generic Raft.Types.Term instance Data.Serialize.Serialize Raft.Types.CurrentLeader instance GHC.Generics.Generic Raft.Types.CurrentLeader instance GHC.Classes.Eq Raft.Types.CurrentLeader instance GHC.Show.Show Raft.Types.CurrentLeader instance Data.Serialize.Serialize Raft.Types.LeaderId instance GHC.Generics.Generic Raft.Types.LeaderId instance GHC.Classes.Eq Raft.Types.LeaderId instance GHC.Read.Read 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.Read.Read Raft.Types.ClientId instance GHC.Show.Show Raft.Types.ClientId instance Database.PostgreSQL.Simple.ToField.ToField Raft.Types.Index instance Database.PostgreSQL.Simple.FromField.FromField Raft.Types.Index instance Database.PostgreSQL.Simple.ToField.ToField Raft.Types.Term instance Database.PostgreSQL.Simple.FromField.FromField Raft.Types.Term 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; } initializePersistentState :: (RaftPersist m, Exception (RaftPersistError m)) => m (Either (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.Classes.Eq Raft.Persistent.PersistentState instance GHC.Show.Show Raft.Persistent.PersistentState module Raft.Log data EntryIssuer ClientIssuer :: ClientId -> SerialNum -> EntryIssuer LeaderIssuer :: LeaderId -> EntryIssuer data EntryValue v EntryValue :: v -> EntryValue v -- | Used as a first committed entry of a new term NoValue :: EntryValue v data EntryHash genesisHash :: EntryHash hashEntry :: Serialize v => Entry v -> EntryHash -- | Representation of an entry in the replicated log data Entry v Entry :: Index -> Term -> EntryValue v -> EntryIssuer -> EntryHash -> 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 [entryPrevHash] :: Entry v -> EntryHash type Entries v = Seq (Entry v) -- | Provides an interface to initialize a fresh log entry storage class RaftInitLog m v where { type family RaftInitLogError m; } initializeLog :: RaftInitLog m v => Proxy v -> m (Either (RaftInitLogError m) ()) data ReadEntriesSpec ByIndex :: Index -> ReadEntriesSpec ByIndices :: IndexInterval -> ReadEntriesSpec -- | The result of reading one or more data ReadEntriesRes v OneEntry :: Entry v -> ReadEntriesRes v ManyEntries :: Entries v -> ReadEntriesRes v data IndexInterval IndexInterval :: Maybe Index -> Maybe Index -> IndexInterval -- | Provides an interface for nodes to read log entries from storage. class (Show (RaftReadLogError m), 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)) -- | Provides an interface for nodes to write log entries to storage. class (Show (RaftWriteLogError m), 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) ()) -- | Provides an interface for nodes to delete log entries from storage. class (Show (RaftDeleteLogError m), 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 >= 7. deleteLogEntriesFrom :: (RaftDeleteLog m v, Exception (RaftDeleteLogError m)) => Index -> m (Either (RaftDeleteLogError m) (DeleteSuccess v)) data DeleteSuccess v DeleteSuccess :: DeleteSuccess v type RaftLog m v = (RaftInitLog 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 type RaftLogExceptions m = (Exception (RaftInitLogError m), Exception (RaftReadLogError m), Exception (RaftWriteLogError m), Exception (RaftDeleteLogError m)) updateLog :: forall m v. (RaftDeleteLog m v, Exception (RaftDeleteLogError m), RaftWriteLog m v, Exception (RaftWriteLogError m)) => Entries v -> m (Either (RaftLogError m) ()) clientReqData :: Entries v -> Map ClientId (SerialNum, Index) readEntries :: forall m v. (RaftReadLog m v, Exception (RaftReadLogError m)) => ReadEntriesSpec -> m (Either (ReadEntriesError m) (ReadEntriesRes v)) instance Data.Serialize.Serialize Raft.Log.ReadEntriesSpec instance GHC.Generics.Generic Raft.Log.ReadEntriesSpec instance GHC.Show.Show Raft.Log.ReadEntriesSpec instance Data.Serialize.Serialize Raft.Log.IndexInterval instance GHC.Generics.Generic Raft.Log.IndexInterval instance GHC.Show.Show Raft.Log.IndexInterval instance GHC.Show.Show Raft.Log.InvalidLog instance Data.Serialize.Serialize v => Data.Serialize.Serialize (Raft.Log.Entry v) instance GHC.Generics.Generic (Raft.Log.Entry v) instance GHC.Classes.Eq v => GHC.Classes.Eq (Raft.Log.Entry v) instance GHC.Show.Show v => GHC.Show.Show (Raft.Log.Entry v) instance Data.Serialize.Serialize Raft.Log.EntryHash instance GHC.Generics.Generic Raft.Log.EntryHash instance GHC.Classes.Ord Raft.Log.EntryHash instance GHC.Classes.Eq Raft.Log.EntryHash instance GHC.Show.Show Raft.Log.EntryHash instance Data.Serialize.Serialize v => Data.Serialize.Serialize (Raft.Log.EntryValue v) instance GHC.Generics.Generic (Raft.Log.EntryValue v) instance GHC.Classes.Eq v => GHC.Classes.Eq (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.Classes.Eq Raft.Log.EntryIssuer instance GHC.Read.Read Raft.Log.EntryIssuer instance GHC.Show.Show Raft.Log.EntryIssuer instance GHC.Show.Show (Raft.Log.RaftLogError m) instance GHC.Show.Show (Raft.Log.ReadEntriesError m) instance Data.Typeable.Internal.Typeable m => GHC.Exception.Type.Exception (Raft.Log.ReadEntriesError m) instance Database.PostgreSQL.Simple.ToField.ToField Raft.Log.EntryHash instance Database.PostgreSQL.Simple.FromField.FromField Raft.Log.EntryHash instance Data.Serialize.Serialize v => Database.PostgreSQL.Simple.ToField.ToField (Raft.Log.EntryValue v) instance (Data.Typeable.Internal.Typeable v, Data.Serialize.Serialize v) => Database.PostgreSQL.Simple.FromField.FromField (Raft.Log.EntryValue v) instance Database.PostgreSQL.Simple.ToField.ToField Raft.Log.EntryIssuer instance Database.PostgreSQL.Simple.FromField.FromField Raft.Log.EntryIssuer module Raft.StateMachine -- | 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 RaftStateMachinePure sm v | sm -> v where { data family RaftStateMachinePureError sm v; type family RaftStateMachinePureCtx sm v = ctx | ctx -> sm v; } rsmTransition :: RaftStateMachinePure sm v => RaftStateMachinePureCtx sm v -> sm -> v -> Either (RaftStateMachinePureError sm v) sm class (Monad m, RaftStateMachinePure sm v) => RaftStateMachine m sm v validateCmd :: RaftStateMachine m sm v => v -> m (Either (RaftStateMachinePureError sm v) ()) askRaftStateMachinePureCtx :: RaftStateMachine m sm v => m (RaftStateMachinePureCtx sm v) applyLogEntry :: RaftStateMachine m sm v => sm -> Entry v -> m (Either (RaftStateMachinePureError sm v) sm) 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 AppendEntriesSpec v FromIndex :: Index -> AppendEntriesSpec v FromNewLeader :: Entry v -> AppendEntriesSpec v FromClientWriteReq :: Entry v -> AppendEntriesSpec v NoEntries :: NoEntriesSpec -> AppendEntriesSpec 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 -> AppendEntriesSpec v -> AppendEntriesData v [aedTerm] :: AppendEntriesData v -> Term [aedLeaderCommit] :: AppendEntriesData v -> Index [aedEntriesSpec] :: AppendEntriesData v -> AppendEntriesSpec 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.AppendEntriesSpec 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.Config -- | Configuration of a node in the cluster data RaftNodeConfig RaftNodeConfig :: NodeId -> NodeIds -> (Natural, Natural) -> Natural -> StorageState -> RaftNodeConfig -- | Node id of the running node [configNodeId] :: RaftNodeConfig -> NodeId -- | Set of all other node ids in the cluster [configNodeIds] :: RaftNodeConfig -> NodeIds -- | Range of times an election timeout can take [configElectionTimeout] :: RaftNodeConfig -> (Natural, Natural) -- | Heartbeat timeout timer [configHeartbeatTimeout] :: RaftNodeConfig -> Natural -- | Create a fresh DB or read from existing [configStorageState] :: RaftNodeConfig -> StorageState data StorageState New :: StorageState Existing :: StorageState instance GHC.Show.Show Raft.Config.RaftNodeConfig instance GHC.Show.Show Raft.Config.StorageState module Raft.Client -- | Interface for Raft nodes to send messages to clients -- -- TODO It would be really nice if RSMP was a superclass, but -- currently this can't happen because of cyclic imports. class RaftSendClient m sm v sendClient :: RaftSendClient m sm v => ClientId -> ClientResponse sm v -> 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)) newtype SerialNum SerialNum :: Natural -> SerialNum -- | 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 :: ClientReadReq -> ClientReq v -- | Write a command ClientWriteReq :: SerialNum -> v -> ClientReq v data ClientReadReq ClientReadEntries :: ReadEntriesSpec -> ClientReadReq ClientReadStateMachine :: ClientReadReq data ReadEntriesSpec -- | The datatype sent back to the client as an actual response data ClientResponse sm v -- | Respond with the latest state of the state machine. ClientReadResponse :: ClientReadResp sm v -> ClientResponse sm v -- | Respond with the index of the entry appended to the log ClientWriteResponse :: ClientWriteResp -> ClientResponse sm v -- | Respond with the node id of the current leader ClientRedirectResponse :: ClientRedirResp -> ClientResponse sm v -- | Specification for the data inside a ClientResponse data ClientRespSpec sm ClientReadRespSpec :: ClientReadRespSpec sm -> ClientRespSpec sm ClientWriteRespSpec :: Index -> SerialNum -> ClientRespSpec sm ClientRedirRespSpec :: CurrentLeader -> ClientRespSpec sm data ClientReadRespSpec sm ClientReadRespSpecEntries :: ReadEntriesSpec -> ClientReadRespSpec sm ClientReadRespSpecStateMachine :: sm -> ClientReadRespSpec sm -- | Representation of a read response to a client data ClientReadResp sm v ClientReadRespStateMachine :: sm -> ClientReadResp sm v ClientReadRespEntry :: Entry v -> ClientReadResp sm v ClientReadRespEntries :: Entries v -> ClientReadResp sm v -- | 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 -> SerialNum -> ClientWriteResp -- | Representation of a redirect response to a client data ClientRedirResp ClientRedirResp :: CurrentLeader -> ClientRedirResp class Monad m => RaftClientSend m v where { type family RaftClientSendError m v; } raftClientSend :: RaftClientSend m v => NodeId -> ClientRequest v -> m (Either (RaftClientSendError m v) ()) class Monad m => RaftClientRecv m sm v | m sm -> v where { type family RaftClientRecvError m sm; } raftClientRecv :: RaftClientRecv m sm v => m (Either (RaftClientRecvError m sm) (ClientResponse sm v)) -- | Each client may have at most one command outstanding at a time and -- commands must be dispatched in serial number order. data RaftClientState RaftClientState :: CurrentLeader -> SerialNum -> Set NodeId -> StdGen -> RaftClientState [raftClientCurrentLeader] :: RaftClientState -> CurrentLeader [raftClientSerialNum] :: RaftClientState -> SerialNum [raftClientRaftNodes] :: RaftClientState -> Set NodeId [raftClientRandomGen] :: RaftClientState -> StdGen data RaftClientEnv RaftClientEnv :: ClientId -> RaftClientEnv [raftClientId] :: RaftClientEnv -> ClientId initRaftClientState :: Set NodeId -> StdGen -> RaftClientState data RaftClientT s v m a runRaftClientT :: Monad m => RaftClientEnv -> RaftClientState -> RaftClientT s v m a -> m a data RaftClientError s v m [RaftClientSendError] :: RaftClientSendError m v -> RaftClientError s v m [RaftClientRecvError] :: RaftClientRecvError m s -> RaftClientError s v m [RaftClientTimeout] :: Text -> RaftClientError s v m [RaftClientUnexpectedReadResp] :: ClientReadResp s v -> RaftClientError s v m [RaftClientUnexpectedWriteResp] :: ClientWriteResp -> RaftClientError s v m [RaftClientUnexpectedRedirect] :: ClientRedirResp -> RaftClientError s v m -- | Send a read request to the curent leader and wait for a response clientRead :: (RaftClientSend m v, RaftClientRecv m s v) => ClientReadReq -> RaftClientT s v m (Either (RaftClientError s v m) (ClientReadResp s v)) -- | Send a read request to a specific raft node, regardless of leader, and -- wait for a response. clientReadFrom :: (RaftClientSend m v, RaftClientRecv m s v) => NodeId -> ClientReadReq -> RaftClientT s v m (Either (RaftClientError s v m) (ClientReadResp s v)) -- | clientRead but with a timeout clientReadTimeout :: (MonadBaseControl IO m, RaftClientSend m v, RaftClientRecv m s v) => Int -> ClientReadReq -> RaftClientT s v m (Either (RaftClientError s v m) (ClientReadResp s v)) -- | Send a write request to the current leader and wait for a response clientWrite :: (RaftClientSend m v, RaftClientRecv m s v) => v -> RaftClientT s v m (Either (RaftClientError s v m) ClientWriteResp) -- | Send a read request to a specific raft node, regardless of leader, and -- wait for a response. clientWriteTo :: (RaftClientSend m v, RaftClientRecv m s v) => NodeId -> v -> RaftClientT s v m (Either (RaftClientError s v m) ClientWriteResp) clientWriteTimeout :: (MonadBaseControl IO m, RaftClientSend m v, RaftClientRecv m s v) => Int -> v -> RaftClientT s v m (Either (RaftClientError s v m) ClientWriteResp) -- | Given a blocking client send/receive, retry if the received value is -- not expected retryOnRedirect :: MonadBaseControl IO m => RaftClientT s v m (Either (RaftClientError s v m) r) -> RaftClientT s v m (Either (RaftClientError s v m) r) clientAddNode :: Monad m => NodeId -> RaftClientT s v m () clientGetNodes :: Monad m => RaftClientT s v m (Set NodeId) instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Raft.Client.RaftClientT s v m) instance GHC.Base.MonadPlus m => GHC.Base.Alternative (Raft.Client.RaftClientT s v m) instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Raft.Client.RaftClientT s v m) instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader Raft.Client.RaftClientEnv (Raft.Client.RaftClientT s v m) instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState Raft.Client.RaftClientState (Raft.Client.RaftClientT s v m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Raft.Client.RaftClientT s v m) instance GHC.Base.Monad m => GHC.Base.Monad (Raft.Client.RaftClientT s v m) instance GHC.Base.Monad m => GHC.Base.Applicative (Raft.Client.RaftClientT s v m) instance GHC.Base.Functor m => GHC.Base.Functor (Raft.Client.RaftClientT s v m) instance GHC.Generics.Generic (Raft.Client.ClientResponse sm v) instance (GHC.Show.Show sm, GHC.Show.Show v) => GHC.Show.Show (Raft.Client.ClientResponse sm v) 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 sm v) instance (GHC.Show.Show sm, GHC.Show.Show v) => GHC.Show.Show (Raft.Client.ClientReadResp sm v) instance Data.Serialize.Serialize sm => Data.Serialize.Serialize (Raft.Client.ClientRespSpec sm) instance GHC.Generics.Generic (Raft.Client.ClientRespSpec sm) instance GHC.Show.Show sm => GHC.Show.Show (Raft.Client.ClientRespSpec sm) instance Data.Serialize.Serialize sm => Data.Serialize.Serialize (Raft.Client.ClientReadRespSpec sm) instance GHC.Generics.Generic (Raft.Client.ClientReadRespSpec sm) instance GHC.Show.Show sm => GHC.Show.Show (Raft.Client.ClientReadRespSpec sm) 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 Raft.Client.ClientReadReq instance GHC.Generics.Generic Raft.Client.ClientReadReq instance GHC.Show.Show Raft.Client.ClientReadReq instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Raft.Client.RaftClientT s v m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Raft.Client.RaftClientT s v m) instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Raft.Client.RaftClientT s v m) instance Control.Monad.Base.MonadBase GHC.Types.IO m => Control.Monad.Base.MonadBase GHC.Types.IO (Raft.Client.RaftClientT s v m) instance (GHC.Show.Show s, GHC.Show.Show v, GHC.Show.Show (Raft.Client.RaftClientSendError m v), GHC.Show.Show (Raft.Client.RaftClientRecvError m s)) => GHC.Show.Show (Raft.Client.RaftClientError s v m) instance Control.Monad.Trans.Class.MonadTrans (Raft.Client.RaftClientT s v) instance Control.Monad.Trans.Control.MonadTransControl (Raft.Client.RaftClientT s v) instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO (Raft.Client.RaftClientT s v m) instance System.Console.Haskeline.MonadException.MonadException m => System.Console.Haskeline.MonadException.MonadException (Raft.Client.RaftClientT s v m) instance Raft.Client.RaftClientSend m v => Raft.Client.RaftClientSend (Raft.Client.RaftClientT s v m) v instance Raft.Client.RaftClientRecv m s v => Raft.Client.RaftClientRecv (Raft.Client.RaftClientT s v m) s v instance (Data.Serialize.Serialize sm, Data.Serialize.Serialize v) => Data.Serialize.Serialize (Raft.Client.ClientResponse sm v) instance Data.Serialize.Serialize Raft.Client.ClientRedirResp instance Data.Serialize.Serialize Raft.Client.ClientWriteResp instance (Data.Serialize.Serialize sm, Data.Serialize.Serialize v) => Data.Serialize.Serialize (Raft.Client.ClientReadResp sm v) 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.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 [HandleClientReq] :: Transition 'Leader '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 v [ResultState] :: Show v => Transition init res -> NodeState res v -> ResultState init v followerResultState :: Show v => Transition init 'Follower -> FollowerState v -> ResultState init v candidateResultState :: Show v => Transition init 'Candidate -> CandidateState v -> ResultState init v leaderResultState :: Show v => Transition init 'Leader -> LeaderState v -> ResultState init v -- | Existential type hiding the internal node state data RaftNodeState v [RaftNodeState] :: {unRaftNodeState :: NodeState s v} -> RaftNodeState v nodeMode :: RaftNodeState v -> Mode -- | A node in Raft begins as a follower initRaftNodeState :: RaftNodeState v -- | The volatile state of a Raft Node data NodeState (a :: Mode) v [NodeFollowerState] :: FollowerState v -> NodeState 'Follower v [NodeCandidateState] :: CandidateState v -> NodeState 'Candidate v [NodeLeaderState] :: LeaderState v -> NodeState 'Leader v data LastLogEntry v LastLogEntry :: Entry v -> LastLogEntry v NoLogEntries :: LastLogEntry v hashLastLogEntry :: Serialize v => LastLogEntry v -> EntryHash lastLogEntryIndex :: LastLogEntry v -> Index lastLogEntryTerm :: LastLogEntry v -> Term lastLogEntryIndexAndTerm :: LastLogEntry v -> (Index, Term) lastLogEntryIssuer :: LastLogEntry v -> Maybe EntryIssuer data FollowerState v FollowerState :: CurrentLeader -> Index -> Index -> LastLogEntry v -> Maybe Term -> ClientWriteReqCache -> FollowerState v -- | Id of the current leader [fsCurrentLeader] :: FollowerState v -> CurrentLeader -- | Index of highest log entry known to be committed [fsCommitIndex] :: FollowerState v -> Index -- | Index of highest log entry applied to state machine [fsLastApplied] :: FollowerState v -> Index -- | Index and term of the last log entry in the node's log [fsLastLogEntry] :: FollowerState v -> LastLogEntry v -- | The term of the log entry specified in and AppendEntriesRPC [fsTermAtAEPrevIndex] :: FollowerState v -> Maybe Term -- | The client write request cache, growing linearly with the number of -- clients [fsClientReqCache] :: FollowerState v -> ClientWriteReqCache data CandidateState v CandidateState :: Index -> Index -> NodeIds -> LastLogEntry v -> ClientWriteReqCache -> CandidateState v -- | Index of highest log entry known to be committed [csCommitIndex] :: CandidateState v -> Index -- | Index of highest log entry applied to state machine [csLastApplied] :: CandidateState v -> Index -- | Votes from other nodes in the raft network [csVotes] :: CandidateState v -> NodeIds -- | Index and term of the last log entry in the node's log [csLastLogEntry] :: CandidateState v -> LastLogEntry v -- | The client write request cache, growing linearly with the number of -- clients [csClientReqCache] :: CandidateState v -> ClientWriteReqCache data ClientReadReqData ClientReadReqData :: ClientId -> ClientReadReq -> ClientReadReqData [crrdClientId] :: ClientReadReqData -> ClientId [crrdReadReq] :: ClientReadReqData -> ClientReadReq -- | The type mapping the number of the read request serviced to the id of -- the client that issued it and the number of success responses from -- followers confirming the leadership of the current leader type ClientReadReqs = Map Int (ClientReadReqData, Int) -- | The type mapping client ids to the serial number of their latest write -- requests and the index of the entry if it has been replicated. type ClientWriteReqCache = Map ClientId (SerialNum, Maybe Index) data LeaderState v LeaderState :: Index -> Index -> Map NodeId Index -> Map NodeId Index -> LastLogEntry v -> Int -> ClientReadReqs -> ClientWriteReqCache -> LeaderState v -- | Index of highest log entry known to be committed [lsCommitIndex] :: LeaderState v -> Index -- | Index of highest log entry applied to state machine [lsLastApplied] :: LeaderState v -> Index -- | For each server, index of the next log entry to send to that server [lsNextIndex] :: LeaderState v -> Map NodeId Index -- | For each server, index of highest log entry known to be replicated on -- server [lsMatchIndex] :: LeaderState v -> 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. [lsLastLogEntry] :: LeaderState v -> LastLogEntry v -- | Number of read requests handled this term [lsReadReqsHandled] :: LeaderState v -> Int -- | The number of successful responses received regarding a specific read -- request heartbeat. [lsReadRequest] :: LeaderState v -> ClientReadReqs -- | The cache of client write requests received by the leader [lsClientReqCache] :: LeaderState v -> ClientWriteReqCache -- | Update the last log entry in the node's log setLastLogEntry :: NodeState s v -> Entries v -> NodeState s v -- | Get the last applied index and the commit index of the last log entry -- in the node's log getLastLogEntry :: NodeState ns v -> LastLogEntry v -- | 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 v -> (Index, Index) -- | Check if node is in a follower state isFollower :: NodeState s v -> Bool -- | Check if node is in a candidate state isCandidate :: NodeState s v -> Bool -- | Check if node is in a leader state isLeader :: NodeState s v -> Bool instance GHC.Show.Show v => GHC.Show.Show (Raft.NodeState.LeaderState v) instance GHC.Show.Show v => GHC.Show.Show (Raft.NodeState.FollowerState v) instance GHC.Show.Show v => GHC.Show.Show (Raft.NodeState.CandidateState v) instance GHC.Show.Show Raft.NodeState.ClientReadReqData instance GHC.Show.Show v => GHC.Show.Show (Raft.NodeState.LastLogEntry v) instance GHC.Show.Show Raft.NodeState.Mode instance GHC.Show.Show (Raft.NodeState.Transition init res) instance GHC.Show.Show v => GHC.Show.Show (Raft.NodeState.ResultState init v) instance GHC.Show.Show v => GHC.Show.Show (Raft.NodeState.RaftNodeState v) instance GHC.Show.Show v => GHC.Show.Show (Raft.NodeState.NodeState s v) module Raft.Logging -- | Representation of the logs' context data LogCtx m LogCtx :: LogDest m -> Severity -> LogCtx m [logCtxDest] :: LogCtx m -> LogDest m [logCtxSeverity] :: LogCtx m -> Severity NoLogs :: LogCtx m -- | Representation of the logs' destination data LogDest m LogWith :: (MonadIO m => Severity -> Text -> m ()) -> LogDest m LogFile :: FilePath -> LogDest m LogStdout :: LogDest m -- | Representation of the severity of the logs data Severity Debug :: Severity Info :: Severity Critical :: Severity data LogMsg LogMsg :: Maybe SystemTime -> Severity -> LogMsgData -> LogMsg [mTime] :: LogMsg -> Maybe SystemTime [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 v m | m -> v loggerCtx :: RaftLogger v m => m (NodeId, RaftNodeState v) mkLogMsgData :: RaftLogger v m => Text -> m LogMsgData logToDest :: MonadIO m => LogCtx m -> LogMsg -> m () logToStdout :: MonadIO m => Severity -> LogMsg -> m () logToFile :: MonadIO m => FilePath -> Severity -> LogMsg -> m () logWithSeverityIO :: forall m v. (RaftLogger v m, MonadIO m) => Severity -> LogCtx m -> Text -> m () logInfoIO :: (RaftLogger v m, MonadIO m) => LogCtx m -> Text -> m () logDebugIO :: (RaftLogger v m, MonadIO m) => LogCtx m -> Text -> m () logCriticalIO :: (RaftLogger v m, MonadIO m) => LogCtx m -> Text -> m () newtype RaftLoggerT v m a RaftLoggerT :: StateT [LogMsg] m a -> RaftLoggerT v m a [unRaftLoggerT] :: RaftLoggerT v m a -> StateT [LogMsg] m a runRaftLoggerT :: Monad m => RaftLoggerT v m a -> m (a, [LogMsg]) type RaftLoggerM v = RaftLoggerT v Identity runRaftLoggerM :: RaftLoggerM v a -> (a, [LogMsg]) logWithSeverity :: RaftLogger v m => Severity -> Text -> RaftLoggerT v m () logInfo :: RaftLogger v m => Text -> RaftLoggerT v m () logDebug :: RaftLogger v m => Text -> RaftLoggerT v m () logCritical :: RaftLogger v m => Text -> RaftLoggerT v m () logAndPanic :: RaftLogger v m => Text -> m a logAndPanicIO :: (RaftLogger v m, MonadIO m) => LogCtx m -> Text -> m a instance Control.Monad.Trans.Class.MonadTrans (Raft.Logging.RaftLoggerT v) instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState [Raft.Logging.LogMsg] (Raft.Logging.RaftLoggerT v m) instance GHC.Base.Monad m => GHC.Base.Monad (Raft.Logging.RaftLoggerT v m) instance GHC.Base.Monad m => GHC.Base.Applicative (Raft.Logging.RaftLoggerT v m) instance GHC.Base.Functor m => GHC.Base.Functor (Raft.Logging.RaftLoggerT v m) instance GHC.Show.Show Raft.Logging.LogMsgData instance GHC.Classes.Ord Raft.Logging.Severity instance GHC.Classes.Eq Raft.Logging.Severity instance GHC.Show.Show Raft.Logging.Severity instance Raft.Logging.RaftLogger v m => Raft.Logging.RaftLogger v (Raft.Logging.RaftLoggerT v m) module Raft.Event -- | Representation of events a raft node can send and receive data Event v MessageEvent :: MessageEvent v -> Event v TimeoutEvent :: SystemTime -> 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.Monad type MonadRaft v m = (MonadRaftChan v m, MonadRaftFork m) -- | The typeclass specifying the datatype used as the core event channel -- in the main raft event loop, as well as functions for creating, -- reading, and writing to the channel, and how to fork a computation -- that performs some action with the channel. -- -- Note: This module uses AllowAmbiguousTypes which removes the necessity -- for Proxy value arguments in lieu of TypeApplication. For example: -- --
--   newRaftChan @v
--   
-- -- instead of -- --
--   newRaftChan (Proxy :: Proxy v)
--   
class Monad m => MonadRaftChan v m where { type family RaftEventChan v m; } readRaftChan :: MonadRaftChan v m => RaftEventChan v m -> m (Event v) writeRaftChan :: MonadRaftChan v m => RaftEventChan v m -> Event v -> m () newRaftChan :: MonadRaftChan v m => m (RaftEventChan v m) data RaftThreadRole RPCHandler :: RaftThreadRole ClientRequestHandler :: RaftThreadRole CustomThreadRole :: Text -> RaftThreadRole -- | The typeclass encapsulating the concurrency operations necessary for -- the implementation of the main event handling loop. class Monad m => MonadRaftFork m where { type family RaftThreadId m; } raftFork :: MonadRaftFork m => RaftThreadRole -> m () -> m (RaftThreadId m) -- | The raft server environment composed of the concurrent variables used -- in the effectful raft layer. data RaftEnv v m RaftEnv :: RaftEventChan v m -> m () -> m () -> RaftNodeConfig -> LogCtx (RaftT v m) -> RaftEnv v m [eventChan] :: RaftEnv v m -> RaftEventChan v m [resetElectionTimer] :: RaftEnv v m -> m () [resetHeartbeatTimer] :: RaftEnv v m -> m () [raftNodeConfig] :: RaftEnv v m -> RaftNodeConfig [raftNodeLogCtx] :: RaftEnv v m -> LogCtx (RaftT v m) newtype RaftT v m a RaftT :: ReaderT (RaftEnv v m) (StateT (RaftNodeState v) m) a -> RaftT v m a [unRaftT] :: RaftT v m a -> ReaderT (RaftEnv v m) (StateT (RaftNodeState v) m) a runRaftT :: Monad m => RaftNodeState v -> RaftEnv v m -> RaftT v m a -> m a logDebug :: MonadIO m => Text -> RaftT v m () logCritical :: MonadIO m => Text -> RaftT v m () logAndPanic :: MonadIO m => Text -> RaftT v m a instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Raft.Monad.RaftT v m) instance GHC.Base.MonadPlus m => GHC.Base.Alternative (Raft.Monad.RaftT v m) instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Raft.Monad.RaftT v m) instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState (Raft.NodeState.RaftNodeState v) (Raft.Monad.RaftT v m) instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (Raft.Monad.RaftEnv v m) (Raft.Monad.RaftT v m) instance GHC.Base.Monad m => GHC.Base.Monad (Raft.Monad.RaftT v m) instance GHC.Base.Monad m => GHC.Base.Applicative (Raft.Monad.RaftT v m) instance GHC.Base.Functor m => GHC.Base.Functor (Raft.Monad.RaftT v m) instance GHC.Show.Show Raft.Monad.RaftThreadRole instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Raft.Monad.RaftT v m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Raft.Monad.RaftT v m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Raft.Monad.RaftT v m) instance Control.Monad.Trans.Class.MonadTrans (Raft.Monad.RaftT v) instance Raft.Monad.MonadRaftFork m => Raft.Monad.MonadRaftFork (Raft.Monad.RaftT v m) instance GHC.Base.Monad m => Raft.Logging.RaftLogger v (Raft.Monad.RaftT v m) instance Raft.Monad.MonadRaftFork GHC.Types.IO instance Raft.Monad.MonadRaftFork Test.DejaFu.Conc.ConcIO instance Raft.Monad.MonadRaftChan v GHC.Types.IO instance Raft.Monad.MonadRaftChan v Test.DejaFu.Conc.ConcIO module Raft.Log.PostgreSQL -- | A single threaded PostgreSQL storage monad transformer newtype RaftPostgresT m a RaftPostgresT :: ReaderT RaftPostgresEnv m a -> RaftPostgresT m a [unRaftPostgresT] :: RaftPostgresT m a -> ReaderT RaftPostgresEnv m a -- | Run a RaftPostgresT computation by supplying the database connection -- info runRaftPostgresT :: MonadIO m => ConnectInfo -> RaftPostgresT m a -> m a runRaftPostgresM :: ConnectInfo -> RaftPostgresM a -> IO a raftDatabaseName :: [Char] -> [Char] raftDatabaseConnInfo :: [Char] -> [Char] -> [Char] -> ConnectInfo initConnInfo :: ConnectInfo -- | Create the libraft database to store all log entries setupDB :: ConnectInfo -> IO (Either PGError Connection) deleteDB :: [Char] -> Connection -> IO Int64 instance GHC.Show.Show Raft.Log.PostgreSQL.RaftPostgresError instance GHC.Show.Show Raft.Log.PostgreSQL.PGError instance (Data.Typeable.Internal.Typeable v, Data.Serialize.Serialize v) => Database.PostgreSQL.Simple.FromRow.FromRow (Raft.Log.PostgreSQL.EntryRow v) instance Data.Serialize.Serialize v => Database.PostgreSQL.Simple.ToRow.ToRow (Raft.Log.PostgreSQL.EntryRow v) instance GHC.Generics.Generic (Raft.Log.PostgreSQL.EntryRow v) instance GHC.Show.Show v => GHC.Show.Show (Raft.Log.PostgreSQL.EntryRow v) instance Control.Monad.Trans.Class.MonadTrans Raft.Log.PostgreSQL.RaftPostgresT instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Raft.Log.PostgreSQL.RaftPostgresT m) instance GHC.Base.Alternative m => GHC.Base.Alternative (Raft.Log.PostgreSQL.RaftPostgresT m) instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader Raft.Log.PostgreSQL.RaftPostgresEnv (Raft.Log.PostgreSQL.RaftPostgresT m) instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Raft.Log.PostgreSQL.RaftPostgresT m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Raft.Log.PostgreSQL.RaftPostgresT m) instance GHC.Base.Monad m => GHC.Base.Monad (Raft.Log.PostgreSQL.RaftPostgresT m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Raft.Log.PostgreSQL.RaftPostgresT m) instance GHC.Base.Functor m => GHC.Base.Functor (Raft.Log.PostgreSQL.RaftPostgresT m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Raft.Log.PostgreSQL.RaftPostgresT m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Raft.Log.PostgreSQL.RaftPostgresT m) instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Raft.Log.PostgreSQL.RaftPostgresT m) instance GHC.Exception.Type.Exception Raft.Log.PostgreSQL.RaftPostgresError instance Control.Monad.IO.Class.MonadIO m => Raft.Log.RaftInitLog (Raft.Log.PostgreSQL.RaftPostgresT m) v instance (Data.Typeable.Internal.Typeable v, Data.Serialize.Serialize v, Control.Monad.IO.Class.MonadIO m) => Raft.Log.RaftReadLog (Raft.Log.PostgreSQL.RaftPostgresT m) v instance (Data.Serialize.Serialize v, Control.Monad.IO.Class.MonadIO m) => Raft.Log.RaftWriteLog (Raft.Log.PostgreSQL.RaftPostgresT m) v instance (Data.Serialize.Serialize v, Control.Monad.IO.Class.MonadIO m) => Raft.Log.RaftDeleteLog (Raft.Log.PostgreSQL.RaftPostgresT m) v instance Raft.Persistent.RaftPersist m => Raft.Persistent.RaftPersist (Raft.Log.PostgreSQL.RaftPostgresT m) instance (GHC.Base.Monad m, Raft.RPC.RaftSendRPC m v) => Raft.RPC.RaftSendRPC (Raft.Log.PostgreSQL.RaftPostgresT m) v instance (GHC.Base.Monad m, Raft.RPC.RaftRecvRPC m v) => Raft.RPC.RaftRecvRPC (Raft.Log.PostgreSQL.RaftPostgresT m) v instance (GHC.Base.Monad m, Raft.Client.RaftSendClient m sm v) => Raft.Client.RaftSendClient (Raft.Log.PostgreSQL.RaftPostgresT m) sm v instance (GHC.Base.Monad m, Raft.Client.RaftRecvClient m v) => Raft.Client.RaftRecvClient (Raft.Log.PostgreSQL.RaftPostgresT m) v instance Raft.StateMachine.RaftStateMachine m sm v => Raft.StateMachine.RaftStateMachine (Raft.Log.PostgreSQL.RaftPostgresT m) sm v instance Raft.Monad.MonadRaftChan v m => Raft.Monad.MonadRaftChan v (Raft.Log.PostgreSQL.RaftPostgresT m) instance (Control.Monad.IO.Class.MonadIO m, Raft.Monad.MonadRaftFork m) => Raft.Monad.MonadRaftFork (Raft.Log.PostgreSQL.RaftPostgresT m) module Examples.Raft.FileStore.Persistent newtype RaftPersistFileStoreError RaftPersistFileStoreError :: Text -> RaftPersistFileStoreError newtype RaftPersistFile RaftPersistFile :: FilePath -> RaftPersistFile newtype RaftPersistFileStoreT m a RaftPersistFileStoreT :: ReaderT RaftPersistFile m a -> RaftPersistFileStoreT m a [unRaftPersistFileStoreT] :: RaftPersistFileStoreT m a -> ReaderT RaftPersistFile m a runRaftPersistFileStoreT :: RaftPersistFile -> RaftPersistFileStoreT m a -> m a instance Control.Monad.Trans.Class.MonadTrans Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance GHC.Base.Alternative m => GHC.Base.Alternative (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader Examples.Raft.FileStore.Persistent.RaftPersistFile (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance GHC.Base.Monad m => GHC.Base.Monad (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance GHC.Base.Functor m => GHC.Base.Functor (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance GHC.Show.Show Examples.Raft.FileStore.Persistent.RaftPersistFileStoreError instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance Control.Monad.IO.Class.MonadIO m => Raft.Persistent.RaftPersist (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance Raft.StateMachine.RaftStateMachine m sm v => Raft.StateMachine.RaftStateMachine (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) sm v instance (Control.Monad.IO.Class.MonadIO m, Control.Monad.Catch.MonadMask m, Raft.Client.RaftSendClient m sm v) => Raft.Client.RaftSendClient (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) sm v instance (Control.Monad.IO.Class.MonadIO m, Raft.Client.RaftRecvClient m v) => Raft.Client.RaftRecvClient (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) v instance (Control.Monad.IO.Class.MonadIO m, Control.Monad.Catch.MonadMask m, Raft.RPC.RaftSendRPC m v) => Raft.RPC.RaftSendRPC (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) v instance (Control.Monad.IO.Class.MonadIO m, Raft.RPC.RaftRecvRPC m v) => Raft.RPC.RaftRecvRPC (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) v instance (Control.Monad.IO.Class.MonadIO m, Raft.Log.RaftInitLog m v) => Raft.Log.RaftInitLog (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) v instance Raft.Log.RaftWriteLog m v => Raft.Log.RaftWriteLog (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) v instance Raft.Log.RaftReadLog m v => Raft.Log.RaftReadLog (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) v instance Raft.Log.RaftDeleteLog m v => Raft.Log.RaftDeleteLog (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) v instance Raft.Monad.MonadRaftChan v m => Raft.Monad.MonadRaftChan v (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance (Control.Monad.IO.Class.MonadIO m, Raft.Monad.MonadRaftFork m) => Raft.Monad.MonadRaftFork (Examples.Raft.FileStore.Persistent.RaftPersistFileStoreT m) instance GHC.Exception.Type.Exception Examples.Raft.FileStore.Persistent.RaftPersistFileStoreError 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 -> ClientRespSpec sm -> Action sm v -- | Reset a timeout timer ResetTimeoutTimer :: Timeout -> Action sm v -- | Update the client request cache from the given index onward UpdateClientReqCacheFrom :: Index -> 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.Transition tellAction :: Action sm v -> TransitionM sm v () tellActions :: [Action sm v] -> TransitionM sm v () data TransitionEnv sm v TransitionEnv :: RaftNodeConfig -> sm -> RaftNodeState v -> TransitionEnv sm v [nodeConfig] :: TransitionEnv sm v -> RaftNodeConfig [stateMachine] :: TransitionEnv sm v -> sm [nodeState] :: TransitionEnv sm v -> RaftNodeState v newtype TransitionM sm v a TransitionM :: RaftLoggerT v (RWS (TransitionEnv sm v) [Action sm v] PersistentState) a -> TransitionM sm v a [unTransitionM] :: TransitionM sm v a -> RaftLoggerT v (RWS (TransitionEnv sm v) [Action sm v] PersistentState) a runTransitionM :: TransitionEnv sm v -> 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, Show v) => NodeState ns v -> NodeId -> r -> TransitionM sm v (ResultState ns v) type TimeoutHandler ns sm v = Show v => NodeState ns v -> Timeout -> TransitionM sm v (ResultState ns v) type ClientReqHandler ns sm v = Show v => NodeState ns v -> ClientRequest v -> TransitionM sm v (ResultState ns v) 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 -> ClientReadReq -> TransitionM sm v () respondClientWrite :: ClientId -> Index -> SerialNum -> TransitionM sm v () respondClientRedir :: ClientId -> CurrentLeader -> TransitionM sm v () appendLogEntries :: Show v => Seq (Entry v) -> TransitionM sm v () updateClientReqCacheFromIdx :: Index -> TransitionM sm v () startElection :: Index -> Index -> LastLogEntry v -> ClientWriteReqCache -> TransitionM sm v (CandidateState v) logInfo :: () => Text -> TransitionM sm v () logDebug :: () => Text -> TransitionM sm v () instance GHC.Base.Monad (Raft.Transition.TransitionM sm v) instance GHC.Base.Applicative (Raft.Transition.TransitionM sm v) instance GHC.Base.Functor (Raft.Transition.TransitionM sm v) instance Control.Monad.Writer.Class.MonadWriter [Raft.Action.Action sm v] (Raft.Transition.TransitionM sm v) instance Control.Monad.Reader.Class.MonadReader (Raft.Transition.TransitionEnv sm v) (Raft.Transition.TransitionM sm v) instance Control.Monad.State.Class.MonadState Raft.Persistent.PersistentState (Raft.Transition.TransitionM sm v) instance Raft.Logging.RaftLogger v (Control.Monad.Trans.RWS.Lazy.RWS (Raft.Transition.TransitionEnv sm v) [Raft.Action.Action sm v] Raft.Persistent.PersistentState) module Raft.Leader -- | Leaders should not respond to AppendEntries messages. handleAppendEntries :: RPCHandler 'Leader sm (AppendEntries v) v handleAppendEntriesResponse :: forall sm v. RPCHandler 'Leader sm AppendEntriesResponse v -- | Leaders should not respond to RequestVote messages. handleRequestVote :: RPCHandler 'Leader sm RequestVote v -- | Leaders should not respond to RequestVoteResponse 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, Serialize v) => ClientReqHandler 'Leader sm v module Raft.Follower -- | Handle AppendEntries RPC message from Leader Sections 5.2 and 5.3 of -- Raft Paper & Figure 2: Receiver Implementation -- -- Note: see PersistentState 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 AppendEntriesResponse messages. handleAppendEntriesResponse :: RPCHandler 'Follower sm AppendEntriesResponse v handleRequestVote :: RPCHandler 'Follower sm RequestVote v -- | Followers should not respond to RequestVoteResponse 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 AppendEntriesResponse -- messages. handleAppendEntriesResponse :: RPCHandler 'Candidate sm AppendEntriesResponse v handleRequestVote :: RPCHandler 'Candidate sm RequestVote v -- | Candidates should not respond to RequestVoteResponse messages. handleRequestVoteResponse :: forall sm v. (Show v, Serialize 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. (RaftStateMachinePure sm v, Show v, Serialize v) => RaftNodeState v -> TransitionEnv sm v -> PersistentState -> Event v -> (RaftNodeState v, 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, Serialize v) => RaftHandler 'Follower sm v candidateRaftHandler :: (Show v, Serialize v) => RaftHandler 'Candidate sm v leaderRaftHandler :: (Show v, Serialize v) => RaftHandler 'Leader sm v mkRaftHandler :: forall ns sm v. (Show v, Serialize v) => NodeState ns v -> RaftHandler ns sm v handleEvent' :: forall ns sm v. (RaftStateMachinePure sm v, Show v, Serialize v) => NodeState ns v -> TransitionEnv sm v -> PersistentState -> Event v -> ((ResultState ns v, [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 RaftStateMachinePure sm v | sm -> v where { data family RaftStateMachinePureError sm v; type family RaftStateMachinePureCtx sm v = ctx | ctx -> sm v; } rsmTransition :: RaftStateMachinePure sm v => RaftStateMachinePureCtx sm v -> sm -> v -> Either (RaftStateMachinePureError sm v) sm class (Monad m, RaftStateMachinePure sm v) => RaftStateMachine m sm v validateCmd :: RaftStateMachine m sm v => v -> m (Either (RaftStateMachinePureError sm v) ()) askRaftStateMachinePureCtx :: RaftStateMachine m sm v => m (RaftStateMachinePureCtx 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 -- -- TODO It would be really nice if RSMP was a superclass, but -- currently this can't happen because of cyclic imports. class RaftSendClient m sm v sendClient :: RaftSendClient m sm v => ClientId -> ClientResponse sm v -> 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; } initializePersistentState :: (RaftPersist m, Exception (RaftPersistError m)) => m (Either (RaftPersistError m) ()) readPersistentState :: (RaftPersist m, Exception (RaftPersistError m)) => m (Either (RaftPersistError m) PersistentState) writePersistentState :: (RaftPersist m, Exception (RaftPersistError m)) => PersistentState -> m (Either (RaftPersistError m) ()) -- | The raft server environment composed of the concurrent variables used -- in the effectful raft layer. data RaftEnv v m RaftEnv :: RaftEventChan v m -> m () -> m () -> RaftNodeConfig -> LogCtx (RaftT v m) -> RaftEnv v m [eventChan] :: RaftEnv v m -> RaftEventChan v m [resetElectionTimer] :: RaftEnv v m -> m () [resetHeartbeatTimer] :: RaftEnv v m -> m () [raftNodeConfig] :: RaftEnv v m -> RaftNodeConfig [raftNodeLogCtx] :: RaftEnv v m -> LogCtx (RaftT v m) -- | Run timers, RPC and client request handlers and start event loop. It -- should run forever runRaftNode :: forall m sm v. (Typeable m, Show v, Show sm, Serialize v, Show (Action sm v), Show (RaftLogError m), Show (RaftStateMachinePureError sm v), MonadIO m, MonadCatch m, MonadFail m, MonadRaft v m, RaftStateMachine m sm v, RaftSendRPC m v, RaftRecvRPC m v, RaftSendClient m sm v, RaftRecvClient m v, RaftLog m v, RaftLogExceptions m, RaftPersist m, Exception (RaftPersistError m)) => RaftNodeConfig -> LogCtx (RaftT v m) -> Int -> sm -> m () runRaftT :: Monad m => RaftNodeState v -> RaftEnv v m -> RaftT v m a -> m a handleEventLoop :: forall sm v m. (Show v, Serialize v, Show sm, Show (Action sm v), Show (RaftLogError m), Typeable m, MonadIO m, MonadRaft v m, MonadFail m, MonadThrow m, RaftStateMachine m sm v, Show (RaftStateMachinePureError sm v), RaftPersist m, RaftSendRPC m v, RaftSendClient m sm v, 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 :: ClientReadReq -> ClientReq v -- | Write a command ClientWriteReq :: SerialNum -> v -> ClientReq v -- | The datatype sent back to the client as an actual response data ClientResponse sm v -- | Respond with the latest state of the state machine. ClientReadResponse :: ClientReadResp sm v -> ClientResponse sm v -- | Respond with the index of the entry appended to the log ClientWriteResponse :: ClientWriteResp -> ClientResponse sm v -- | Respond with the node id of the current leader ClientRedirectResponse :: ClientRedirResp -> ClientResponse sm v -- | Representation of a read response to a client data ClientReadResp sm v ClientReadRespStateMachine :: sm -> ClientReadResp sm v ClientReadRespEntry :: Entry v -> ClientReadResp sm v ClientReadRespEntries :: Entries v -> ClientReadResp sm v -- | 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 -> SerialNum -> ClientWriteResp -- | Representation of a redirect response to a client data ClientRedirResp ClientRedirResp :: CurrentLeader -> ClientRedirResp -- | Configuration of a node in the cluster data RaftNodeConfig RaftNodeConfig :: NodeId -> NodeIds -> (Natural, Natural) -> Natural -> StorageState -> RaftNodeConfig -- | Node id of the running node [configNodeId] :: RaftNodeConfig -> NodeId -- | Set of all other node ids in the cluster [configNodeIds] :: RaftNodeConfig -> NodeIds -- | Range of times an election timeout can take [configElectionTimeout] :: RaftNodeConfig -> (Natural, Natural) -- | Heartbeat timeout timer [configHeartbeatTimeout] :: RaftNodeConfig -> Natural -- | Create a fresh DB or read from existing [configStorageState] :: RaftNodeConfig -> StorageState -- | Representation of events a raft node can send and receive data Event v MessageEvent :: MessageEvent v -> Event v TimeoutEvent :: SystemTime -> 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 -> EntryHash -> 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 [entryPrevHash] :: Entry v -> EntryHash type Entries v = Seq (Entry v) -- | Provides an interface for nodes to write log entries to storage. class (Show (RaftWriteLogError m), 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 (Show (RaftDeleteLogError m), 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 >= 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 (Show (RaftReadLogError m), 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 = (RaftInitLog 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 type RaftLogExceptions m = (Exception (RaftInitLogError m), Exception (RaftReadLogError m), Exception (RaftWriteLogError m), Exception (RaftDeleteLogError m)) -- | Representation of the logs' context data LogCtx m LogCtx :: LogDest m -> Severity -> LogCtx m [logCtxDest] :: LogCtx m -> LogDest m [logCtxSeverity] :: LogCtx m -> Severity NoLogs :: LogCtx m -- | Representation of the logs' destination data LogDest m LogWith :: (MonadIO m => Severity -> Text -> m ()) -> LogDest m LogFile :: FilePath -> LogDest m LogStdout :: LogDest m -- | Representation of the severity of the logs data Severity Debug :: Severity Info :: Severity Critical :: Severity data Mode Follower :: Mode Candidate :: Mode Leader :: Mode -- | Existential type hiding the internal node state data RaftNodeState v [RaftNodeState] :: {unRaftNodeState :: NodeState s v} -> RaftNodeState v -- | The volatile state of a Raft Node data NodeState (a :: Mode) v [NodeFollowerState] :: FollowerState v -> NodeState 'Follower v [NodeCandidateState] :: CandidateState v -> NodeState 'Candidate v [NodeLeaderState] :: LeaderState v -> NodeState 'Leader v -- | 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 v FollowerState :: CurrentLeader -> Index -> Index -> LastLogEntry v -> Maybe Term -> ClientWriteReqCache -> FollowerState v -- | Id of the current leader [fsCurrentLeader] :: FollowerState v -> CurrentLeader -- | Index of highest log entry known to be committed [fsCommitIndex] :: FollowerState v -> Index -- | Index of highest log entry applied to state machine [fsLastApplied] :: FollowerState v -> Index -- | Index and term of the last log entry in the node's log [fsLastLogEntry] :: FollowerState v -> LastLogEntry v -- | The term of the log entry specified in and AppendEntriesRPC [fsTermAtAEPrevIndex] :: FollowerState v -> Maybe Term -- | The client write request cache, growing linearly with the number of -- clients [fsClientReqCache] :: FollowerState v -> ClientWriteReqCache data CandidateState v CandidateState :: Index -> Index -> NodeIds -> LastLogEntry v -> ClientWriteReqCache -> CandidateState v -- | Index of highest log entry known to be committed [csCommitIndex] :: CandidateState v -> Index -- | Index of highest log entry applied to state machine [csLastApplied] :: CandidateState v -> Index -- | Votes from other nodes in the raft network [csVotes] :: CandidateState v -> NodeIds -- | Index and term of the last log entry in the node's log [csLastLogEntry] :: CandidateState v -> LastLogEntry v -- | The client write request cache, growing linearly with the number of -- clients [csClientReqCache] :: CandidateState v -> ClientWriteReqCache data LeaderState v LeaderState :: Index -> Index -> Map NodeId Index -> Map NodeId Index -> LastLogEntry v -> Int -> ClientReadReqs -> ClientWriteReqCache -> LeaderState v -- | Index of highest log entry known to be committed [lsCommitIndex] :: LeaderState v -> Index -- | Index of highest log entry applied to state machine [lsLastApplied] :: LeaderState v -> Index -- | For each server, index of the next log entry to send to that server [lsNextIndex] :: LeaderState v -> Map NodeId Index -- | For each server, index of highest log entry known to be replicated on -- server [lsMatchIndex] :: LeaderState v -> 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. [lsLastLogEntry] :: LeaderState v -> LastLogEntry v -- | Number of read requests handled this term [lsReadReqsHandled] :: LeaderState v -> Int -- | The number of successful responses received regarding a specific read -- request heartbeat. [lsReadRequest] :: LeaderState v -> ClientReadReqs -- | The cache of client write requests received by the leader [lsClientReqCache] :: LeaderState v -> ClientWriteReqCache -- | A node in Raft begins as a follower initRaftNodeState :: RaftNodeState v -- | Check if node is in a follower state isFollower :: NodeState s v -> Bool -- | Check if node is in a candidate state isCandidate :: NodeState s v -> Bool -- | Check if node is in a leader state isLeader :: NodeState s v -> Bool -- | Update the last log entry in the node's log setLastLogEntry :: NodeState s v -> Entries v -> NodeState s v -- | Get the last applied index and the commit index of the last log entry -- in the node's log getLastLogEntry :: NodeState ns v -> LastLogEntry v -- | 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 v -> (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 -> AppendEntriesSpec v -> AppendEntriesData v [aedTerm] :: AppendEntriesData v -> Term [aedLeaderCommit] :: AppendEntriesData v -> Index [aedEntriesSpec] :: AppendEntriesData v -> AppendEntriesSpec v module Examples.Raft.Socket.Common -- | Convert a host and a port to a valid NodeId hostPortToNid :: (HostName, ServiceName) -> NodeId hostPortToNidBS :: (HostName, ServiceName) -> ByteString -- | Retrieve the host and port from a valid NodeId nidToHostPort :: NodeId -> (HostName, ServiceName) -- | Get a free port number. getFreePort :: IO ServiceName -- | Receive bytes on a socket until an entire message can be decoded. This -- function fixes the deserialization of the bytes sent on the socket to -- the implementation of the Serialize typeclass. recvSerialized :: Serialize a => Socket -> IO (Maybe a) module Examples.Raft.Socket.Node data ResponseSignal sm v -- | we managed to write a valid response to the TMVar OkResponse :: ClientResponse sm v -> ResponseSignal sm v -- | if we get overlapping requests coming in with the same client id, we -- "kill" one of them DeadResponse :: ResponseSignal sm v data NodeSocketEnv sm v NodeSocketEnv :: TChan (RPCMessage v) -> TChan (ClientRequest v) -> TVar (Map ClientId (TMVar (ResponseSignal sm v))) -> NodeSocketEnv sm v -- | Queue of RPC messages to be processed by event handlers [nsMsgQueue] :: NodeSocketEnv sm v -> TChan (RPCMessage v) -- | Queue of client request messages to be processed by event handlers [nsClientReqQueue] :: NodeSocketEnv sm v -> TChan (ClientRequest v) -- | Map of variables to which responses to a request are written. N.B.: -- this assumes a client id uniquely identifies a request; A client will -- never send a request without having either 1) given up on the a -- previous request because of a timeout, or 2) received a response to -- each previous request issued. [nsClientReqResps] :: NodeSocketEnv sm v -> TVar (Map ClientId (TMVar (ResponseSignal sm v))) newtype RaftSocketT sm v m a RaftSocketT :: ReaderT (NodeSocketEnv sm v) m a -> RaftSocketT sm v m a [unRaftSocketT] :: RaftSocketT sm v m a -> ReaderT (NodeSocketEnv sm v) m a runRaftSocketT :: MonadIO m => NodeSocketEnv sm v -> RaftSocketT sm v m a -> m a acceptConnections :: forall sm v m. (Serialize sm, Serialize v, MonadIO m) => HostName -> ServiceName -> RaftSocketT sm v m () instance Control.Monad.Trans.Class.MonadTrans (Examples.Raft.Socket.Node.RaftSocketT sm v) instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance GHC.Base.Alternative m => GHC.Base.Alternative (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (Examples.Raft.Socket.Node.NodeSocketEnv sm v) (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance GHC.Base.Monad m => GHC.Base.Monad (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance GHC.Base.Functor m => GHC.Base.Functor (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance (Control.Monad.Catch.MonadMask m, Control.Monad.Catch.MonadCatch m, Control.Monad.IO.Class.MonadIO m, Data.Serialize.Serialize sm, Data.Serialize.Serialize v) => Raft.Client.RaftSendClient (Examples.Raft.Socket.Node.RaftSocketT sm v m) sm v instance (Control.Monad.IO.Class.MonadIO m, Data.Serialize.Serialize v) => Raft.Client.RaftRecvClient (Examples.Raft.Socket.Node.RaftSocketT sm v m) v instance (Control.Monad.Catch.MonadCatch m, Control.Monad.Catch.MonadMask m, Control.Monad.IO.Class.MonadIO m, Data.Serialize.Serialize v, GHC.Show.Show v) => Raft.RPC.RaftSendRPC (Examples.Raft.Socket.Node.RaftSocketT sm v m) v instance (Control.Monad.IO.Class.MonadIO m, GHC.Show.Show v) => Raft.RPC.RaftRecvRPC (Examples.Raft.Socket.Node.RaftSocketT sm v m) v instance (Control.Monad.IO.Class.MonadIO m, Raft.Persistent.RaftPersist m) => Raft.Persistent.RaftPersist (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance (Control.Monad.IO.Class.MonadIO m, Raft.Log.RaftInitLog m v) => Raft.Log.RaftInitLog (Examples.Raft.Socket.Node.RaftSocketT sm v m) v instance Raft.Log.RaftWriteLog m v => Raft.Log.RaftWriteLog (Examples.Raft.Socket.Node.RaftSocketT sm v m) v instance Raft.Log.RaftReadLog m v => Raft.Log.RaftReadLog (Examples.Raft.Socket.Node.RaftSocketT sm v m) v instance Raft.Log.RaftDeleteLog m v => Raft.Log.RaftDeleteLog (Examples.Raft.Socket.Node.RaftSocketT sm v m) v instance Raft.StateMachine.RaftStateMachine m sm v => Raft.StateMachine.RaftStateMachine (Examples.Raft.Socket.Node.RaftSocketT sm v m) sm v instance Raft.Monad.MonadRaftChan v m => Raft.Monad.MonadRaftChan v (Examples.Raft.Socket.Node.RaftSocketT sm v m) instance (Control.Monad.IO.Class.MonadIO m, Raft.Monad.MonadRaftFork m) => Raft.Monad.MonadRaftFork (Examples.Raft.Socket.Node.RaftSocketT sm v m) module Examples.Raft.Socket.Client newtype ClientRespChan s v ClientRespChan :: TChan (STM IO) (ClientResponse s v) -> ClientRespChan s v [clientRespChan] :: ClientRespChan s v -> TChan (STM IO) (ClientResponse s v) newClientRespChan :: IO (ClientRespChan s v) newtype RaftClientRespChanT s v m a RaftClientRespChanT :: ReaderT (ClientRespChan s v) m a -> RaftClientRespChanT s v m a [unRaftClientRespChanT] :: RaftClientRespChanT s v m a -> ReaderT (ClientRespChan s v) m a type RaftSocketClientM s v = RaftClientT s v (RaftClientRespChanT s v IO) runRaftSocketClientM :: ClientId -> Set NodeId -> ClientRespChan s v -> RaftSocketClientM s v a -> IO a -- | Send a client read request using the example socket interface of -- RaftSocketClientM socketClientRead :: (Serialize s, Serialize v, Show s, Show v, Show (RaftClientError s v (RaftSocketClientM s v))) => ClientReadReq -> RaftSocketClientM s v (Either Text (ClientReadResp s v)) socketClientWrite :: (Serialize s, Serialize v, Show s, Show v, Show (RaftClientError s v (RaftSocketClientM s v))) => v -> RaftSocketClientM s v (Either Text ClientWriteResp) instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance GHC.Base.Alternative m => GHC.Base.Alternative (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (Examples.Raft.Socket.Client.ClientRespChan s v) (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance GHC.Base.Monad m => GHC.Base.Monad (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance GHC.Base.Functor m => GHC.Base.Functor (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance Control.Monad.Base.MonadBase GHC.Types.IO m => Control.Monad.Base.MonadBase GHC.Types.IO (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance Control.Monad.STM.Class.MonadSTM m => Control.Monad.STM.Class.MonadSTM (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance Control.Monad.Trans.Class.MonadTrans (Examples.Raft.Socket.Client.RaftClientRespChanT s v) instance Control.Monad.Trans.Control.MonadTransControl (Examples.Raft.Socket.Client.RaftClientRespChanT s v) instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO m => Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance System.Console.Haskeline.MonadException.MonadException m => System.Console.Haskeline.MonadException.MonadException (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) instance (Data.Serialize.Serialize s, Data.Serialize.Serialize v, Control.Monad.IO.Class.MonadIO m) => Raft.Client.RaftClientSend (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) v instance (Data.Serialize.Serialize s, Data.Serialize.Serialize v, Control.Monad.IO.Class.MonadIO m) => Raft.Client.RaftClientRecv (Examples.Raft.Socket.Client.RaftClientRespChanT s v m) s v module Examples.Raft.FileStore.Log newtype RaftLogFileStoreError RaftLogFileStoreError :: Text -> RaftLogFileStoreError newtype RaftLogFile RaftLogFile :: FilePath -> RaftLogFile [unRaftLogFile] :: RaftLogFile -> FilePath newtype RaftLogFileStoreT m a RaftLogFileStoreT :: ReaderT RaftLogFile m a -> RaftLogFileStoreT m a [unRaftLogFileStoreT] :: RaftLogFileStoreT m a -> ReaderT RaftLogFile m a runRaftLogFileStoreT :: RaftLogFile -> RaftLogFileStoreT m a -> m a readLogEntries :: (MonadIO m, Serialize v) => RaftLogFileStoreT m (Either Text (Entries v)) instance Control.Monad.Trans.Class.MonadTrans Examples.Raft.FileStore.Log.RaftLogFileStoreT instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance GHC.Base.Alternative m => GHC.Base.Alternative (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader Examples.Raft.FileStore.Log.RaftLogFile (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance GHC.Base.Monad m => GHC.Base.Monad (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance GHC.Base.Functor m => GHC.Base.Functor (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance GHC.Show.Show Examples.Raft.FileStore.Log.RaftLogFileStoreError instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance (Data.Serialize.Serialize v, Control.Monad.IO.Class.MonadIO m) => Raft.Log.RaftInitLog (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) v instance (Control.Monad.IO.Class.MonadIO m, Data.Serialize.Serialize v) => Raft.Log.RaftWriteLog (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) v instance (Control.Monad.IO.Class.MonadIO m, Data.Serialize.Serialize v) => Raft.Log.RaftReadLog (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) v instance (Control.Monad.IO.Class.MonadIO m, Data.Serialize.Serialize v) => Raft.Log.RaftDeleteLog (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) v instance Raft.Persistent.RaftPersist m => Raft.Persistent.RaftPersist (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance (GHC.Base.Monad m, Raft.RPC.RaftSendRPC m v) => Raft.RPC.RaftSendRPC (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) v instance (GHC.Base.Monad m, Raft.RPC.RaftRecvRPC m v) => Raft.RPC.RaftRecvRPC (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) v instance (GHC.Base.Monad m, Raft.Client.RaftSendClient m sm v) => Raft.Client.RaftSendClient (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) sm v instance (GHC.Base.Monad m, Raft.Client.RaftRecvClient m v) => Raft.Client.RaftRecvClient (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) v instance Raft.StateMachine.RaftStateMachine m sm v => Raft.StateMachine.RaftStateMachine (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) sm v instance Raft.Monad.MonadRaftChan v m => Raft.Monad.MonadRaftChan v (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance (Control.Monad.IO.Class.MonadIO m, Raft.Monad.MonadRaftFork m) => Raft.Monad.MonadRaftFork (Examples.Raft.FileStore.Log.RaftLogFileStoreT m) instance GHC.Exception.Type.Exception Examples.Raft.FileStore.Log.RaftLogFileStoreError