All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.azure.cosmos.implementation.ConnectionPolicy Maven / Gradle / Ivy

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.cosmos.implementation;

import com.azure.core.http.ProxyOptions;
import com.azure.cosmos.BridgeInternal;
import com.azure.cosmos.ConnectionMode;
import com.azure.cosmos.CosmosExcludedRegions;
import com.azure.cosmos.DirectConnectionConfig;
import com.azure.cosmos.GatewayConnectionConfig;
import com.azure.cosmos.ThrottlingRetryOptions;

import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;

/**
 * Represents the Connection policy associated with a Cosmos client in the Azure Cosmos DB service.
 */
public final class ConnectionPolicy {

    private static final int defaultGatewayMaxConnectionPoolSize = GatewayConnectionConfig.getDefaultConfig()
        .getMaxConnectionPoolSize();

    private ConnectionMode connectionMode;
    private boolean endpointDiscoveryEnabled;
    private boolean multipleWriteRegionsEnabled;
    private List preferredRegions;
    private Supplier excludedRegionsSupplier;
    private boolean readRequestsFallbackEnabled;
    private ThrottlingRetryOptions throttlingRetryOptions;
    private String userAgentSuffix;

    //  Gateway connection config properties
    private int maxConnectionPoolSize;
    private Duration httpNetworkRequestTimeout;
    private ProxyOptions proxy;
    private Duration idleHttpConnectionTimeout;

    //  Direct connection config properties
    private Duration connectTimeout;
    private Duration idleTcpConnectionTimeout;
    private Duration idleTcpEndpointTimeout;
    private int maxConnectionsPerEndpoint;
    private int maxRequestsPerConnection;
    private Duration tcpNetworkRequestTimeout;
    private boolean tcpConnectionEndpointRediscoveryEnabled;
    private int ioThreadCountPerCoreFactor;
    private int ioThreadPriority;
    private boolean tcpHealthCheckTimeoutDetectionEnabled;
    private int minConnectionPoolSizePerEndpoint;
    private int openConnectionsConcurrency;
    private int aggressiveWarmupConcurrency;

    /**
     * Constructor.
     */
    public ConnectionPolicy(DirectConnectionConfig directConnectionConfig, GatewayConnectionConfig gatewayConnectionConfig) {
        this(ConnectionMode.DIRECT, directConnectionConfig, gatewayConnectionConfig);
    }

    public ConnectionPolicy(DirectConnectionConfig directConnectionConfig) {
        this(ConnectionMode.DIRECT, directConnectionConfig, GatewayConnectionConfig.getDefaultConfig());
    }

    public ConnectionPolicy(GatewayConnectionConfig gatewayConnectionConfig) {
        this(ConnectionMode.GATEWAY, DirectConnectionConfig.getDefaultConfig(), gatewayConnectionConfig);
    }

    private ConnectionPolicy(
        ConnectionMode connectionMode,
        DirectConnectionConfig directConnectionConfig,
        GatewayConnectionConfig gatewayConnectionConfig) {
        this();
        this.connectionMode = connectionMode;
        this.connectTimeout = directConnectionConfig.getConnectTimeout();
        this.idleTcpConnectionTimeout = directConnectionConfig.getIdleConnectionTimeout();
        this.idleTcpEndpointTimeout = directConnectionConfig.getIdleEndpointTimeout();
        this.maxConnectionsPerEndpoint = directConnectionConfig.getMaxConnectionsPerEndpoint();
        this.maxRequestsPerConnection = directConnectionConfig.getMaxRequestsPerConnection();
        this.tcpNetworkRequestTimeout = directConnectionConfig.getNetworkRequestTimeout();
        this.tcpConnectionEndpointRediscoveryEnabled = directConnectionConfig.isConnectionEndpointRediscoveryEnabled();
        this.ioThreadCountPerCoreFactor = ImplementationBridgeHelpers
            .DirectConnectionConfigHelper
            .getDirectConnectionConfigAccessor()
            .getIoThreadCountPerCoreFactor(directConnectionConfig);
        this.ioThreadPriority = ImplementationBridgeHelpers
            .DirectConnectionConfigHelper
            .getDirectConnectionConfigAccessor()
            .getIoThreadPriority(directConnectionConfig);
        this.idleHttpConnectionTimeout = gatewayConnectionConfig.getIdleConnectionTimeout();
        this.maxConnectionPoolSize = gatewayConnectionConfig.getMaxConnectionPoolSize();
        this.httpNetworkRequestTimeout = BridgeInternal.getNetworkRequestTimeoutFromGatewayConnectionConfig(gatewayConnectionConfig);
        this.proxy = gatewayConnectionConfig.getProxy();
        this.tcpHealthCheckTimeoutDetectionEnabled =
            ImplementationBridgeHelpers
                .DirectConnectionConfigHelper
                .getDirectConnectionConfigAccessor()
                .isHealthCheckTimeoutDetectionEnabled(directConnectionConfig);

        // NOTE: should be compared with COSMOS.MIN_CONNECTION_POOL_SIZE_PER_ENDPOINT
        // read during client initialization before connections are created for the container
        this.minConnectionPoolSizePerEndpoint =
                Math.max(ImplementationBridgeHelpers
                    .DirectConnectionConfigHelper
                    .getDirectConnectionConfigAccessor()
                    .getMinConnectionPoolSizePerEndpoint(directConnectionConfig), Configs.getMinConnectionPoolSizePerEndpoint());
    }

    private ConnectionPolicy() {
        //  Default values
        this.endpointDiscoveryEnabled = true;
        this.multipleWriteRegionsEnabled = true;
        this.readRequestsFallbackEnabled = true;
        this.throttlingRetryOptions = new ThrottlingRetryOptions();
        this.userAgentSuffix = "";
        this.ioThreadPriority = Thread.NORM_PRIORITY;
        this.tcpHealthCheckTimeoutDetectionEnabled = true;
        this.minConnectionPoolSizePerEndpoint = Configs.getMinConnectionPoolSizePerEndpoint();
        this.openConnectionsConcurrency = Configs.getOpenConnectionsConcurrency();
        this.aggressiveWarmupConcurrency = Configs.getAggressiveWarmupConcurrency();
    }

    /**
     * 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.
     *
     * @return the default connection policy.
     */
    public static ConnectionPolicy getDefaultPolicy() {
        return new ConnectionPolicy(DirectConnectionConfig.getDefaultConfig());
    }

    /**
     * Gets the http network request timeout interval (time to wait for response from network peer).
     * The default is 60 seconds.
     *
     * @return the http request timeout duration.
     */
    public Duration getHttpNetworkRequestTimeout() {
        return this.httpNetworkRequestTimeout;
    }

    /**
     * Sets the http network request timeout interval (time to wait for response from network peer).
     * The default is 60 seconds.
     *
     * @param httpNetworkRequestTimeout the http request timeout duration.
     * @return the ConnectionPolicy.
     */
    public ConnectionPolicy setHttpNetworkRequestTimeout(Duration httpNetworkRequestTimeout) {
        this.httpNetworkRequestTimeout = httpNetworkRequestTimeout;
        return this;
    }

    /**
     * Gets the tcp network request timeout interval (time to wait for response from network peer).
     *
     * Default value is 5 seconds
     *
     * @return the network request timeout interval
     */
    public Duration getTcpNetworkRequestTimeout() {
        return this.tcpNetworkRequestTimeout;
    }

    /**
     * Sets the tcp network request timeout interval (time to wait for response from network peer).
     *
     * Default value is 5 seconds.
     * It only allows values ≥5s and ≤10s. (backend allows requests to take up-to 5 seconds processing time - 5 seconds
     * buffer so 10 seconds in total for transport is more than sufficient).
     *
     * Attention! Please adjust this value with caution.
     * This config represents the max time allowed to wait for and consume a service response after the request has been written to the network connection.
     * Setting a value too low can result in having not enough time to wait for the service response - which could cause too aggressive retries and degrade performance.
     * Setting a value too high can result in fewer retries and reduce chances of success by retries.
     *
     * @param tcpNetworkRequestTimeout the network request timeout interval.
     * @return the {@link ConnectionPolicy}
     */
    public ConnectionPolicy setTcpNetworkRequestTimeout(Duration tcpNetworkRequestTimeout) {
        this.tcpNetworkRequestTimeout = tcpNetworkRequestTimeout;
        return this;
    }

    /**
     * Gets the connection mode used in the client.
     *
     * @return the connection mode.
     */
    public ConnectionMode getConnectionMode() {
        return this.connectionMode;
    }

    /**
     * Sets the connection mode used in the client.
     *
     * @param connectionMode the connection mode.
     * @return the ConnectionPolicy.
     */
    public ConnectionPolicy setConnectionMode(ConnectionMode connectionMode) {
        this.connectionMode = connectionMode;
        return this;
    }

    /**
     * Gets the value of the connection pool size the client is using.
     *
     * @return connection pool size.
     */
    public int getMaxConnectionPoolSize() {
        return this.maxConnectionPoolSize;
    }

    /**
     * Sets the value of the connection pool size, the default
     * is 1000.
     *
     * @param maxConnectionPoolSize The value of the connection pool size.
     * @return the ConnectionPolicy.
     */
    public ConnectionPolicy setMaxConnectionPoolSize(int maxConnectionPoolSize) {
        this.maxConnectionPoolSize = maxConnectionPoolSize;
        return this;
    }

    /**
     * Gets the value of the timeout for an idle http connection, the default is 60
     * seconds.
     *
     * @return Idle connection timeout duration.
     */
    public Duration getIdleHttpConnectionTimeout() {
        return this.idleHttpConnectionTimeout;
    }

    /**
     * sets the value of the timeout for an idle http connection. After that time,
     * the connection will be automatically closed.
     *
     * @param idleHttpConnectionTimeout the duration for an idle connection.
     * @return the ConnectionPolicy.
     */
    public ConnectionPolicy setIdleHttpConnectionTimeout(Duration idleHttpConnectionTimeout) {
        this.idleHttpConnectionTimeout = idleHttpConnectionTimeout;
        return this;
    }

    /**
     * Gets the idle tcp connection timeout for direct client
     *
     * Default value is {@link Duration#ZERO}
     *
     * Direct client doesn't close a single connection to an endpoint
     * by default unless specified.
     *
     * @return idle tcp connection timeout
     */
    public Duration getIdleTcpConnectionTimeout() {
        return idleTcpConnectionTimeout;
    }

    /**
     * Sets the idle tcp connection timeout
     *
     * Default value is {@link Duration#ZERO}
     *
     * Direct client doesn't close a single connection to an endpoint
     * by default unless specified.
     *
     * @param idleTcpConnectionTimeout idle connection timeout
     * @return the {@link ConnectionPolicy}
     */
    public ConnectionPolicy setIdleTcpConnectionTimeout(Duration idleTcpConnectionTimeout) {
        this.idleTcpConnectionTimeout = idleTcpConnectionTimeout;
        return this;
    }

    /**
     * Gets the value of user-agent suffix.
     *
     * @return the value of user-agent suffix.
     */
    public String getUserAgentSuffix() {
        return this.userAgentSuffix;
    }

    /**
     * sets the value of the user-agent suffix.
     *
     * @param userAgentSuffix The value to be appended to the user-agent header, this is
     * used for monitoring purposes.
     * @return the ConnectionPolicy.
     */
    public ConnectionPolicy setUserAgentSuffix(String userAgentSuffix) {
        this.userAgentSuffix = userAgentSuffix;
        return this;
    }

    /**
     * Gets the retry policy options associated with the DocumentClient instance.
     *
     * @return the RetryOptions instance.
     */
    public ThrottlingRetryOptions getThrottlingRetryOptions() {
        return this.throttlingRetryOptions;
    }

    /**
     * Sets the retry policy options associated with the DocumentClient instance.
     * 

* Properties in the RetryOptions class allow application to customize the built-in * retry policies. This property is optional. When it's not set, the SDK uses the * default values for configuring the retry policies. See RetryOptions class for * more details. * * @param throttlingRetryOptions the RetryOptions instance. * @return the ConnectionPolicy. * @throws IllegalArgumentException thrown if an error occurs */ public ConnectionPolicy setThrottlingRetryOptions(ThrottlingRetryOptions throttlingRetryOptions) { if (throttlingRetryOptions == null) { throw new IllegalArgumentException("retryOptions value must not be null."); } this.throttlingRetryOptions = throttlingRetryOptions; return this; } /** * Gets the flag to enable endpoint discovery for geo-replicated database accounts. * * @return whether endpoint discovery is enabled. */ public boolean isEndpointDiscoveryEnabled() { return this.endpointDiscoveryEnabled; } /** * Sets the flag to enable endpoint discovery for geo-replicated database accounts. *

* When EnableEndpointDiscovery is true, the SDK will automatically discover the * current write and read regions to ensure requests are sent to the correct region * based on the capability of the region and the user's preference. *

* The default value for this property is true indicating endpoint discovery is enabled. * * @param endpointDiscoveryEnabled true if EndpointDiscovery is enabled. * @return the ConnectionPolicy. */ public ConnectionPolicy setEndpointDiscoveryEnabled(boolean endpointDiscoveryEnabled) { this.endpointDiscoveryEnabled = endpointDiscoveryEnabled; return this; } /** * Gets the flag to enable writes on any regions for geo-replicated database accounts in the Azure * Cosmos DB service. *

* When the value of this property is true, the SDK will direct write operations to * available writable regions of geo-replicated database account. Writable regions * are ordered by PreferredRegions property. Setting the property value * to true has no effect until EnableMultipleWriteRegions in DatabaseAccount * is also set to true. *

* DEFAULT value is true indicating that writes are directed to * available writable regions of geo-replicated database account. * * @return flag to enable writes on any regions for geo-replicated database accounts. */ public boolean isMultipleWriteRegionsEnabled() { return this.multipleWriteRegionsEnabled; } /** * Gets whether to allow for reads to go to multiple regions configured on an account of Azure Cosmos DB service. *

* DEFAULT value is true. *

* If this property is not set, the default is true for all Consistency Levels other than Bounded Staleness, * The default is false for Bounded Staleness. * 1. {@link #endpointDiscoveryEnabled} is true * 2. the Azure Cosmos DB account has more than one region * * @return flag to allow for reads to go to multiple regions configured on an account of Azure Cosmos DB service. */ public boolean isReadRequestsFallbackEnabled() { return this.readRequestsFallbackEnabled; } /** * Sets the flag to enable writes on any regions for geo-replicated database accounts in the Azure * Cosmos DB service. *

* When the value of this property is true, the SDK will direct write operations to * available writable regions of geo-replicated database account. Writable regions * are ordered by PreferredRegions property. Setting the property value * to true has no effect until EnableMultipleWriteRegions in DatabaseAccount * is also set to true. *

* DEFAULT value is false indicating that writes are only directed to * first region in PreferredRegions property. * * @param multipleWriteRegionsEnabled flag to enable writes on any regions for geo-replicated * database accounts. * @return the ConnectionPolicy. */ public ConnectionPolicy setMultipleWriteRegionsEnabled(boolean multipleWriteRegionsEnabled) { this.multipleWriteRegionsEnabled = multipleWriteRegionsEnabled; return this; } /** * Sets whether to allow for reads to go to multiple regions configured on an account of Azure Cosmos DB service. *

* DEFAULT value is true. *

* If this property is not set, the default is true for all Consistency Levels other than Bounded Staleness, * The default is false for Bounded Staleness. * 1. {@link #endpointDiscoveryEnabled} is true * 2. the Azure Cosmos DB account has more than one region * * @param readRequestsFallbackEnabled flag to enable reads to go to multiple regions configured on an account of * Azure Cosmos DB service. * @return the ConnectionPolicy. */ public ConnectionPolicy setReadRequestsFallbackEnabled(boolean readRequestsFallbackEnabled) { this.readRequestsFallbackEnabled = readRequestsFallbackEnabled; return this; } /** * Gets the preferred regions for geo-replicated database accounts * * @return the list of preferred region. */ public List getPreferredRegions() { return this.preferredRegions != null ? this.preferredRegions : Collections.emptyList(); } /** * Sets the preferred regions for geo-replicated database accounts. For example, * "East US" as the preferred region. *

* When EnableEndpointDiscovery is true and PreferredRegions is non-empty, * the SDK will prefer to use the regions in the collection in the order * they are specified to perform operations. *

* If EnableEndpointDiscovery is set to false, this property is ignored. * * @param preferredRegions the list of preferred regions. * @return the ConnectionPolicy. */ public ConnectionPolicy setPreferredRegions(List preferredRegions) { this.preferredRegions = preferredRegions; return this; } public ConnectionPolicy setExcludedRegionsSupplier(Supplier excludedRegionsSupplier) { this.excludedRegionsSupplier = excludedRegionsSupplier; return this; } public Supplier getExcludedRegionsSupplier() { return this.excludedRegionsSupplier; } /** * Gets the proxy options which contain the InetSocketAddress of proxy server. * * @return the proxy options. */ public ProxyOptions getProxy() { return this.proxy; } /** * Sets the proxy options. * * Currently only support Http proxy type with just the routing address. Username and password will be ignored. * * @param proxy The proxy options. * @return the ConnectionPolicy. */ public ConnectionPolicy setProxy(ProxyOptions proxy) { this.proxy = proxy; return this; } /** * Gets the direct connect timeout * @return direct connect timeout */ public Duration getConnectTimeout() { return connectTimeout; } /** * Sets the direct connect timeout * @param connectTimeout the connect timeout * @return the {@link ConnectionPolicy} */ public ConnectionPolicy setConnectTimeout(Duration connectTimeout) { this.connectTimeout = connectTimeout; return this; } /** * Gets the idle endpoint timeout * @return the idle endpoint timeout */ public Duration getIdleTcpEndpointTimeout() { return idleTcpEndpointTimeout; } /** * Sets the idle endpoint timeout * @param idleTcpEndpointTimeout the idle endpoint timeout * @return the {@link ConnectionPolicy} */ public ConnectionPolicy setIdleTcpEndpointTimeout(Duration idleTcpEndpointTimeout) { this.idleTcpEndpointTimeout = idleTcpEndpointTimeout; return this; } /** * Gets the max channels per endpoint * @return the max channels per endpoint */ public int getMaxConnectionsPerEndpoint() { return maxConnectionsPerEndpoint; } /** * Sets the max channels per endpoint * @param maxConnectionsPerEndpoint the max channels per endpoint * @return the {@link ConnectionPolicy} */ public ConnectionPolicy setMaxConnectionsPerEndpoint(int maxConnectionsPerEndpoint) { this.maxConnectionsPerEndpoint = maxConnectionsPerEndpoint; return this; } /** * Gets the max requests per endpoint * @return the max requests per endpoint */ public int getMaxRequestsPerConnection() { return maxRequestsPerConnection; } /** * Sets the max requests per endpoint * @param maxRequestsPerConnection the max requests per endpoint * @return the {@link ConnectionPolicy} */ public ConnectionPolicy setMaxRequestsPerConnection(int maxRequestsPerConnection) { this.maxRequestsPerConnection = maxRequestsPerConnection; return this; } public int getIoThreadCountPerCoreFactor() { return this.ioThreadCountPerCoreFactor; } public int getIoThreadPriority() { return this.ioThreadPriority; } public boolean isTcpHealthCheckTimeoutDetectionEnabled() { return this.tcpHealthCheckTimeoutDetectionEnabled; } public ConnectionPolicy setIoThreadCountPerCoreFactor(int ioThreadCountPerCoreFactor) { this.ioThreadCountPerCoreFactor = ioThreadCountPerCoreFactor; return this; } public ConnectionPolicy setIoThreadPriority(int ioThreadPriority) { this.ioThreadPriority = ioThreadPriority; return this; } public int getMinConnectionPoolSizePerEndpoint() { return minConnectionPoolSizePerEndpoint; } public String getExcludedRegionsAsString() { if (this.excludedRegionsSupplier != null && this.excludedRegionsSupplier.get() != null) { CosmosExcludedRegions excludedRegions = this.excludedRegionsSupplier.get(); return excludedRegions.toString(); } return "[]"; } @Override public String toString() { return "ConnectionPolicy{" + "httpNetworkRequestTimeout=" + httpNetworkRequestTimeout + ", tcpNetworkRequestTimeout=" + tcpNetworkRequestTimeout + ", connectionMode=" + connectionMode + ", maxConnectionPoolSize=" + maxConnectionPoolSize + ", idleHttpConnectionTimeout=" + idleHttpConnectionTimeout + ", idleTcpConnectionTimeout=" + idleTcpConnectionTimeout + ", userAgentSuffix='" + userAgentSuffix + '\'' + ", throttlingRetryOptions=" + throttlingRetryOptions + ", endpointDiscoveryEnabled=" + endpointDiscoveryEnabled + ", preferredRegions=" + preferredRegions + ", multipleWriteRegionsEnabled=" + multipleWriteRegionsEnabled + ", proxyType=" + (proxy != null ? proxy.getType() : null) + ", inetSocketProxyAddress=" + (proxy != null ? proxy.getAddress() : null) + ", readRequestsFallbackEnabled=" + readRequestsFallbackEnabled + ", connectTimeout=" + connectTimeout + ", idleTcpEndpointTimeout=" + idleTcpEndpointTimeout + ", maxConnectionsPerEndpoint=" + maxConnectionsPerEndpoint + ", maxRequestsPerConnection=" + maxRequestsPerConnection + ", tcpConnectionEndpointRediscoveryEnabled=" + tcpConnectionEndpointRediscoveryEnabled + ", ioThreadPriority=" + ioThreadPriority + ", ioThreadCountPerCoreFactor=" + ioThreadCountPerCoreFactor + ", tcpHealthCheckTimeoutDetectionEnabled=" + tcpHealthCheckTimeoutDetectionEnabled + ", minConnectionPoolSizePerEndpoint=" + minConnectionPoolSizePerEndpoint + ", openConnectionsConcurrency=" + openConnectionsConcurrency + ", aggressiveWarmupConcurrency=" + aggressiveWarmupConcurrency + '}'; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy