diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 15b7a9033..7bf3882a3 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -42,6 +42,7 @@ jobs: topology: - single - cluster + - active-failover steps: - uses: actions/checkout@v1 diff --git a/ChangeLog.md b/ChangeLog.md index c3424611b..8e7aad555 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## [Unreleased] +- fixed active failover behavior for the asynchronous driver + ## [6.10.0] - 2021-03-27 - closing VST connection after 3 consecutive keepAlive failures (#ES-837) diff --git a/docker/clean_active-failover.sh b/docker/clean_active-failover.sh new file mode 100755 index 000000000..8aa365983 --- /dev/null +++ b/docker/clean_active-failover.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +for c in server1 \ + server2 \ + server3; do + docker rm -f $c +done diff --git a/docker/start_db_active-failover.sh b/docker/start_db_active-failover.sh new file mode 100755 index 000000000..05653b54a --- /dev/null +++ b/docker/start_db_active-failover.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +# USAGE: +# export ARANGO_LICENSE_KEY= +# ./start_active-failover.sh + +# EXAMPLE: +# ./start_active-failover.sh docker.io/arangodb/arangodb:3.7.10 + +docker pull "$1" + +LOCATION=$(pwd)/$(dirname "$0") + +docker network create arangodb --subnet 172.28.0.0/16 + +echo "Averysecretword" >"$LOCATION"/jwtSecret +docker run --rm -v "$LOCATION"/jwtSecret:/jwtSecret "$1" arangodb auth header --auth.jwt-secret /jwtSecret >"$LOCATION"/jwtHeader +AUTHORIZATION_HEADER=$(cat "$LOCATION"/jwtHeader) + +echo "Starting containers..." + +docker run -d -v "$LOCATION"/jwtSecret:/jwtSecret -e ARANGO_LICENSE_KEY="$ARANGO_LICENSE_KEY" --network arangodb --ip 172.28.3.1 --name server1 "$1" sh -c 'arangodb --starter.address=$(hostname -i) --starter.mode=activefailover --starter.join server1,server2,server3 --auth.jwt-secret /jwtSecret' +docker run -d -v "$LOCATION"/jwtSecret:/jwtSecret -e ARANGO_LICENSE_KEY="$ARANGO_LICENSE_KEY" --network arangodb --ip 172.28.3.2 --name server2 "$1" sh -c 'arangodb --starter.address=$(hostname -i) --starter.mode=activefailover --starter.join server1,server2,server3 --auth.jwt-secret /jwtSecret' +docker run -d -v "$LOCATION"/jwtSecret:/jwtSecret -e ARANGO_LICENSE_KEY="$ARANGO_LICENSE_KEY" --network arangodb --ip 172.28.3.3 --name server3 "$1" sh -c 'arangodb --starter.address=$(hostname -i) --starter.mode=activefailover --starter.join server1,server2,server3 --auth.jwt-secret /jwtSecret' + +debug_container() { + running=$(docker inspect -f '{{.State.Running}}' "$1") + + if [ "$running" = false ]; then + echo "$1 is not running!" + echo "---" + docker logs "$1" + echo "---" + exit 1 + fi +} + +debug() { + for c in server1 \ + server2 \ + server3; do + debug_container $c + done +} + +wait_server() { + # shellcheck disable=SC2091 + until $(curl --output /dev/null --silent --head --fail -i -H "$AUTHORIZATION_HEADER" "http://$1/_api/version"); do + printf '.' + debug + sleep 1 + done +} + +echo "Waiting..." + +# Wait for agents: +for a in 172.28.3.1:8529 \ + 172.28.3.2:8529 \ + 172.28.3.3:8529; do + wait_server $a +done + +docker exec server1 arangosh --server.authentication=false --javascript.execute-string='require("org/arangodb/users").update("root", "test")' +docker exec server2 arangosh --server.authentication=false --javascript.execute-string='require("org/arangodb/users").update("root", "test")' +docker exec server3 arangosh --server.authentication=false --javascript.execute-string='require("org/arangodb/users").update("root", "test")' + +#rm "$LOCATION"/jwtHeader "$LOCATION"/jwtSecret + +echo "Done, your cluster is ready." diff --git a/docker/start_db_active-failover_retry_fail.sh b/docker/start_db_active-failover_retry_fail.sh new file mode 100755 index 000000000..a0b31603e --- /dev/null +++ b/docker/start_db_active-failover_retry_fail.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# USAGE: +# export ARANGO_LICENSE_KEY= +# ./docker/start_db_active-failover_retry_fail.sh + +# EXAMPLE: +# ./docker/start_db_active-failover_retry_fail.sh docker.io/arangodb/arangodb:3.7.10 + +./docker/start_db_active-failover.sh "$1" +while [ $? -ne 0 ]; do + echo "=== === ===" + echo "active-failover startup failed, retrying ..." + ./docker/clean_active-failover.sh + ./docker/start_db_active-failover.sh "$1" +done diff --git a/src/main/java/com/arangodb/ArangoDB.java b/src/main/java/com/arangodb/ArangoDB.java index 55859c819..1f63c6013 100644 --- a/src/main/java/com/arangodb/ArangoDB.java +++ b/src/main/java/com/arangodb/ArangoDB.java @@ -286,6 +286,7 @@ public Builder keepAliveInterval(final Integer keepAliveInterval) { /** * Whether or not the driver should acquire a list of available coordinators in an ArangoDB cluster or a single * server with active failover. + * In case of Active-Failover deployment set to {@code true} to enable automatic master discovery. * *

* The host list will be used for failover and load balancing. @@ -312,6 +313,8 @@ public Builder acquireHostListInterval(final Integer acquireHostListInterval) { /** * Sets the load balancing strategy to be used in an ArangoDB cluster setup. + * In case of Active-Failover deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that + * would be the default. * * @param loadBalancingStrategy the load balancing strategy to be used (default: {@link LoadBalancingStrategy#NONE} * @return {@link ArangoDB.Builder} diff --git a/src/main/java/com/arangodb/async/ArangoDBAsync.java b/src/main/java/com/arangodb/async/ArangoDBAsync.java index 888e616c8..002ff5db8 100644 --- a/src/main/java/com/arangodb/async/ArangoDBAsync.java +++ b/src/main/java/com/arangodb/async/ArangoDBAsync.java @@ -442,6 +442,7 @@ public Builder keepAliveInterval(final Integer keepAliveInterval) { /** * Whether or not the driver should acquire a list of available coordinators in an ArangoDB cluster or a single * server with active failover. + * In case of Active-Failover deployment set to {@code true} to enable automatic master discovery. * *

* The host list will be used for failover and load balancing. @@ -457,6 +458,8 @@ public Builder acquireHostList(final Boolean acquireHostList) { /** * Sets the load balancing strategy to be used in an ArangoDB cluster setup. + * In case of Active-Failover deployment set to {@link LoadBalancingStrategy#NONE} or not set at all, since that + * would be the default. * * @param loadBalancingStrategy the load balancing strategy to be used (default: {@link LoadBalancingStrategy#NONE} * @return {@link ArangoDBAsync.Builder} diff --git a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java index c597de11c..e86e2cf0a 100644 --- a/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java +++ b/src/main/java/com/arangodb/async/internal/velocystream/VstCommunicationAsync.java @@ -21,8 +21,11 @@ package com.arangodb.async.internal.velocystream; import com.arangodb.ArangoDBException; -import com.arangodb.entity.ErrorEntity; +import com.arangodb.internal.net.ArangoDBRedirectException; +import com.arangodb.internal.net.HostDescription; +import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; +import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.velocystream.VstCommunication; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.Message; @@ -58,23 +61,37 @@ protected CompletableFuture execute(final Request request, final VstCo final Message message = createMessage(request); send(message, connection).whenComplete((m, ex) -> { if (m != null) { + final Response response; try { - final Response response = createResponse(m); - if (response.getResponseCode() >= 300) { - if (response.getBody() != null) { - final ErrorEntity errorEntity = util.deserialize(response.getBody(), ErrorEntity.class); - rfuture.completeExceptionally(new ArangoDBException(errorEntity)); - } else { - rfuture.completeExceptionally(new ArangoDBException( - String.format("Response Code: %s", response.getResponseCode()), response.getResponseCode())); - } - } else { - rfuture.complete(response); - } + response = createResponse(m); } catch (final VPackParserException e) { LOGGER.error(e.getMessage(), e); rfuture.completeExceptionally(e); + return; } + + try { + checkError(response); + } catch (final ArangoDBRedirectException e) { + final String location = e.getLocation(); + final HostDescription redirectHost = HostUtils.createFromLocation(location); + hostHandler.closeCurrentOnError(); + hostHandler.fail(); + execute(request, new HostHandle().setHost(redirectHost)) + .whenComplete((v, err) -> { + if (v != null) { + rfuture.complete(v); + } else if (err != null) { + rfuture.completeExceptionally(err); + } else { + rfuture.cancel(true); + } + }); + return; + } catch (ArangoDBException e) { + rfuture.completeExceptionally(e); + } + rfuture.complete(response); } else if (ex != null) { LOGGER.error(ex.getMessage(), ex); rfuture.completeExceptionally(ex); diff --git a/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java b/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java index f71ff6da7..43ab86d86 100644 --- a/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java +++ b/src/main/java/com/arangodb/internal/net/ConnectionPoolImpl.java @@ -79,7 +79,7 @@ public synchronized Connection connection() { } @Override - public void close() throws IOException { + public synchronized void close() throws IOException { for (final Connection connection : connections) { connection.close(); } diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java index 97d9f0ba7..3fedb48a3 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunication.java @@ -23,12 +23,9 @@ import com.arangodb.ArangoDBException; import com.arangodb.internal.ArangoDefaults; import com.arangodb.internal.net.AccessType; -import com.arangodb.internal.net.ArangoDBRedirectException; import com.arangodb.internal.net.Host; -import com.arangodb.internal.net.HostDescription; import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; -import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.util.RequestUtils; import com.arangodb.internal.util.ResponseUtils; import com.arangodb.internal.velocystream.internal.Chunk; @@ -64,7 +61,7 @@ public abstract class VstCommunication implements Cl protected final String password; protected final Integer chunksize; - private final HostHandler hostHandler; + protected final HostHandler hostHandler; protected VstCommunication(final Integer timeout, final String user, final String password, final Boolean useSsl, final SSLContext sslContext, final ArangoSerialization util, final Integer chunksize, @@ -134,20 +131,8 @@ public void close() throws IOException { } public R execute(final Request request, final HostHandle hostHandle) throws ArangoDBException { - try { - final C connection = connect(hostHandle, RequestUtils.determineAccessType(request)); - return execute(request, connection); - } catch (final ArangoDBException e) { - if (e instanceof ArangoDBRedirectException) { - final String location = ((ArangoDBRedirectException) e).getLocation(); - final HostDescription redirectHost = HostUtils.createFromLocation(location); - hostHandler.closeCurrentOnError(); - hostHandler.fail(); - return execute(request, new HostHandle().setHost(redirectHost)); - } else { - throw e; - } - } + final C connection = connect(hostHandle, RequestUtils.determineAccessType(request)); + return execute(request, connection); } protected abstract R execute(final Request request, C connection) throws ArangoDBException; diff --git a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java index 9cb8472df..36b7bdb91 100644 --- a/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java +++ b/src/main/java/com/arangodb/internal/velocystream/VstCommunicationSync.java @@ -21,7 +21,11 @@ package com.arangodb.internal.velocystream; import com.arangodb.ArangoDBException; +import com.arangodb.internal.net.ArangoDBRedirectException; +import com.arangodb.internal.net.HostDescription; +import com.arangodb.internal.net.HostHandle; import com.arangodb.internal.net.HostHandler; +import com.arangodb.internal.util.HostUtils; import com.arangodb.internal.velocystream.internal.AuthenticationRequest; import com.arangodb.internal.velocystream.internal.Message; import com.arangodb.internal.velocystream.internal.VstConnectionSync; @@ -127,6 +131,12 @@ protected Response execute(final Request request, final VstConnectionSync connec return response; } catch (final VPackParserException e) { throw new ArangoDBException(e); + } catch (final ArangoDBRedirectException e) { + final String location = e.getLocation(); + final HostDescription redirectHost = HostUtils.createFromLocation(location); + hostHandler.closeCurrentOnError(); + hostHandler.fail(); + return execute(request, new HostHandle().setHost(redirectHost)); } } diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java b/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java index 74948b484..657b17bfa 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/MessageStore.java @@ -82,7 +82,7 @@ public void cancel(final long messageId) { } } - public void clear(final Exception e) { + public synchronized void clear(final Exception e) { if (!task.isEmpty()) { LOGGER.error(e.getMessage(), e); } @@ -96,7 +96,7 @@ public void clear(final Exception e) { task.clear(); } - public void clear() { + public synchronized void clear() { for (final Entry> entry : task.entrySet()) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(String.format("Cancel Message (id=%s).", entry.getKey())); diff --git a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java index fac8d0823..e1a656642 100644 --- a/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java +++ b/src/main/java/com/arangodb/internal/velocystream/internal/VstConnection.java @@ -118,14 +118,14 @@ protected VstConnection(final HostDescription host, this.messageStore = messageStore; connectionName = "connection_" + System.currentTimeMillis() + "_" + Math.random(); - LOGGER.debug("Connection " + connectionName + " created"); + LOGGER.debug("[" + connectionName + "]: Connection created"); } protected T sendKeepAlive() { long id = keepAliveId.decrementAndGet(); Message message = new Message(id, keepAliveRequest, null); if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Send keepalive probe (id=%s, head=%s, body=%s)", message.getId(), message.getHead(), + LOGGER.debug(String.format("[%s]: Send keepalive probe (id=%s, head=%s, body=%s)", connectionName, message.getId(), message.getHead(), message.getBody() != null ? message.getBody() : "{}")); } return write(message, Collections.singleton(new Chunk( @@ -162,7 +162,7 @@ public synchronized void open() throws IOException { return; } if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Open connection to %s", host)); + LOGGER.debug(String.format("[%s]: Open connection to %s", connectionName, host)); } if (Boolean.TRUE == useSsl) { if (sslContext != null) { @@ -177,7 +177,7 @@ public synchronized void open() throws IOException { socket.setKeepAlive(true); socket.setTcpNoDelay(true); if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Connected to %s", socket)); + LOGGER.debug(String.format("[%s]: Connected to %s", connectionName, socket)); } outputStream = new BufferedOutputStream(socket.getOutputStream()); @@ -185,7 +185,7 @@ public synchronized void open() throws IOException { if (Boolean.TRUE == useSsl) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Start Handshake on %s", socket)); + LOGGER.debug(String.format("[%s]: Start Handshake on %s", connectionName, socket)); } ((SSLSocket) socket).startHandshake(); } @@ -193,7 +193,7 @@ public synchronized void open() throws IOException { executor = Executors.newSingleThreadExecutor(); executor.submit((Callable) () -> { - LOGGER.debug("Start Callable for " + connectionName); + LOGGER.debug("[" + connectionName + "]: Start Callable"); final long openTime = new Date().getTime(); final Long ttlTime = ttl != null ? openTime + ttl : null; @@ -224,7 +224,7 @@ public synchronized void open() throws IOException { } } - LOGGER.debug("Stop Callable for " + connectionName); + LOGGER.debug("[" + connectionName + "]: Stop Callable"); return null; }); @@ -248,7 +248,7 @@ public synchronized void close() { if (socket != null && !socket.isClosed()) { try { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Close connection %s", socket)); + LOGGER.debug(String.format("[%s]: Close connection %s", connectionName, socket)); } socket.close(); } catch (final IOException e) { @@ -259,7 +259,7 @@ public synchronized void close() { private synchronized void sendProtocolHeader() throws IOException { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Send velocystream protocol header to %s", socket)); + LOGGER.debug(String.format("[%s]: Send velocystream protocol header to %s", connectionName, socket)); } outputStream.write(PROTOCOL_HEADER); outputStream.flush(); @@ -270,7 +270,7 @@ protected synchronized void writeIntern(final Message message, final Collection< for (final Chunk chunk : chunks) { try { if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Send chunk %s:%s from message %s", chunk.getChunk(), + LOGGER.debug(String.format("[%s]: Send chunk %s:%s from message %s", connectionName, chunk.getChunk(), chunk.isFirstChunk() ? 1 : 0, chunk.getMessageId())); sendTimestamps.put(chunk.getMessageId(), System.currentTimeMillis()); } @@ -328,8 +328,8 @@ protected Chunk readChunk() throws IOException { final Chunk chunk = new Chunk(messageId, chunkX, messageLength, 0, contentLength); if (LOGGER.isDebugEnabled()) { - LOGGER.debug(String.format("Received chunk %s:%s from message %s", chunk.getChunk(), chunk.isFirstChunk() ? 1 : 0, chunk.getMessageId())); - LOGGER.debug("Responsetime for Message " + chunk.getMessageId() + " is " + (System.currentTimeMillis() - sendTimestamps.get(chunk.getMessageId()))); + LOGGER.debug(String.format("[%s]: Received chunk %s:%s from message %s", connectionName, chunk.getChunk(), chunk.isFirstChunk() ? 1 : 0, chunk.getMessageId())); + LOGGER.debug("[" + connectionName + "]: Responsetime for Message " + chunk.getMessageId() + " is " + (System.currentTimeMillis() - sendTimestamps.get(chunk.getMessageId()))); } return chunk; diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index a732cbfa2..b4f4cf7d8 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -410,9 +410,10 @@ public void getDocumentWrongKey() { } @Test - public void getDocumentDirtyRead() { + public void getDocumentDirtyRead() throws InterruptedException { final BaseDocument doc = new BaseDocument(); - collection.insertDocument(doc); + collection.insertDocument(doc, new DocumentCreateOptions()); + Thread.sleep(2000); final VPackSlice document = collection .getDocument(doc.getKey(), VPackSlice.class, new DocumentReadOptions().allowDirtyRead(true)); assertThat(document, is(notNullValue())); diff --git a/src/test/java/com/arangodb/ArangoDBTest.java b/src/test/java/com/arangodb/ArangoDBTest.java index 280b452ca..b22d77540 100644 --- a/src/test/java/com/arangodb/ArangoDBTest.java +++ b/src/test/java/com/arangodb/ArangoDBTest.java @@ -175,7 +175,7 @@ public void createDatabaseWithOptionsSatellite() { } @Test - public void createDatabaseWithUsers() { + public void createDatabaseWithUsers() throws InterruptedException { final String dbName = "testDB-" + UUID.randomUUID().toString(); final Map extra = Collections.singletonMap("key", "value"); final Boolean resultCreate = arangoDB.createDatabase(new DBCreateOptions() @@ -201,6 +201,9 @@ public void createDatabaseWithUsers() { assertThat(retrievedUser.getActive(), is(true)); assertThat(retrievedUser.getExtra(), is(extra)); + // needed for active-failover tests only + Thread.sleep(1_000); + ArangoDB arangoDBTestUser = new ArangoDB.Builder() .user("testUser") .password("testPasswd") @@ -392,6 +395,7 @@ public void execute() throws VPackException { @Test public void getLogs() { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final LogEntity logs = arangoDB.getLogs(null); assertThat(logs, is(notNullValue())); assertThat(logs.getTotalAmount(), greaterThan(0L)); @@ -403,6 +407,7 @@ public void getLogs() { @Test public void getLogsUpto() { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final LogEntity logsUpto = arangoDB.getLogs(new LogOptions().upto(LogLevel.WARNING)); assertThat(logsUpto, is(notNullValue())); assertThat(logsUpto.getLevel(), not(contains(LogLevel.INFO))); @@ -410,6 +415,7 @@ public void getLogsUpto() { @Test public void getLogsLevel() { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final LogEntity logsInfo = arangoDB.getLogs(new LogOptions().level(LogLevel.INFO)); assertThat(logsInfo, is(notNullValue())); assertThat(logsInfo.getLevel(), everyItem(is(LogLevel.INFO))); @@ -417,6 +423,7 @@ public void getLogsLevel() { @Test public void getLogsStart() { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final LogEntity logs = arangoDB.getLogs(null); assertThat(logs.getLid(), not(empty())); final LogEntity logsStart = arangoDB.getLogs(new LogOptions().start(logs.getLid().get(0) + 1)); @@ -426,6 +433,7 @@ public void getLogsStart() { @Test public void getLogsSize() { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final LogEntity logs = arangoDB.getLogs(null); assertThat(logs.getLid().size(), greaterThan(0)); final LogEntity logsSize = arangoDB.getLogs(new LogOptions().size(logs.getLid().size() - 1)); @@ -435,6 +443,7 @@ public void getLogsSize() { @Test public void getLogsOffset() { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final LogEntity logs = arangoDB.getLogs(null); assertThat(logs.getTotalAmount(), greaterThan(0L)); final LogEntity logsOffset = arangoDB.getLogs(new LogOptions().offset(1)); @@ -444,6 +453,7 @@ public void getLogsOffset() { @Test public void getLogsSearch() { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final LogEntity logs = arangoDB.getLogs(null); final LogEntity logsSearch = arangoDB.getLogs(new LogOptions().search(BaseTest.TEST_DB)); assertThat(logsSearch, is(notNullValue())); @@ -452,6 +462,7 @@ public void getLogsSearch() { @Test public void getLogsSortAsc() { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final LogEntity logs = arangoDB.getLogs(new LogOptions().sort(SortOrder.asc)); assertThat(logs, is(notNullValue())); long lastId = -1; @@ -463,6 +474,7 @@ public void getLogsSortAsc() { @Test public void getLogsSortDesc() { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final LogEntity logs = arangoDB.getLogs(new LogOptions().sort(SortOrder.desc)); assertThat(logs, is(notNullValue())); long lastId = Long.MAX_VALUE; @@ -474,6 +486,7 @@ public void getLogsSortDesc() { @Test public void getLogLevel() { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final LogLevelEntity logLevel = arangoDB.getLogLevel(); assertThat(logLevel, is(notNullValue())); assertThat(logLevel.getAgency(), is(LogLevelEntity.LogLevel.INFO)); @@ -481,6 +494,7 @@ public void getLogLevel() { @Test public void setLogLevel() { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final LogLevelEntity entity = new LogLevelEntity(); try { entity.setAgency(LogLevelEntity.LogLevel.ERROR); diff --git a/src/test/java/com/arangodb/async/ArangoDBTest.java b/src/test/java/com/arangodb/async/ArangoDBTest.java index 25f23a022..35227a5b8 100644 --- a/src/test/java/com/arangodb/async/ArangoDBTest.java +++ b/src/test/java/com/arangodb/async/ArangoDBTest.java @@ -462,6 +462,7 @@ public void execute_acquireHostList_enabled() throws VPackException, Interrupted @Test public void getLogs() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); arangoDB.getLogs(null) .whenComplete((logs, ex) -> { @@ -477,6 +478,7 @@ public void getLogs() throws InterruptedException, ExecutionException { @Test public void getLogsUpto() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); final LogEntity logs = arangoDB.getLogs(null).get(); arangoDB.getLogs(new LogOptions().upto(LogLevel.WARNING)) @@ -490,6 +492,7 @@ public void getLogsUpto() throws InterruptedException, ExecutionException { @Test public void getLogsLevel() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); final LogEntity logs = arangoDB.getLogs(null).get(); arangoDB.getLogs(new LogOptions().level(LogLevel.INFO)) @@ -503,6 +506,7 @@ public void getLogsLevel() throws InterruptedException, ExecutionException { @Test public void getLogsStart() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); final LogEntity logs = arangoDB.getLogs(null).get(); assertThat(logs.getLid(), not(empty())); @@ -516,6 +520,7 @@ public void getLogsStart() throws InterruptedException, ExecutionException { @Test public void getLogsSize() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); final LogEntity logs = arangoDB.getLogs(null).get(); assertThat(logs.getLid().size(), greaterThan(0)); @@ -529,6 +534,7 @@ public void getLogsSize() throws InterruptedException, ExecutionException { @Test public void getLogsOffset() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); final LogEntity logs = arangoDB.getLogs(null).get(); assertThat(logs.getTotalAmount(), greaterThan(0L)); @@ -542,6 +548,7 @@ public void getLogsOffset() throws InterruptedException, ExecutionException { @Test public void getLogsSearch() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); final LogEntity logs = arangoDB.getLogs(null).get(); arangoDB.getLogs(new LogOptions().search(BaseTest.TEST_DB)) @@ -554,6 +561,7 @@ public void getLogsSearch() throws InterruptedException, ExecutionException { @Test public void getLogsSortAsc() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); arangoDB.getLogs(new LogOptions().sort(SortOrder.asc)) .whenComplete((logs, ex) -> { @@ -569,6 +577,7 @@ public void getLogsSortAsc() throws InterruptedException, ExecutionException { @Test public void getLogsSortDesc() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); arangoDB.getLogs(new LogOptions().sort(SortOrder.desc)) .whenComplete((logs, ex) -> { @@ -584,6 +593,7 @@ public void getLogsSortDesc() throws InterruptedException, ExecutionException { @Test public void getLogLevel() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); arangoDB.getLogLevel() .whenComplete((logLevel, ex) -> { @@ -595,6 +605,7 @@ public void getLogLevel() throws InterruptedException, ExecutionException { @Test public void setLogLevel() throws InterruptedException, ExecutionException { + assumeTrue(isAtLeastVersion(3, 7)); // it fails in 3.6 active-failover (BTS-362) final ArangoDBAsync arangoDB = new ArangoDBAsync.Builder().build(); final LogLevelEntity entity = new LogLevelEntity(); try { diff --git a/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java b/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java index f8eba33d0..cf5fc53b6 100644 --- a/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java +++ b/src/test/java/com/arangodb/async/StreamTransactionGraphTest.java @@ -169,7 +169,7 @@ public void replaceVertex() throws ExecutionException, InterruptedException { doc.getProperties().clear(); doc.addAttribute("test", "bar"); vertexCollection1.replaceVertex(createdVertex.getKey(), doc, - new VertexReplaceOptions().streamTransactionId(tx.getId())); + new VertexReplaceOptions().streamTransactionId(tx.getId())).get(); // assert that the vertex has not been replaced from outside the tx assertThat(vertexCollection1.getVertex(createdVertex.getKey(), BaseDocument.class, null).get() @@ -205,7 +205,7 @@ public void updateVertex() throws ExecutionException, InterruptedException { // update vertex from within the tx doc.getProperties().clear(); doc.addAttribute("test", "bar"); - vertexCollection1.updateVertex(createdDoc.getKey(), doc, new VertexUpdateOptions().streamTransactionId(tx.getId())); + vertexCollection1.updateVertex(createdDoc.getKey(), doc, new VertexUpdateOptions().streamTransactionId(tx.getId())).get(); // assert that the vertex has not been updated from outside the tx assertThat(vertexCollection1.getVertex(createdDoc.getKey(), BaseDocument.class, null).get() @@ -322,7 +322,7 @@ public void replaceEdge() throws ExecutionException, InterruptedException { doc.getProperties().clear(); doc.addAttribute("test", "bar"); edgeCollection.replaceEdge(createdEdge.getKey(), doc, - new EdgeReplaceOptions().streamTransactionId(tx.getId())); + new EdgeReplaceOptions().streamTransactionId(tx.getId())).get(); // assert that the edge has not been replaced from outside the tx assertThat(edgeCollection.getEdge(createdEdge.getKey(), BaseEdgeDocument.class, null).get() diff --git a/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java b/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java index 51ef5a507..87e8e5db9 100644 --- a/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java +++ b/src/test/java/com/arangodb/internal/velocystream/CommunicationTest.java @@ -52,7 +52,7 @@ public void chunkSizeSmall() { @Test public void multiThread() throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder().build(); - arangoDB.getVersion();// authentication + arangoDB.getUsers(); // authentication and active-failover connection redirect to master final Collection result = new ConcurrentLinkedQueue<>(); final Thread fast = new Thread(() -> { @@ -78,7 +78,7 @@ public void multiThread() throws Exception { @Test public void multiThreadSameDatabases() throws Exception { final ArangoDB arangoDB = new ArangoDB.Builder().build(); - arangoDB.getVersion();// authentication + arangoDB.getUsers(); // authentication and active-failover connection redirect to master final ArangoDatabase db = arangoDB.db(); diff --git a/src/test/resources/arangodb.properties b/src/test/resources/arangodb.properties index 222fbb05a..f188baa57 100644 --- a/src/test/resources/arangodb.properties +++ b/src/test/resources/arangodb.properties @@ -1,4 +1,4 @@ arangodb.hosts=172.28.3.1:8529 arangodb.connections.max=1 -arangodb.acquireHostList=false +arangodb.acquireHostList=true arangodb.password=test