Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
*/
public final class DirectConnectionConfig {
// Constants
private static final Boolean DEFAULT_CONNECTION_ENDPOINT_REDISCOVERY_ENABLED = true;
private static final Duration DEFAULT_IDLE_ENDPOINT_TIMEOUT = Duration.ofHours(1l);
private static final Duration DEFAULT_CONNECT_TIMEOUT = Duration.ofSeconds(5L);
private static final Duration DEFAULT_REQUEST_TIMEOUT = Duration.ofSeconds(5L);
private static final int DEFAULT_MAX_CONNECTIONS_PER_ENDPOINT = 130;
private static final int DEFAULT_MAX_REQUESTS_PER_CONNECTION = 30;

private boolean connectionEndpointRediscoveryEnabled;
private Duration connectTimeout;
private Duration idleConnectionTimeout;
private Duration idleEndpointTimeout;
Expand All @@ -32,6 +34,7 @@ public final class DirectConnectionConfig {
* Constructor
*/
public DirectConnectionConfig() {
this.connectionEndpointRediscoveryEnabled = DEFAULT_CONNECTION_ENDPOINT_REDISCOVERY_ENABLED;
this.connectTimeout = DEFAULT_CONNECT_TIMEOUT;
this.idleConnectionTimeout = Duration.ZERO;
this.idleEndpointTimeout = DEFAULT_IDLE_ENDPOINT_TIMEOUT;
Expand All @@ -40,6 +43,47 @@ public DirectConnectionConfig() {
this.requestTimeout = DEFAULT_REQUEST_TIMEOUT;
}

/**
* Gets a value indicating whether Direct TCP connection endpoint rediscovery is enabled.
* <p>
* The connection endpoint rediscovery feature is designed to reduce and spread-out latency spikes that are likely
* to occur:
* <ul>
* <li>During rolling upgrades of a Cosmos instance or
* <li>When a backend node is being decommissioned or restarted (e.g., to restart or remove an unhealthy replica.)
Comment thread
xinlian12 marked this conversation as resolved.
Outdated
* </ul>
*
* By default, connection endpoint rediscovery is enabled.
*
* @return {@code true} if Direct TCP connection endpoint rediscovery is enabled; {@code false} otherwise.
*/
public boolean isConnectionEndpointRediscoveryEnabled() {
Comment thread
xinlian12 marked this conversation as resolved.
return this.connectionEndpointRediscoveryEnabled;
}

/**
* Sets a value indicating whether Direct TCP connection endpoint rediscovery should be enabled.
* <p>
* The connection endpoint rediscovery feature is designed to reduce and spread-out latency spikes that are likely
* to occur:
* <ul>
* <li>During rolling upgrades of a Cosmos instance or
* <li>When a backend node is being decommissioned or restarted (e.g., to restart or remove an unhealthy replica.)
Comment thread
xinlian12 marked this conversation as resolved.
Outdated
* </ul>
*
* By default, connection endpoint rediscovery is enabled.
*
* @param connectionEndpointRediscoveryEnabled {@code true} if connection endpoint rediscovery is enabled; {@code
* false} otherwise.
*
* @return the {@linkplain DirectConnectionConfig}.
*/
public DirectConnectionConfig setConnectionEndpointRediscoveryEnabled(boolean connectionEndpointRediscoveryEnabled) {
Comment thread
xinlian12 marked this conversation as resolved.
this.connectionEndpointRediscoveryEnabled = connectionEndpointRediscoveryEnabled;
return this;
}


/**
* Gets the default DIRECT connection configuration.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ public final class ConnectionPolicy {

// Direct connection config properties
private Duration connectTimeout;
private Duration idleEndpointTimeout;
private Duration idleTcpConnectionTimeout;
private Duration idleTcpEndpointTimeout;
private int maxConnectionsPerEndpoint;
private int maxRequestsPerConnection;
private Duration idleTcpConnectionTimeout;
private boolean tcpConnectionEndpointRediscoveryEnabled;

/**
* Constructor.
Expand All @@ -52,16 +53,18 @@ public ConnectionPolicy(GatewayConnectionConfig gatewayConnectionConfig) {
this.maxConnectionPoolSize = gatewayConnectionConfig.getMaxConnectionPoolSize();
this.requestTimeout = BridgeInternal.getRequestTimeoutFromGatewayConnectionConfig(gatewayConnectionConfig);
this.proxy = gatewayConnectionConfig.getProxy();
this.tcpConnectionEndpointRediscoveryEnabled = true;
}

public ConnectionPolicy(DirectConnectionConfig directConnectionConfig) {
this(ConnectionMode.DIRECT);
this.connectTimeout = directConnectionConfig.getConnectTimeout();
this.idleTcpConnectionTimeout = directConnectionConfig.getIdleConnectionTimeout();
this.idleEndpointTimeout = directConnectionConfig.getIdleEndpointTimeout();
this.idleTcpEndpointTimeout = directConnectionConfig.getIdleEndpointTimeout();
this.maxConnectionsPerEndpoint = directConnectionConfig.getMaxConnectionsPerEndpoint();
this.maxRequestsPerConnection = directConnectionConfig.getMaxRequestsPerConnection();
this.requestTimeout = BridgeInternal.getRequestTimeoutFromDirectConnectionConfig(directConnectionConfig);
this.tcpConnectionEndpointRediscoveryEnabled = directConnectionConfig.isConnectionEndpointRediscoveryEnabled();
}

private ConnectionPolicy(ConnectionMode connectionMode) {
Expand All @@ -75,6 +78,26 @@ private ConnectionPolicy(ConnectionMode connectionMode) {
this.userAgentSuffix = "";
}

/**
* Gets a value that indicates whether Direct TCP connection endpoint rediscovery is enabled.
*
* @return {@code true} if Direct TCP connection endpoint rediscovery should is enabled; {@code false} otherwise.
*/
public boolean isTcpConnectionEndpointRediscoveryEnabled() {
return this.tcpConnectionEndpointRediscoveryEnabled;
}

/**
* Sets a value that indicates whether Direct TCP connection endpoint rediscovery is enabled.
*
* @return the {@linkplain ConnectionPolicy}.
*/
public ConnectionPolicy setTcpConnectionEndpointRediscoveryEnabled(boolean tcpConnectionEndpointRediscoveryEnabled) {
this.tcpConnectionEndpointRediscoveryEnabled = tcpConnectionEndpointRediscoveryEnabled;
return this;
}


/**
* Gets the default connection policy.
*
Expand Down Expand Up @@ -423,17 +446,17 @@ public ConnectionPolicy setConnectTimeout(Duration connectTimeout) {
* Gets the idle endpoint timeout
* @return the idle endpoint timeout
*/
public Duration getIdleEndpointTimeout() {
return idleEndpointTimeout;
public Duration getIdleTcpEndpointTimeout() {
return idleTcpEndpointTimeout;
}

/**
* Sets the idle endpoint timeout
* @param idleEndpointTimeout the idle endpoint timeout
* @param idleTcpEndpointTimeout the idle endpoint timeout
* @return the {@link ConnectionPolicy}
*/
public ConnectionPolicy setIdleEndpointTimeout(Duration idleEndpointTimeout) {
this.idleEndpointTimeout = idleEndpointTimeout;
public ConnectionPolicy setIdleTcpEndpointTimeout(Duration idleTcpEndpointTimeout) {
this.idleTcpEndpointTimeout = idleTcpEndpointTimeout;
return this;
}

Expand Down Expand Up @@ -490,9 +513,10 @@ public String toString() {
", inetSocketProxyAddress=" + (proxy != null ? proxy.getAddress() : null) +
", readRequestsFallbackEnabled=" + readRequestsFallbackEnabled +
", connectTimeout=" + connectTimeout +
", idleEndpointTimeout=" + idleEndpointTimeout +
", idleTcpEndpointTimeout=" + idleTcpEndpointTimeout +
", maxConnectionsPerEndpoint=" + maxConnectionsPerEndpoint +
", maxRequestsPerConnection=" + maxRequestsPerConnection +
", tcpConnectionEndpointRediscoveryEnabled=" + tcpConnectionEndpointRediscoveryEnabled +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ public GoneException(String message, String requestUri) {
this(message, null, new HashMap<>(), requestUri);
}

/**
* Instantiates a new {@link GoneException Gone exception}.
*
* @param message the message
* @param requestUri the request uri
* @param cause the cause of this (client-side) {@link GoneException}
*/
public GoneException(String message, URI requestUri, Exception cause) {
this(message, cause, null, requestUri);
}

GoneException(Exception innerException) {
this(RMResources.Gone, innerException, new HashMap<>(), null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,19 +151,17 @@ public String toString() {
return RntbdObjectMapper.toString(this);
}

@JsonPropertyOrder({ "name", "startTimeUTC", "durationInMicroSec" })
@JsonPropertyOrder({ "name", "startTimeUTC" })
public static final class Event {

@JsonIgnore
private final Duration duration;

@JsonSerialize(using = ToStringSerializer.class)
private final long durationInMicroSec;
Comment thread
xinlian12 marked this conversation as resolved.

@JsonProperty("eventName")
private final String name;

@JsonSerialize(using = ToStringSerializer.class)
@JsonProperty("startTimeUTC")
private final Instant startTime;

public Event(final String name, final Instant from, final Instant to) {
Expand All @@ -173,11 +171,12 @@ public Event(final String name, final Instant from, final Instant to) {
this.name = name;
this.startTime = from;

this.duration = from == null ? null : to == null ? Duration.ZERO : Duration.between(from, to);
if(this.duration != null) {
this.durationInMicroSec = duration.toNanos()/1000L;
if (from == null) {
this.duration = null;
} else if (to == null) {
this.duration = Duration.ZERO;
} else {
this.durationInMicroSec = 0;
this.duration = Duration.between(from, to);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
import static com.azure.cosmos.models.ModelBridgeInternal.toDatabaseAccount;

/**
* While this class is public, but it is not part of our published public APIs.
* While this class is public, it is not part of our published public APIs.
* This is meant to be internally used only by our sdk.
*/
public class RxDocumentClientImpl implements AsyncDocumentClient, IAuthorizationTokenProvider, CpuListener, DiagnosticsClientContext {
Expand Down Expand Up @@ -391,15 +391,6 @@ public void init() {

private void initializeDirectConnectivity() {

this.storeClientFactory = new StoreClientFactory(
this.diagnosticsClientConfig,
this.configs,
this.connectionPolicy,
// this.maxConcurrentConnectionOpenRequests,
this.userAgentContainer,
this.connectionSharingAcrossClientsEnabled
);

this.addressResolver = new GlobalAddressResolver(this,
this.reactorHttpClient,
this.globalEndpointManager,
Expand All @@ -413,6 +404,16 @@ private void initializeDirectConnectivity() {
null,
this.connectionPolicy);

this.storeClientFactory = new StoreClientFactory(
this.addressResolver,
this.diagnosticsClientConfig,
this.configs,
this.connectionPolicy,
// this.maxConcurrentConnectionOpenRequests,
this.userAgentContainer,
this.connectionSharingAcrossClientsEnabled
);

this.createStoreModel(true);
}

Expand Down Expand Up @@ -1677,7 +1678,7 @@ public <T> Mono<FeedResponse<T>> readMany(
OperationType.Query,
ResourceType.Document,
collectionLink, null
);
);

// This should not got to backend
Mono<Utils.ValueHolder<DocumentCollection>> collectionObs =
Expand Down Expand Up @@ -1879,8 +1880,6 @@ private SqlQuerySpec createReadManyQuerySpec(List<CosmosItemIdentity> itemIdenti
return new SqlQuerySpec(queryStringBuilder.toString(), parameters);
}



private String createPkSelector(PartitionKeyDefinition partitionKeyDefinition) {
return partitionKeyDefinition.getPaths()
.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,18 @@
import com.azure.cosmos.implementation.RxDocumentServiceRequest;
import com.azure.cosmos.implementation.Strings;
import com.azure.cosmos.implementation.Utils;
import com.azure.cosmos.implementation.apachecommons.lang.NotImplementedException;
import com.azure.cosmos.implementation.apachecommons.lang.StringUtils;
import com.azure.cosmos.implementation.caches.RxCollectionCache;
import com.azure.cosmos.implementation.routing.CollectionRoutingMap;
import com.azure.cosmos.implementation.routing.PartitionKeyInternal;
import com.azure.cosmos.implementation.routing.PartitionKeyInternalHelper;
import com.azure.cosmos.implementation.routing.PartitionKeyRangeIdentity;
import com.azure.cosmos.implementation.apachecommons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;

import java.util.Set;
import java.util.concurrent.Callable;
import java.util.function.Function;

Expand Down Expand Up @@ -62,6 +64,11 @@ public void initializeCaches(
this.collectionRoutingMapCache = collectionRoutingMapCache;
}

@Override
public void remove(RxDocumentServiceRequest request, Set<PartitionKeyRangeIdentity> partitionKeyRangeIdentitySet) {
throw new NotImplementedException("remove() is not supported in AddressResolver");
Comment thread
xinlian12 marked this conversation as resolved.
}

public Mono<AddressInformation[]> resolveAsync(
RxDocumentServiceRequest request,
boolean forceRefreshPartitionAddresses) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import com.azure.cosmos.implementation.http.HttpResponse;
import com.azure.cosmos.implementation.routing.PartitionKeyRangeIdentity;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.timeout.ReadTimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
Expand All @@ -55,6 +54,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -142,6 +142,18 @@ public GatewayAddressCache(
DefaultSuboptimalPartitionForceRefreshIntervalInSeconds);
}

@Override
public void removeAddress(final PartitionKeyRangeIdentity partitionKeyRangeIdentity) {

Objects.requireNonNull(partitionKeyRangeIdentity, "expected non-null partitionKeyRangeIdentity");

if (partitionKeyRangeIdentity.getPartitionKeyRangeId().equals(PartitionKeyRange.MASTER_PARTITION_KEY_RANGE_ID)) {
this.masterPartitionAddressCache = null;
} else {
this.serverPartitionAddressCache.remove(partitionKeyRangeIdentity);
}
}

@Override
public Mono<Utils.ValueHolder<AddressInformation[]>> tryGetAddresses(RxDocumentServiceRequest request,
PartitionKeyRangeIdentity partitionKeyRangeIdentity,
Expand Down
Loading