doVolunteer :: (RaftLog l e v) => Raft l e v -> IO Bool
doVolunteer vRaft = do
    raft <- atomically $ do
        modifyTVar (raftContext vRaft) $ \oldRaft ->
            setRaftTerm ((raftCurrentTerm oldRaft) + 1)
                $ setRaftLastCandidate Nothing oldRaft
        readTVar (raftContext vRaft)
    let candidate = raftName raft
        cfg = raftStateConfiguration $ raftState raft
        endpoint = raftEndpoint raft
        members = clusterMembers $ clusterConfiguration cfg
        cs = newCallSite endpoint candidate
        term = raftCurrentTerm raft
        log = raftLog raft
        RaftTime lastTerm lastIndex = lastAppendedTime log
    infoM _log $ printf "Server %v volunteering in term %v" candidate (show $ raftCurrentTerm raft)
    debugM _log $ printf "Server %v is soliciting votes from %v" candidate (show members)
    votes <- goRequestVote cs cfg term candidate (RaftTime lastTerm lastIndex)
    debugM _log $ printf "Server %v (%v) received votes %v" candidate (show (term,lastIndex)) (show votes)
    return $ wonElection votes
    where
        wonElection :: M.Map Name (Maybe MemberResult) -> Bool
        wonElection votes = majority votes $ M.foldl (\tally ballot -> 
            case ballot of
                Just (result) -> if (memberActionSuccess result) then tally + 1 else tally
                _ -> tally) 0 votes
        majority :: M.Map Name (Maybe MemberResult) -> Int -> Bool
        majority votes tally = tally > ((M.size $ votes) `quot` 2)
doVolunteer :: (RaftLog l e v) => Raft l e v -> IO Bool
doVolunteer vRaft = do
    raft <- atomically $ do
        modifyTVar (raftContext vRaft) $ \oldRaft ->
            setRaftTerm ((raftCurrentTerm oldRaft) + 1)
                $ setRaftLastCandidate Nothing oldRaft
        readTVar (raftContext vRaft)
    let candidate = raftName raft
        cfg = raftStateConfiguration $ raftState raft
        endpoint = raftEndpoint raft
        members = clusterMembers $ clusterConfiguration cfg
        cs = newCallSite endpoint candidate
        term = raftCurrentTerm raft
        log = raftLog raft
        RaftTime lastTerm lastIndex = lastAppendedTime log
    infoM _log $ printf "Server %v volunteering in term %v" candidate (show $ raftCurrentTerm raft)
    debugM _log $ printf "Server %v is soliciting votes from %v" candidate (show members)
    votes <- goRequestVote cs cfg term candidate (RaftTime lastTerm lastIndex)
    debugM _log $ printf "Server %v (%v) received votes %v" candidate (show (term,lastIndex)) (show votes)
    return $ wonElection votes
    where
        wonElection :: M.Map Name (Maybe MemberResult) -> Bool
        wonElection votes = majority votes $ M.foldl (\tally ballot -> 
            case ballot of
                Just (result) -> if (memberActionSuccess result) then tally + 1 else tally
                _ -> tally) 0 votes
        majority :: M.Map Name (Maybe MemberResult) -> Int -> Bool
        majority votes tally = tally > ((M.size $ votes) `quot` 2)
doVolunteer vRaft = do
    raft <- atomically $ do
        modifyTVar (raftContext vRaft) $ \oldRaft ->
            setRaftTerm ((raftCurrentTerm oldRaft) + 1)
                $ setRaftLastCandidate Nothing oldRaft
        readTVar (raftContext vRaft)
    let candidate = raftName raft
        cfg = raftStateConfiguration $ raftState raft
        endpoint = raftEndpoint raft
        members = clusterMembers $ clusterConfiguration cfg
        cs = newCallSite endpoint candidate
        term = raftCurrentTerm raft
        log = raftLog raft
        RaftTime lastTerm lastIndex = lastAppendedTime log
    infoM _log $ printf "Server %v volunteering in term %v" candidate (show $ raftCurrentTerm raft)
    debugM _log $ printf "Server %v is soliciting votes from %v" candidate (show members)
    votes <- goRequestVote cs cfg term candidate (RaftTime lastTerm lastIndex)
    debugM _log $ printf "Server %v (%v) received votes %v" candidate (show (term,lastIndex)) (show votes)
    return $ wonElection votes
    where
        wonElection :: M.Map Name (Maybe MemberResult) -> Bool
        wonElection votes = majority votes $ M.foldl (\tally ballot -> 
            case ballot of
                Just (result) -> if (memberActionSuccess result) then tally + 1 else tally
                _ -> tally) 0 votes
        majority :: M.Map Name (Maybe MemberResult) -> Int -> Bool
        majority votes tally = tally > ((M.size $ votes) `quot` 2)