diff --git a/3rdParty/fuerte/src/HttpConnection.cpp b/3rdParty/fuerte/src/HttpConnection.cpp index de04ec2cd6..c6150267c7 100644 --- a/3rdParty/fuerte/src/HttpConnection.cpp +++ b/3rdParty/fuerte/src/HttpConnection.cpp @@ -287,7 +287,7 @@ std::string HttpConnection::buildRequestBody(Request const& req) { // construct request path ("/_db//" prefix) if (!req.header.database.empty()) { - header.append("/_db/"); + header.append("/_db/", 5); http::urlEncode(header, req.header.database); } // must start with /, also turns /_db/abc into /_db/abc/ diff --git a/3rdParty/fuerte/src/connection.cpp b/3rdParty/fuerte/src/connection.cpp index 4ab8b70d66..709123a680 100644 --- a/3rdParty/fuerte/src/connection.cpp +++ b/3rdParty/fuerte/src/connection.cpp @@ -32,12 +32,11 @@ Connection::~Connection() { } // sendRequest and wait for it to finished. -std::unique_ptr Connection::sendRequest( - std::unique_ptr request) { +std::unique_ptr Connection::sendRequest(std::unique_ptr request) { FUERTE_LOG_TRACE << "sendRequest (sync): before send" << std::endl; WaitGroup wg; - auto rv = std::unique_ptr(nullptr); + std::unique_ptr rv; ::arangodb::fuerte::v1::Error error = Error::NoError; auto cb = [&](::arangodb::fuerte::v1::Error e, @@ -69,11 +68,14 @@ std::unique_ptr Connection::sendRequest( std::string Connection::endpoint() const { std::string endpoint; - endpoint.reserve(16); + endpoint.reserve(32); + // http/vst endpoint.append(fuerte::to_string(_config._protocolType)); endpoint.push_back('+'); + // tcp/ssl/unix endpoint.append(fuerte::to_string(_config._socketType)); endpoint.append("://"); + // domain name or IP (xxx.xxx.xxx.xxx) endpoint.append(_config._host); if (_config._socketType != SocketType::Unix) { endpoint.push_back(':'); diff --git a/arangosh/Shell/V8ClientConnection.cpp b/arangosh/Shell/V8ClientConnection.cpp index e2b6d0cced..5b0bdad361 100644 --- a/arangosh/Shell/V8ClientConnection.cpp +++ b/arangosh/Shell/V8ClientConnection.cpp @@ -161,12 +161,12 @@ std::shared_ptr V8ClientConnection::createConnection() { return newConnection; } } + return _connection; } catch (fuerte::Error const& e) { // connection error _lastErrorMessage = fuerte::to_string(e); _lastHttpReturnCode = 503; + return nullptr; } - - return nullptr; } std::shared_ptr V8ClientConnection::acquireConnection() { @@ -175,7 +175,9 @@ std::shared_ptr V8ClientConnection::acquireConnection() { _lastErrorMessage = ""; _lastHttpReturnCode = 0; - if (!_connection || _connection->state() == fuerte::Connection::State::Failed) { + if (!_connection || + (_connection->state() == fuerte::Connection::State::Disconnected || + _connection->state() == fuerte::Connection::State::Failed)) { return createConnection(); } return _connection; @@ -186,7 +188,8 @@ void V8ClientConnection::setInterrupted(bool interrupted) { if (interrupted && _connection != nullptr) { shutdownConnection(); } else if (!interrupted && (_connection == nullptr || - _connection->state() == fuerte::Connection::State::Failed)) { + (_connection->state() == fuerte::Connection::State::Disconnected || + _connection->state() == fuerte::Connection::State::Failed))) { createConnection(); } } @@ -218,7 +221,6 @@ void V8ClientConnection::timeout(double value) { } void V8ClientConnection::connect(ClientFeature* client) { - TRI_ASSERT(client); std::lock_guard guard(_lock); _forceJson = client->forceJson(); @@ -1514,6 +1516,9 @@ v8::Local V8ClientConnection::requestData( v8::Local const& body, std::unordered_map const& headerFields, bool isFile) { + bool retry = true; + +again: auto req = std::make_unique(); req->header.restVerb = method; req->header.database = _databaseName; @@ -1589,21 +1594,30 @@ v8::Local V8ClientConnection::requestData( return v8::Undefined(isolate); } + fuerte::Error rc = fuerte::Error::NoError; std::unique_ptr response; try { response = connection->sendRequest(std::move(req)); } catch (fuerte::Error const& ec) { - return handleResult(isolate, nullptr, ec); + rc = ec; + } + + if (rc == fuerte::Error::ConnectionClosed && retry) { + retry = false; + goto again; } - return handleResult(isolate, std::move(response), fuerte::Error::NoError); + return handleResult(isolate, std::move(response), rc); } v8::Local V8ClientConnection::requestDataRaw( v8::Isolate* isolate, fuerte::RestVerb method, arangodb::velocypack::StringRef const& location, v8::Local const& body, std::unordered_map const& headerFields) { + + bool retry = true; +again: auto req = std::make_unique(); req->header.restVerb = method; req->header.database = _databaseName; @@ -1651,20 +1665,26 @@ v8::Local V8ClientConnection::requestDataRaw( req->timeout(std::chrono::duration_cast(_requestTimeout)); std::shared_ptr connection = acquireConnection(); - if (!connection || connection->state() == fuerte::Connection::State::Failed) { TRI_V8_SET_EXCEPTION_MESSAGE(TRI_ERROR_SIMPLE_CLIENT_COULD_NOT_CONNECT, "not connected"); return v8::Undefined(isolate); } + fuerte::Error rc = fuerte::Error::NoError; std::unique_ptr response; try { response = connection->sendRequest(std::move(req)); } catch (fuerte::Error const& e) { + rc = e; _lastErrorMessage.assign(fuerte::to_string(e)); _lastHttpReturnCode = 503; } + + if (rc == fuerte::Error::ConnectionClosed && retry) { + retry = false; + goto again; + } v8::Local result = v8::Object::New(isolate); if (!response) {