doPulse :: (RaftLog l e v) => Raft l e v -> Actions c -> IO ()
doPulse vRaft actions = do
    raft <- atomically $ do
        raft <- readTVar (raftContext vRaft)
        empty <- isEmptyMailbox actions
        if empty
            then writeMailbox actions Nothing
            else return ()
        return raft
    let cfg = raftStateConfiguration $ raftState raft
    threadDelay $ timeoutPulse $ clusterTimeouts cfg
    doPulse vRaft actions

{-|
    As a leader, wait for 'AppendEntries' requests and process them, 
    commit new changes as necessary, and stop when no heartbeat received.
-}
doPulse :: (RaftLog l e v) => Raft l e v -> Actions c -> IO ()
doPulse vRaft actions = do
    raft <- atomically $ do
        raft <- readTVar (raftContext vRaft)
        empty <- isEmptyMailbox actions
        if empty
            then writeMailbox actions Nothing
            else return ()
        return raft
    let cfg = raftStateConfiguration $ raftState raft
    threadDelay $ timeoutPulse $ clusterTimeouts cfg
    doPulse vRaft actions

{-|
    As a leader, wait for 'AppendEntries' requests and process them, 
    commit new changes as necessary, and stop when no heartbeat received.
-}
doPulse vRaft actions = do
    raft <- atomically $ do
        raft <- readTVar (raftContext vRaft)
        empty <- isEmptyMailbox actions
        if empty
            then writeMailbox actions Nothing
            else return ()
        return raft
    let cfg = raftStateConfiguration $ raftState raft
    threadDelay $ timeoutPulse $ clusterTimeouts cfg
    doPulse vRaft actions

{-|
    As a leader, wait for 'AppendEntries' requests and process them, 
    commit new changes as necessary, and stop when no heartbeat received.
-}