diff --git a/arangod/Agency/Agent.cpp b/arangod/Agency/Agent.cpp index 04f24828d7..c0c76dcf4b 100644 --- a/arangod/Agency/Agent.cpp +++ b/arangod/Agency/Agent.cpp @@ -484,22 +484,22 @@ read_ret_t Agent::read(query_t const& query) { // Only leader else redirect if (!_constituent.leading()) { return read_ret_t(false, _constituent.leaderID()); - } - - // Still leading? - size_t good = 0; - for (auto const& i : _lastAcked) { - std::chrono::duration m = - std::chrono::system_clock::now() - i.second; - if(0.9*_config.minPing() > m.count()) { - ++good; + } else { + // Still leading? + size_t good = 0; + for (auto const& i : _lastAcked) { + std::chrono::duration m = + std::chrono::system_clock::now() - i.second; + if(0.9*_config.minPing() > m.count()) { + ++good; + } + } + if (good < size() / 2) { + _constituent.candidate(); + return read_ret_t(false, NO_LEADER); } } - - if (good < size() / 2) { - _constituent.candidate(); - } - + // Retrieve data from readDB auto result = std::make_shared(); std::vector success = _readDB.read(query, result); diff --git a/arangod/Agency/Constituent.cpp b/arangod/Agency/Constituent.cpp index a571ee2be2..838329acfd 100644 --- a/arangod/Agency/Constituent.cpp +++ b/arangod/Agency/Constituent.cpp @@ -214,6 +214,8 @@ void Constituent::lead(std::map const& votes) { void Constituent::candidate() { MUTEX_LOCKER(guard, _castLock); + + _leaderID = NO_LEADER; if (_role != CANDIDATE) LOG_TOPIC(DEBUG, Logger::AGENCY) diff --git a/arangod/Agency/RestAgencyHandler.cpp b/arangod/Agency/RestAgencyHandler.cpp index 73ca25d408..c1e29a57c8 100644 --- a/arangod/Agency/RestAgencyHandler.cpp +++ b/arangod/Agency/RestAgencyHandler.cpp @@ -140,9 +140,8 @@ RestHandler::status RestAgencyHandler::handleWrite() { } auto s = std::chrono::system_clock::now(); // Leadership established? - std::chrono::seconds timeout(1); + std::chrono::duration timeout(_agent->config().minPing()); while(_agent->size() > 1 && _agent->leaderID() == "") { - std::this_thread::sleep_for(duration_t(100)); if ((std::chrono::system_clock::now()-s) > timeout) { Builder body; body.openObject(); @@ -153,12 +152,12 @@ RestHandler::status RestAgencyHandler::handleWrite() { LOG_TOPIC(ERR, Logger::AGENCY) << "We don't know who the leader is"; return status::DONE; } + std::this_thread::sleep_for(duration_t(100)); } write_ret_t ret = _agent->write(query); if (ret.accepted) { // We're leading and handling the request - bool found; std::string call_mode = _request->header("x-arangodb-agency-mode", found); if (!found) { @@ -227,9 +226,8 @@ inline RestHandler::status RestAgencyHandler::handleRead() { } auto s = std::chrono::system_clock::now(); // Leadership established? - std::chrono::seconds timeout(1); - while(_agent->size() > 1 && _agent->leaderID() == "") { - std::this_thread::sleep_for(duration_t(100)); + std::chrono::duration timeout(_agent->config().minPing()); + while(_agent->size() > 1 && _agent->leaderID() == NO_LEADER) { if ((std::chrono::system_clock::now()-s) > timeout) { Builder body; body.openObject(); @@ -240,6 +238,7 @@ inline RestHandler::status RestAgencyHandler::handleRead() { LOG_TOPIC(ERR, Logger::AGENCY) << "We don't know who the leader is"; return status::DONE; } + std::this_thread::sleep_for(duration_t(100)); } read_ret_t ret = _agent->read(query); @@ -252,7 +251,20 @@ inline RestHandler::status RestAgencyHandler::handleRead() { generateResult(GeneralResponse::ResponseCode::OK, ret.result->slice()); } } else { // Redirect to leader - redirectRequest(ret.redirect); + if (_agent->leaderID() == NO_LEADER) { + + Builder body; + body.openObject(); + body.add("message", VPackValue("No leader")); + body.close(); + generateResult(GeneralResponse::ResponseCode::SERVICE_UNAVAILABLE, + body.slice()); + LOG_TOPIC(ERR, Logger::AGENCY) << "We don't know who the leader is"; + return status::DONE; + + } else { + redirectRequest(ret.redirect); + } return status::DONE; } } else { @@ -263,6 +275,7 @@ inline RestHandler::status RestAgencyHandler::handleRead() { } RestHandler::status RestAgencyHandler::handleConfig() { + Builder body; body.add(VPackValue(VPackValueType::Object)); body.add("term", Value(_agent->term()));