Skip to content

Feature/vst keep alive #370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions src/main/java/com/arangodb/ArangoDB.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,25 @@

package com.arangodb;

import com.arangodb.entity.*;
import com.arangodb.entity.ArangoDBEngine;
import com.arangodb.entity.ArangoDBVersion;
import com.arangodb.entity.LoadBalancingStrategy;
import com.arangodb.entity.LogEntity;
import com.arangodb.entity.LogLevelEntity;
import com.arangodb.entity.Permissions;
import com.arangodb.entity.ServerRole;
import com.arangodb.entity.UserEntity;
import com.arangodb.internal.ArangoContext;
import com.arangodb.internal.ArangoDBImpl;
import com.arangodb.internal.ArangoDefaults;
import com.arangodb.internal.InternalArangoDBBuilder;
import com.arangodb.internal.http.HttpCommunication;
import com.arangodb.internal.http.HttpConnectionFactory;
import com.arangodb.internal.net.*;
import com.arangodb.internal.net.ConnectionFactory;
import com.arangodb.internal.net.Host;
import com.arangodb.internal.net.HostHandle;
import com.arangodb.internal.net.HostHandler;
import com.arangodb.internal.net.HostResolver;
import com.arangodb.internal.util.ArangoDeserializerImpl;
import com.arangodb.internal.util.ArangoSerializationFactory;
import com.arangodb.internal.util.ArangoSerializerImpl;
Expand All @@ -42,7 +53,18 @@
import com.arangodb.util.ArangoDeserializer;
import com.arangodb.util.ArangoSerialization;
import com.arangodb.util.ArangoSerializer;
import com.arangodb.velocypack.*;
import com.arangodb.velocypack.VPack;
import com.arangodb.velocypack.VPackAnnotationFieldFilter;
import com.arangodb.velocypack.VPackAnnotationFieldNaming;
import com.arangodb.velocypack.VPackDeserializer;
import com.arangodb.velocypack.VPackInstanceCreator;
import com.arangodb.velocypack.VPackJsonDeserializer;
import com.arangodb.velocypack.VPackJsonSerializer;
import com.arangodb.velocypack.VPackModule;
import com.arangodb.velocypack.VPackParser;
import com.arangodb.velocypack.VPackParserModule;
import com.arangodb.velocypack.VPackSerializer;
import com.arangodb.velocypack.ValueType;
import com.arangodb.velocystream.Request;
import com.arangodb.velocystream.Response;
import org.apache.http.client.HttpRequestRetryHandler;
Expand Down Expand Up @@ -248,6 +270,19 @@ public Builder connectionTtl(final Long connectionTtl) {
return this;
}

/**
* Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request every
* {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the external
* environment, eg. firewall, intermediate routers, operating system).
*
* @param keepAliveInterval interval in seconds
* @return {@link ArangoDB.Builder}
*/
public Builder keepAliveInterval(final Integer keepAliveInterval) {
setKeepAliveInterval(keepAliveInterval);
return this;
}

/**
* Whether or not the driver should acquire a list of available coordinators in an ArangoDB cluster or a single
* server with active failover.
Expand Down Expand Up @@ -600,7 +635,7 @@ public synchronized ArangoDB build() {
final int max = maxConnections != null ? Math.max(1, maxConnections) : protocolMaxConnections;

final ConnectionFactory connectionFactory = (protocol == null || Protocol.VST == protocol)
? new VstConnectionFactorySync(host, timeout, connectionTtl, useSsl, sslContext)
? new VstConnectionFactorySync(host, timeout, connectionTtl, keepAliveInterval, useSsl, sslContext)
: new HttpConnectionFactory(timeout, user, password, useSsl, sslContext, hostnameVerifier, custom,
protocol, connectionTtl, httpCookieSpec, httpRequestRetryHandler);

Expand Down
36 changes: 33 additions & 3 deletions src/main/java/com/arangodb/async/ArangoDBAsync.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@
import com.arangodb.async.internal.ArangoDBAsyncImpl;
import com.arangodb.async.internal.velocystream.VstCommunicationAsync;
import com.arangodb.async.internal.velocystream.VstConnectionFactoryAsync;
import com.arangodb.entity.*;
import com.arangodb.entity.ArangoDBVersion;
import com.arangodb.entity.LoadBalancingStrategy;
import com.arangodb.entity.LogEntity;
import com.arangodb.entity.LogLevelEntity;
import com.arangodb.entity.Permissions;
import com.arangodb.entity.ServerRole;
import com.arangodb.entity.UserEntity;
import com.arangodb.internal.ArangoContext;
import com.arangodb.internal.ArangoDefaults;
import com.arangodb.internal.InternalArangoDBBuilder;
Expand All @@ -45,7 +51,18 @@
import com.arangodb.util.ArangoDeserializer;
import com.arangodb.util.ArangoSerialization;
import com.arangodb.util.ArangoSerializer;
import com.arangodb.velocypack.*;
import com.arangodb.velocypack.VPack;
import com.arangodb.velocypack.VPackAnnotationFieldFilter;
import com.arangodb.velocypack.VPackAnnotationFieldNaming;
import com.arangodb.velocypack.VPackDeserializer;
import com.arangodb.velocypack.VPackInstanceCreator;
import com.arangodb.velocypack.VPackJsonDeserializer;
import com.arangodb.velocypack.VPackJsonSerializer;
import com.arangodb.velocypack.VPackModule;
import com.arangodb.velocypack.VPackParser;
import com.arangodb.velocypack.VPackParserModule;
import com.arangodb.velocypack.VPackSerializer;
import com.arangodb.velocypack.ValueType;
import com.arangodb.velocystream.Request;
import com.arangodb.velocystream.Response;

Expand Down Expand Up @@ -408,6 +425,19 @@ public Builder connectionTtl(final Long connectionTtl) {
return this;
}

/**
* Set the keep-alive interval for VST connections. If set, every VST connection will perform a no-op request every
* {@code keepAliveInterval} seconds, to avoid to be closed due to inactivity by the server (or by the external
* environment, eg. firewall, intermediate routers, operating system).
*
* @param keepAliveInterval interval in seconds
* @return {@link ArangoDBAsync.Builder}
*/
public Builder keepAliveInterval(final Integer keepAliveInterval) {
setKeepAliveInterval(keepAliveInterval);
return this;
}

/**
* Whether or not the driver should acquire a list of available coordinators in an ArangoDB cluster or a single
* server with active failover.
Expand Down Expand Up @@ -746,7 +776,7 @@ public synchronized ArangoDBAsync build() {
final int max = maxConnections != null ? Math.max(1, maxConnections)
: ArangoDefaults.MAX_CONNECTIONS_VST_DEFAULT;
final ConnectionFactory connectionFactory = new VstConnectionFactoryAsync(host, timeout, connectionTtl,
useSsl, sslContext);
keepAliveInterval, useSsl, sslContext);
final HostResolver hostResolver = createHostResolver(createHostList(max, connectionFactory), max,
connectionFactory);
final HostHandler hostHandler = createHostHandler(hostResolver);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@
/**
* @author Mark Vollmary
*/
public class VstConnectionAsync extends VstConnection {
public class VstConnectionAsync extends VstConnection<CompletableFuture<Message>> {

private VstConnectionAsync(final HostDescription host, final Integer timeout, final Long ttl, final Boolean useSsl,
final SSLContext sslContext, final MessageStore messageStore) {
super(host, timeout, ttl, useSsl, sslContext, messageStore);
private VstConnectionAsync(final HostDescription host, final Integer timeout, final Long ttl, final Integer keepAliveInterval,
final Boolean useSsl, final SSLContext sslContext, final MessageStore messageStore) {
super(host, timeout, ttl, keepAliveInterval, useSsl, sslContext, messageStore);
}

@Override
public synchronized CompletableFuture<Message> write(final Message message, final Collection<Chunk> chunks) {
final CompletableFuture<Message> future = new CompletableFuture<>();
final FutureTask<Message> task = new FutureTask<>(() -> {
Expand All @@ -56,12 +57,18 @@ public synchronized CompletableFuture<Message> write(final Message message, fina
return future;
}

@Override
protected void doKeepAlive() {
sendKeepAlive().join();
}

public static class Builder {

private MessageStore messageStore;
private HostDescription host;
private Integer timeout;
private Long ttl;
private Integer keepAliveInterval;
private Boolean useSsl;
private SSLContext sslContext;

Expand Down Expand Up @@ -89,6 +96,11 @@ public Builder ttl(final Long ttl) {
return this;
}

public Builder keepAliveInterval(final Integer keepAliveInterval) {
this.keepAliveInterval = keepAliveInterval;
return this;
}

public Builder useSsl(final Boolean useSsl) {
this.useSsl = useSsl;
return this;
Expand All @@ -100,7 +112,7 @@ public Builder sslContext(final SSLContext sslContext) {
}

public VstConnectionAsync build() {
return new VstConnectionAsync(host, timeout, ttl, useSsl, sslContext, messageStore);
return new VstConnectionAsync(host, timeout, ttl, keepAliveInterval, useSsl, sslContext, messageStore);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ public class VstConnectionFactoryAsync implements ConnectionFactory {
private final VstConnectionAsync.Builder builder;

public VstConnectionFactoryAsync(final HostDescription host, final Integer timeout, final Long connectionTtl,
final Boolean useSsl, final SSLContext sslContext) {
final Integer keepAliveInterval, final Boolean useSsl, final SSLContext sslContext) {
super();
builder = new VstConnectionAsync.Builder().timeout(timeout).ttl(connectionTtl).useSsl(useSsl)
builder = new VstConnectionAsync.Builder().timeout(timeout).ttl(connectionTtl)
.keepAliveInterval(keepAliveInterval).useSsl(useSsl)
.sslContext(sslContext);
}

Expand Down
26 changes: 25 additions & 1 deletion src/main/java/com/arangodb/internal/InternalArangoDBBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,18 @@
import com.arangodb.ArangoDB;
import com.arangodb.ArangoDBException;
import com.arangodb.entity.LoadBalancingStrategy;
import com.arangodb.internal.net.*;
import com.arangodb.internal.net.Connection;
import com.arangodb.internal.net.ConnectionFactory;
import com.arangodb.internal.net.DirtyReadHostHandler;
import com.arangodb.internal.net.ExtendedHostResolver;
import com.arangodb.internal.net.FallbackHostHandler;
import com.arangodb.internal.net.Host;
import com.arangodb.internal.net.HostDescription;
import com.arangodb.internal.net.HostHandler;
import com.arangodb.internal.net.HostResolver;
import com.arangodb.internal.net.RandomHostHandler;
import com.arangodb.internal.net.RoundRobinHostHandler;
import com.arangodb.internal.net.SimpleHostResolver;
import com.arangodb.internal.util.HostUtils;
import com.arangodb.internal.velocypack.VPackDriverModule;
import com.arangodb.util.ArangoDeserializer;
Expand Down Expand Up @@ -63,6 +74,7 @@ public abstract class InternalArangoDBBuilder {
private static final String PROPERTY_KEY_V_STREAM_CHUNK_CONTENT_SIZE = "arangodb.chunksize";
private static final String PROPERTY_KEY_MAX_CONNECTIONS = "arangodb.connections.max";
private static final String PROPERTY_KEY_CONNECTION_TTL = "arangodb.connections.ttl";
private static final String PROPERTY_KEEP_ALIVE_INTERVAL = "arangodb.connections.keepAlive.interval";
private static final String PROPERTY_KEY_ACQUIRE_HOST_LIST = "arangodb.acquireHostList";
private static final String PROPERTY_KEY_ACQUIRE_HOST_LIST_INTERVAL = "arangodb.acquireHostList.interval";
private static final String PROPERTY_KEY_LOAD_BALANCING_STRATEGY = "arangodb.loadBalancingStrategy";
Expand All @@ -81,6 +93,7 @@ public abstract class InternalArangoDBBuilder {
protected Integer chunksize;
protected Integer maxConnections;
protected Long connectionTtl;
protected Integer keepAliveInterval;
protected final VPack.Builder vpackBuilder;
protected final VPackParser.Builder vpackParserBuilder;
protected ArangoSerializer serializer;
Expand Down Expand Up @@ -135,6 +148,7 @@ protected void loadProperties(final Properties properties) {
chunksize = loadChunkSize(properties, chunksize);
maxConnections = loadMaxConnections(properties, maxConnections);
connectionTtl = loadConnectionTtl(properties, connectionTtl);
keepAliveInterval = loadKeepAliveInterval(properties, keepAliveInterval);
acquireHostList = loadAcquireHostList(properties, acquireHostList);
acquireHostListInterval = loadAcquireHostListInterval(properties, acquireHostListInterval);
loadBalancingStrategy = loadLoadBalancingStrategy(properties, loadBalancingStrategy);
Expand Down Expand Up @@ -184,6 +198,10 @@ protected void setConnectionTtl(final Long connectionTtl) {
this.connectionTtl = connectionTtl;
}

protected void setKeepAliveInterval(final Integer keepAliveInterval) {
this.keepAliveInterval = keepAliveInterval;
}

protected void setAcquireHostList(final Boolean acquireHostList) {
this.acquireHostList = acquireHostList;
}
Expand Down Expand Up @@ -315,6 +333,12 @@ private static Long loadConnectionTtl(final Properties properties, final Long cu
return ttl != null ? Long.parseLong(ttl) : null;
}

private static Integer loadKeepAliveInterval(final Properties properties, final Integer currentValue) {
final String keepAliveInterval = getProperty(properties, PROPERTY_KEEP_ALIVE_INTERVAL, currentValue,
null);
return keepAliveInterval != null ? Integer.parseInt(keepAliveInterval) : null;
}

private static Boolean loadAcquireHostList(final Properties properties, final Boolean currentValue) {
return Boolean.parseBoolean(getProperty(properties, PROPERTY_KEY_ACQUIRE_HOST_LIST, currentValue,
ArangoDefaults.DEFAULT_ACQUIRE_HOST_LIST));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ public class VstConnectionFactorySync implements ConnectionFactory {
private final VstConnectionSync.Builder builder;

public VstConnectionFactorySync(final HostDescription host, final Integer timeout, final Long connectionTtl,
final Boolean useSsl, final SSLContext sslContext) {
final Integer keepAliveInterval, final Boolean useSsl, final SSLContext sslContext) {
super();
builder = new VstConnectionSync.Builder().timeout(timeout).ttl(connectionTtl).useSsl(useSsl)
builder = new VstConnectionSync.Builder().timeout(timeout).ttl(connectionTtl)
.keepAliveInterval(keepAliveInterval).useSsl(useSsl)
.sslContext(sslContext);
}

Expand Down
Loading