append :: (RaftLog l e v) => Raft l e v -> Actions e -> Clients -> IO ()
append vRaft actions clients = do
    (raft,maybeAction) <- atomically $ do
        maybeAction <- readMailbox actions
        raft <- readTVar (raftContext vRaft)
        return (raft,maybeAction)
    case maybeAction of
        Nothing -> return ()
        Just (action,reply) -> do
            let oldLog = raftLog raft
                oldState = raftState raft
                term = raftCurrentTerm raft
                nextIndex = (lastAppended oldLog) + 1
                revisedAction = case action of
                    Cmd _ -> action
                    cfgAction -> Cfg $ SetConfiguration $ applyConfigurationAction (clusterConfiguration $ raftStateConfiguration oldState) cfgAction
            newLog <- appendEntries oldLog nextIndex [RaftLogEntry term revisedAction]
            (revisedLog,revisedState) <- case revisedAction of
                Cfg (SetConfiguration newCfg) -> do
                    let newState = oldState {
                        raftStateConfiguration = (raftStateConfiguration oldState) {
                            clusterConfiguration = newCfg
                        },
                        raftStateConfigurationIndex = case newCfg of
                            JointConfiguration _ _ -> Just nextIndex
                            _ -> Nothing
                        }
                    checkpoint newLog newState
                _ -> return (newLog,oldState)
            atomically $ do
                modifyTVar (raftContext vRaft) $ \oldRaft ->
                    setRaftLog revisedLog $ setRaftState revisedState oldRaft
                writeMailbox clients (lastAppended revisedLog,reply)
            infoM _log $ printf "%v: Appended 1 action at index %v" (raftName raft) nextIndex
            return ()
append :: (RaftLog l e v) => Raft l e v -> Actions e -> Clients -> IO ()
append vRaft actions clients = do
    (raft,maybeAction) <- atomically $ do
        maybeAction <- readMailbox actions
        raft <- readTVar (raftContext vRaft)
        return (raft,maybeAction)
    case maybeAction of
        Nothing -> return ()
        Just (action,reply) -> do
            let oldLog = raftLog raft
                oldState = raftState raft
                term = raftCurrentTerm raft
                nextIndex = (lastAppended oldLog) + 1
                revisedAction = case action of
                    Cmd _ -> action
                    cfgAction -> Cfg $ SetConfiguration $ applyConfigurationAction (clusterConfiguration $ raftStateConfiguration oldState) cfgAction
            newLog <- appendEntries oldLog nextIndex [RaftLogEntry term revisedAction]
            (revisedLog,revisedState) <- case revisedAction of
                Cfg (SetConfiguration newCfg) -> do
                    let newState = oldState {
                        raftStateConfiguration = (raftStateConfiguration oldState) {
                            clusterConfiguration = newCfg
                        },
                        raftStateConfigurationIndex = case newCfg of
                            JointConfiguration _ _ -> Just nextIndex
                            _ -> Nothing
                        }
                    checkpoint newLog newState
                _ -> return (newLog,oldState)
            atomically $ do
                modifyTVar (raftContext vRaft) $ \oldRaft ->
                    setRaftLog revisedLog $ setRaftState revisedState oldRaft
                writeMailbox clients (lastAppended revisedLog,reply)
            infoM _log $ printf "%v: Appended 1 action at index %v" (raftName raft) nextIndex
            return ()
append vRaft actions clients = do
    (raft,maybeAction) <- atomically $ do
        maybeAction <- readMailbox actions
        raft <- readTVar (raftContext vRaft)
        return (raft,maybeAction)
    case maybeAction of
        Nothing -> return ()
        Just (action,reply) -> do
            let oldLog = raftLog raft
                oldState = raftState raft
                term = raftCurrentTerm raft
                nextIndex = (lastAppended oldLog) + 1
                revisedAction = case action of
                    Cmd _ -> action
                    cfgAction -> Cfg $ SetConfiguration $ applyConfigurationAction (clusterConfiguration $ raftStateConfiguration oldState) cfgAction
            newLog <- appendEntries oldLog nextIndex [RaftLogEntry term revisedAction]
            (revisedLog,revisedState) <- case revisedAction of
                Cfg (SetConfiguration newCfg) -> do
                    let newState = oldState {
                        raftStateConfiguration = (raftStateConfiguration oldState) {
                            clusterConfiguration = newCfg
                        },
                        raftStateConfigurationIndex = case newCfg of
                            JointConfiguration _ _ -> Just nextIndex
                            _ -> Nothing
                        }
                    checkpoint newLog newState
                _ -> return (newLog,oldState)
            atomically $ do
                modifyTVar (raftContext vRaft) $ \oldRaft ->
                    setRaftLog revisedLog $ setRaftState revisedState oldRaft
                writeMailbox clients (lastAppended revisedLog,reply)
            infoM _log $ printf "%v: Appended 1 action at index %v" (raftName raft) nextIndex
            return ()