diff --git a/driver-core/src/main/com/mongodb/ConnectionString.java b/driver-core/src/main/com/mongodb/ConnectionString.java
index 659e8fd02aa..8d5e53af25d 100644
--- a/driver-core/src/main/com/mongodb/ConnectionString.java
+++ b/driver-core/src/main/com/mongodb/ConnectionString.java
@@ -19,6 +19,7 @@
import com.mongodb.annotations.Alpha;
import com.mongodb.annotations.Reason;
import com.mongodb.connection.ClusterSettings;
+import com.mongodb.connection.ClusterType;
import com.mongodb.connection.ConnectionPoolSettings;
import com.mongodb.connection.ServerMonitoringMode;
import com.mongodb.connection.ServerSettings;
@@ -272,6 +273,9 @@
* Defaults to true.
*
{@code retryReads=true|false}. If true the driver will retry supported read operations if they fail due to a network error.
* Defaults to true.
+ * {@code enableOverloadRetargeting=true|false}. If true the driver may route a request to a different server on a subsequent
+ * retry attempt if the previously used server is overloaded. Does not take effect for {@linkplain ClusterType#SHARDED sharded clusters}.
+ * Defaults to false.
* {@code uuidRepresentation=unspecified|standard|javaLegacy|csharpLegacy|pythonLegacy}. See
* {@link MongoClientSettings#getUuidRepresentation()} for documentation of semantics of this parameter. Defaults to "javaLegacy", but
* will change to "unspecified" in the next major release.
@@ -308,6 +312,7 @@ public class ConnectionString {
private WriteConcern writeConcern;
private Boolean retryWrites;
private Boolean retryReads;
+ private Boolean enableOverloadRetargeting;
private ReadConcern readConcern;
private Integer minConnectionPoolSize;
@@ -558,6 +563,7 @@ public ConnectionString(final String connectionString, @Nullable final DnsClient
GENERAL_OPTIONS_KEYS.add("servermonitoringmode");
GENERAL_OPTIONS_KEYS.add("retrywrites");
GENERAL_OPTIONS_KEYS.add("retryreads");
+ GENERAL_OPTIONS_KEYS.add("enableoverloadretargeting");
GENERAL_OPTIONS_KEYS.add("appname");
@@ -706,6 +712,9 @@ private void translateOptions(final Map> optionsMap) {
case "retryreads":
retryReads = parseBoolean(value, "retryreads");
break;
+ case "enableoverloadretargeting":
+ enableOverloadRetargeting = parseBoolean(value, "enableoverloadretargeting");
+ break;
case "uuidrepresentation":
uuidRepresentation = createUuidRepresentation(value);
break;
@@ -1473,7 +1482,7 @@ public Boolean getRetryWritesValue() {
/**
* Gets whether reads should be retried if they fail due to a network error
*
- * @return the retryWrites value
+ * @return the retryReads value
* @since 3.11
* @mongodb.server.release 3.6
*/
@@ -1482,6 +1491,29 @@ public Boolean getRetryReads() {
return retryReads;
}
+ /**
+ * Gets whether overload retargeting is enabled.
+ *
+ * When enabled, the previously selected servers on which attempts failed with an error
+ * {@linkplain MongoException#hasErrorLabel(String) having}
+ * the {@value MongoException#SYSTEM_OVERLOADED_ERROR_LABEL} label may be deprioritized during
+ * server selection on subsequent retry attempts. This applies to reads when retryReads is enabled,
+ * and to writes when retryWrites is enabled.
+ *
+ * This setting does not take effect for
+ * {@linkplain com.mongodb.connection.ClusterType#SHARDED sharded clusters}.
+ *
+ * Defaults to {@code false}.
+ *
+ * @return the enableOverloadRetargeting value, or null if not set
+ * @see MongoClientSettings.Builder#enableOverloadRetargeting(boolean)
+ * @since 5.7
+ */
+ @Nullable
+ public Boolean getEnableOverloadRetargeting() {
+ return enableOverloadRetargeting;
+ }
+
/**
* Gets the minimum connection pool size specified in the connection string.
* @return the minimum connection pool size
@@ -1795,6 +1827,7 @@ public boolean equals(final Object o) {
&& Objects.equals(writeConcern, that.writeConcern)
&& Objects.equals(retryWrites, that.retryWrites)
&& Objects.equals(retryReads, that.retryReads)
+ && Objects.equals(enableOverloadRetargeting, that.enableOverloadRetargeting)
&& Objects.equals(readConcern, that.readConcern)
&& Objects.equals(minConnectionPoolSize, that.minConnectionPoolSize)
&& Objects.equals(maxConnectionPoolSize, that.maxConnectionPoolSize)
@@ -1826,8 +1859,8 @@ public boolean equals(final Object o) {
@Override
public int hashCode() {
return Objects.hash(credential, isSrvProtocol, hosts, database, collection, directConnection, readPreference,
- writeConcern, retryWrites, retryReads, readConcern, minConnectionPoolSize, maxConnectionPoolSize, maxWaitTime,
- maxConnectionIdleTime, maxConnectionLifeTime, maxConnecting, connectTimeout, timeout, socketTimeout, sslEnabled,
+ writeConcern, retryWrites, retryReads, enableOverloadRetargeting, readConcern, minConnectionPoolSize, maxConnectionPoolSize,
+ maxWaitTime, maxConnectionIdleTime, maxConnectionLifeTime, maxConnecting, connectTimeout, timeout, socketTimeout, sslEnabled,
sslInvalidHostnameAllowed, requiredReplicaSetName, serverSelectionTimeout, localThreshold, heartbeatFrequency,
serverMonitoringMode, applicationName, compressorList, uuidRepresentation, srvServiceName, srvMaxHosts, proxyHost,
proxyPort, proxyUsername, proxyPassword);
diff --git a/driver-core/src/main/com/mongodb/MongoClientSettings.java b/driver-core/src/main/com/mongodb/MongoClientSettings.java
index 41c5f73a1d7..bf6ef0430b2 100644
--- a/driver-core/src/main/com/mongodb/MongoClientSettings.java
+++ b/driver-core/src/main/com/mongodb/MongoClientSettings.java
@@ -24,6 +24,7 @@
import com.mongodb.client.model.geojson.codecs.GeoJsonCodecProvider;
import com.mongodb.client.model.mql.ExpressionCodecProvider;
import com.mongodb.connection.ClusterSettings;
+import com.mongodb.connection.ClusterType;
import com.mongodb.connection.ConnectionPoolSettings;
import com.mongodb.connection.ServerSettings;
import com.mongodb.connection.SocketSettings;
@@ -93,6 +94,7 @@ public final class MongoClientSettings {
private final WriteConcern writeConcern;
private final boolean retryWrites;
private final boolean retryReads;
+ private final boolean enableOverloadRetargeting;
private final ReadConcern readConcern;
private final MongoCredential credential;
private final TransportSettings transportSettings;
@@ -214,6 +216,7 @@ public static final class Builder {
private WriteConcern writeConcern = WriteConcern.ACKNOWLEDGED;
private boolean retryWrites = true;
private boolean retryReads = true;
+ private boolean enableOverloadRetargeting = false;
private ReadConcern readConcern = ReadConcern.DEFAULT;
private CodecRegistry codecRegistry = MongoClientSettings.getDefaultCodecRegistry();
private TransportSettings transportSettings;
@@ -255,6 +258,7 @@ private Builder(final MongoClientSettings settings) {
writeConcern = settings.getWriteConcern();
retryWrites = settings.getRetryWrites();
retryReads = settings.getRetryReads();
+ enableOverloadRetargeting = settings.getEnableOverloadRetargeting();
readConcern = settings.getReadConcern();
credential = settings.getCredential();
uuidRepresentation = settings.getUuidRepresentation();
@@ -314,6 +318,10 @@ public Builder applyConnectionString(final ConnectionString connectionString) {
if (retryReadsValue != null) {
retryReads = retryReadsValue;
}
+ Boolean enableOverloadRetargetingValue = connectionString.getEnableOverloadRetargeting();
+ if (enableOverloadRetargetingValue != null) {
+ enableOverloadRetargeting = enableOverloadRetargetingValue;
+ }
if (connectionString.getUuidRepresentation() != null) {
uuidRepresentation = connectionString.getUuidRepresentation();
}
@@ -456,6 +464,30 @@ public Builder retryReads(final boolean retryReads) {
return this;
}
+ /**
+ * Sets whether to enable overload retargeting.
+ *
+ * When enabled, the previously selected servers on which attempts failed with an error
+ * {@linkplain MongoException#hasErrorLabel(String) having}
+ * the {@value MongoException#SYSTEM_OVERLOADED_ERROR_LABEL} label may be deprioritized during
+ * server selection on subsequent retry attempts. This applies to reads when
+ * {@linkplain #retryReads(boolean) retryReads} is enabled, and to writes when
+ * {@linkplain #retryWrites(boolean) retryWrites} is enabled.
+ *
+ * This setting does not take effect for {@linkplain ClusterType#SHARDED sharded clusters}.
+ *
+ * Defaults to {@code false}.
+ *
+ * @param enableOverloadRetargeting whether to enable overload retargeting.
+ * @return this
+ * @see #getEnableOverloadRetargeting()
+ * @since 5.7
+ */
+ public Builder enableOverloadRetargeting(final boolean enableOverloadRetargeting) {
+ this.enableOverloadRetargeting = enableOverloadRetargeting;
+ return this;
+ }
+
/**
* Sets the read concern.
*
@@ -807,6 +839,18 @@ public boolean getRetryReads() {
return retryReads;
}
+ /**
+ * Returns whether overload retargeting is enabled.
+ * See {@link Builder#enableOverloadRetargeting(boolean)} for more information.
+ *
+ * @return the enableOverloadRetargeting value
+ * @see Builder#enableOverloadRetargeting(boolean)
+ * @since 5.7
+ */
+ public boolean getEnableOverloadRetargeting() {
+ return enableOverloadRetargeting;
+ }
+
/**
* The read concern to use.
*
@@ -1080,6 +1124,7 @@ public boolean equals(final Object o) {
MongoClientSettings that = (MongoClientSettings) o;
return retryWrites == that.retryWrites
&& retryReads == that.retryReads
+ && enableOverloadRetargeting == that.enableOverloadRetargeting
&& heartbeatSocketTimeoutSetExplicitly == that.heartbeatSocketTimeoutSetExplicitly
&& heartbeatConnectTimeoutSetExplicitly == that.heartbeatConnectTimeoutSetExplicitly
&& Objects.equals(readPreference, that.readPreference)
@@ -1109,8 +1154,8 @@ public boolean equals(final Object o) {
@Override
public int hashCode() {
- return Objects.hash(readPreference, writeConcern, retryWrites, retryReads, readConcern, credential, transportSettings,
- commandListeners, codecRegistry, loggerSettings, clusterSettings, socketSettings,
+ return Objects.hash(readPreference, writeConcern, retryWrites, retryReads, enableOverloadRetargeting, readConcern, credential,
+ transportSettings, commandListeners, codecRegistry, loggerSettings, clusterSettings, socketSettings,
heartbeatSocketSettings, connectionPoolSettings, serverSettings, sslSettings, applicationName, compressorList,
uuidRepresentation, serverApi, autoEncryptionSettings, heartbeatSocketTimeoutSetExplicitly,
heartbeatConnectTimeoutSetExplicitly, dnsClient, inetAddressResolver, contextProvider, timeoutMS);
@@ -1124,6 +1169,7 @@ public String toString() {
+ ", writeConcern=" + writeConcern
+ ", retryWrites=" + retryWrites
+ ", retryReads=" + retryReads
+ + ", enableOverloadRetargeting=" + enableOverloadRetargeting
+ ", readConcern=" + readConcern
+ ", credential=" + credential
+ ", transportSettings=" + transportSettings
@@ -1154,6 +1200,7 @@ private MongoClientSettings(final Builder builder) {
writeConcern = builder.writeConcern;
retryWrites = builder.retryWrites;
retryReads = builder.retryReads;
+ enableOverloadRetargeting = builder.enableOverloadRetargeting;
readConcern = builder.readConcern;
credential = builder.credential;
transportSettings = builder.transportSettings;
diff --git a/driver-core/src/main/com/mongodb/internal/connection/BaseCluster.java b/driver-core/src/main/com/mongodb/internal/connection/BaseCluster.java
index 4146d06c22e..2f0fcaa6379 100644
--- a/driver-core/src/main/com/mongodb/internal/connection/BaseCluster.java
+++ b/driver-core/src/main/com/mongodb/internal/connection/BaseCluster.java
@@ -113,9 +113,9 @@ abstract class BaseCluster implements Cluster {
private volatile ClusterDescription description;
BaseCluster(final ClusterId clusterId,
- final ClusterSettings settings,
- final ClusterableServerFactory serverFactory,
- final ClientMetadata clientMetadata) {
+ final ClusterSettings settings,
+ final ClusterableServerFactory serverFactory,
+ final ClientMetadata clientMetadata) {
this.clusterId = notNull("clusterId", clusterId);
this.settings = notNull("settings", settings);
this.serverFactory = notNull("serverFactory", serverFactory);
@@ -159,7 +159,7 @@ public ServerTuple selectServer(final ServerSelector serverSelector, final Opera
if (serverTuple != null) {
ServerAddress serverAddress = serverTuple.getServerDescription().getAddress();
logServerSelectionSucceeded(operationContext, clusterId, serverAddress, serverSelector, currentDescription);
- serverDeprioritization.updateCandidate(serverAddress);
+ serverDeprioritization.updateCandidate(serverAddress, currentDescription.getType());
return serverTuple;
}
computedServerSelectionTimeout.onExpired(() ->
@@ -302,7 +302,7 @@ private boolean handleServerSelectionRequest(
if (serverTuple != null) {
ServerAddress serverAddress = serverTuple.getServerDescription().getAddress();
logServerSelectionSucceeded(operationContext, clusterId, serverAddress, request.originalSelector, description);
- serverDeprioritization.updateCandidate(serverAddress);
+ serverDeprioritization.updateCandidate(serverAddress, description.getType());
request.onResult(serverTuple, null);
return true;
}
@@ -361,8 +361,7 @@ private static ServerSelector getCompleteServerSelector(
final ClusterSettings settings) {
List selectors = Stream.of(
getRaceConditionPreFilteringSelector(serversSnapshot),
- serverSelector,
- serverDeprioritization.getServerSelector(),
+ serverDeprioritization.apply(serverSelector),
settings.getServerSelector(), // may be null
new LatencyMinimizingServerSelector(settings.getLocalThreshold(MILLISECONDS), MILLISECONDS),
AtMostTwoRandomServerSelector.instance(),
diff --git a/driver-core/src/main/com/mongodb/internal/connection/OperationContext.java b/driver-core/src/main/com/mongodb/internal/connection/OperationContext.java
index f23d5e5226b..3779cefeaba 100644
--- a/driver-core/src/main/com/mongodb/internal/connection/OperationContext.java
+++ b/driver-core/src/main/com/mongodb/internal/connection/OperationContext.java
@@ -17,6 +17,7 @@
import com.mongodb.Function;
import com.mongodb.MongoConnectionPoolClearedException;
+import com.mongodb.MongoException;
import com.mongodb.ReadConcern;
import com.mongodb.RequestContext;
import com.mongodb.ServerAddress;
@@ -27,7 +28,6 @@
import com.mongodb.internal.IgnorableRequestContext;
import com.mongodb.internal.TimeoutContext;
import com.mongodb.internal.TimeoutSettings;
-import com.mongodb.internal.VisibleForTesting;
import com.mongodb.internal.observability.micrometer.Span;
import com.mongodb.internal.observability.micrometer.TracingManager;
import com.mongodb.internal.session.SessionContext;
@@ -40,6 +40,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
+import static com.mongodb.MongoException.SYSTEM_OVERLOADED_ERROR_LABEL;
import static java.util.stream.Collectors.toList;
/**
@@ -61,14 +62,14 @@ public class OperationContext {
private Span tracingSpan;
public OperationContext(final RequestContext requestContext, final SessionContext sessionContext, final TimeoutContext timeoutContext,
- @Nullable final ServerApi serverApi) {
+ @Nullable final ServerApi serverApi) {
this(requestContext, sessionContext, timeoutContext, TracingManager.NO_OP, serverApi, null);
}
public OperationContext(final RequestContext requestContext, final SessionContext sessionContext, final TimeoutContext timeoutContext,
- final TracingManager tracingManager,
- @Nullable final ServerApi serverApi,
- @Nullable final String operationName) {
+ final TracingManager tracingManager,
+ @Nullable final ServerApi serverApi,
+ @Nullable final String operationName) {
this(NEXT_ID.incrementAndGet(), requestContext, sessionContext, timeoutContext, new ServerDeprioritization(),
tracingManager,
serverApi,
@@ -76,7 +77,19 @@ public OperationContext(final RequestContext requestContext, final SessionContex
null);
}
- public static OperationContext simpleOperationContext(
+ public OperationContext(final RequestContext requestContext, final SessionContext sessionContext, final TimeoutContext timeoutContext,
+ final TracingManager tracingManager,
+ @Nullable final ServerApi serverApi,
+ @Nullable final String operationName,
+ final ServerDeprioritization serverDeprioritization) {
+ this(NEXT_ID.incrementAndGet(), requestContext, sessionContext, timeoutContext, serverDeprioritization,
+ tracingManager,
+ serverApi,
+ operationName,
+ null);
+ }
+
+ static OperationContext simpleOperationContext(
final TimeoutSettings timeoutSettings, @Nullable final ServerApi serverApi) {
return new OperationContext(
IgnorableRequestContext.INSTANCE,
@@ -85,7 +98,7 @@ public static OperationContext simpleOperationContext(
TracingManager.NO_OP,
serverApi,
null
- );
+ );
}
public static OperationContext simpleOperationContext(final TimeoutContext timeoutContext) {
@@ -113,6 +126,16 @@ public OperationContext withOperationName(final String operationName) {
operationName, tracingSpan);
}
+ /**
+ * TODO-JAVA-6058: This method enables overriding the ServerDeprioritization state.
+ * It is a temporary solution to handle cases where deprioritization state persists across operations.
+ */
+ public OperationContext withNewServerDeprioritization() {
+ return new OperationContext(id, requestContext, sessionContext, timeoutContext,
+ new ServerDeprioritization(serverDeprioritization.enableOverloadRetargeting), tracingManager, serverApi,
+ operationName, tracingSpan);
+ }
+
public long getId() {
return id;
}
@@ -152,16 +175,15 @@ public void setTracingSpan(final Span tracingSpan) {
this.tracingSpan = tracingSpan;
}
- @VisibleForTesting(otherwise = VisibleForTesting.AccessModifier.PRIVATE)
- public OperationContext(final long id,
- final RequestContext requestContext,
- final SessionContext sessionContext,
- final TimeoutContext timeoutContext,
- final ServerDeprioritization serverDeprioritization,
- final TracingManager tracingManager,
- @Nullable final ServerApi serverApi,
- @Nullable final String operationName,
- @Nullable final Span tracingSpan) {
+ private OperationContext(final long id,
+ final RequestContext requestContext,
+ final SessionContext sessionContext,
+ final TimeoutContext timeoutContext,
+ final ServerDeprioritization serverDeprioritization,
+ final TracingManager tracingManager,
+ @Nullable final ServerApi serverApi,
+ @Nullable final String operationName,
+ @Nullable final Span tracingSpan) {
this.id = id;
this.serverDeprioritization = serverDeprioritization;
@@ -174,26 +196,6 @@ public OperationContext(final long id,
this.tracingSpan = tracingSpan;
}
- @VisibleForTesting(otherwise = VisibleForTesting.AccessModifier.PRIVATE)
- public OperationContext(final long id,
- final RequestContext requestContext,
- final SessionContext sessionContext,
- final TimeoutContext timeoutContext,
- final TracingManager tracingManager,
- @Nullable final ServerApi serverApi,
- @Nullable final String operationName) {
- this.id = id;
- this.serverDeprioritization = new ServerDeprioritization();
- this.requestContext = requestContext;
- this.sessionContext = sessionContext;
- this.timeoutContext = timeoutContext;
- this.tracingManager = tracingManager;
- this.serverApi = serverApi;
- this.operationName = operationName;
- this.tracingSpan = null;
- }
-
-
/**
* @return The same {@link ServerDeprioritization} if called on the same {@link OperationContext}.
*/
@@ -217,7 +219,8 @@ public OperationContext withConnectionEstablishmentSessionContext() {
}
public OperationContext withMinRoundTripTime(final ServerDescription serverDescription) {
- return withTimeoutContext(timeoutContext.withMinRoundTripTime(TimeUnit.NANOSECONDS.toMillis(serverDescription.getMinRoundTripTimeNanos())));
+ return withTimeoutContext(
+ timeoutContext.withMinRoundTripTime(TimeUnit.NANOSECONDS.toMillis(serverDescription.getMinRoundTripTimeNanos())));
}
public OperationContext withOverride(final TimeoutContextOverride timeoutContextOverrideFunction) {
@@ -227,26 +230,38 @@ public OperationContext withOverride(final TimeoutContextOverride timeoutContext
public static final class ServerDeprioritization {
@Nullable
private ServerAddress candidate;
+ @Nullable
+ private ClusterType clusterType;
private final Set deprioritized;
- private final DeprioritizingSelector selector;
+ private final boolean enableOverloadRetargeting;
- private ServerDeprioritization() {
- candidate = null;
- deprioritized = new HashSet<>();
- selector = new DeprioritizingSelector();
+ public ServerDeprioritization() {
+ this(false);
+ }
+
+ public ServerDeprioritization(final boolean enableOverloadRetargeting) {
+ this.enableOverloadRetargeting = enableOverloadRetargeting;
+ this.candidate = null;
+ this.deprioritized = new HashSet<>();
+ this.clusterType = null;
}
/**
- * The returned {@link ServerSelector} tries to {@linkplain ServerSelector#select(ClusterDescription) select}
- * only the {@link ServerDescription}s that do not have deprioritized {@link ServerAddress}es.
- * If no such {@link ServerDescription} can be selected, then it selects {@link ClusterDescription#getServerDescriptions()}.
+ * The returned {@link ServerSelector} wraps the provided selector and attempts
+ * {@linkplain ServerSelector#select(ClusterDescription) server selection} in two passes:
+ *
+ * First pass: selects using the wrapped selector with only non-deprioritized {@link ServerDescription}s.
+ * Second pass: if the first pass selects no {@link ServerDescription}s,
+ * selects using the wrapped selector again with all {@link ServerDescription}s, including deprioritized ones.
+ *
*/
- ServerSelector getServerSelector() {
- return selector;
+ ServerSelector apply(final ServerSelector wrappedSelector) {
+ return new DeprioritizingSelector(wrappedSelector);
}
- void updateCandidate(final ServerAddress serverAddress) {
- candidate = serverAddress;
+ void updateCandidate(final ServerAddress serverAddress, final ClusterType clusterType) {
+ this.candidate = serverAddress;
+ this.clusterType = clusterType;
}
public void onAttemptFailure(final Throwable failure) {
@@ -254,7 +269,13 @@ public void onAttemptFailure(final Throwable failure) {
candidate = null;
return;
}
- deprioritized.add(candidate);
+
+ boolean isSystemOverloadedError = failure instanceof MongoException
+ && ((MongoException) failure).hasErrorLabel(SYSTEM_OVERLOADED_ERROR_LABEL);
+
+ if (clusterType == ClusterType.SHARDED || (isSystemOverloadedError && enableOverloadRetargeting)) {
+ deprioritized.add(candidate);
+ }
}
/**
@@ -263,28 +284,46 @@ public void onAttemptFailure(final Throwable failure) {
* which indeed may be used concurrently. {@link DeprioritizingSelector} does not need to be thread-safe.
*/
private final class DeprioritizingSelector implements ServerSelector {
- private DeprioritizingSelector() {
+ private final ServerSelector wrappedSelector;
+
+ private DeprioritizingSelector(final ServerSelector wrappedSelector) {
+ this.wrappedSelector = wrappedSelector;
}
@Override
public List select(final ClusterDescription clusterDescription) {
List serverDescriptions = clusterDescription.getServerDescriptions();
- if (!isEnabled(clusterDescription.getType())) {
- return serverDescriptions;
+
+ // TODO-JAVA-5908: Evaluate whether using the early-return optimization has a meaningful performance impact on server selection.
+ if (serverDescriptions.size() == 1 || deprioritized.isEmpty()) {
+ return wrappedSelector.select(clusterDescription);
}
+
+ // TODO-JAVA-5908: Evaluate whether using a loop instead of Stream has a meaningful performance impact on server selection.
List nonDeprioritizedServerDescriptions = serverDescriptions
.stream()
.filter(serverDescription -> !deprioritized.contains(serverDescription.getAddress()))
.collect(toList());
- return nonDeprioritizedServerDescriptions.isEmpty() ? serverDescriptions : nonDeprioritizedServerDescriptions;
- }
- private boolean isEnabled(final ClusterType clusterType) {
- return clusterType == ClusterType.SHARDED;
+ // TODO-JAVA-5908: Evaluate whether using the early-return optimization has a meaningful performance impact on server selection.
+ if (nonDeprioritizedServerDescriptions.isEmpty()) {
+ return wrappedSelector.select(clusterDescription);
+ }
+
+ List selected = wrappedSelector.select(
+ new ClusterDescription(
+ clusterDescription.getConnectionMode(),
+ clusterDescription.getType(),
+ clusterDescription.getSrvResolutionException(),
+ nonDeprioritizedServerDescriptions,
+ clusterDescription.getClusterSettings(),
+ clusterDescription.getServerSettings()));
+ return selected.isEmpty() ? wrappedSelector.select(clusterDescription) : selected;
}
}
}
- public interface TimeoutContextOverride extends Function {}
+ public interface TimeoutContextOverride extends Function {
+ }
}
diff --git a/driver-core/src/main/com/mongodb/internal/operation/AsyncChangeStreamBatchCursor.java b/driver-core/src/main/com/mongodb/internal/operation/AsyncChangeStreamBatchCursor.java
index ce7127e0dc3..7c32dc41404 100644
--- a/driver-core/src/main/com/mongodb/internal/operation/AsyncChangeStreamBatchCursor.java
+++ b/driver-core/src/main/com/mongodb/internal/operation/AsyncChangeStreamBatchCursor.java
@@ -73,7 +73,9 @@ final class AsyncChangeStreamBatchCursor implements AsyncAggregateResponseBat
this.wrapped = new AtomicReference<>(assertNotNull(wrapped));
this.binding = binding;
binding.retain();
- this.initialOperationContext = operationContext.withOverride(TimeoutContext::withMaxTimeAsMaxAwaitTimeOverride);
+ this.initialOperationContext = operationContext
+ .withOverride(TimeoutContext::withMaxTimeAsMaxAwaitTimeOverride)
+ .withNewServerDeprioritization();
this.resumeToken = resumeToken;
this.maxWireVersion = maxWireVersion;
isClosed = new AtomicBoolean();
diff --git a/driver-core/src/main/com/mongodb/internal/operation/ChangeStreamBatchCursor.java b/driver-core/src/main/com/mongodb/internal/operation/ChangeStreamBatchCursor.java
index cf9f1dcf6c4..226deafa9fa 100644
--- a/driver-core/src/main/com/mongodb/internal/operation/ChangeStreamBatchCursor.java
+++ b/driver-core/src/main/com/mongodb/internal/operation/ChangeStreamBatchCursor.java
@@ -85,7 +85,9 @@ final class ChangeStreamBatchCursor implements AggregateResponseBatchCursor("admin",
new BsonDocument("buildInfo", new BsonInt32(1)), new BsonDocumentCodec())
- .execute(new ClusterBinding(getCluster(), ReadPreference.nearest()), OPERATION_CONTEXT));
+ .execute(new ClusterBinding(getCluster(), ReadPreference.nearest()), createOperationContext()));
}
return serverVersion;
}
- public static final OperationContext OPERATION_CONTEXT = new OperationContext(
- IgnorableRequestContext.INSTANCE,
- new ReadConcernAwareNoOpSessionContext(ReadConcern.DEFAULT),
- new TimeoutContext(TIMEOUT_SETTINGS),
- getServerApi());
+ public static OperationContext createOperationContext() {
+ return new OperationContext(
+ IgnorableRequestContext.INSTANCE,
+ new ReadConcernAwareNoOpSessionContext(ReadConcern.DEFAULT),
+ new TimeoutContext(TIMEOUT_SETTINGS),
+ getServerApi());
+ }
public static final InternalOperationContextFactory OPERATION_CONTEXT_FACTORY =
new InternalOperationContextFactory(TIMEOUT_SETTINGS, getServerApi());
@@ -255,7 +257,7 @@ public static boolean hasEncryptionTestsEnabled() {
public static Document getServerStatus() {
return new CommandReadOperation<>("admin", new BsonDocument("serverStatus", new BsonInt32(1)),
new DocumentCodec())
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), createOperationContext());
}
public static boolean supportsFsync() {
@@ -270,7 +272,7 @@ static class ShutdownHook extends Thread {
public void run() {
if (cluster != null) {
try {
- new DropDatabaseOperation(getDefaultDatabaseName(), WriteConcern.ACKNOWLEDGED).execute(getBinding(), OPERATION_CONTEXT);
+ new DropDatabaseOperation(getDefaultDatabaseName(), WriteConcern.ACKNOWLEDGED).execute(getBinding(), createOperationContext());
} catch (MongoCommandException e) {
// if we do not have permission to drop the database, assume it is cleaned up in some other way
if (!e.getMessage().contains("Command dropDatabase requires authentication")) {
@@ -322,7 +324,7 @@ public static synchronized ConnectionString getConnectionString() {
try {
BsonDocument helloResult = new CommandReadOperation<>("admin",
new BsonDocument(LEGACY_HELLO, new BsonInt32(1)), new BsonDocumentCodec())
- .execute(new ClusterBinding(cluster, ReadPreference.nearest()), OPERATION_CONTEXT);
+ .execute(new ClusterBinding(cluster, ReadPreference.nearest()), createOperationContext());
if (helloResult.containsKey("setName")) {
connectionString = new ConnectionString(DEFAULT_URI + "/?replicaSet="
+ helloResult.getString("setName").getValue());
@@ -374,7 +376,9 @@ public static ReadWriteBinding getBinding(final Cluster cluster) {
}
public static ReadWriteBinding getBinding(final TimeoutSettings timeoutSettings) {
- return getBinding(getCluster(), ReadPreference.primary(), createNewOperationContext(timeoutSettings));
+ return getBinding(getCluster(),
+ ReadPreference.primary(),
+ createOperationContext().withTimeoutContext(new TimeoutContext(timeoutSettings)));
}
public static ReadWriteBinding getBinding(final OperationContext operationContext) {
@@ -382,11 +386,7 @@ public static ReadWriteBinding getBinding(final OperationContext operationContex
}
public static ReadWriteBinding getBinding(final ReadPreference readPreference) {
- return getBinding(getCluster(), readPreference, OPERATION_CONTEXT);
- }
-
- public static OperationContext createNewOperationContext(final TimeoutSettings timeoutSettings) {
- return OPERATION_CONTEXT.withTimeoutContext(new TimeoutContext(timeoutSettings));
+ return getBinding(getCluster(), readPreference, createOperationContext());
}
private static ReadWriteBinding getBinding(final Cluster cluster,
@@ -403,7 +403,7 @@ private static ReadWriteBinding getBinding(final Cluster cluster,
}
public static SingleConnectionBinding getSingleConnectionBinding() {
- return new SingleConnectionBinding(getCluster(), ReadPreference.primary(), OPERATION_CONTEXT);
+ return new SingleConnectionBinding(getCluster(), ReadPreference.primary(), createOperationContext());
}
public static AsyncSingleConnectionBinding getAsyncSingleConnectionBinding() {
@@ -411,7 +411,7 @@ public static AsyncSingleConnectionBinding getAsyncSingleConnectionBinding() {
}
public static AsyncSingleConnectionBinding getAsyncSingleConnectionBinding(final Cluster cluster) {
- return new AsyncSingleConnectionBinding(cluster, ReadPreference.primary(), OPERATION_CONTEXT);
+ return new AsyncSingleConnectionBinding(cluster, ReadPreference.primary(), createOperationContext());
}
public static AsyncReadWriteBinding getAsyncBinding(final Cluster cluster) {
@@ -419,11 +419,11 @@ public static AsyncReadWriteBinding getAsyncBinding(final Cluster cluster) {
}
public static AsyncReadWriteBinding getAsyncBinding() {
- return getAsyncBinding(getAsyncCluster(), ReadPreference.primary(), OPERATION_CONTEXT);
+ return getAsyncBinding(getAsyncCluster(), ReadPreference.primary(), createOperationContext());
}
public static AsyncReadWriteBinding getAsyncBinding(final TimeoutSettings timeoutSettings) {
- return getAsyncBinding(createNewOperationContext(timeoutSettings));
+ return getAsyncBinding(createOperationContext().withTimeoutContext(new TimeoutContext(timeoutSettings)));
}
public static AsyncReadWriteBinding getAsyncBinding(final OperationContext operationContext) {
@@ -431,7 +431,7 @@ public static AsyncReadWriteBinding getAsyncBinding(final OperationContext opera
}
public static AsyncReadWriteBinding getAsyncBinding(final ReadPreference readPreference) {
- return getAsyncBinding(getAsyncCluster(), readPreference, OPERATION_CONTEXT);
+ return getAsyncBinding(getAsyncCluster(), readPreference, createOperationContext());
}
public static AsyncReadWriteBinding getAsyncBinding(
@@ -605,7 +605,7 @@ public static BsonDocument getServerParameters() {
if (serverParameters == null) {
serverParameters = new CommandReadOperation<>("admin",
new BsonDocument("getParameter", new BsonString("*")), new BsonDocumentCodec())
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), createOperationContext());
}
return serverParameters;
}
@@ -673,7 +673,7 @@ public static void configureFailPoint(final BsonDocument failPointDocument) {
if (!isSharded()) {
try {
new CommandReadOperation<>("admin", failPointDocument, new BsonDocumentCodec())
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), createOperationContext());
} catch (MongoCommandException e) {
if (e.getErrorCode() == COMMAND_NOT_FOUND_ERROR_CODE) {
failsPointsSupported = false;
@@ -689,7 +689,7 @@ public static void disableFailPoint(final String failPoint) {
.append("mode", new BsonString("off"));
try {
new CommandReadOperation<>("admin", failPointDocument, new BsonDocumentCodec())
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), createOperationContext());
} catch (MongoCommandException e) {
// ignore
}
@@ -703,7 +703,7 @@ public static T executeSync(final WriteOperation op) {
@SuppressWarnings("overloads")
public static T executeSync(final WriteOperation op, final ReadWriteBinding binding) {
- return op.execute(binding, applySessionContext(OPERATION_CONTEXT, binding.getReadPreference()));
+ return op.execute(binding, applySessionContext(createOperationContext(), binding.getReadPreference()));
}
@SuppressWarnings("overloads")
@@ -713,7 +713,7 @@ public static T executeSync(final ReadOperation op) {
@SuppressWarnings("overloads")
public static T executeSync(final ReadOperation op, final ReadWriteBinding binding) {
- return op.execute(binding, OPERATION_CONTEXT);
+ return op.execute(binding, createOperationContext());
}
@SuppressWarnings("overloads")
@@ -729,7 +729,7 @@ public static T executeAsync(final WriteOperation op) throws Throwable {
@SuppressWarnings("overloads")
public static T executeAsync(final WriteOperation op, final AsyncReadWriteBinding binding) throws Throwable {
FutureResultCallback futureResultCallback = new FutureResultCallback<>();
- op.executeAsync(binding, applySessionContext(OPERATION_CONTEXT, binding.getReadPreference()), futureResultCallback);
+ op.executeAsync(binding, applySessionContext(createOperationContext(), binding.getReadPreference()), futureResultCallback);
return futureResultCallback.get(TIMEOUT, SECONDS);
}
@@ -741,7 +741,7 @@ public static T executeAsync(final ReadOperation, T> op) throws Throwable
@SuppressWarnings("overloads")
public static T executeAsync(final ReadOperation, T> op, final AsyncReadBinding binding) throws Throwable {
FutureResultCallback futureResultCallback = new FutureResultCallback<>();
- op.executeAsync(binding, OPERATION_CONTEXT, futureResultCallback);
+ op.executeAsync(binding, createOperationContext(), futureResultCallback);
return futureResultCallback.get(TIMEOUT, SECONDS);
}
@@ -811,19 +811,19 @@ public static List collectCursorResults(final BatchCursor batchCursor)
public static AsyncConnectionSource getWriteConnectionSource(final AsyncReadWriteBinding binding) throws Throwable {
FutureResultCallback futureResultCallback = new FutureResultCallback<>();
- binding.getWriteConnectionSource(OPERATION_CONTEXT, futureResultCallback);
+ binding.getWriteConnectionSource(createOperationContext(), futureResultCallback);
return futureResultCallback.get(TIMEOUT, SECONDS);
}
public static AsyncConnectionSource getReadConnectionSource(final AsyncReadWriteBinding binding) throws Throwable {
FutureResultCallback futureResultCallback = new FutureResultCallback<>();
- binding.getReadConnectionSource(OPERATION_CONTEXT, futureResultCallback);
+ binding.getReadConnectionSource(createOperationContext(), futureResultCallback);
return futureResultCallback.get(TIMEOUT, SECONDS);
}
public static AsyncConnection getConnection(final AsyncConnectionSource source) throws Throwable {
FutureResultCallback futureResultCallback = new FutureResultCallback<>();
- source.getConnection(OPERATION_CONTEXT, futureResultCallback);
+ source.getConnection(createOperationContext(), futureResultCallback);
return futureResultCallback.get(TIMEOUT, SECONDS);
}
@@ -866,7 +866,7 @@ private static OperationContext applySessionContext(final OperationContext opera
return operationContext.withSessionContext(simpleSessionContext);
}
- public static OperationContext getOperationContext(final ReadPreference readPreference) {
- return applySessionContext(OPERATION_CONTEXT, readPreference);
+ public static OperationContext createOperationContext(final ReadPreference readPreference) {
+ return applySessionContext(createOperationContext(), readPreference);
}
}
diff --git a/driver-core/src/test/functional/com/mongodb/OperationFunctionalSpecification.groovy b/driver-core/src/test/functional/com/mongodb/OperationFunctionalSpecification.groovy
index 6648edc50c7..a0dd685d4b3 100644
--- a/driver-core/src/test/functional/com/mongodb/OperationFunctionalSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/OperationFunctionalSpecification.groovy
@@ -61,7 +61,7 @@ import spock.lang.Specification
import java.util.concurrent.TimeUnit
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.TIMEOUT
import static com.mongodb.ClusterFixture.checkReferenceCountReachesTarget
import static com.mongodb.ClusterFixture.executeAsync
@@ -108,7 +108,7 @@ class OperationFunctionalSpecification extends Specification {
void acknowledgeWrite(final SingleConnectionBinding binding) {
new MixedBulkWriteOperation(getNamespace(), [new InsertRequest(new BsonDocument())], true,
- ACKNOWLEDGED, false).execute(binding, OPERATION_CONTEXT)
+ ACKNOWLEDGED, false).execute(binding, createOperationContext())
binding.release()
}
@@ -279,7 +279,7 @@ class OperationFunctionalSpecification extends Specification {
BsonDocument expectedCommand=null, Boolean checkSecondaryOk=false,
ReadPreference readPreference=ReadPreference.primary(), Boolean retryable = false,
ServerType serverType = ServerType.STANDALONE, Boolean activeTransaction = false) {
- def operationContext = OPERATION_CONTEXT
+ def operationContext = createOperationContext()
.withSessionContext(Stub(SessionContext) {
hasActiveTransaction() >> activeTransaction
getReadConcern() >> readConcern
@@ -353,7 +353,7 @@ class OperationFunctionalSpecification extends Specification {
Boolean checkCommand = true, BsonDocument expectedCommand = null, Boolean checkSecondaryOk = false,
ReadPreference readPreference = ReadPreference.primary(), Boolean retryable = false,
ServerType serverType = ServerType.STANDALONE, Boolean activeTransaction = false) {
- def operationContext = OPERATION_CONTEXT
+ def operationContext = createOperationContext()
.withSessionContext(Stub(SessionContext) {
hasActiveTransaction() >> activeTransaction
getReadConcern() >> readConcern
@@ -447,7 +447,7 @@ class OperationFunctionalSpecification extends Specification {
}
}
- def operationContext = OPERATION_CONTEXT.withSessionContext(
+ def operationContext = createOperationContext().withSessionContext(
Stub(SessionContext) {
hasSession() >> true
hasActiveTransaction() >> false
@@ -488,7 +488,7 @@ class OperationFunctionalSpecification extends Specification {
}
}
- def operationContext = OPERATION_CONTEXT.withSessionContext(
+ def operationContext = createOperationContext().withSessionContext(
Stub(SessionContext) {
hasSession() >> true
hasActiveTransaction() >> false
diff --git a/driver-core/src/test/functional/com/mongodb/client/test/CollectionHelper.java b/driver-core/src/test/functional/com/mongodb/client/test/CollectionHelper.java
index 935c2979fc4..e6c28d9d5bc 100644
--- a/driver-core/src/test/functional/com/mongodb/client/test/CollectionHelper.java
+++ b/driver-core/src/test/functional/com/mongodb/client/test/CollectionHelper.java
@@ -16,6 +16,7 @@
package com.mongodb.client.test;
+import com.mongodb.ClusterFixture;
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoCommandException;
import com.mongodb.MongoNamespace;
@@ -72,7 +73,6 @@
import java.util.Optional;
import java.util.stream.Collectors;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.executeAsync;
import static com.mongodb.ClusterFixture.getBinding;
import static java.lang.String.format;
@@ -93,7 +93,7 @@ public CollectionHelper(final Codec codec, final MongoNamespace namespace) {
public T hello() {
return new CommandReadOperation<>("admin", BsonDocument.parse("{isMaster: 1}"), codec)
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), ClusterFixture.createOperationContext());
}
public static void drop(final MongoNamespace namespace) {
@@ -106,7 +106,7 @@ public static void drop(final MongoNamespace namespace, final WriteConcern write
boolean success = false;
while (!success) {
try {
- new DropCollectionOperation(namespace, writeConcern).execute(getBinding(), OPERATION_CONTEXT);
+ new DropCollectionOperation(namespace, writeConcern).execute(getBinding(), ClusterFixture.createOperationContext());
success = true;
} catch (MongoWriteConcernException e) {
LOGGER.info("Retrying drop collection after a write concern error: " + e);
@@ -131,7 +131,7 @@ public static void dropDatabase(final String name, final WriteConcern writeConce
return;
}
try {
- new DropDatabaseOperation(name, writeConcern).execute(getBinding(), OPERATION_CONTEXT);
+ new DropDatabaseOperation(name, writeConcern).execute(getBinding(), ClusterFixture.createOperationContext());
} catch (MongoCommandException e) {
if (!e.getErrorMessage().contains("ns not found")) {
throw e;
@@ -141,7 +141,7 @@ public static void dropDatabase(final String name, final WriteConcern writeConce
public static BsonDocument getCurrentClusterTime() {
return new CommandReadOperation("admin", new BsonDocument("ping", new BsonInt32(1)), new BsonDocumentCodec())
- .execute(getBinding(), OPERATION_CONTEXT).getDocument("$clusterTime", null);
+ .execute(getBinding(), ClusterFixture.createOperationContext()).getDocument("$clusterTime", null);
}
public MongoNamespace getNamespace() {
@@ -235,7 +235,7 @@ public void create(final String collectionName, final CreateCollectionOptions op
boolean success = false;
while (!success) {
try {
- operation.execute(getBinding(), OPERATION_CONTEXT);
+ operation.execute(getBinding(), ClusterFixture.createOperationContext());
success = true;
} catch (MongoCommandException e) {
if ("Interrupted".equals(e.getErrorCodeName())) {
@@ -254,7 +254,7 @@ public void killCursor(final MongoNamespace namespace, final ServerCursor server
.append("cursors", new BsonArray(singletonList(new BsonInt64(serverCursor.getId()))));
try {
new CommandReadOperation<>(namespace.getDatabaseName(), command, new BsonDocumentCodec())
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), ClusterFixture.createOperationContext());
} catch (Exception e) {
// Ignore any exceptions killing old cursors
}
@@ -286,7 +286,7 @@ public void insertDocuments(final List documents, final WriteConce
for (BsonDocument document : documents) {
insertRequests.add(new InsertRequest(document));
}
- new MixedBulkWriteOperation(namespace, insertRequests, true, writeConcern, false).execute(binding, OPERATION_CONTEXT);
+ new MixedBulkWriteOperation(namespace, insertRequests, true, writeConcern, false).execute(binding, ClusterFixture.createOperationContext());
}
public void insertDocuments(final Document... documents) {
@@ -329,7 +329,7 @@ public List find() {
public Optional listSearchIndex(final String indexName) {
ListSearchIndexesOperation listSearchIndexesOperation =
new ListSearchIndexesOperation<>(namespace, codec, indexName, null, null, null, null, true);
- BatchCursor cursor = listSearchIndexesOperation.execute(getBinding(), OPERATION_CONTEXT);
+ BatchCursor cursor = listSearchIndexesOperation.execute(getBinding(), ClusterFixture.createOperationContext());
List results = new ArrayList<>();
while (cursor.hasNext()) {
@@ -342,13 +342,13 @@ public Optional listSearchIndex(final String indexName) {
public void createSearchIndex(final SearchIndexRequest searchIndexModel) {
CreateSearchIndexesOperation searchIndexesOperation =
new CreateSearchIndexesOperation(namespace, singletonList(searchIndexModel));
- searchIndexesOperation.execute(getBinding(), OPERATION_CONTEXT);
+ searchIndexesOperation.execute(getBinding(), ClusterFixture.createOperationContext());
}
public List find(final Codec codec) {
BatchCursor cursor = new FindOperation<>(namespace, codec)
.sort(new BsonDocument("_id", new BsonInt32(1)))
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), ClusterFixture.createOperationContext());
List results = new ArrayList<>();
while (cursor.hasNext()) {
results.addAll(cursor.next());
@@ -367,7 +367,7 @@ public void updateOne(final Bson filter, final Bson update, final boolean isUpse
WriteRequest.Type.UPDATE)
.upsert(isUpsert)),
true, WriteConcern.ACKNOWLEDGED, false)
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), ClusterFixture.createOperationContext());
}
public void replaceOne(final Bson filter, final Bson update, final boolean isUpsert) {
@@ -377,7 +377,7 @@ public void replaceOne(final Bson filter, final Bson update, final boolean isUps
WriteRequest.Type.REPLACE)
.upsert(isUpsert)),
true, WriteConcern.ACKNOWLEDGED, false)
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), ClusterFixture.createOperationContext());
}
public void deleteOne(final Bson filter) {
@@ -392,7 +392,7 @@ private void delete(final Bson filter, final boolean multi) {
new MixedBulkWriteOperation(namespace,
singletonList(new DeleteRequest(filter.toBsonDocument(Document.class, registry)).multi(multi)),
true, WriteConcern.ACKNOWLEDGED, false)
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), ClusterFixture.createOperationContext());
}
public List find(final Bson filter) {
@@ -417,7 +417,7 @@ private List aggregate(final List pipeline, final Decoder decode
bsonDocumentPipeline.add(cur.toBsonDocument(Document.class, registry));
}
BatchCursor cursor = new AggregateOperation<>(namespace, bsonDocumentPipeline, decoder, level)
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), ClusterFixture.createOperationContext());
List results = new ArrayList<>();
while (cursor.hasNext()) {
results.addAll(cursor.next());
@@ -452,7 +452,7 @@ public List find(final BsonDocument filter, final BsonDocument sort, fina
public List find(final BsonDocument filter, final BsonDocument sort, final BsonDocument projection, final Decoder decoder) {
BatchCursor cursor = new FindOperation<>(namespace, decoder).filter(filter).sort(sort)
- .projection(projection).execute(getBinding(), OPERATION_CONTEXT);
+ .projection(projection).execute(getBinding(), ClusterFixture.createOperationContext());
List results = new ArrayList<>();
while (cursor.hasNext()) {
results.addAll(cursor.next());
@@ -465,7 +465,7 @@ public long count() {
}
public long count(final ReadBinding binding) {
- return new CountDocumentsOperation(namespace).execute(binding, OPERATION_CONTEXT);
+ return new CountDocumentsOperation(namespace).execute(binding, ClusterFixture.createOperationContext());
}
public long count(final AsyncReadWriteBinding binding) throws Throwable {
@@ -474,7 +474,7 @@ public long count(final AsyncReadWriteBinding binding) throws Throwable {
public long count(final Bson filter) {
return new CountDocumentsOperation(namespace)
- .filter(toBsonDocument(filter)).execute(getBinding(), OPERATION_CONTEXT);
+ .filter(toBsonDocument(filter)).execute(getBinding(), ClusterFixture.createOperationContext());
}
public BsonDocument wrap(final Document document) {
@@ -487,36 +487,36 @@ public BsonDocument toBsonDocument(final Bson document) {
public void createIndex(final BsonDocument key) {
new CreateIndexesOperation(namespace, singletonList(new IndexRequest(key)), WriteConcern.ACKNOWLEDGED)
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), ClusterFixture.createOperationContext());
}
public void createIndex(final Document key) {
new CreateIndexesOperation(namespace, singletonList(new IndexRequest(wrap(key))), WriteConcern.ACKNOWLEDGED)
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), ClusterFixture.createOperationContext());
}
public void createUniqueIndex(final Document key) {
new CreateIndexesOperation(namespace, singletonList(new IndexRequest(wrap(key)).unique(true)),
WriteConcern.ACKNOWLEDGED)
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), ClusterFixture.createOperationContext());
}
public void createIndex(final Document key, final String defaultLanguage) {
new CreateIndexesOperation(namespace,
singletonList(new IndexRequest(wrap(key)).defaultLanguage(defaultLanguage)), WriteConcern.ACKNOWLEDGED).execute(
- getBinding(), OPERATION_CONTEXT);
+ getBinding(), ClusterFixture.createOperationContext());
}
public void createIndex(final Bson key) {
new CreateIndexesOperation(namespace,
singletonList(new IndexRequest(key.toBsonDocument(Document.class, registry))), WriteConcern.ACKNOWLEDGED).execute(
- getBinding(), OPERATION_CONTEXT);
+ getBinding(), ClusterFixture.createOperationContext());
}
public List listIndexes(){
List indexes = new ArrayList<>();
BatchCursor cursor = new ListIndexesOperation<>(namespace, new BsonDocumentCodec())
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), ClusterFixture.createOperationContext());
while (cursor.hasNext()) {
indexes.addAll(cursor.next());
}
@@ -526,7 +526,7 @@ public List listIndexes(){
public static void killAllSessions() {
try {
new CommandReadOperation<>("admin",
- new BsonDocument("killAllSessions", new BsonArray()), new BsonDocumentCodec()).execute(getBinding(), OPERATION_CONTEXT);
+ new BsonDocument("killAllSessions", new BsonArray()), new BsonDocumentCodec()).execute(getBinding(), ClusterFixture.createOperationContext());
} catch (MongoCommandException e) {
// ignore exception caused by killing the implicit session that the killAllSessions command itself is running in
}
@@ -537,7 +537,7 @@ public void renameCollection(final MongoNamespace newNamespace) {
new CommandReadOperation<>("admin",
new BsonDocument("renameCollection", new BsonString(getNamespace().getFullName()))
.append("to", new BsonString(newNamespace.getFullName())), new BsonDocumentCodec()).execute(
- getBinding(), OPERATION_CONTEXT);
+ getBinding(), ClusterFixture.createOperationContext());
} catch (MongoCommandException e) {
// do nothing
}
@@ -549,11 +549,11 @@ public void runAdminCommand(final String command) {
public void runAdminCommand(final BsonDocument command) {
new CommandReadOperation<>("admin", command, new BsonDocumentCodec())
- .execute(getBinding(), OPERATION_CONTEXT);
+ .execute(getBinding(), ClusterFixture.createOperationContext());
}
public void runAdminCommand(final BsonDocument command, final ReadPreference readPreference) {
new CommandReadOperation<>("admin", command, new BsonDocumentCodec())
- .execute(getBinding(readPreference), OPERATION_CONTEXT);
+ .execute(getBinding(readPreference), ClusterFixture.createOperationContext());
}
}
diff --git a/driver-core/src/test/functional/com/mongodb/connection/ConnectionSpecification.groovy b/driver-core/src/test/functional/com/mongodb/connection/ConnectionSpecification.groovy
index 5658ec5ea43..5dd6145f063 100644
--- a/driver-core/src/test/functional/com/mongodb/connection/ConnectionSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/connection/ConnectionSpecification.groovy
@@ -17,13 +17,14 @@
package com.mongodb.connection
import com.mongodb.OperationFunctionalSpecification
+import com.mongodb.internal.connection.OperationContext
import com.mongodb.internal.operation.CommandReadOperation
import org.bson.BsonDocument
import org.bson.BsonInt32
import org.bson.codecs.BsonDocumentCodec
import static com.mongodb.ClusterFixture.LEGACY_HELLO
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getBinding
import static com.mongodb.connection.ConnectionDescription.getDefaultMaxMessageSize
import static com.mongodb.connection.ConnectionDescription.getDefaultMaxWriteBatchSize
@@ -32,8 +33,9 @@ class ConnectionSpecification extends OperationFunctionalSpecification {
def 'should have id'() {
when:
- def source = getBinding().getReadConnectionSource(OPERATION_CONTEXT)
- def connection = source.getConnection(OPERATION_CONTEXT)
+ def operationContext = createOperationContext()
+ def source = getBinding().getReadConnectionSource(operationContext)
+ def connection = source.getConnection(operationContext)
then:
connection.getDescription().getConnectionId() != null
@@ -45,13 +47,14 @@ class ConnectionSpecification extends OperationFunctionalSpecification {
def 'should have description'() {
when:
- def commandResult = getHelloResult()
+ def operationContext = createOperationContext()
+ def commandResult = getHelloResult(operationContext)
def expectedMaxMessageSize = commandResult.getNumber('maxMessageSizeBytes',
new BsonInt32(getDefaultMaxMessageSize())).intValue()
def expectedMaxBatchCount = commandResult.getNumber('maxWriteBatchSize',
new BsonInt32(getDefaultMaxWriteBatchSize())).intValue()
- def source = getBinding().getReadConnectionSource(OPERATION_CONTEXT)
- def connection = source.getConnection(OPERATION_CONTEXT)
+ def source = getBinding().getReadConnectionSource(operationContext)
+ def connection = source.getConnection(operationContext)
then:
connection.description.serverAddress == source.getServerDescription().getAddress()
@@ -64,8 +67,8 @@ class ConnectionSpecification extends OperationFunctionalSpecification {
connection?.release()
source?.release()
}
- private static BsonDocument getHelloResult() {
+ private static BsonDocument getHelloResult(OperationContext operationContext) {
new CommandReadOperation('admin', new BsonDocument(LEGACY_HELLO, new BsonInt32(1)),
- new BsonDocumentCodec()).execute(getBinding(), OPERATION_CONTEXT)
+ new BsonDocumentCodec()).execute(getBinding(), operationContext)
}
}
diff --git a/driver-core/src/test/functional/com/mongodb/connection/netty/NettyStreamSpecification.groovy b/driver-core/src/test/functional/com/mongodb/connection/netty/NettyStreamSpecification.groovy
index e582e0fc398..8747b8c75b9 100644
--- a/driver-core/src/test/functional/com/mongodb/connection/netty/NettyStreamSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/connection/netty/NettyStreamSpecification.groovy
@@ -18,7 +18,7 @@ import com.mongodb.spock.Slow
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getSslSettings
class NettyStreamSpecification extends Specification {
@@ -43,7 +43,7 @@ class NettyStreamSpecification extends Specification {
def stream = factory.create(new ServerAddress())
when:
- stream.open(OPERATION_CONTEXT)
+ stream.open(createOperationContext())
then:
!stream.isClosed()
@@ -69,7 +69,7 @@ class NettyStreamSpecification extends Specification {
def stream = factory.create(new ServerAddress())
when:
- stream.open(OPERATION_CONTEXT)
+ stream.open(createOperationContext())
then:
thrown(MongoSocketOpenException)
@@ -96,7 +96,7 @@ class NettyStreamSpecification extends Specification {
def callback = new CallbackErrorHolder()
when:
- stream.openAsync(OPERATION_CONTEXT, callback)
+ stream.openAsync(createOperationContext(), callback)
then:
callback.getError().is(exception)
diff --git a/driver-core/src/test/functional/com/mongodb/internal/binding/AsyncSessionBindingSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/binding/AsyncSessionBindingSpecification.groovy
index 173cd9f0935..81ab2ead1e2 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/binding/AsyncSessionBindingSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/binding/AsyncSessionBindingSpecification.groovy
@@ -16,17 +16,17 @@
package com.mongodb.internal.binding
+import com.mongodb.ClusterFixture
import com.mongodb.internal.async.SingleResultCallback
import spock.lang.Specification
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
-
class AsyncSessionBindingSpecification extends Specification {
def 'should wrap the passed in async binding'() {
given:
def wrapped = Mock(AsyncReadWriteBinding)
def binding = new AsyncSessionBinding(wrapped)
+ def operationContext = ClusterFixture.createOperationContext()
when:
binding.getCount()
@@ -52,17 +52,18 @@ class AsyncSessionBindingSpecification extends Specification {
then:
1 * wrapped.release()
+
when:
- binding.getReadConnectionSource(OPERATION_CONTEXT, Stub(SingleResultCallback))
+ binding.getReadConnectionSource(operationContext, Stub(SingleResultCallback))
then:
- 1 * wrapped.getReadConnectionSource(OPERATION_CONTEXT, _)
+ 1 * wrapped.getReadConnectionSource(operationContext, _)
when:
- binding.getWriteConnectionSource(OPERATION_CONTEXT, Stub(SingleResultCallback))
+ binding.getWriteConnectionSource(operationContext, Stub(SingleResultCallback))
then:
- 1 * wrapped.getWriteConnectionSource(OPERATION_CONTEXT, _)
+ 1 * wrapped.getWriteConnectionSource(operationContext, _)
}
}
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncSocketChannelStreamSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncSocketChannelStreamSpecification.groovy
index 85f23350984..2660693eccf 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncSocketChannelStreamSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncSocketChannelStreamSpecification.groovy
@@ -13,7 +13,7 @@ import com.mongodb.spock.Slow
import java.util.concurrent.CountDownLatch
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getSslSettings
import static java.util.concurrent.TimeUnit.MILLISECONDS
@@ -40,7 +40,7 @@ class AsyncSocketChannelStreamSpecification extends Specification {
def stream = factory.create(new ServerAddress('host1'))
when:
- stream.open(OPERATION_CONTEXT)
+ stream.open(createOperationContext())
then:
!stream.isClosed()
@@ -66,7 +66,7 @@ class AsyncSocketChannelStreamSpecification extends Specification {
def stream = factory.create(new ServerAddress())
when:
- stream.open(OPERATION_CONTEXT)
+ stream.open(createOperationContext())
then:
thrown(MongoSocketOpenException)
@@ -90,7 +90,7 @@ class AsyncSocketChannelStreamSpecification extends Specification {
def callback = new CallbackErrorHolder()
when:
- stream.openAsync(OPERATION_CONTEXT, callback)
+ stream.openAsync(createOperationContext(), callback)
then:
callback.getError().is(exception)
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncStreamTimeoutsSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncStreamTimeoutsSpecification.groovy
index 3589362b8ac..fc4cd8be576 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncStreamTimeoutsSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/AsyncStreamTimeoutsSpecification.groovy
@@ -30,7 +30,7 @@ import com.mongodb.spock.Slow
import java.util.concurrent.TimeUnit
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getCredentialWithCache
import static com.mongodb.ClusterFixture.getServerApi
import static com.mongodb.ClusterFixture.getSslSettings
@@ -49,7 +49,7 @@ class AsyncStreamTimeoutsSpecification extends OperationFunctionalSpecification
.create(new ServerId(new ClusterId(), new ServerAddress(new InetSocketAddress('192.168.255.255', 27017))))
when:
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
then:
thrown(MongoSocketOpenException)
@@ -63,7 +63,7 @@ class AsyncStreamTimeoutsSpecification extends OperationFunctionalSpecification
new ServerAddress(new InetSocketAddress('192.168.255.255', 27017))))
when:
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
then:
thrown(MongoSocketOpenException)
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/AwsAuthenticationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/AwsAuthenticationSpecification.groovy
index 8dd53bc1c03..501be77d6d9 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/AwsAuthenticationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/AwsAuthenticationSpecification.groovy
@@ -19,7 +19,7 @@ import spock.lang.Specification
import java.util.function.Supplier
import static com.mongodb.AuthenticationMechanism.MONGODB_AWS
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getClusterConnectionMode
import static com.mongodb.ClusterFixture.getConnectionString
import static com.mongodb.ClusterFixture.getCredential
@@ -52,7 +52,7 @@ class AwsAuthenticationSpecification extends Specification {
when:
openConnection(connection, async)
executeCommand(getConnectionString().getDatabase(), new BsonDocument('count', new BsonString('test')),
- getClusterConnectionMode(), null, connection, OPERATION_CONTEXT)
+ getClusterConnectionMode(), null, connection, createOperationContext())
then:
thrown(MongoCommandException)
@@ -71,7 +71,7 @@ class AwsAuthenticationSpecification extends Specification {
when:
openConnection(connection, async)
executeCommand(getConnectionString().getDatabase(), new BsonDocument('count', new BsonString('test')),
- getClusterConnectionMode(), null, connection, OPERATION_CONTEXT)
+ getClusterConnectionMode(), null, connection, createOperationContext())
then:
true
@@ -101,7 +101,7 @@ class AwsAuthenticationSpecification extends Specification {
when:
openConnection(connection, async)
executeCommand(getConnectionString().getDatabase(), new BsonDocument('count', new BsonString('test')),
- getClusterConnectionMode(), null, connection, OPERATION_CONTEXT)
+ getClusterConnectionMode(), null, connection, createOperationContext())
then:
true
@@ -160,10 +160,10 @@ class AwsAuthenticationSpecification extends Specification {
private static void openConnection(final InternalConnection connection, final boolean async) {
if (async) {
FutureResultCallback futureResultCallback = new FutureResultCallback()
- connection.openAsync(OPERATION_CONTEXT, futureResultCallback)
+ connection.openAsync(createOperationContext(), futureResultCallback)
futureResultCallback.get(ClusterFixture.TIMEOUT, SECONDS)
} else {
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
}
}
}
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/CommandHelperSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/CommandHelperSpecification.groovy
index f1585f82595..ec5f3644549 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/CommandHelperSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/CommandHelperSpecification.groovy
@@ -31,7 +31,7 @@ import java.util.concurrent.CountDownLatch
import static com.mongodb.ClusterFixture.CLIENT_METADATA
import static com.mongodb.ClusterFixture.LEGACY_HELLO
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getClusterConnectionMode
import static com.mongodb.ClusterFixture.getCredentialWithCache
import static com.mongodb.ClusterFixture.getPrimary
@@ -48,7 +48,7 @@ class CommandHelperSpecification extends Specification {
new NettyStreamFactory(SocketSettings.builder().build(), getSslSettings()),
getCredentialWithCache(), CLIENT_METADATA, [], LoggerSettings.builder().build(), null, getServerApi())
.create(new ServerId(new ClusterId(), getPrimary()))
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
}
def cleanup() {
@@ -62,7 +62,7 @@ class CommandHelperSpecification extends Specification {
Throwable receivedException = null
def latch1 = new CountDownLatch(1)
executeCommandAsync('admin', new BsonDocument(LEGACY_HELLO, new BsonInt32(1)), getClusterConnectionMode(),
- getServerApi(), connection, OPERATION_CONTEXT)
+ getServerApi(), connection, createOperationContext())
{ document, exception -> receivedDocument = document; receivedException = exception; latch1.countDown() }
latch1.await()
@@ -74,7 +74,7 @@ class CommandHelperSpecification extends Specification {
when:
def latch2 = new CountDownLatch(1)
executeCommandAsync('admin', new BsonDocument('non-existent-command', new BsonInt32(1)), getClusterConnectionMode(),
- getServerApi(), connection, OPERATION_CONTEXT)
+ getServerApi(), connection, createOperationContext())
{ document, exception -> receivedDocument = document; receivedException = exception; latch2.countDown() }
latch2.await()
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/DefaultConnectionPoolTest.java b/driver-core/src/test/functional/com/mongodb/internal/connection/DefaultConnectionPoolTest.java
index 81e778b4a61..5187f692459 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/DefaultConnectionPoolTest.java
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/DefaultConnectionPoolTest.java
@@ -16,6 +16,7 @@
package com.mongodb.internal.connection;
+import com.mongodb.ClusterFixture;
import com.mongodb.MongoConnectionPoolClearedException;
import com.mongodb.MongoServerUnavailableException;
import com.mongodb.ServerAddress;
@@ -60,7 +61,6 @@
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Stream;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.OPERATION_CONTEXT_FACTORY;
import static com.mongodb.ClusterFixture.TIMEOUT_SETTINGS;
import static com.mongodb.ClusterFixture.createOperationContext;
@@ -173,7 +173,7 @@ public void shouldThrowOnPoolClosed() {
String expectedExceptionMessage = "The server at 127.0.0.1:27017 is no longer available";
MongoServerUnavailableException exception;
- exception = assertThrows(MongoServerUnavailableException.class, () -> provider.get(OPERATION_CONTEXT));
+ exception = assertThrows(MongoServerUnavailableException.class, () -> provider.get(ClusterFixture.createOperationContext()));
assertEquals(expectedExceptionMessage, exception.getMessage());
SupplyingCallback supplyingCallback = new SupplyingCallback<>();
provider.getAsync(createOperationContext(TIMEOUT_SETTINGS.withMaxWaitTimeMS(50)), supplyingCallback);
@@ -194,10 +194,10 @@ public void shouldExpireConnectionAfterMaxLifeTime() throws InterruptedException
provider.ready();
// when
- provider.get(OPERATION_CONTEXT).close();
+ provider.get(ClusterFixture.createOperationContext()).close();
sleep(100);
provider.doMaintenance();
- provider.get(OPERATION_CONTEXT);
+ provider.get(ClusterFixture.createOperationContext());
// then
assertTrue(connectionFactory.getNumCreatedConnections() >= 2); // should really be two, but it's racy
@@ -215,7 +215,7 @@ public void shouldExpireConnectionAfterLifeTimeOnClose() throws InterruptedExcep
provider.ready();
// when
- InternalConnection connection = provider.get(OPERATION_CONTEXT);
+ InternalConnection connection = provider.get(ClusterFixture.createOperationContext());
sleep(50);
connection.close();
@@ -236,10 +236,10 @@ public void shouldExpireConnectionAfterMaxIdleTime() throws InterruptedException
provider.ready();
// when
- provider.get(OPERATION_CONTEXT).close();
+ provider.get(ClusterFixture.createOperationContext()).close();
sleep(100);
provider.doMaintenance();
- provider.get(OPERATION_CONTEXT);
+ provider.get(ClusterFixture.createOperationContext());
// then
assertTrue(connectionFactory.getNumCreatedConnections() >= 2); // should really be two, but it's racy
@@ -258,10 +258,10 @@ public void shouldCloseConnectionAfterExpiration() throws InterruptedException {
provider.ready();
// when
- provider.get(OPERATION_CONTEXT).close();
+ provider.get(ClusterFixture.createOperationContext()).close();
sleep(50);
provider.doMaintenance();
- provider.get(OPERATION_CONTEXT);
+ provider.get(ClusterFixture.createOperationContext());
// then
assertTrue(connectionFactory.getCreatedConnections().get(0).isClosed());
@@ -280,10 +280,10 @@ public void shouldCreateNewConnectionAfterExpiration() throws InterruptedExcepti
provider.ready();
// when
- provider.get(OPERATION_CONTEXT).close();
+ provider.get(ClusterFixture.createOperationContext()).close();
sleep(50);
provider.doMaintenance();
- InternalConnection secondConnection = provider.get(OPERATION_CONTEXT);
+ InternalConnection secondConnection = provider.get(ClusterFixture.createOperationContext());
// then
assertNotNull(secondConnection);
@@ -302,7 +302,7 @@ public void shouldPruneAfterMaintenanceTaskRuns() throws InterruptedException {
.build(),
mockSdamProvider(), OPERATION_CONTEXT_FACTORY);
provider.ready();
- provider.get(OPERATION_CONTEXT).close();
+ provider.get(ClusterFixture.createOperationContext()).close();
// when
@@ -322,7 +322,7 @@ void infiniteMaxSize() {
List connections = new ArrayList<>();
try {
for (int i = 0; i < 2 * defaultMaxSize; i++) {
- connections.add(provider.get(OPERATION_CONTEXT));
+ connections.add(provider.get(ClusterFixture.createOperationContext()));
}
} finally {
connections.forEach(connection -> {
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/GSSAPIAuthenticationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/GSSAPIAuthenticationSpecification.groovy
index cc3e0401bb5..fa649022aaa 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/GSSAPIAuthenticationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/GSSAPIAuthenticationSpecification.groovy
@@ -36,7 +36,7 @@ import javax.security.auth.Subject
import javax.security.auth.login.LoginContext
import static com.mongodb.AuthenticationMechanism.GSSAPI
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getClusterConnectionMode
import static com.mongodb.ClusterFixture.getConnectionString
import static com.mongodb.ClusterFixture.getCredential
@@ -58,7 +58,7 @@ class GSSAPIAuthenticationSpecification extends Specification {
when:
openConnection(connection, async)
executeCommand(getConnectionString().getDatabase(), new BsonDocument('count', new BsonString('test')),
- getClusterConnectionMode(), null, connection, OPERATION_CONTEXT)
+ getClusterConnectionMode(), null, connection, createOperationContext())
then:
thrown(MongoCommandException)
@@ -77,7 +77,7 @@ class GSSAPIAuthenticationSpecification extends Specification {
when:
openConnection(connection, async)
executeCommand(getConnectionString().getDatabase(), new BsonDocument('count', new BsonString('test')),
- getClusterConnectionMode(), null, connection, OPERATION_CONTEXT)
+ getClusterConnectionMode(), null, connection, createOperationContext())
then:
true
@@ -99,7 +99,7 @@ class GSSAPIAuthenticationSpecification extends Specification {
when:
openConnection(connection, async)
executeCommand(getConnectionString().getDatabase(), new BsonDocument('count', new BsonString('test')),
- getClusterConnectionMode(), null, connection, OPERATION_CONTEXT)
+ getClusterConnectionMode(), null, connection, createOperationContext())
then:
thrown(MongoSecurityException)
@@ -131,7 +131,7 @@ class GSSAPIAuthenticationSpecification extends Specification {
def connection = createConnection(async, getMongoCredential(subject))
openConnection(connection, async)
executeCommand(getConnectionString().getDatabase(), new BsonDocument('count', new BsonString('test')),
- getClusterConnectionMode(), null, connection, OPERATION_CONTEXT)
+ getClusterConnectionMode(), null, connection, createOperationContext())
then:
true
@@ -175,7 +175,7 @@ class GSSAPIAuthenticationSpecification extends Specification {
def connection = createConnection(async, getMongoCredential(saslClientProperties))
openConnection(connection, async)
executeCommand(getConnectionString().getDatabase(), new BsonDocument('count', new BsonString('test')),
- getClusterConnectionMode(), null, connection, OPERATION_CONTEXT)
+ getClusterConnectionMode(), null, connection, createOperationContext())
then:
true
@@ -219,10 +219,10 @@ class GSSAPIAuthenticationSpecification extends Specification {
private static void openConnection(final InternalConnection connection, final boolean async) {
if (async) {
FutureResultCallback futureResultCallback = new FutureResultCallback()
- connection.openAsync(OPERATION_CONTEXT, futureResultCallback)
+ connection.openAsync(createOperationContext(), futureResultCallback)
futureResultCallback.get(ClusterFixture.TIMEOUT, SECONDS)
} else {
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
}
}
}
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/GSSAPIAuthenticatorSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/GSSAPIAuthenticatorSpecification.groovy
index 223698d561c..f7fd3534960 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/GSSAPIAuthenticatorSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/GSSAPIAuthenticatorSpecification.groovy
@@ -30,7 +30,7 @@ import spock.lang.Specification
import javax.security.auth.login.LoginContext
import static com.mongodb.AuthenticationMechanism.GSSAPI
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getLoginContextName
import static com.mongodb.ClusterFixture.getPrimary
import static com.mongodb.ClusterFixture.getServerApi
@@ -57,7 +57,7 @@ class GSSAPIAuthenticatorSpecification extends Specification {
.create(new ServerId(new ClusterId(), getPrimary()))
when:
- internalConnection.open(OPERATION_CONTEXT)
+ internalConnection.open(createOperationContext())
then:
1 * subjectProvider.getSubject() >> subject
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/PlainAuthenticationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/PlainAuthenticationSpecification.groovy
index e8c2a408220..b1078711f7d 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/PlainAuthenticationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/PlainAuthenticationSpecification.groovy
@@ -32,7 +32,7 @@ import spock.lang.IgnoreIf
import spock.lang.Specification
import static com.mongodb.AuthenticationMechanism.PLAIN
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getClusterConnectionMode
import static com.mongodb.ClusterFixture.getConnectionString
import static com.mongodb.ClusterFixture.getCredential
@@ -52,7 +52,7 @@ class PlainAuthenticationSpecification extends Specification {
when:
openConnection(connection, async)
executeCommand(getConnectionString().getDatabase(), new BsonDocument('count', new BsonString('test')),
- getClusterConnectionMode(), null, connection, OPERATION_CONTEXT)
+ getClusterConnectionMode(), null, connection, createOperationContext())
then:
thrown(MongoCommandException)
@@ -71,7 +71,7 @@ class PlainAuthenticationSpecification extends Specification {
when:
openConnection(connection, async)
executeCommand(getConnectionString().getDatabase(), new BsonDocument('count', new BsonString('test')),
- getClusterConnectionMode(), null, connection, OPERATION_CONTEXT)
+ getClusterConnectionMode(), null, connection, createOperationContext())
then:
true
@@ -90,7 +90,7 @@ class PlainAuthenticationSpecification extends Specification {
when:
openConnection(connection, async)
executeCommand(getConnectionString().getDatabase(), new BsonDocument('count', new BsonString('test')),
- getClusterConnectionMode(), null, connection, OPERATION_CONTEXT)
+ getClusterConnectionMode(), null, connection, createOperationContext())
then:
thrown(MongoSecurityException)
@@ -123,10 +123,10 @@ class PlainAuthenticationSpecification extends Specification {
private static void openConnection(final InternalConnection connection, final boolean async) {
if (async) {
FutureResultCallback futureResultCallback = new FutureResultCallback()
- connection.openAsync(OPERATION_CONTEXT, futureResultCallback)
+ connection.openAsync(createOperationContext(), futureResultCallback)
futureResultCallback.get(ClusterFixture.TIMEOUT, SECONDS)
} else {
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
}
}
}
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/PlainAuthenticatorTest.java b/driver-core/src/test/functional/com/mongodb/internal/connection/PlainAuthenticatorTest.java
index b95b9c96894..6fb9f48d078 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/PlainAuthenticatorTest.java
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/PlainAuthenticatorTest.java
@@ -16,6 +16,7 @@
package com.mongodb.internal.connection;
+import com.mongodb.ClusterFixture;
import com.mongodb.LoggerSettings;
import com.mongodb.MongoCredential;
import com.mongodb.MongoSecurityException;
@@ -33,7 +34,6 @@
import java.util.Collections;
import static com.mongodb.ClusterFixture.CLIENT_METADATA;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.getClusterConnectionMode;
import static com.mongodb.ClusterFixture.getServerApi;
import static com.mongodb.ClusterFixture.getSslSettings;
@@ -69,14 +69,14 @@ public void tearDown() {
public void testSuccessfulAuthentication() {
PlainAuthenticator authenticator = new PlainAuthenticator(getCredentialWithCache(userName, source, password.toCharArray()),
getClusterConnectionMode(), getServerApi());
- authenticator.authenticate(internalConnection, connectionDescription, OPERATION_CONTEXT);
+ authenticator.authenticate(internalConnection, connectionDescription, ClusterFixture.createOperationContext());
}
@Test(expected = MongoSecurityException.class)
public void testUnsuccessfulAuthentication() {
PlainAuthenticator authenticator = new PlainAuthenticator(getCredentialWithCache(userName, source, "wrong".toCharArray()),
getClusterConnectionMode(), getServerApi());
- authenticator.authenticate(internalConnection, connectionDescription, OPERATION_CONTEXT);
+ authenticator.authenticate(internalConnection, connectionDescription, ClusterFixture.createOperationContext());
}
private static MongoCredentialWithCache getCredentialWithCache(final String userName, final String source, final char[] password) {
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/ScramSha256AuthenticationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/ScramSha256AuthenticationSpecification.groovy
index 36aac9b6908..b5baa3837f3 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/ScramSha256AuthenticationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/ScramSha256AuthenticationSpecification.groovy
@@ -33,7 +33,7 @@ import org.bson.codecs.DocumentCodec
import spock.lang.IgnoreIf
import spock.lang.Specification
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.createAsyncCluster
import static com.mongodb.ClusterFixture.createCluster
import static com.mongodb.ClusterFixture.getBinding
@@ -88,12 +88,12 @@ class ScramSha256AuthenticationSpecification extends Specification {
def binding = getBinding()
new CommandReadOperation<>('admin',
new BsonDocumentWrapper(createUserCommand, new DocumentCodec()), new DocumentCodec())
- .execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ .execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
}
def dropUser(final String userName) {
def binding = getBinding()
- def operationContext = ClusterFixture.getOperationContext(binding.getReadPreference())
+ def operationContext = ClusterFixture.createOperationContext(binding.getReadPreference())
new CommandReadOperation<>('admin', new BsonDocument('dropUser', new BsonString(userName)),
new BsonDocumentCodec()).execute(binding, operationContext)
}
@@ -105,7 +105,7 @@ class ScramSha256AuthenticationSpecification extends Specification {
when:
new CommandReadOperation('admin',
new BsonDocumentWrapper(new Document('dbstats', 1), new DocumentCodec()), new DocumentCodec())
- .execute(new ClusterBinding(cluster, ReadPreference.primary()), OPERATION_CONTEXT)
+ .execute(new ClusterBinding(cluster, ReadPreference.primary()), createOperationContext())
then:
noExceptionThrown()
@@ -128,7 +128,7 @@ class ScramSha256AuthenticationSpecification extends Specification {
def binding = new AsyncClusterBinding(cluster, ReadPreference.primary())
new CommandReadOperation('admin',
new BsonDocumentWrapper(new Document('dbstats', 1), new DocumentCodec()), new DocumentCodec())
- .executeAsync(binding, OPERATION_CONTEXT, callback)
+ .executeAsync(binding, createOperationContext(), callback)
callback.get()
then:
@@ -148,7 +148,7 @@ class ScramSha256AuthenticationSpecification extends Specification {
when:
new CommandReadOperation('admin',
new BsonDocumentWrapper(new Document('dbstats', 1), new DocumentCodec()), new DocumentCodec())
- .execute(new ClusterBinding(cluster, ReadPreference.primary()), OPERATION_CONTEXT)
+ .execute(new ClusterBinding(cluster, ReadPreference.primary()), createOperationContext())
then:
thrown(MongoSecurityException)
@@ -168,7 +168,7 @@ class ScramSha256AuthenticationSpecification extends Specification {
when:
new CommandReadOperation('admin',
new BsonDocumentWrapper(new Document('dbstats', 1), new DocumentCodec()), new DocumentCodec())
- .executeAsync(new AsyncClusterBinding(cluster, ReadPreference.primary()), OPERATION_CONTEXT,
+ .executeAsync(new AsyncClusterBinding(cluster, ReadPreference.primary()), createOperationContext(),
callback)
callback.get()
@@ -189,7 +189,7 @@ class ScramSha256AuthenticationSpecification extends Specification {
when:
new CommandReadOperation('admin',
new BsonDocumentWrapper(new Document('dbstats', 1), new DocumentCodec()), new DocumentCodec())
- .execute(new ClusterBinding(cluster, ReadPreference.primary()), OPERATION_CONTEXT)
+ .execute(new ClusterBinding(cluster, ReadPreference.primary()), createOperationContext())
then:
noExceptionThrown()
@@ -209,7 +209,7 @@ class ScramSha256AuthenticationSpecification extends Specification {
when:
new CommandReadOperation('admin',
new BsonDocumentWrapper(new Document('dbstats', 1), new DocumentCodec()), new DocumentCodec())
- .executeAsync(new AsyncClusterBinding(cluster, ReadPreference.primary()), OPERATION_CONTEXT,
+ .executeAsync(new AsyncClusterBinding(cluster, ReadPreference.primary()), createOperationContext(),
callback)
callback.get()
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/ServerHelper.java b/driver-core/src/test/functional/com/mongodb/internal/connection/ServerHelper.java
index 0295e8c1f9f..8e9b2385ee5 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/ServerHelper.java
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/ServerHelper.java
@@ -23,7 +23,6 @@
import com.mongodb.internal.binding.AsyncConnectionSource;
import com.mongodb.internal.selector.ServerAddressSelector;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.getAsyncCluster;
import static com.mongodb.ClusterFixture.getCluster;
import static com.mongodb.assertions.Assertions.fail;
@@ -54,7 +53,7 @@ public static void waitForLastRelease(final Cluster cluster) {
public static void waitForLastRelease(final ServerAddress address, final Cluster cluster) {
ConcurrentPool pool = connectionPool(
- cluster.selectServer(new ServerAddressSelector(address), OPERATION_CONTEXT).getServer());
+ cluster.selectServer(new ServerAddressSelector(address), ClusterFixture.createOperationContext()).getServer());
long startTime = System.currentTimeMillis();
while (pool.getInUseCount() > 0) {
try {
@@ -70,7 +69,7 @@ public static void waitForLastRelease(final ServerAddress address, final Cluster
}
private static ConcurrentPool getConnectionPool(final ServerAddress address, final Cluster cluster) {
- return connectionPool(cluster.selectServer(new ServerAddressSelector(address), OPERATION_CONTEXT).getServer());
+ return connectionPool(cluster.selectServer(new ServerAddressSelector(address), ClusterFixture.createOperationContext()).getServer());
}
private static void checkPool(final ServerAddress address, final Cluster cluster) {
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/SingleServerClusterTest.java b/driver-core/src/test/functional/com/mongodb/internal/connection/SingleServerClusterTest.java
index 62fa6c27032..a624a27454c 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/SingleServerClusterTest.java
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/SingleServerClusterTest.java
@@ -16,6 +16,7 @@
package com.mongodb.internal.connection;
+import com.mongodb.ClusterFixture;
import com.mongodb.LoggerSettings;
import com.mongodb.ReadPreference;
import com.mongodb.ServerAddress;
@@ -37,7 +38,6 @@
import java.util.Collections;
import static com.mongodb.ClusterFixture.CLIENT_METADATA;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.OPERATION_CONTEXT_FACTORY;
import static com.mongodb.ClusterFixture.getCredential;
import static com.mongodb.ClusterFixture.getDefaultDatabaseName;
@@ -93,7 +93,7 @@ public void shouldGetServerWithOkDescription() {
setUpCluster(getPrimary());
// when
- ServerTuple serverTuple = cluster.selectServer(clusterDescription -> getPrimaries(clusterDescription), OPERATION_CONTEXT);
+ ServerTuple serverTuple = cluster.selectServer(clusterDescription -> getPrimaries(clusterDescription), ClusterFixture.createOperationContext());
// then
assertTrue(serverTuple.getServerDescription().isOk());
@@ -102,7 +102,7 @@ public void shouldGetServerWithOkDescription() {
@Test
public void shouldSuccessfullyQueryASecondaryWithPrimaryReadPreference() {
// given
- OperationContext operationContext = OPERATION_CONTEXT;
+ OperationContext operationContext = ClusterFixture.createOperationContext();
ServerAddress secondary = getSecondary();
setUpCluster(secondary);
String collectionName = getClass().getName();
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/SocketStreamHelperSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/SocketStreamHelperSpecification.groovy
index 68a82fcbf74..ef0e7d09264 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/SocketStreamHelperSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/SocketStreamHelperSpecification.groovy
@@ -33,7 +33,6 @@ import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory
import java.lang.reflect.Method
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
import static com.mongodb.ClusterFixture.TIMEOUT_SETTINGS
import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getPrimary
@@ -87,7 +86,7 @@ class SocketStreamHelperSpecification extends Specification {
when:
SocketStreamHelper.initialize(
- OPERATION_CONTEXT.withTimeoutContext(new TimeoutContext(
+ createOperationContext().withTimeoutContext(new TimeoutContext(
new TimeoutSettings(
1,
100,
@@ -110,7 +109,8 @@ class SocketStreamHelperSpecification extends Specification {
Socket socket = SocketFactory.default.createSocket()
when:
- SocketStreamHelper.initialize(OPERATION_CONTEXT, socket, getSocketAddresses(getPrimary(), new DefaultInetAddressResolver()).get(0),
+ SocketStreamHelper.initialize(createOperationContext(), socket, getSocketAddresses(getPrimary(),
+ new DefaultInetAddressResolver()).get(0),
SocketSettings.builder().build(), SslSettings.builder().build())
then:
@@ -126,7 +126,8 @@ class SocketStreamHelperSpecification extends Specification {
SSLSocket socket = SSLSocketFactory.default.createSocket()
when:
- SocketStreamHelper.initialize(OPERATION_CONTEXT, socket, getSocketAddresses(getPrimary(), new DefaultInetAddressResolver()).get(0),
+ SocketStreamHelper.initialize(createOperationContext(), socket, getSocketAddresses(getPrimary(),
+ new DefaultInetAddressResolver()).get(0),
SocketSettings.builder().build(), sslSettings)
then:
@@ -147,7 +148,8 @@ class SocketStreamHelperSpecification extends Specification {
SSLSocket socket = SSLSocketFactory.default.createSocket()
when:
- SocketStreamHelper.initialize(OPERATION_CONTEXT, socket, getSocketAddresses(getPrimary(), new DefaultInetAddressResolver()).get(0),
+ SocketStreamHelper.initialize(createOperationContext(), socket, getSocketAddresses(getPrimary(),
+ new DefaultInetAddressResolver()).get(0),
SocketSettings.builder().build(), sslSettings)
then:
@@ -166,7 +168,8 @@ class SocketStreamHelperSpecification extends Specification {
Socket socket = SocketFactory.default.createSocket()
when:
- SocketStreamHelper.initialize(OPERATION_CONTEXT, socket, getSocketAddresses(getPrimary(), new DefaultInetAddressResolver()).get(0),
+ SocketStreamHelper.initialize(createOperationContext(), socket, getSocketAddresses(getPrimary(),
+ new DefaultInetAddressResolver()).get(0),
SocketSettings.builder().build(), SslSettings.builder().enabled(true).build())
then:
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/StreamSocketAddressSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/connection/StreamSocketAddressSpecification.groovy
index 0283ce44f7b..520dd3932de 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/StreamSocketAddressSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/StreamSocketAddressSpecification.groovy
@@ -13,7 +13,7 @@ import com.mongodb.spock.Slow
import javax.net.SocketFactory
import java.util.concurrent.TimeUnit
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getSslSettings
class StreamSocketAddressSpecification extends Specification {
@@ -44,7 +44,7 @@ class StreamSocketAddressSpecification extends Specification {
def socketStream = new SocketStream(serverAddress, null, socketSettings, sslSettings, socketFactory, bufferProvider)
when:
- socketStream.open(OPERATION_CONTEXT)
+ socketStream.open(createOperationContext())
then:
!socket0.isConnected()
@@ -83,7 +83,7 @@ class StreamSocketAddressSpecification extends Specification {
def socketStream = new SocketStream(serverAddress, inetAddressResolver, socketSettings, sslSettings, socketFactory, bufferProvider)
when:
- socketStream.open(OPERATION_CONTEXT)
+ socketStream.open(createOperationContext())
then:
thrown(MongoSocketOpenException)
diff --git a/driver-core/src/test/functional/com/mongodb/internal/connection/TlsChannelStreamFunctionalTest.java b/driver-core/src/test/functional/com/mongodb/internal/connection/TlsChannelStreamFunctionalTest.java
index 3af1eaa33e1..46e0cc6f964 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/connection/TlsChannelStreamFunctionalTest.java
+++ b/driver-core/src/test/functional/com/mongodb/internal/connection/TlsChannelStreamFunctionalTest.java
@@ -184,11 +184,11 @@ void shouldNotCallBeginHandshakeMoreThenOnceDuringTlsSessionEstablishment() thro
.build());
Stream stream = streamFactory.create(getPrimaryServerDescription().getAddress());
- stream.open(ClusterFixture.OPERATION_CONTEXT);
+ stream.open(ClusterFixture.createOperationContext());
ByteBuf wrap = new ByteBufNIO(ByteBuffer.wrap(new byte[]{1, 3, 4}));
//when
- stream.write(Collections.singletonList(wrap), ClusterFixture.OPERATION_CONTEXT);
+ stream.write(Collections.singletonList(wrap), ClusterFixture.createOperationContext());
//then
SECONDS.sleep(5);
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/AggregateOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/AggregateOperationSpecification.groovy
index aa7506d6516..a39b7ca6448 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/AggregateOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/AggregateOperationSpecification.groovy
@@ -52,12 +52,11 @@ import org.bson.codecs.BsonDocumentCodec
import org.bson.codecs.DocumentCodec
import spock.lang.IgnoreIf
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
import static com.mongodb.ClusterFixture.collectCursorResults
import static com.mongodb.ClusterFixture.executeAsync
import static com.mongodb.ClusterFixture.getAsyncCluster
import static com.mongodb.ClusterFixture.getCluster
-import static com.mongodb.ClusterFixture.getOperationContext
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.isSharded
import static com.mongodb.ClusterFixture.isStandalone
import static com.mongodb.ExplainVerbosity.QUERY_PLANNER
@@ -232,7 +231,7 @@ class AggregateOperationSpecification extends OperationFunctionalSpecification {
def binding = ClusterFixture.getBinding(ClusterFixture.getCluster())
new CreateViewOperation(getDatabaseName(), viewName, getCollectionName(), [], WriteConcern.ACKNOWLEDGED)
- .execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ .execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
when:
AggregateOperation operation = new AggregateOperation(viewNamespace, [], new DocumentCodec())
@@ -246,7 +245,7 @@ class AggregateOperationSpecification extends OperationFunctionalSpecification {
cleanup:
binding = ClusterFixture.getBinding(ClusterFixture.getCluster())
new DropCollectionOperation(viewNamespace, WriteConcern.ACKNOWLEDGED)
- .execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ .execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
where:
async << [true, false]
@@ -273,7 +272,7 @@ class AggregateOperationSpecification extends OperationFunctionalSpecification {
.allowDiskUse(allowDiskUse)
def binding = ClusterFixture.getBinding()
- def cursor = operation.execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
then:
cursor.next()*.getString('name') == ['Pete', 'Sam', 'Pete']
@@ -288,7 +287,7 @@ class AggregateOperationSpecification extends OperationFunctionalSpecification {
.batchSize(batchSize)
def binding = ClusterFixture.getBinding()
- def cursor = operation.execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
then:
cursor.next()*.getString('name') == ['Pete', 'Sam', 'Pete']
@@ -356,7 +355,7 @@ class AggregateOperationSpecification extends OperationFunctionalSpecification {
def binding = ClusterFixture.getBinding()
new CommandReadOperation<>(getDatabaseName(), new BsonDocument('profile', new BsonInt32(2)),
- new BsonDocumentCodec()).execute(binding, getOperationContext(binding.getReadPreference()))
+ new BsonDocumentCodec()).execute(binding, createOperationContext(binding.getReadPreference()))
def expectedComment = 'this is a comment'
def operation = new AggregateOperation(getNamespace(), [], new DocumentCodec())
.comment(new BsonString(expectedComment))
@@ -372,7 +371,7 @@ class AggregateOperationSpecification extends OperationFunctionalSpecification {
cleanup:
binding = ClusterFixture.getBinding()
new CommandReadOperation<>(getDatabaseName(), new BsonDocument('profile', new BsonInt32(0)),
- new BsonDocumentCodec()).execute(binding, getOperationContext(binding.getReadPreference()))
+ new BsonDocumentCodec()).execute(binding, createOperationContext(binding.getReadPreference()))
profileCollectionHelper.drop()
where:
@@ -381,7 +380,7 @@ class AggregateOperationSpecification extends OperationFunctionalSpecification {
def 'should add read concern to command'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
def binding = Stub(ReadBinding)
def source = Stub(ConnectionSource)
def connection = Mock(Connection)
@@ -423,7 +422,7 @@ class AggregateOperationSpecification extends OperationFunctionalSpecification {
def 'should add read concern to command asynchronously'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
def binding = Stub(AsyncReadBinding)
def source = Stub(AsyncConnectionSource)
def connection = Mock(AsyncConnection)
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/AggregateToCollectionOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/AggregateToCollectionOperationSpecification.groovy
index 6ebdcdc6b40..a14c4323fdd 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/AggregateToCollectionOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/AggregateToCollectionOperationSpecification.groovy
@@ -278,7 +278,7 @@ class AggregateToCollectionOperationSpecification extends OperationFunctionalSpe
def profileCollectionHelper = getCollectionHelper(new MongoNamespace(getDatabaseName(), 'system.profile'))
def binding = getBinding()
new CommandReadOperation<>(getDatabaseName(), new BsonDocument('profile', new BsonInt32(2)),
- new BsonDocumentCodec()).execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ new BsonDocumentCodec()).execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
def expectedComment = 'this is a comment'
AggregateToCollectionOperation operation = createOperation(getNamespace(),
[Aggregates.out('outputCollection').toBsonDocument(BsonDocument, registry)], ACKNOWLEDGED)
@@ -293,7 +293,7 @@ class AggregateToCollectionOperationSpecification extends OperationFunctionalSpe
cleanup:
new CommandReadOperation<>(getDatabaseName(), new BsonDocument('profile', new BsonInt32(0)),
- new BsonDocumentCodec()).execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ new BsonDocumentCodec()).execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
profileCollectionHelper.drop()
where:
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/AsyncCommandBatchCursorFunctionalTest.java b/driver-core/src/test/functional/com/mongodb/internal/operation/AsyncCommandBatchCursorFunctionalTest.java
index 58e3e47ba74..103a18df32e 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/AsyncCommandBatchCursorFunctionalTest.java
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/AsyncCommandBatchCursorFunctionalTest.java
@@ -17,6 +17,7 @@
package com.mongodb.internal.operation;
+import com.mongodb.ClusterFixture;
import com.mongodb.MongoCursorNotFoundException;
import com.mongodb.MongoQueryException;
import com.mongodb.ReadPreference;
@@ -55,7 +56,6 @@
import java.util.stream.IntStream;
import java.util.stream.Stream;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.checkReferenceCountReachesTarget;
import static com.mongodb.ClusterFixture.getAsyncBinding;
import static com.mongodb.ClusterFixture.getConnection;
@@ -111,7 +111,7 @@ void cleanup() {
void shouldExhaustCursorAsyncWithMultipleBatches() {
// given
BsonDocument commandResult = executeFindCommand(0, 3); // Fetch in batches of size 3
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new AsyncCommandCursor<>(commandResult, 3, DOCUMENT_DECODER, null, connectionSource, connection));
// when
@@ -133,7 +133,7 @@ void shouldExhaustCursorAsyncWithMultipleBatches() {
void shouldExhaustCursorAsyncWithClosedCursor() {
// given
BsonDocument commandResult = executeFindCommand(0, 3);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new AsyncCommandCursor<>(commandResult, 3, DOCUMENT_DECODER, null, connectionSource, connection));
cursor.close();
@@ -156,7 +156,7 @@ void shouldExhaustCursorAsyncWithEmptyCursor() {
getCollectionHelper().deleteMany(Filters.empty());
BsonDocument commandResult = executeFindCommand(0, 3); // No documents to fetch
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new AsyncCommandCursor<>(commandResult, 3, DOCUMENT_DECODER, null, connectionSource, connection));
// when
@@ -175,7 +175,7 @@ void theServerCursorShouldNotBeNull() {
BsonDocument commandResult = executeFindCommand(2);
AsyncCommandCursor coreCursor =
new AsyncCommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
coreCursor);
assertNotNull(coreCursor.getServerCursor());
@@ -187,7 +187,7 @@ void shouldGetExceptionsForOperationsOnTheCursorAfterClosing() {
BsonDocument commandResult = executeFindCommand(5);
AsyncCommandCursor coreCursor =
new AsyncCommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
coreCursor);
cursor.close();
@@ -202,7 +202,7 @@ void shouldGetExceptionsForOperationsOnTheCursorAfterClosing() {
@DisplayName("should throw an Exception when going off the end")
void shouldThrowAnExceptionWhenGoingOffTheEnd() {
BsonDocument commandResult = executeFindCommand(2, 1);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new AsyncCommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection));
cursorNext();
@@ -216,7 +216,7 @@ void shouldThrowAnExceptionWhenGoingOffTheEnd() {
@DisplayName("test normal exhaustion")
void testNormalExhaustion() {
BsonDocument commandResult = executeFindCommand();
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new AsyncCommandCursor<>(commandResult, 3, DOCUMENT_DECODER, null, connectionSource, connection));
assertEquals(10, cursorFlatten().size());
@@ -227,7 +227,7 @@ void testNormalExhaustion() {
@DisplayName("test limit exhaustion")
void testLimitExhaustion(final int limit, final int batchSize, final int expectedTotal) {
BsonDocument commandResult = executeFindCommand(limit, batchSize);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new AsyncCommandCursor<>(commandResult, batchSize, DOCUMENT_DECODER, null, connectionSource, connection));
@@ -246,7 +246,7 @@ void shouldBlockWaitingForNextBatchOnATailableCursor(final boolean awaitData, fi
BsonDocument commandResult = executeFindCommand(new BsonDocument("ts",
new BsonDocument("$gte", new BsonTimestamp(5, 0))), 0, 2, true, awaitData);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, maxTimeMS, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, maxTimeMS, ClusterFixture.createOperationContext(),
new AsyncCommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
assertFalse(cursor.isClosed());
@@ -269,7 +269,7 @@ void testTailableInterrupt() throws InterruptedException {
BsonDocument commandResult = executeFindCommand(new BsonDocument("ts",
new BsonDocument("$gte", new BsonTimestamp(5, 0))), 0, 2, true, true);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new AsyncCommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
CountDownLatch latch = new CountDownLatch(1);
@@ -304,7 +304,7 @@ void shouldKillCursorIfLimitIsReachedOnInitialQuery() {
BsonDocument commandResult = executeFindCommand(5, 10);
AsyncCommandCursor coreCursor =
new AsyncCommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
coreCursor);
assertNotNull(cursorNext());
@@ -319,7 +319,7 @@ void shouldKillCursorIfLimitIsReachedOnGetMore() {
BsonDocument commandResult = executeFindCommand(5, 3);
AsyncCommandCursor coreCursor =
new AsyncCommandCursor<>(commandResult, 3, DOCUMENT_DECODER, null, connectionSource, connection);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
coreCursor);
ServerCursor serverCursor = coreCursor.getServerCursor();
@@ -341,7 +341,7 @@ void shouldReleaseConnectionSourceIfLimitIsReachedOnInitialQuery() {
BsonDocument commandResult = executeFindCommand(5, 10);
AsyncCommandCursor coreCursor =
new AsyncCommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
coreCursor);
assertDoesNotThrow(() -> checkReferenceCountReachesTarget(connectionSource, 1));
@@ -354,7 +354,7 @@ void shouldReleaseConnectionSourceIfLimitIsReachedOnInitialQuery() {
void shouldReleaseConnectionSourceIfLimitIsReachedOnGetMore() {
assumeFalse(isSharded());
BsonDocument commandResult = executeFindCommand(5, 3);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new AsyncCommandCursor<>(commandResult, 3, DOCUMENT_DECODER, null, connectionSource, connection));
assertNotNull(cursorNext());
@@ -367,7 +367,7 @@ void shouldReleaseConnectionSourceIfLimitIsReachedOnGetMore() {
@DisplayName("test limit with get more")
void testLimitWithGetMore() {
BsonDocument commandResult = executeFindCommand(5, 2);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new AsyncCommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
assertNotNull(cursorNext());
@@ -390,7 +390,7 @@ void testLimitWithLargeDocuments() {
);
BsonDocument commandResult = executeFindCommand(300, 0);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new AsyncCommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection));
assertEquals(300, cursorFlatten().size());
@@ -400,7 +400,7 @@ void testLimitWithLargeDocuments() {
@DisplayName("should respect batch size")
void shouldRespectBatchSize() {
BsonDocument commandResult = executeFindCommand(2);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new AsyncCommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
assertEquals(2, cursor.getBatchSize());
@@ -419,7 +419,7 @@ void shouldThrowCursorNotFoundException() throws Throwable {
BsonDocument commandResult = executeFindCommand(2);
AsyncCommandCursor coreCursor =
new AsyncCommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection);
- cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new AsyncCommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
coreCursor);
ServerCursor serverCursor = coreCursor.getServerCursor();
@@ -428,7 +428,7 @@ void shouldThrowCursorNotFoundException() throws Throwable {
this.block(cb -> localConnection.commandAsync(getNamespace().getDatabaseName(),
new BsonDocument("killCursors", new BsonString(getNamespace().getCollectionName()))
.append("cursors", new BsonArray(singletonList(new BsonInt64(serverCursor.getId())))),
- NoOpFieldNameValidator.INSTANCE, ReadPreference.primary(), new BsonDocumentCodec(), OPERATION_CONTEXT, cb));
+ NoOpFieldNameValidator.INSTANCE, ReadPreference.primary(), new BsonDocumentCodec(), ClusterFixture.createOperationContext(), cb));
localConnection.release();
cursorNext();
@@ -494,7 +494,7 @@ private BsonDocument executeFindCommand(final BsonDocument filter, final int lim
BsonDocument results = block(cb -> connection.commandAsync(getDatabaseName(), findCommand,
NoOpFieldNameValidator.INSTANCE, readPreference, CommandResultDocumentCodec.create(DOCUMENT_DECODER, FIRST_BATCH),
- OPERATION_CONTEXT, cb));
+ ClusterFixture.createOperationContext(), cb));
assertNotNull(results);
return results;
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/ChangeStreamOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/ChangeStreamOperationSpecification.groovy
index 19285eda077..f2374e92160 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/ChangeStreamOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/ChangeStreamOperationSpecification.groovy
@@ -53,7 +53,7 @@ import org.bson.codecs.DocumentCodec
import org.bson.codecs.ValueCodecProvider
import spock.lang.IgnoreIf
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getAsyncCluster
import static com.mongodb.ClusterFixture.getCluster
import static com.mongodb.ClusterFixture.isStandalone
@@ -635,7 +635,7 @@ class ChangeStreamOperationSpecification extends OperationFunctionalSpecificatio
def 'should set the startAtOperationTime on the sync cursor'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(
+ def operationContext = createOperationContext().withSessionContext(
Stub(SessionContext) {
getReadConcern() >> ReadConcern.DEFAULT
getOperationTime() >> new BsonTimestamp()
@@ -690,7 +690,7 @@ class ChangeStreamOperationSpecification extends OperationFunctionalSpecificatio
def 'should set the startAtOperationTime on the async cursor'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(
+ def operationContext = createOperationContext().withSessionContext(
Stub(SessionContext) {
getReadConcern() >> ReadConcern.DEFAULT
getOperationTime() >> new BsonTimestamp()
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/CommandBatchCursorFunctionalTest.java b/driver-core/src/test/functional/com/mongodb/internal/operation/CommandBatchCursorFunctionalTest.java
index 407b03f5246..946e5504db3 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/CommandBatchCursorFunctionalTest.java
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/CommandBatchCursorFunctionalTest.java
@@ -27,6 +27,7 @@
import com.mongodb.client.model.OperationTest;
import com.mongodb.internal.binding.ConnectionSource;
import com.mongodb.internal.connection.Connection;
+import com.mongodb.internal.connection.OperationContext;
import com.mongodb.internal.validator.NoOpFieldNameValidator;
import org.bson.BsonArray;
import org.bson.BsonBoolean;
@@ -55,7 +56,6 @@
import java.util.stream.IntStream;
import java.util.stream.Stream;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.checkReferenceCountReachesTarget;
import static com.mongodb.ClusterFixture.getBinding;
import static com.mongodb.ClusterFixture.getReferenceCountAfterTimeout;
@@ -87,8 +87,9 @@ void setup() {
.collect(Collectors.toList());
getCollectionHelper().insertDocuments(documents);
- connectionSource = getBinding().getWriteConnectionSource(ClusterFixture.OPERATION_CONTEXT);
- connection = connectionSource.getConnection(ClusterFixture.OPERATION_CONTEXT);
+ OperationContext operationContext = ClusterFixture.createOperationContext();
+ connectionSource = getBinding().getWriteConnectionSource(operationContext);
+ connection = connectionSource.getConnection(operationContext);
}
@AfterEach
@@ -109,7 +110,7 @@ void cleanup() {
void shouldExhaustCursorWithMultipleBatches() {
// given
BsonDocument commandResult = executeFindCommand(0, 3); // Fetch in batches of size 3
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 3, DOCUMENT_DECODER, null, connectionSource, connection));
// when
@@ -127,7 +128,7 @@ void shouldExhaustCursorWithMultipleBatches() {
void shouldExhaustCursorWithClosedCursor() {
// given
BsonDocument commandResult = executeFindCommand(0, 3);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 3, DOCUMENT_DECODER, null, connectionSource, connection));
cursor.close();
@@ -143,7 +144,7 @@ void shouldExhaustCursorWithEmptyCursor() {
getCollectionHelper().deleteMany(Filters.empty());
BsonDocument commandResult = executeFindCommand(0, 3); // No documents to fetch
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 3, DOCUMENT_DECODER, null, connectionSource, connection));
// when
@@ -157,7 +158,7 @@ void shouldExhaustCursorWithEmptyCursor() {
@DisplayName("server cursor should not be null")
void theServerCursorShouldNotBeNull() {
BsonDocument commandResult = executeFindCommand(2);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection));
assertNotNull(cursor.getServerCursor());
@@ -167,7 +168,7 @@ void theServerCursorShouldNotBeNull() {
@DisplayName("test server address should not be null")
void theServerAddressShouldNotNull() {
BsonDocument commandResult = executeFindCommand();
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection));
assertNotNull(cursor.getServerAddress());
@@ -177,7 +178,7 @@ void theServerAddressShouldNotNull() {
@DisplayName("should get Exceptions for operations on the cursor after closing")
void shouldGetExceptionsForOperationsOnTheCursorAfterClosing() {
BsonDocument commandResult = executeFindCommand();
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection));
cursor.close();
@@ -192,7 +193,7 @@ void shouldGetExceptionsForOperationsOnTheCursorAfterClosing() {
@DisplayName("should throw an Exception when going off the end")
void shouldThrowAnExceptionWhenGoingOffTheEnd() {
BsonDocument commandResult = executeFindCommand(1);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection));
cursor.next();
@@ -204,7 +205,7 @@ void shouldThrowAnExceptionWhenGoingOffTheEnd() {
@DisplayName("test cursor remove")
void testCursorRemove() {
BsonDocument commandResult = executeFindCommand();
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection));
assertThrows(UnsupportedOperationException.class, () -> cursor.remove());
@@ -214,7 +215,7 @@ void testCursorRemove() {
@DisplayName("test normal exhaustion")
void testNormalExhaustion() {
BsonDocument commandResult = executeFindCommand();
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection));
assertEquals(10, cursorFlatten().size());
@@ -225,7 +226,7 @@ void testNormalExhaustion() {
@DisplayName("test limit exhaustion")
void testLimitExhaustion(final int limit, final int batchSize, final int expectedTotal) {
BsonDocument commandResult = executeFindCommand(limit, batchSize);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection));
assertEquals(expectedTotal, cursorFlatten().size());
@@ -244,7 +245,7 @@ void shouldBlockWaitingForNextBatchOnATailableCursor(final boolean awaitData, fi
BsonDocument commandResult = executeFindCommand(new BsonDocument("ts",
new BsonDocument("$gte", new BsonTimestamp(5, 0))), 0, 2, true, awaitData);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, maxTimeMS, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, maxTimeMS, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
assertTrue(cursor.hasNext());
@@ -267,7 +268,7 @@ void testTryNextWithTailable() {
BsonDocument commandResult = executeFindCommand(new BsonDocument("ts",
new BsonDocument("$gte", new BsonTimestamp(5, 0))), 0, 2, true, true);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
List nextBatch = cursor.tryNext();
@@ -293,7 +294,7 @@ void hasNextShouldThrowWhenCursorIsClosedInAnotherThread() throws InterruptedExc
BsonDocument commandResult = executeFindCommand(new BsonDocument("ts",
new BsonDocument("$gte", new BsonTimestamp(5, 0))), 0, 2, true, true);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
assertTrue(cursor.hasNext());
@@ -320,7 +321,7 @@ void testMaxTimeMS() {
long maxTimeMS = 500;
BsonDocument commandResult = executeFindCommand(new BsonDocument("ts",
new BsonDocument("$gte", new BsonTimestamp(5, 0))), 0, 2, true, true);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, maxTimeMS, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, maxTimeMS, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
List nextBatch = cursor.tryNext();
@@ -344,7 +345,7 @@ void testTailableInterrupt() throws InterruptedException {
BsonDocument commandResult = executeFindCommand(new BsonDocument("ts",
new BsonDocument("$gte", new BsonTimestamp(5, 0))), 0, 2, true, true);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
CountDownLatch latch = new CountDownLatch(1);
@@ -377,7 +378,7 @@ void testTailableInterrupt() throws InterruptedException {
void shouldKillCursorIfLimitIsReachedOnInitialQuery() {
assumeFalse(isSharded());
BsonDocument commandResult = executeFindCommand(5, 10);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection));
assertNotNull(cursor.next());
@@ -390,7 +391,7 @@ void shouldKillCursorIfLimitIsReachedOnInitialQuery() {
void shouldKillCursorIfLimitIsReachedOnGetMore() {
assumeFalse(isSharded());
BsonDocument commandResult = executeFindCommand(5, 3);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 3, DOCUMENT_DECODER, null, connectionSource, connection));
ServerCursor serverCursor = cursor.getServerCursor();
@@ -409,7 +410,7 @@ void shouldKillCursorIfLimitIsReachedOnGetMore() {
void shouldReleaseConnectionSourceIfLimitIsReachedOnInitialQuery() {
assumeFalse(isSharded());
BsonDocument commandResult = executeFindCommand(5, 10);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection));
assertNull(cursor.getServerCursor());
@@ -422,7 +423,7 @@ void shouldReleaseConnectionSourceIfLimitIsReachedOnInitialQuery() {
void shouldReleaseConnectionSourceIfLimitIsReachedOnGetMore() {
assumeFalse(isSharded());
BsonDocument commandResult = executeFindCommand(5, 3);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 3, DOCUMENT_DECODER, null, connectionSource, connection));
assertNotNull(cursor.next());
@@ -435,7 +436,7 @@ void shouldReleaseConnectionSourceIfLimitIsReachedOnGetMore() {
@DisplayName("test limit with get more")
void testLimitWithGetMore() {
BsonDocument commandResult = executeFindCommand(5, 2);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
assertNotNull(cursor.next());
@@ -456,7 +457,7 @@ void testLimitWithLargeDocuments() {
);
BsonDocument commandResult = executeFindCommand(300, 0);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 0, DOCUMENT_DECODER, null, connectionSource, connection));
assertEquals(300, cursorFlatten().size());
@@ -466,7 +467,7 @@ void testLimitWithLargeDocuments() {
@DisplayName("should respect batch size")
void shouldRespectBatchSize() {
BsonDocument commandResult = executeFindCommand(2);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
assertEquals(2, cursor.getBatchSize());
@@ -483,16 +484,16 @@ void shouldRespectBatchSize() {
@DisplayName("should throw cursor not found exception")
void shouldThrowCursorNotFoundException() {
BsonDocument commandResult = executeFindCommand(2);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
ServerCursor serverCursor = cursor.getServerCursor();
assertNotNull(serverCursor);
- Connection localConnection = connectionSource.getConnection(OPERATION_CONTEXT);
+ Connection localConnection = connectionSource.getConnection(ClusterFixture.createOperationContext());
localConnection.command(getNamespace().getDatabaseName(),
new BsonDocument("killCursors", new BsonString(getNamespace().getCollectionName()))
.append("cursors", new BsonArray(singletonList(new BsonInt64(serverCursor.getId())))),
- NoOpFieldNameValidator.INSTANCE, ReadPreference.primary(), new BsonDocumentCodec(), OPERATION_CONTEXT);
+ NoOpFieldNameValidator.INSTANCE, ReadPreference.primary(), new BsonDocumentCodec(), ClusterFixture.createOperationContext());
localConnection.release();
cursor.next();
@@ -506,7 +507,7 @@ void shouldThrowCursorNotFoundException() {
@DisplayName("should report available documents")
void shouldReportAvailableDocuments() {
BsonDocument commandResult = executeFindCommand(3);
- cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, OPERATION_CONTEXT,
+ cursor = new CommandBatchCursor<>(TimeoutMode.CURSOR_LIFETIME, 0, ClusterFixture.createOperationContext(),
new CommandCursor<>(commandResult, 2, DOCUMENT_DECODER, null, connectionSource, connection));
assertEquals(3, cursor.available());
@@ -584,7 +585,7 @@ private BsonDocument executeFindCommand(final BsonDocument filter, final int lim
BsonDocument results = connection.command(getDatabaseName(), findCommand,
NoOpFieldNameValidator.INSTANCE, readPreference,
CommandResultDocumentCodec.create(DOCUMENT_DECODER, FIRST_BATCH),
- OPERATION_CONTEXT);
+ ClusterFixture.createOperationContext());
assertNotNull(results);
return results;
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/CountDocumentsOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/CountDocumentsOperationSpecification.groovy
index 1e538b1af11..dc9746053c3 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/CountDocumentsOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/CountDocumentsOperationSpecification.groovy
@@ -46,7 +46,7 @@ import org.bson.BsonTimestamp
import org.bson.Document
import org.bson.codecs.DocumentCodec
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.executeAsync
import static com.mongodb.connection.ServerType.STANDALONE
import static com.mongodb.internal.operation.OperationReadConcernHelper.appendReadConcernToCommand
@@ -156,7 +156,7 @@ class CountDocumentsOperationSpecification extends OperationFunctionalSpecificat
def binding = ClusterFixture.getBinding()
new CreateIndexesOperation(getNamespace(), [new IndexRequest(indexDefinition).sparse(true)], null)
- .execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ .execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
def operation = new CountDocumentsOperation(getNamespace()).hint(indexDefinition)
when:
@@ -259,7 +259,7 @@ class CountDocumentsOperationSpecification extends OperationFunctionalSpecificat
def 'should add read concern to command'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
def binding = Stub(ReadBinding)
def source = Stub(ConnectionSource)
def connection = Mock(Connection)
@@ -297,7 +297,7 @@ class CountDocumentsOperationSpecification extends OperationFunctionalSpecificat
def 'should add read concern to command asynchronously'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
def binding = Stub(AsyncReadBinding)
def source = Stub(AsyncConnectionSource)
def connection = Mock(AsyncConnection)
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/CreateCollectionOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/CreateCollectionOperationSpecification.groovy
index 860ffb4a2bf..a0b80cc178a 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/CreateCollectionOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/CreateCollectionOperationSpecification.groovy
@@ -113,7 +113,7 @@ class CreateCollectionOperationSpecification extends OperationFunctionalSpecific
then:
def binding = ClusterFixture.getBinding()
new ListCollectionsOperation(getDatabaseName(), new BsonDocumentCodec())
- .execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ .execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
.next()
.find { it -> it.getString('name').value == getCollectionName() }
.getDocument('options').getDocument('storageEngine') == operation.storageEngineOptions
@@ -134,7 +134,7 @@ class CreateCollectionOperationSpecification extends OperationFunctionalSpecific
then:
def binding = ClusterFixture.getBinding()
new ListCollectionsOperation(getDatabaseName(), new BsonDocumentCodec())
- .execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ .execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
.next()
.find { it -> it.getString('name').value == getCollectionName() }
.getDocument('options').getDocument('storageEngine') == operation.storageEngineOptions
@@ -255,7 +255,7 @@ class CreateCollectionOperationSpecification extends OperationFunctionalSpecific
def binding = getBinding()
new ListCollectionsOperation(databaseName, new BsonDocumentCodec()).filter(new BsonDocument('name',
new BsonString(collectionName))).execute(binding,
- ClusterFixture.getOperationContext(binding.getReadPreference())).tryNext()?.head()
+ ClusterFixture.createOperationContext(binding.getReadPreference())).tryNext()?.head()
}
def collectionNameExists(String collectionName) {
@@ -268,13 +268,13 @@ class CreateCollectionOperationSpecification extends OperationFunctionalSpecific
def binding = getBinding()
return new CommandReadOperation<>(getDatabaseName(),
new BsonDocument('collStats', new BsonString(getCollectionName())),
- new BsonDocumentCodec()).execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ new BsonDocumentCodec()).execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
}
def binding = ClusterFixture.getBinding()
BatchCursor cursor = new AggregateOperation(
getNamespace(),
singletonList(new BsonDocument('$collStats', new BsonDocument('storageStats', new BsonDocument()))),
- new BsonDocumentCodec()).execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ new BsonDocumentCodec()).execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
try {
return cursor.next().first().getDocument('storageStats')
} finally {
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/CreateIndexesOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/CreateIndexesOperationSpecification.groovy
index fce0904b786..5365f19f1de 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/CreateIndexesOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/CreateIndexesOperationSpecification.groovy
@@ -494,7 +494,7 @@ class CreateIndexesOperationSpecification extends OperationFunctionalSpecificati
def binding = ClusterFixture.getBinding()
def cursor = new ListIndexesOperation(getNamespace(), new DocumentCodec())
- .execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ .execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
while (cursor.hasNext()) {
indexes.addAll(cursor.next())
}
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/CreateViewOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/CreateViewOperationSpecification.groovy
index b8145de44b4..3e90c21363e 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/CreateViewOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/CreateViewOperationSpecification.groovy
@@ -29,8 +29,8 @@ import org.bson.BsonString
import org.bson.codecs.BsonDocumentCodec
import spock.lang.IgnoreIf
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.getBinding
-import static com.mongodb.ClusterFixture.getOperationContext
import static com.mongodb.ClusterFixture.isDiscoverableReplicaSet
class CreateViewOperationSpecification extends OperationFunctionalSpecification {
@@ -124,7 +124,7 @@ class CreateViewOperationSpecification extends OperationFunctionalSpecification
def getCollectionInfo(String collectionName) {
def binding = getBinding()
new ListCollectionsOperation(databaseName, new BsonDocumentCodec()).filter(new BsonDocument('name',
- new BsonString(collectionName))).execute(binding, getOperationContext(binding.getReadPreference())).tryNext()?.head()
+ new BsonString(collectionName))).execute(binding, createOperationContext(binding.getReadPreference())).tryNext()?.head()
}
def collectionNameExists(String collectionName) {
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/DistinctOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/DistinctOperationSpecification.groovy
index f73c301d422..66936080558 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/DistinctOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/DistinctOperationSpecification.groovy
@@ -51,7 +51,7 @@ import org.bson.codecs.StringCodec
import org.bson.codecs.ValueCodecProvider
import org.bson.types.ObjectId
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.executeAsync
import static com.mongodb.connection.ServerType.STANDALONE
import static com.mongodb.internal.operation.OperationReadConcernHelper.appendReadConcernToCommand
@@ -227,7 +227,7 @@ class DistinctOperationSpecification extends OperationFunctionalSpecification {
def 'should add read concern to command'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
def binding = Stub(ReadBinding)
def source = Stub(ConnectionSource)
def connection = Mock(Connection)
@@ -266,7 +266,7 @@ class DistinctOperationSpecification extends OperationFunctionalSpecification {
def 'should add read concern to command asynchronously'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
def binding = Stub(AsyncReadBinding)
def source = Stub(AsyncConnectionSource)
def connection = Mock(AsyncConnection)
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/DropCollectionOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/DropCollectionOperationSpecification.groovy
index eb8f3efa573..703d0e14212 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/DropCollectionOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/DropCollectionOperationSpecification.groovy
@@ -39,7 +39,7 @@ class DropCollectionOperationSpecification extends OperationFunctionalSpecificat
when:
def binding = getBinding()
new DropCollectionOperation(getNamespace(), WriteConcern.ACKNOWLEDGED)
- .execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ .execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
then:
!collectionNameExists(getCollectionName())
@@ -64,7 +64,7 @@ class DropCollectionOperationSpecification extends OperationFunctionalSpecificat
when:
new DropCollectionOperation(namespace, WriteConcern.ACKNOWLEDGED)
- .execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ .execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
then:
!collectionNameExists('nonExistingCollection')
@@ -91,7 +91,7 @@ class DropCollectionOperationSpecification extends OperationFunctionalSpecificat
when:
def binding = getBinding()
- async ? executeAsync(operation) : operation.execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ async ? executeAsync(operation) : operation.execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
then:
def ex = thrown(MongoWriteConcernException)
@@ -104,7 +104,7 @@ class DropCollectionOperationSpecification extends OperationFunctionalSpecificat
def collectionNameExists(String collectionName) {
def cursor = new ListCollectionsOperation(databaseName, new DocumentCodec())
- .execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ .execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
if (!cursor.hasNext()) {
return false
}
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/DropDatabaseOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/DropDatabaseOperationSpecification.groovy
index b56e2c1fe50..955b5efcaa3 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/DropDatabaseOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/DropDatabaseOperationSpecification.groovy
@@ -16,7 +16,6 @@
package com.mongodb.internal.operation
-
import com.mongodb.MongoWriteConcernException
import com.mongodb.OperationFunctionalSpecification
import com.mongodb.WriteConcern
@@ -25,10 +24,10 @@ import org.bson.Document
import org.bson.codecs.DocumentCodec
import spock.lang.IgnoreIf
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.configureFailPoint
import static com.mongodb.ClusterFixture.executeAsync
import static com.mongodb.ClusterFixture.getBinding
-import static com.mongodb.ClusterFixture.getOperationContext
import static com.mongodb.ClusterFixture.isDiscoverableReplicaSet
import static com.mongodb.ClusterFixture.isSharded
@@ -80,7 +79,7 @@ class DropDatabaseOperationSpecification extends OperationFunctionalSpecificatio
def binding = getBinding()
when:
- async ? executeAsync(operation) : operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ async ? executeAsync(operation) : operation.execute(binding, createOperationContext(binding.getReadPreference()))
then:
def ex = thrown(MongoWriteConcernException)
@@ -93,7 +92,7 @@ class DropDatabaseOperationSpecification extends OperationFunctionalSpecificatio
def databaseNameExists(String databaseName) {
new ListDatabasesOperation(new DocumentCodec()).execute(binding,
- getOperationContext(binding.getReadPreference())).next()*.name.contains(databaseName)
+ createOperationContext(binding.getReadPreference())).next()*.name.contains(databaseName)
}
}
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/DropIndexOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/DropIndexOperationSpecification.groovy
index 7b1f5b2a392..0aff76df1cb 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/DropIndexOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/DropIndexOperationSpecification.groovy
@@ -159,7 +159,7 @@ class DropIndexOperationSpecification extends OperationFunctionalSpecification {
def indexes = []
def binding = getBinding()
def cursor = new ListIndexesOperation(getNamespace(), new DocumentCodec())
- .execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ .execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
while (cursor.hasNext()) {
indexes.addAll(cursor.next())
}
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/FindOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/FindOperationSpecification.groovy
index 5eb707201d5..c584ee463f9 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/FindOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/FindOperationSpecification.groovy
@@ -54,13 +54,12 @@ import org.bson.codecs.BsonDocumentCodec
import org.bson.codecs.DocumentCodec
import spock.lang.IgnoreIf
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
import static com.mongodb.ClusterFixture.executeAsync
import static com.mongodb.ClusterFixture.executeSync
import static com.mongodb.ClusterFixture.getAsyncCluster
import static com.mongodb.ClusterFixture.getBinding
import static com.mongodb.ClusterFixture.getCluster
-import static com.mongodb.ClusterFixture.getOperationContext
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.isSharded
import static com.mongodb.ClusterFixture.serverVersionLessThan
import static com.mongodb.CursorType.NonTailable
@@ -390,7 +389,7 @@ class FindOperationSpecification extends OperationFunctionalSpecification {
def binding = getBinding()
new CommandReadOperation<>(getDatabaseName(), new BsonDocument('profile', new BsonInt32(2)),
- new BsonDocumentCodec()).execute(binding, getOperationContext(binding.getReadPreference()))
+ new BsonDocumentCodec()).execute(binding, createOperationContext(binding.getReadPreference()))
def expectedComment = 'this is a comment'
def operation = new FindOperation(getNamespace(), new DocumentCodec())
.comment(new BsonString(expectedComment))
@@ -405,7 +404,7 @@ class FindOperationSpecification extends OperationFunctionalSpecification {
cleanup:
new CommandReadOperation<>(getDatabaseName(), new BsonDocument('profile', new BsonInt32(0)),
new BsonDocumentCodec())
- .execute(binding, getOperationContext(binding.getReadPreference()))
+ .execute(binding, createOperationContext(binding.getReadPreference()))
profileCollectionHelper.drop()
where:
@@ -482,7 +481,7 @@ class FindOperationSpecification extends OperationFunctionalSpecification {
def 'should add read concern to command'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
def binding = Stub(ReadBinding)
def source = Stub(ConnectionSource)
def connection = Mock(Connection)
@@ -522,7 +521,7 @@ class FindOperationSpecification extends OperationFunctionalSpecification {
def 'should add read concern to command asynchronously'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
def binding = Stub(AsyncReadBinding)
def source = Stub(AsyncConnectionSource)
def connection = Mock(AsyncConnection)
@@ -562,7 +561,7 @@ class FindOperationSpecification extends OperationFunctionalSpecification {
def 'should add allowDiskUse to command if the server version >= 3.2'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
def binding = Stub(ReadBinding)
def source = Stub(ConnectionSource)
def connection = Mock(Connection)
@@ -602,7 +601,7 @@ class FindOperationSpecification extends OperationFunctionalSpecification {
def 'should add allowDiskUse to command if the server version >= 3.2 asynchronously'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
def binding = Stub(AsyncReadBinding)
def source = Stub(AsyncConnectionSource)
def connection = Mock(AsyncConnection)
@@ -646,7 +645,7 @@ class FindOperationSpecification extends OperationFunctionalSpecification {
def (cursorType, long maxAwaitTimeMS, long maxTimeMSForCursor) = cursorDetails
def timeoutSettings = ClusterFixture.TIMEOUT_SETTINGS_WITH_INFINITE_TIMEOUT.withMaxAwaitTimeMS(maxAwaitTimeMS)
def timeoutContext = new TimeoutContext(timeoutSettings)
- def operationContext = OPERATION_CONTEXT.withTimeoutContext(timeoutContext)
+ def operationContext = createOperationContext().withTimeoutContext(timeoutContext)
collectionHelper.create(getCollectionName(), new CreateCollectionOptions().capped(true).sizeInBytes(1000))
def operation = new FindOperation(namespace, new BsonDocumentCodec())
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/ListCollectionsOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/ListCollectionsOperationSpecification.groovy
index ad55b706ba2..b44b341d202 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/ListCollectionsOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/ListCollectionsOperationSpecification.groovy
@@ -16,6 +16,7 @@
package com.mongodb.internal.operation
+import com.mongodb.ClusterFixture
import com.mongodb.MongoNamespace
import com.mongodb.OperationFunctionalSpecification
import com.mongodb.ReadPreference
@@ -43,10 +44,9 @@ import org.bson.Document
import org.bson.codecs.Decoder
import org.bson.codecs.DocumentCodec
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.executeAsync
import static com.mongodb.ClusterFixture.getBinding
-import static com.mongodb.ClusterFixture.getOperationContext
import static org.junit.jupiter.api.Assertions.assertEquals
class ListCollectionsOperationSpecification extends OperationFunctionalSpecification {
@@ -60,7 +60,7 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def binding = getBinding()
when:
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
then:
!cursor.hasNext()
@@ -98,7 +98,7 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def binding = getBinding()
when:
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
def collections = cursor.next()
def names = collections*.get('name')
@@ -121,7 +121,7 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def binding = getBinding()
when:
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference())
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference())
)
def collections = cursor.next()
def names = collections*.get('name')
@@ -143,7 +143,7 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def binding = getBinding()
when:
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
def collections = cursor.next()
def names = collections*.get('name')
@@ -161,7 +161,7 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def binding = getBinding()
when:
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
def collection = cursor.next()[0]
then:
@@ -178,7 +178,7 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def binding = getBinding()
when:
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
def collection = cursor.next()[0]
then:
@@ -195,7 +195,7 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def binding = getBinding()
when:
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
def collection = cursor.next()[0]
then:
@@ -227,14 +227,14 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def binding = getBinding()
given:
new DropDatabaseOperation(databaseName, WriteConcern.ACKNOWLEDGED)
- .execute(binding, getOperationContext(binding.getReadPreference()))
+ .execute(binding, createOperationContext(binding.getReadPreference()))
addSeveralIndexes()
def operation = new ListCollectionsOperation(databaseName, new DocumentCodec()).batchSize(2)
when:
binding = getBinding()
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
then:
cursor.hasNext()
@@ -247,13 +247,13 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def binding = getBinding()
given:
new DropDatabaseOperation(databaseName, WriteConcern.ACKNOWLEDGED)
- .execute(binding, getOperationContext(binding.getReadPreference()))
+ .execute(binding, createOperationContext(binding.getReadPreference()))
addSeveralIndexes()
def operation = new ListCollectionsOperation(databaseName, new DocumentCodec()).batchSize(2)
when:
binding = getBinding()
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
def list = cursorToListWithNext(cursor)
then:
@@ -272,14 +272,14 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def binding = getBinding()
given:
new DropDatabaseOperation(databaseName, WriteConcern.ACKNOWLEDGED)
- .execute(binding, getOperationContext(binding.getReadPreference()))
+ .execute(binding, createOperationContext(binding.getReadPreference()))
addSeveralIndexes()
def operation = new ListCollectionsOperation(databaseName, new DocumentCodec()).batchSize(2)
when:
binding = getBinding()
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
then:
cursor.hasNext()
@@ -298,13 +298,13 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
given:
def binding = getBinding()
new DropDatabaseOperation(databaseName, WriteConcern.ACKNOWLEDGED)
- .execute(binding, getOperationContext(binding.getReadPreference()))
+ .execute(binding, createOperationContext(binding.getReadPreference()))
addSeveralIndexes()
def operation = new ListCollectionsOperation(databaseName, new DocumentCodec()).batchSize(2)
when:
binding = getBinding()
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
def list = cursorToListWithTryNext(cursor)
then:
@@ -318,7 +318,7 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
given:
def binding = getBinding()
new DropDatabaseOperation(databaseName, WriteConcern.ACKNOWLEDGED)
- .execute(binding, getOperationContext(binding.getReadPreference()))
+ .execute(binding, createOperationContext(binding.getReadPreference()))
addSeveralIndexes()
def operation = new ListCollectionsOperation(databaseName, new DocumentCodec()).batchSize(2)
@@ -344,7 +344,7 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
when:
def binding = getBinding()
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
def collections = cursor.next()
then:
@@ -398,6 +398,7 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def 'should use the readPreference to set secondaryOk'() {
given:
+ def operationContext = ClusterFixture.createOperationContext()
def connection = Mock(Connection)
def connectionSource = Stub(ConnectionSource) {
getConnection(_) >> connection
@@ -410,12 +411,12 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def operation = new ListCollectionsOperation(helper.dbName, helper.decoder)
when: '3.6.0'
- operation.execute(readBinding, OPERATION_CONTEXT)
+ operation.execute(readBinding, operationContext)
then:
_ * connection.getDescription() >> helper.threeSixConnectionDescription
1 * connection.command(_, _, _, readPreference, _, _) >> {
- assertEquals(((OperationContext) it[5]).getId(), OPERATION_CONTEXT.getId())
+ assertEquals(((OperationContext) it[5]).getId(), operationContext.getId())
helper.commandResult
}
1 * connection.release()
@@ -426,6 +427,7 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
def 'should use the readPreference to set secondaryOk in async'() {
given:
+ def operationContext = ClusterFixture.createOperationContext()
def connection = Mock(AsyncConnection)
def connectionSource = Stub(AsyncConnectionSource) {
getConnection(_, _) >> { it[1].onResult(connection, null) }
@@ -436,14 +438,13 @@ class ListCollectionsOperationSpecification extends OperationFunctionalSpecifica
getReadPreference() >> readPreference
}
def operation = new ListCollectionsOperation(helper.dbName, helper.decoder)
-
when: '3.6.0'
- operation.executeAsync(readBinding, OPERATION_CONTEXT, Stub(SingleResultCallback))
+ operation.executeAsync(readBinding, operationContext, Stub(SingleResultCallback))
then:
_ * connection.getDescription() >> helper.threeSixConnectionDescription
1 * connection.commandAsync(helper.dbName, _, _, readPreference, _, _, *_) >> {
- assertEquals(((OperationContext) it[5]).getId(), OPERATION_CONTEXT.getId())
+ assertEquals(((OperationContext) it[5]).getId(), operationContext.getId())
it.last().onResult(helper.commandResult, null) }
where:
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/ListDatabasesOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/ListDatabasesOperationSpecification.groovy
index 55504d0babc..a6ed542bde2 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/ListDatabasesOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/ListDatabasesOperationSpecification.groovy
@@ -33,7 +33,7 @@ import org.bson.Document
import org.bson.codecs.Decoder
import org.bson.codecs.DocumentCodec
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
class ListDatabasesOperationSpecification extends OperationFunctionalSpecification {
def codec = new DocumentCodec()
@@ -82,7 +82,7 @@ class ListDatabasesOperationSpecification extends OperationFunctionalSpecificati
def operation = new ListDatabasesOperation(helper.decoder)
when:
- operation.execute(readBinding, OPERATION_CONTEXT)
+ operation.execute(readBinding, createOperationContext())
then:
_ * connection.getDescription() >> helper.connectionDescription
@@ -107,7 +107,7 @@ class ListDatabasesOperationSpecification extends OperationFunctionalSpecificati
def operation = new ListDatabasesOperation(helper.decoder)
when:
- operation.executeAsync(readBinding, OPERATION_CONTEXT, Stub(SingleResultCallback))
+ operation.executeAsync(readBinding, createOperationContext(), Stub(SingleResultCallback))
then:
_ * connection.getDescription() >> helper.connectionDescription
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/ListIndexesOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/ListIndexesOperationSpecification.groovy
index c11d67bcf22..823de9bfd91 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/ListIndexesOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/ListIndexesOperationSpecification.groovy
@@ -16,7 +16,7 @@
package com.mongodb.internal.operation
-
+import com.mongodb.ClusterFixture
import com.mongodb.MongoNamespace
import com.mongodb.OperationFunctionalSpecification
import com.mongodb.ReadPreference
@@ -44,10 +44,9 @@ import org.bson.codecs.Decoder
import org.bson.codecs.DocumentCodec
import org.junit.jupiter.api.Assertions
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
import static com.mongodb.ClusterFixture.executeAsync
import static com.mongodb.ClusterFixture.getBinding
-import static com.mongodb.ClusterFixture.getOperationContext
+import static com.mongodb.ClusterFixture.createOperationContext
class ListIndexesOperationSpecification extends OperationFunctionalSpecification {
@@ -58,7 +57,7 @@ class ListIndexesOperationSpecification extends OperationFunctionalSpecification
def binding = getBinding()
when:
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
then:
!cursor.hasNext()
@@ -87,7 +86,7 @@ class ListIndexesOperationSpecification extends OperationFunctionalSpecification
def binding = getBinding()
when:
- BatchCursor indexes = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ BatchCursor indexes = operation.execute(binding, createOperationContext(binding.getReadPreference()))
then:
def firstBatch = indexes.next()
@@ -122,11 +121,11 @@ class ListIndexesOperationSpecification extends OperationFunctionalSpecification
def binding = getBinding()
new CreateIndexesOperation(namespace,
[new IndexRequest(new BsonDocument('unique', new BsonInt32(1))).unique(true)], null).execute(binding,
- getOperationContext(binding.getReadPreference()))
+ createOperationContext(binding.getReadPreference()))
when:
binding = getBinding()
- BatchCursor cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ BatchCursor cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
then:
def indexes = cursor.next()
@@ -146,7 +145,7 @@ class ListIndexesOperationSpecification extends OperationFunctionalSpecification
def binding = getBinding()
new CreateIndexesOperation(namespace,
[new IndexRequest(new BsonDocument('unique', new BsonInt32(1))).unique(true)], null).execute(binding,
- getOperationContext(binding.getReadPreference()))
+ createOperationContext(binding.getReadPreference()))
when:
def cursor = executeAsync(operation)
@@ -172,7 +171,7 @@ class ListIndexesOperationSpecification extends OperationFunctionalSpecification
def binding = getBinding()
when:
- def cursor = operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ def cursor = operation.execute(binding, createOperationContext(binding.getReadPreference()))
def collections = cursor.next()
then:
@@ -226,6 +225,7 @@ class ListIndexesOperationSpecification extends OperationFunctionalSpecification
def 'should use the readPreference to set secondaryOk'() {
given:
def connection = Mock(Connection)
+ def operationContext = ClusterFixture.createOperationContext()
def connectionSource = Stub(ConnectionSource) {
getConnection(_) >> connection
getReadPreference() >> readPreference
@@ -237,12 +237,12 @@ class ListIndexesOperationSpecification extends OperationFunctionalSpecification
def operation = new ListIndexesOperation(helper.namespace, helper.decoder)
when: '3.6.0'
- operation.execute(readBinding, OPERATION_CONTEXT)
+ operation.execute(readBinding, operationContext)
then:
_ * connection.getDescription() >> helper.threeSixConnectionDescription
1 * connection.command(_, _, _, readPreference, _, _) >> {
- Assertions.assertEquals(((OperationContext) it[5]).getId(), OPERATION_CONTEXT.getId())
+ Assertions.assertEquals(((OperationContext) it[5]).getId(), operationContext.getId())
helper.commandResult
}
1 * connection.release()
@@ -265,7 +265,7 @@ class ListIndexesOperationSpecification extends OperationFunctionalSpecification
def operation = new ListIndexesOperation(helper.namespace, helper.decoder)
when: '3.6.0'
- operation.executeAsync(readBinding, OPERATION_CONTEXT, Stub(SingleResultCallback))
+ operation.executeAsync(readBinding, createOperationContext(), Stub(SingleResultCallback))
then:
_ * connection.getDescription() >> helper.threeSixConnectionDescription
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/MapReduceToCollectionOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/MapReduceToCollectionOperationSpecification.groovy
index 5d6be781d1f..31f8ed45715 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/MapReduceToCollectionOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/MapReduceToCollectionOperationSpecification.groovy
@@ -64,7 +64,7 @@ class MapReduceToCollectionOperationSpecification extends OperationFunctionalSpe
def cleanup() {
def binding = getBinding()
- def operationContext = ClusterFixture.getOperationContext(binding.getReadPreference())
+ def operationContext = ClusterFixture.createOperationContext(binding.getReadPreference())
new DropCollectionOperation(mapReduceInputNamespace, WriteConcern.ACKNOWLEDGED)
.execute(binding, operationContext)
new DropCollectionOperation(mapReduceOutputNamespace, WriteConcern.ACKNOWLEDGED)
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/MapReduceWithInlineResultsOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/MapReduceWithInlineResultsOperationSpecification.groovy
index 8efd4e00f6c..14ee33d7ec5 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/MapReduceWithInlineResultsOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/MapReduceWithInlineResultsOperationSpecification.groovy
@@ -46,7 +46,7 @@ import org.bson.Document
import org.bson.codecs.BsonDocumentCodec
import org.bson.codecs.DocumentCodec
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.executeAsync
import static com.mongodb.connection.ServerType.STANDALONE
import static com.mongodb.internal.operation.OperationReadConcernHelper.appendReadConcernToCommand
@@ -217,7 +217,7 @@ class MapReduceWithInlineResultsOperationSpecification extends OperationFunction
def 'should add read concern to command'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
def binding = Stub(ReadBinding)
def source = Stub(ConnectionSource)
def connection = Mock(Connection)
@@ -264,7 +264,7 @@ class MapReduceWithInlineResultsOperationSpecification extends OperationFunction
def 'should add read concern to command asynchronously'() {
given:
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
def binding = Stub(AsyncReadBinding)
def source = Stub(AsyncConnectionSource)
def connection = Mock(AsyncConnection)
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/RenameCollectionOperationSpecification.groovy b/driver-core/src/test/functional/com/mongodb/internal/operation/RenameCollectionOperationSpecification.groovy
index bc55bf5a134..080861047f1 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/RenameCollectionOperationSpecification.groovy
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/RenameCollectionOperationSpecification.groovy
@@ -26,9 +26,9 @@ import org.bson.Document
import org.bson.codecs.DocumentCodec
import spock.lang.IgnoreIf
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.executeAsync
import static com.mongodb.ClusterFixture.getBinding
-import static com.mongodb.ClusterFixture.getOperationContext
import static com.mongodb.ClusterFixture.isDiscoverableReplicaSet
import static com.mongodb.ClusterFixture.isSharded
@@ -38,7 +38,7 @@ class RenameCollectionOperationSpecification extends OperationFunctionalSpecific
def cleanup() {
def binding = getBinding()
new DropCollectionOperation(new MongoNamespace(getDatabaseName(), 'newCollection'),
- WriteConcern.ACKNOWLEDGED).execute(binding, getOperationContext(binding.getReadPreference()))
+ WriteConcern.ACKNOWLEDGED).execute(binding, createOperationContext(binding.getReadPreference()))
}
def 'should return rename a collection'() {
@@ -87,7 +87,7 @@ class RenameCollectionOperationSpecification extends OperationFunctionalSpecific
def binding = getBinding()
when:
- async ? executeAsync(operation) : operation.execute(binding, getOperationContext(binding.getReadPreference()))
+ async ? executeAsync(operation) : operation.execute(binding, createOperationContext(binding.getReadPreference()))
then:
def ex = thrown(MongoWriteConcernException)
@@ -101,7 +101,7 @@ class RenameCollectionOperationSpecification extends OperationFunctionalSpecific
def collectionNameExists(String collectionName) {
def binding = getBinding()
def cursor = new ListCollectionsOperation(databaseName, new DocumentCodec()).execute(binding,
- getOperationContext(binding.getReadPreference()))
+ createOperationContext(binding.getReadPreference()))
if (!cursor.hasNext()) {
return false
}
diff --git a/driver-core/src/test/functional/com/mongodb/internal/operation/TestOperationHelper.java b/driver-core/src/test/functional/com/mongodb/internal/operation/TestOperationHelper.java
index 824517e10db..2565521deb7 100644
--- a/driver-core/src/test/functional/com/mongodb/internal/operation/TestOperationHelper.java
+++ b/driver-core/src/test/functional/com/mongodb/internal/operation/TestOperationHelper.java
@@ -16,6 +16,7 @@
package com.mongodb.internal.operation;
+import com.mongodb.ClusterFixture;
import com.mongodb.MongoCommandException;
import com.mongodb.MongoCursorNotFoundException;
import com.mongodb.MongoNamespace;
@@ -31,8 +32,6 @@
import org.bson.BsonString;
import org.bson.codecs.BsonDocumentCodec;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
-
final class TestOperationHelper {
static BsonDocument getKeyPattern(final BsonDocument explainPlan) {
@@ -56,7 +55,7 @@ static void makeAdditionalGetMoreCall(final MongoNamespace namespace, final Serv
connection.command(namespace.getDatabaseName(),
new BsonDocument("getMore", new BsonInt64(serverCursor.getId()))
.append("collection", new BsonString(namespace.getCollectionName())),
- NoOpFieldNameValidator.INSTANCE, ReadPreference.primary(), new BsonDocumentCodec(), OPERATION_CONTEXT));
+ NoOpFieldNameValidator.INSTANCE, ReadPreference.primary(), new BsonDocumentCodec(), ClusterFixture.createOperationContext()));
}
static void makeAdditionalGetMoreCall(final MongoNamespace namespace, final ServerCursor serverCursor,
@@ -66,7 +65,7 @@ static void makeAdditionalGetMoreCall(final MongoNamespace namespace, final Serv
connection.commandAsync(namespace.getDatabaseName(),
new BsonDocument("getMore", new BsonInt64(serverCursor.getId()))
.append("collection", new BsonString(namespace.getCollectionName())),
- NoOpFieldNameValidator.INSTANCE, ReadPreference.primary(), new BsonDocumentCodec(), OPERATION_CONTEXT, callback);
+ NoOpFieldNameValidator.INSTANCE, ReadPreference.primary(), new BsonDocumentCodec(), ClusterFixture.createOperationContext(), callback);
callback.get();
});
}
diff --git a/driver-core/src/test/unit/com/mongodb/AbstractConnectionStringTest.java b/driver-core/src/test/unit/com/mongodb/AbstractConnectionStringTest.java
index d511d2750eb..89b32fd6aab 100644
--- a/driver-core/src/test/unit/com/mongodb/AbstractConnectionStringTest.java
+++ b/driver-core/src/test/unit/com/mongodb/AbstractConnectionStringTest.java
@@ -112,7 +112,7 @@ protected void testValidOptions() {
if (option.getKey().equals("authmechanism")) {
String expected = option.getValue().asString().getValue();
- if (expected.equals("MONGODB-CR")) {
+ if (expected.equals("MONGODB-CR")) {
assertNotNull(connectionString.getCredential());
assertNull(connectionString.getCredential().getAuthenticationMechanism());
} else {
@@ -122,6 +122,9 @@ protected void testValidOptions() {
} else if (option.getKey().equalsIgnoreCase("retrywrites")) {
boolean expected = option.getValue().asBoolean().getValue();
assertEquals(expected, connectionString.getRetryWritesValue().booleanValue());
+ } else if (option.getKey().equalsIgnoreCase("enableoverloadretargeting")) {
+ boolean expected = option.getValue().asBoolean().getValue();
+ assertEquals(expected, connectionString.getEnableOverloadRetargeting().booleanValue());
} else if (option.getKey().equalsIgnoreCase("replicaset")) {
String expected = option.getValue().asString().getValue();
assertEquals(expected, connectionString.getRequiredReplicaSetName());
diff --git a/driver-core/src/test/unit/com/mongodb/ConnectionStringUnitTest.java b/driver-core/src/test/unit/com/mongodb/ConnectionStringUnitTest.java
index 0b3dd1a0814..1e72ce211b1 100644
--- a/driver-core/src/test/unit/com/mongodb/ConnectionStringUnitTest.java
+++ b/driver-core/src/test/unit/com/mongodb/ConnectionStringUnitTest.java
@@ -69,7 +69,10 @@ private static String encode(final String string) {
}
@ParameterizedTest
- @ValueSource(strings = {DEFAULT_OPTIONS + "serverMonitoringMode=stream"})
+ @ValueSource(strings = {
+ DEFAULT_OPTIONS + "serverMonitoringMode=stream",
+ DEFAULT_OPTIONS + "enableOverloadRetargeting=true"
+ })
void equalAndHashCode(final String connectionString) {
ConnectionString default1 = new ConnectionString(DEFAULT_OPTIONS);
ConnectionString default2 = new ConnectionString(DEFAULT_OPTIONS);
@@ -94,6 +97,15 @@ void serverMonitoringMode() {
);
}
+ @Test
+ void enableOverloadRetargeting() {
+ assertAll(
+ () -> assertNull(new ConnectionString("mongodb://localhost/").getEnableOverloadRetargeting()),
+ () -> assertEquals(false, new ConnectionString(DEFAULT_OPTIONS + "enableOverloadRetargeting=false").getEnableOverloadRetargeting()),
+ () -> assertEquals(true, new ConnectionString(DEFAULT_OPTIONS + "enableOverloadRetargeting=true").getEnableOverloadRetargeting()),
+ () -> assertNull(new ConnectionString(DEFAULT_OPTIONS + "enableOverloadRetargeting=foos").getEnableOverloadRetargeting())
+ );
+ }
@ParameterizedTest
@ValueSource(strings = {"mongodb://foo:bar/@hostname/java?", "mongodb://foo:bar?@hostname/java/",
diff --git a/driver-core/src/test/unit/com/mongodb/MongoClientSettingsSpecification.groovy b/driver-core/src/test/unit/com/mongodb/MongoClientSettingsSpecification.groovy
index c8910751552..2ba4dd3a1da 100644
--- a/driver-core/src/test/unit/com/mongodb/MongoClientSettingsSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/MongoClientSettingsSpecification.groovy
@@ -552,6 +552,7 @@ class MongoClientSettingsSpecification extends Specification {
def actual = MongoClientSettings.Builder.declaredFields.grep { !it.synthetic } *.name.sort()
def expected = ['applicationName', 'autoEncryptionSettings', 'clusterSettingsBuilder', 'codecRegistry', 'commandListeners',
'compressorList', 'connectionPoolSettingsBuilder', 'contextProvider', 'credential', 'dnsClient',
+ 'enableOverloadRetargeting',
'heartbeatConnectTimeoutMS', 'heartbeatSocketTimeoutMS', 'inetAddressResolver', 'loggerSettingsBuilder',
'observabilitySettings',
'readConcern', 'readPreference', 'retryReads',
@@ -571,6 +572,7 @@ class MongoClientSettingsSpecification extends Specification {
'applyToConnectionPoolSettings', 'applyToLoggerSettings', 'applyToServerSettings', 'applyToSocketSettings',
'applyToSslSettings', 'autoEncryptionSettings', 'build', 'codecRegistry', 'commandListenerList',
'compressorList', 'contextProvider', 'credential', 'dnsClient',
+ 'enableOverloadRetargeting',
'heartbeatConnectTimeoutMS',
'heartbeatSocketTimeoutMS', 'inetAddressResolver', 'observabilitySettings', 'readConcern',
'readPreference',
diff --git a/driver-core/src/test/unit/com/mongodb/UriOptionsTest.java b/driver-core/src/test/unit/com/mongodb/UriOptionsTest.java
index 736e3f5d201..ae456cec0eb 100644
--- a/driver-core/src/test/unit/com/mongodb/UriOptionsTest.java
+++ b/driver-core/src/test/unit/com/mongodb/UriOptionsTest.java
@@ -46,6 +46,8 @@ public void shouldPassAllOutcomes() {
// No CANONICALIZE_HOST_NAME support https://jira.mongodb.org/browse/JAVA-4278
assumeFalse(getDescription().equals("Valid auth options are parsed correctly (GSSAPI)"));
+ // TODO-BACKPRESSURE Valentin add support for maxAdaptiveRetries.
+ assumeFalse(getDescription().contains("maxAdaptiveRetries"));
if (getDefinition().getBoolean("valid", BsonBoolean.TRUE).getValue()) {
testValidOptions();
diff --git a/driver-core/src/test/unit/com/mongodb/internal/binding/SingleServerBindingSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/binding/SingleServerBindingSpecification.groovy
index d52fb593a70..64bd904aaed 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/binding/SingleServerBindingSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/binding/SingleServerBindingSpecification.groovy
@@ -26,7 +26,7 @@ import com.mongodb.internal.connection.Server
import com.mongodb.internal.connection.ServerTuple
import spock.lang.Specification
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
class SingleServerBindingSpecification extends Specification {
@@ -68,7 +68,7 @@ class SingleServerBindingSpecification extends Specification {
binding.count == 1
when:
- def source = binding.getReadConnectionSource(OPERATION_CONTEXT)
+ def source = binding.getReadConnectionSource(createOperationContext())
then:
source.count == 1
@@ -96,7 +96,7 @@ class SingleServerBindingSpecification extends Specification {
binding.count == 1
when:
- source = binding.getWriteConnectionSource(OPERATION_CONTEXT)
+ source = binding.getWriteConnectionSource(createOperationContext())
then:
source.count == 1
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractConnectionPoolTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractConnectionPoolTest.java
index 69a2c236048..deaeacafb07 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractConnectionPoolTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractConnectionPoolTest.java
@@ -77,7 +77,6 @@
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.OPERATION_CONTEXT_FACTORY;
import static com.mongodb.ClusterFixture.TIMEOUT_SETTINGS;
import static com.mongodb.assertions.Assertions.assertFalse;
@@ -542,7 +541,7 @@ private Event getNextEvent(final Iterator eventsIterator, final
private static void executeAdminCommand(final BsonDocument command) {
new CommandReadOperation<>("admin", command, new BsonDocumentCodec())
- .execute(ClusterFixture.getBinding(), OPERATION_CONTEXT);
+ .execute(ClusterFixture.getBinding(), ClusterFixture.createOperationContext());
}
private void setFailPoint() {
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractServerDiscoveryAndMonitoringTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractServerDiscoveryAndMonitoringTest.java
index e187e94da7b..d1b1f27a901 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractServerDiscoveryAndMonitoringTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/AbstractServerDiscoveryAndMonitoringTest.java
@@ -16,6 +16,7 @@
package com.mongodb.internal.connection;
+import com.mongodb.ClusterFixture;
import com.mongodb.ConnectionString;
import com.mongodb.MongoSocketReadException;
import com.mongodb.MongoSocketReadTimeoutException;
@@ -43,7 +44,6 @@
import java.util.concurrent.TimeUnit;
import static com.mongodb.ClusterFixture.CLIENT_METADATA;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.TIMEOUT_SETTINGS;
import static com.mongodb.connection.ServerConnectionState.CONNECTING;
import static com.mongodb.internal.connection.DescriptionHelper.createServerDescription;
@@ -82,7 +82,8 @@ protected void applyResponse(final BsonArray response) {
}
protected void applyApplicationError(final BsonDocument applicationError) {
- Timeout serverSelectionTimeout = OPERATION_CONTEXT.getTimeoutContext().computeServerSelectionTimeout();
+ OperationContext operationContext = ClusterFixture.createOperationContext();
+ Timeout serverSelectionTimeout = operationContext.getTimeoutContext().computeServerSelectionTimeout();
ServerAddress serverAddress = new ServerAddress(applicationError.getString("address").getValue());
TimeoutContext timeoutContext = new TimeoutContext(TIMEOUT_SETTINGS);
int errorGeneration = applicationError.getNumber("generation",
@@ -98,7 +99,7 @@ protected void applyApplicationError(final BsonDocument applicationError) {
switch (type) {
case "command":
exception = getCommandFailureException(applicationError.getDocument("response"), serverAddress,
- OPERATION_CONTEXT.getTimeoutContext());
+ operationContext.getTimeoutContext());
break;
case "network":
exception = new MongoSocketReadException("Read error", serverAddress, new IOException());
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/BaseClusterSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/connection/BaseClusterSpecification.groovy
index 56c500c6183..25a1b904e1f 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/BaseClusterSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/BaseClusterSpecification.groovy
@@ -42,7 +42,6 @@ import spock.lang.Specification
import java.util.concurrent.CountDownLatch
import static com.mongodb.ClusterFixture.CLIENT_METADATA
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
import static com.mongodb.ClusterFixture.TIMEOUT_SETTINGS
import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.connection.ClusterConnectionMode.MULTIPLE
@@ -135,7 +134,7 @@ class BaseClusterSpecification extends Specification {
factory.sendNotification(thirdServer, REPLICA_SET_PRIMARY, allServers)
expect:
- cluster.selectServer(new ReadPreferenceServerSelector(ReadPreference.secondary()), OPERATION_CONTEXT)
+ cluster.selectServer(new ReadPreferenceServerSelector(ReadPreference.secondary()), createOperationContext())
.serverDescription.address == firstServer
}
@@ -171,7 +170,7 @@ class BaseClusterSpecification extends Specification {
factory.sendNotification(thirdServer, 1, REPLICA_SET_PRIMARY, allServers)
expect:
- cluster.selectServer(new ReadPreferenceServerSelector(ReadPreference.nearest()), OPERATION_CONTEXT)
+ cluster.selectServer(new ReadPreferenceServerSelector(ReadPreference.nearest()), createOperationContext())
.serverDescription.address == firstServer
}
@@ -189,7 +188,7 @@ class BaseClusterSpecification extends Specification {
factory.sendNotification(thirdServer, 1, REPLICA_SET_PRIMARY, allServers)
expect: // firstServer is the only secondary within the latency threshold
- cluster.selectServer(new ReadPreferenceServerSelector(ReadPreference.secondary()), OPERATION_CONTEXT)
+ cluster.selectServer(new ReadPreferenceServerSelector(ReadPreference.secondary()), createOperationContext())
.serverDescription.address == firstServer
}
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/BaseClusterTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/BaseClusterTest.java
index 1cba6d91c3c..d1e6c454bc9 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/BaseClusterTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/BaseClusterTest.java
@@ -48,7 +48,7 @@ void selectServerToleratesWhenThereIsNoServerForTheSelectedAddress() {
new ServerAddressSelector(serverAddressA),
clusterDescriptionAB,
serversSnapshotB,
- ClusterFixture.OPERATION_CONTEXT.getServerDeprioritization(),
+ ClusterFixture.createOperationContext().getServerDeprioritization(),
ClusterSettings.builder().build()));
}
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultConnectionPoolSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultConnectionPoolSpecification.groovy
index b3e78d2dc54..3872f6cb1e2 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultConnectionPoolSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultConnectionPoolSpecification.groovy
@@ -41,7 +41,6 @@ import java.util.concurrent.CountDownLatch
import java.util.regex.Matcher
import java.util.regex.Pattern
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
import static com.mongodb.ClusterFixture.OPERATION_CONTEXT_FACTORY
import static com.mongodb.ClusterFixture.TIMEOUT_SETTINGS
import static com.mongodb.ClusterFixture.createOperationContext
@@ -78,7 +77,7 @@ class DefaultConnectionPoolSpecification extends Specification {
pool.ready()
expect:
- pool.get(OPERATION_CONTEXT) != null
+ pool.get(createOperationContext()) != null
}
def 'should reuse released connection'() throws InterruptedException {
@@ -86,10 +85,11 @@ class DefaultConnectionPoolSpecification extends Specification {
pool = new DefaultConnectionPool(SERVER_ID, connectionFactory,
builder().maxSize(1).build(), mockSdamProvider(), OPERATION_CONTEXT_FACTORY)
pool.ready()
+ def operationContext = createOperationContext()
when:
- pool.get(OPERATION_CONTEXT).close()
- pool.get(OPERATION_CONTEXT)
+ pool.get(operationContext).close()
+ pool.get(operationContext)
then:
1 * connectionFactory.create(SERVER_ID, _)
@@ -102,7 +102,7 @@ class DefaultConnectionPoolSpecification extends Specification {
pool.ready()
when:
- pool.get(OPERATION_CONTEXT).close()
+ pool.get(createOperationContext()).close()
then:
!connectionFactory.getCreatedConnections().get(0).isClosed()
@@ -220,7 +220,7 @@ class DefaultConnectionPoolSpecification extends Specification {
when:
pool.ready()
- pool.get(OPERATION_CONTEXT)
+ pool.get(createOperationContext())
then:
1 * listener.connectionCreated { it.connectionId.serverId == SERVER_ID }
@@ -239,6 +239,7 @@ class DefaultConnectionPoolSpecification extends Specification {
connectionDescription.getConnectionId() >> id
connection.getDescription() >> connectionDescription
connection.opened() >> false
+ def operationContext = createOperationContext()
when: 'connection pool is created'
pool = new DefaultConnectionPool(SERVER_ID, connectionFactory, settings, mockSdamProvider(), OPERATION_CONTEXT_FACTORY)
@@ -257,7 +258,7 @@ class DefaultConnectionPoolSpecification extends Specification {
"Connection pool ready for ${SERVER_ADDRESS.getHost()}:${SERVER_ADDRESS.getPort()}" == poolReadyLogMessage
when: 'connection is created'
- pool.get(OPERATION_CONTEXT)
+ pool.get(operationContext)
then: '"connection created" and "connection ready" log messages are emitted'
def createdLogMessage = getMessage( "Connection created")
def readyLogMessage = getMessage("Connection ready")
@@ -267,7 +268,7 @@ class DefaultConnectionPoolSpecification extends Specification {
", driver-generated ID=${driverConnectionId}, established in=\\d+ ms"
when: 'connection is released back into the pool on close'
- pool.get(OPERATION_CONTEXT).close()
+ pool.get(operationContext).close()
then: '"connection check out" and "connection checked in" log messages are emitted'
def checkoutStartedMessage = getMessage("Connection checkout started")
def connectionCheckedInMessage = getMessage("Connection checked in")
@@ -302,7 +303,7 @@ class DefaultConnectionPoolSpecification extends Specification {
"Connection pool closed for ${SERVER_ADDRESS.getHost()}:${SERVER_ADDRESS.getPort()}" == poolClosedLogMessage
when: 'connection checked out on closed pool'
- pool.get(OPERATION_CONTEXT)
+ pool.get(operationContext)
then:
thrown(MongoServerUnavailableException)
def connectionCheckoutFailedInMessage = getMessage("Connection checkout failed")
@@ -351,7 +352,7 @@ class DefaultConnectionPoolSpecification extends Specification {
when:
pool.ready()
- pool.get(OPERATION_CONTEXT).close()
+ pool.get(createOperationContext()).close()
//not cool - but we have no way of waiting for connection to become idle
Thread.sleep(500)
pool.close();
@@ -386,11 +387,12 @@ class DefaultConnectionPoolSpecification extends Specification {
def 'should log connection checkout failed with Reason.CONNECTION_ERROR if fails to open a connection'() {
given:
+ def operationContext = createOperationContext()
def listener = Mock(ConnectionPoolListener)
def connection = Mock(InternalConnection)
connection.getDescription() >> new ConnectionDescription(SERVER_ID)
connection.opened() >> false
- connection.open(OPERATION_CONTEXT) >> { throw new UncheckedIOException('expected failure', new IOException()) }
+ connection.open(operationContext) >> { throw new UncheckedIOException('expected failure', new IOException()) }
connectionFactory.create(SERVER_ID, _) >> connection
pool = new DefaultConnectionPool(SERVER_ID, connectionFactory, builder().addConnectionPoolListener(listener).build(),
mockSdamProvider(), OPERATION_CONTEXT_FACTORY)
@@ -398,7 +400,7 @@ class DefaultConnectionPoolSpecification extends Specification {
when:
try {
- pool.get(OPERATION_CONTEXT)
+ pool.get(operationContext)
} catch (UncheckedIOException e) {
if ('expected failure' != e.getMessage()) {
throw e
@@ -435,7 +437,7 @@ class DefaultConnectionPoolSpecification extends Specification {
pool = new DefaultConnectionPool(SERVER_ID, connectionFactory, builder().maxSize(10)
.addConnectionPoolListener(listener).build(), mockSdamProvider(), OPERATION_CONTEXT_FACTORY)
pool.ready()
- def connection = pool.get(OPERATION_CONTEXT)
+ def connection = pool.get(createOperationContext())
connection.close()
when:
@@ -463,15 +465,16 @@ class DefaultConnectionPoolSpecification extends Specification {
def 'should fire connection pool events on check out and check in'() {
given:
+ def operationContext = createOperationContext()
def listener = Mock(ConnectionPoolListener)
pool = new DefaultConnectionPool(SERVER_ID, connectionFactory, builder().maxSize(1)
.addConnectionPoolListener(listener).build(), mockSdamProvider(), OPERATION_CONTEXT_FACTORY)
pool.ready()
- def connection = pool.get(OPERATION_CONTEXT)
+ def connection = pool.get(operationContext)
connection.close()
when:
- connection = pool.get(OPERATION_CONTEXT)
+ connection = pool.get(operationContext)
then:
1 * listener.connectionCheckedOut { it.connectionId.serverId == SERVER_ID }
@@ -493,7 +496,7 @@ class DefaultConnectionPoolSpecification extends Specification {
connection.close()
when:
- connection = pool.get(OPERATION_CONTEXT)
+ connection = pool.get(createOperationContext())
then:
1 * listener.connectionCheckedOut { it.connectionId.serverId == SERVER_ID }
@@ -507,11 +510,12 @@ class DefaultConnectionPoolSpecification extends Specification {
def 'should fire connection checkout failed with Reason.CONNECTION_ERROR if fails to open a connection'() {
given:
+ def operationContext = createOperationContext()
def listener = Mock(ConnectionPoolListener)
def connection = Mock(InternalConnection)
connection.getDescription() >> new ConnectionDescription(SERVER_ID)
connection.opened() >> false
- connection.open(OPERATION_CONTEXT) >> { throw new UncheckedIOException('expected failure', new IOException()) }
+ connection.open(operationContext) >> { throw new UncheckedIOException('expected failure', new IOException()) }
connectionFactory.create(SERVER_ID, _) >> connection
pool = new DefaultConnectionPool(SERVER_ID, connectionFactory, builder().addConnectionPoolListener(listener).build(),
mockSdamProvider(), OPERATION_CONTEXT_FACTORY)
@@ -519,7 +523,7 @@ class DefaultConnectionPoolSpecification extends Specification {
when:
try {
- pool.get(OPERATION_CONTEXT)
+ pool.get(operationContext)
} catch (UncheckedIOException e) {
if ('expected failure' != e.getMessage()) {
throw e
@@ -564,7 +568,7 @@ class DefaultConnectionPoolSpecification extends Specification {
when:
try {
- pool.get(OPERATION_CONTEXT)
+ pool.get(createOperationContext())
} catch (MongoConnectionPoolClearedException e) {
caught = e
}
@@ -579,7 +583,7 @@ class DefaultConnectionPoolSpecification extends Specification {
CompletableFuture caught = new CompletableFuture<>()
when:
- pool.getAsync(OPERATION_CONTEXT) { InternalConnection result, Throwable t ->
+ pool.getAsync(createOperationContext()) { InternalConnection result, Throwable t ->
if (t != null) {
caught.complete(t)
}
@@ -599,7 +603,7 @@ class DefaultConnectionPoolSpecification extends Specification {
when:
pool.invalidate(cause)
try {
- pool.get(OPERATION_CONTEXT)
+ pool.get(createOperationContext())
} catch (MongoConnectionPoolClearedException e) {
caught = e
}
@@ -630,7 +634,7 @@ class DefaultConnectionPoolSpecification extends Specification {
pool = new DefaultConnectionPool(SERVER_ID, connectionFactory, builder().maxSize(1)
.addConnectionPoolListener(listener).build(), mockSdamProvider(), OPERATION_CONTEXT_FACTORY)
pool.ready()
- def connection = pool.get(OPERATION_CONTEXT)
+ def connection = pool.get(createOperationContext())
pool.close()
when:
@@ -674,7 +678,7 @@ class DefaultConnectionPoolSpecification extends Specification {
pool.ready()
when:
- def connection = pool.get(OPERATION_CONTEXT)
+ def connection = pool.get(createOperationContext())
def connectionLatch = selectConnectionAsync(pool)
connection.close()
@@ -684,12 +688,13 @@ class DefaultConnectionPoolSpecification extends Specification {
def 'when getting a connection asynchronously should send MongoTimeoutException to callback after timeout period'() {
given:
+ def operationContext = createOperationContext()
pool = new DefaultConnectionPool(SERVER_ID, connectionFactory,
builder().maxSize(1).maxWaitTime(5, MILLISECONDS).build(), mockSdamProvider(), OPERATION_CONTEXT_FACTORY)
pool.ready()
- pool.get(OPERATION_CONTEXT)
- def firstConnectionLatch = selectConnectionAsync(pool)
- def secondConnectionLatch = selectConnectionAsync(pool)
+ pool.get(operationContext)
+ def firstConnectionLatch = selectConnectionAsync(pool, operationContext)
+ def secondConnectionLatch = selectConnectionAsync(pool, operationContext)
when:
firstConnectionLatch.get()
@@ -721,9 +726,9 @@ class DefaultConnectionPoolSpecification extends Specification {
selectConnectionAsync(pool).get()
}
- def selectConnectionAsync(DefaultConnectionPool pool) {
+ def selectConnectionAsync(DefaultConnectionPool pool, operationContext = createOperationContext()) {
def serverLatch = new ConnectionLatch()
- pool.getAsync(OPERATION_CONTEXT) { InternalConnection result, Throwable e ->
+ pool.getAsync(operationContext) { InternalConnection result, Throwable e ->
serverLatch.connection = result
serverLatch.throwable = e
serverLatch.latch.countDown()
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultServerConnectionSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultServerConnectionSpecification.groovy
index be6fbe06b83..26348f16198 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultServerConnectionSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultServerConnectionSpecification.groovy
@@ -16,7 +16,7 @@
package com.mongodb.internal.connection
-
+import com.mongodb.ClusterFixture
import com.mongodb.ReadPreference
import com.mongodb.connection.ClusterConnectionMode
import com.mongodb.internal.async.SingleResultCallback
@@ -27,7 +27,6 @@ import org.bson.BsonInt32
import org.bson.codecs.BsonDocumentCodec
import spock.lang.Specification
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
import static com.mongodb.CustomMatchers.compare
import static com.mongodb.internal.async.ErrorHandlingResultCallback.errorHandlingCallback
import static com.mongodb.internal.connection.MessageHelper.LEGACY_HELLO_LOWER
@@ -43,14 +42,16 @@ class DefaultServerConnectionSpecification extends Specification {
def codec = new BsonDocumentCodec()
def executor = Mock(ProtocolExecutor)
def connection = new DefaultServerConnection(internalConnection, executor, ClusterConnectionMode.MULTIPLE)
+ def operationContext = ClusterFixture.createOperationContext()
+
when:
- connection.commandAsync('test', command, validator, ReadPreference.primary(), codec, OPERATION_CONTEXT, callback)
+ connection.commandAsync('test', command, validator, ReadPreference.primary(), codec, operationContext, callback)
then:
1 * executor.executeAsync({
compare(new CommandProtocolImpl('test', command, validator, ReadPreference.primary(), codec, true,
- MessageSequences.EmptyMessageSequences.INSTANCE, ClusterConnectionMode.MULTIPLE, OPERATION_CONTEXT), it)
- }, internalConnection, OPERATION_CONTEXT.getSessionContext(), callback)
+ MessageSequences.EmptyMessageSequences.INSTANCE, ClusterConnectionMode.MULTIPLE, operationContext), it)
+ }, internalConnection, operationContext.getSessionContext(), callback)
}
}
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultServerSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultServerSpecification.groovy
index 3910da575f0..230301e9033 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultServerSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultServerSpecification.groovy
@@ -54,7 +54,7 @@ import spock.lang.Specification
import java.util.concurrent.CountDownLatch
import static com.mongodb.ClusterFixture.CLIENT_METADATA
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.MongoCredential.createCredential
import static com.mongodb.connection.ClusterConnectionMode.MULTIPLE
import static com.mongodb.connection.ClusterConnectionMode.SINGLE
@@ -74,7 +74,7 @@ class DefaultServerSpecification extends Specification {
Mock(SdamServerDescriptionManager), Mock(ServerListener), Mock(CommandListener), new ClusterClock(), false)
when:
- def receivedConnection = server.getConnection(OPERATION_CONTEXT)
+ def receivedConnection = server.getConnection(createOperationContext())
then:
receivedConnection
@@ -100,7 +100,7 @@ class DefaultServerSpecification extends Specification {
when:
def callback = new SupplyingCallback()
- server.getConnectionAsync(OPERATION_CONTEXT, callback)
+ server.getConnectionAsync(createOperationContext(), callback)
then:
callback.get() == connection
@@ -117,7 +117,7 @@ class DefaultServerSpecification extends Specification {
server.close()
when:
- server.getConnection(OPERATION_CONTEXT)
+ server.getConnection(createOperationContext())
then:
def ex = thrown(MongoServerUnavailableException)
@@ -127,7 +127,7 @@ class DefaultServerSpecification extends Specification {
def latch = new CountDownLatch(1)
def receivedConnection = null
def receivedThrowable = null
- server.getConnectionAsync(OPERATION_CONTEXT) {
+ server.getConnectionAsync(createOperationContext()) {
result, throwable ->
receivedConnection = result; receivedThrowable = throwable; latch.countDown()
}
@@ -210,7 +210,6 @@ class DefaultServerSpecification extends Specification {
given:
def connectionPool = Mock(ConnectionPool)
def serverMonitor = Mock(ServerMonitor)
- connectionPool.get(OPERATION_CONTEXT) >> { throw exceptionToThrow }
def server = defaultServer(connectionPool, serverMonitor)
server.close()
@@ -242,7 +241,7 @@ class DefaultServerSpecification extends Specification {
def server = defaultServer(connectionPool, serverMonitor)
when:
- server.getConnection(OPERATION_CONTEXT)
+ server.getConnection(createOperationContext())
then:
def e = thrown(MongoException)
@@ -267,7 +266,7 @@ class DefaultServerSpecification extends Specification {
def server = defaultServer(connectionPool, serverMonitor)
when:
- server.getConnection(OPERATION_CONTEXT)
+ server.getConnection(createOperationContext())
then:
def e = thrown(MongoSecurityException)
@@ -292,7 +291,7 @@ class DefaultServerSpecification extends Specification {
def latch = new CountDownLatch(1)
def receivedConnection = null
def receivedThrowable = null
- server.getConnectionAsync(OPERATION_CONTEXT) {
+ server.getConnectionAsync(createOperationContext()) {
result, throwable ->
receivedConnection = result; receivedThrowable = throwable; latch.countDown()
}
@@ -325,7 +324,7 @@ class DefaultServerSpecification extends Specification {
def latch = new CountDownLatch(1)
def receivedConnection = null
def receivedThrowable = null
- server.getConnectionAsync(OPERATION_CONTEXT) {
+ server.getConnectionAsync(createOperationContext()) {
result, throwable ->
receivedConnection = result; receivedThrowable = throwable; latch.countDown()
}
@@ -350,7 +349,7 @@ class DefaultServerSpecification extends Specification {
clusterClock.advance(clusterClockClusterTime)
def server = new DefaultServer(serverId, SINGLE, Mock(ConnectionPool), new TestConnectionFactory(), Mock(ServerMonitor),
Mock(SdamServerDescriptionManager), Mock(ServerListener), Mock(CommandListener), clusterClock, false)
- def testConnection = (TestConnection) server.getConnection(OPERATION_CONTEXT)
+ def testConnection = (TestConnection) server.getConnection(createOperationContext())
def sessionContext = new TestSessionContext(initialClusterTime)
def response = BsonDocument.parse(
'''{
@@ -361,7 +360,7 @@ class DefaultServerSpecification extends Specification {
''')
def protocol = new TestCommandProtocol(response)
testConnection.enqueueProtocol(protocol)
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
when:
if (async) {
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/InternalStreamConnectionSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/connection/InternalStreamConnectionSpecification.groovy
index 3cdabf31da3..10074ba9d3c 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/InternalStreamConnectionSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/InternalStreamConnectionSpecification.groovy
@@ -58,7 +58,7 @@ import java.util.concurrent.CountDownLatch
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.TIMEOUT_SETTINGS_WITH_INFINITE_TIMEOUT
import static com.mongodb.ReadPreference.primary
import static com.mongodb.connection.ClusterConnectionMode.MULTIPLE
@@ -114,7 +114,7 @@ class InternalStreamConnectionSpecification extends Specification {
def getOpenedConnection() {
def connection = getConnection()
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
connection
}
@@ -132,7 +132,7 @@ class InternalStreamConnectionSpecification extends Specification {
.lastUpdateTimeNanos(connection.getInitialServerDescription().getLastUpdateTime(NANOSECONDS))
.build()
when:
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
then:
connection.opened()
@@ -159,7 +159,7 @@ class InternalStreamConnectionSpecification extends Specification {
.build()
when:
- connection.openAsync(OPERATION_CONTEXT, futureResultCallback)
+ connection.openAsync(createOperationContext(), futureResultCallback)
futureResultCallback.get()
then:
@@ -177,7 +177,7 @@ class InternalStreamConnectionSpecification extends Specification {
failedInitializer)
when:
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
then:
thrown MongoInternalException
@@ -195,7 +195,7 @@ class InternalStreamConnectionSpecification extends Specification {
when:
def futureResultCallback = new FutureResultCallback()
- connection.openAsync(OPERATION_CONTEXT, futureResultCallback)
+ connection.openAsync(createOperationContext(), futureResultCallback)
futureResultCallback.get()
then:
@@ -212,14 +212,14 @@ class InternalStreamConnectionSpecification extends Specification {
def (buffers2, messageId2) = helper.hello()
when:
- connection.sendMessage(buffers1, messageId1, OPERATION_CONTEXT)
+ connection.sendMessage(buffers1, messageId1, createOperationContext())
then:
connection.isClosed()
thrown MongoSocketWriteException
when:
- connection.sendMessage(buffers2, messageId2, OPERATION_CONTEXT)
+ connection.sendMessage(buffers2, messageId2, createOperationContext())
then:
thrown MongoSocketClosedException
@@ -243,7 +243,7 @@ class InternalStreamConnectionSpecification extends Specification {
def connection = getOpenedConnection()
when:
- connection.sendMessageAsync(buffers1, messageId1, OPERATION_CONTEXT, sndCallbck1)
+ connection.sendMessageAsync(buffers1, messageId1, createOperationContext(), sndCallbck1)
sndCallbck1.get(10, SECONDS)
then:
@@ -251,7 +251,7 @@ class InternalStreamConnectionSpecification extends Specification {
connection.isClosed()
when:
- connection.sendMessageAsync(buffers2, messageId2, OPERATION_CONTEXT, sndCallbck2)
+ connection.sendMessageAsync(buffers2, messageId2, createOperationContext(), sndCallbck2)
sndCallbck2.get(10, SECONDS)
then:
@@ -267,16 +267,16 @@ class InternalStreamConnectionSpecification extends Specification {
def (buffers2, messageId2) = helper.hello()
when:
- connection.sendMessage(buffers1, messageId1, OPERATION_CONTEXT)
- connection.sendMessage(buffers2, messageId2, OPERATION_CONTEXT)
- connection.receiveMessage(messageId1, OPERATION_CONTEXT)
+ connection.sendMessage(buffers1, messageId1, createOperationContext())
+ connection.sendMessage(buffers2, messageId2, createOperationContext())
+ connection.receiveMessage(messageId1, createOperationContext())
then:
connection.isClosed()
thrown MongoSocketReadException
when:
- connection.receiveMessage(messageId2, OPERATION_CONTEXT)
+ connection.receiveMessage(messageId2, createOperationContext())
then:
thrown MongoSocketClosedException
@@ -289,7 +289,7 @@ class InternalStreamConnectionSpecification extends Specification {
def connection = getOpenedConnection()
when:
- connection.receiveMessage(1, OPERATION_CONTEXT)
+ connection.receiveMessage(1, createOperationContext())
then:
thrown(MongoInternalException)
@@ -306,7 +306,7 @@ class InternalStreamConnectionSpecification extends Specification {
def callback = new FutureResultCallback()
when:
- connection.receiveMessageAsync(1, OPERATION_CONTEXT, callback)
+ connection.receiveMessageAsync(1, createOperationContext(), callback)
callback.get()
then:
@@ -321,7 +321,7 @@ class InternalStreamConnectionSpecification extends Specification {
Thread.currentThread().interrupt()
when:
- connection.sendMessage([new ByteBufNIO(ByteBuffer.allocate(1))], 1, OPERATION_CONTEXT)
+ connection.sendMessage([new ByteBufNIO(ByteBuffer.allocate(1))], 1, createOperationContext())
then:
Thread.interrupted()
@@ -335,7 +335,7 @@ class InternalStreamConnectionSpecification extends Specification {
def connection = getOpenedConnection()
when:
- connection.sendMessage([new ByteBufNIO(ByteBuffer.allocate(1))], 1, OPERATION_CONTEXT)
+ connection.sendMessage([new ByteBufNIO(ByteBuffer.allocate(1))], 1, createOperationContext())
then:
!Thread.interrupted()
@@ -350,7 +350,7 @@ class InternalStreamConnectionSpecification extends Specification {
Thread.currentThread().interrupt()
when:
- connection.sendMessage([new ByteBufNIO(ByteBuffer.allocate(1))], 1, OPERATION_CONTEXT)
+ connection.sendMessage([new ByteBufNIO(ByteBuffer.allocate(1))], 1, createOperationContext())
then:
Thread.interrupted()
@@ -365,7 +365,7 @@ class InternalStreamConnectionSpecification extends Specification {
Thread.currentThread().interrupt()
when:
- connection.sendMessage([new ByteBufNIO(ByteBuffer.allocate(1))], 1, OPERATION_CONTEXT)
+ connection.sendMessage([new ByteBufNIO(ByteBuffer.allocate(1))], 1, createOperationContext())
then:
Thread.interrupted()
@@ -379,7 +379,7 @@ class InternalStreamConnectionSpecification extends Specification {
def connection = getOpenedConnection()
when:
- connection.sendMessage([new ByteBufNIO(ByteBuffer.allocate(1))], 1, OPERATION_CONTEXT)
+ connection.sendMessage([new ByteBufNIO(ByteBuffer.allocate(1))], 1, createOperationContext())
then:
thrown(MongoSocketWriteException)
@@ -393,7 +393,7 @@ class InternalStreamConnectionSpecification extends Specification {
Thread.currentThread().interrupt()
when:
- connection.receiveMessage(1, OPERATION_CONTEXT)
+ connection.receiveMessage(1, createOperationContext())
then:
Thread.interrupted()
@@ -407,7 +407,7 @@ class InternalStreamConnectionSpecification extends Specification {
def connection = getOpenedConnection()
when:
- connection.receiveMessage(1, OPERATION_CONTEXT)
+ connection.receiveMessage(1, createOperationContext())
then:
!Thread.interrupted()
@@ -422,7 +422,7 @@ class InternalStreamConnectionSpecification extends Specification {
Thread.currentThread().interrupt()
when:
- connection.receiveMessage(1, OPERATION_CONTEXT)
+ connection.receiveMessage(1, createOperationContext())
then:
Thread.interrupted()
@@ -437,7 +437,7 @@ class InternalStreamConnectionSpecification extends Specification {
Thread.currentThread().interrupt()
when:
- connection.receiveMessage(1, OPERATION_CONTEXT)
+ connection.receiveMessage(1, createOperationContext())
then:
Thread.interrupted()
@@ -451,7 +451,7 @@ class InternalStreamConnectionSpecification extends Specification {
def connection = getOpenedConnection()
when:
- connection.receiveMessage(1, OPERATION_CONTEXT)
+ connection.receiveMessage(1, createOperationContext())
then:
thrown(MongoSocketReadException)
@@ -464,7 +464,7 @@ class InternalStreamConnectionSpecification extends Specification {
def connection = getOpenedConnection()
when:
- connection.receiveMessage(1, OPERATION_CONTEXT.withTimeoutContext(
+ connection.receiveMessage(1, createOperationContext().withTimeoutContext(
new TimeoutContext(TIMEOUT_SETTINGS_WITH_INFINITE_TIMEOUT)))
then:
@@ -482,7 +482,7 @@ class InternalStreamConnectionSpecification extends Specification {
def connection = getOpenedConnection()
when:
- connection.receiveMessage(1, OPERATION_CONTEXT.withTimeoutContext(
+ connection.receiveMessage(1, createOperationContext().withTimeoutContext(
new TimeoutContext(TIMEOUT_SETTINGS_WITH_INFINITE_TIMEOUT)))
then:
@@ -502,7 +502,7 @@ class InternalStreamConnectionSpecification extends Specification {
}
def connection = getOpenedConnection()
def callback = new FutureResultCallback()
- def operationContext = OPERATION_CONTEXT.withTimeoutContext(
+ def operationContext = createOperationContext().withTimeoutContext(
new TimeoutContext(TIMEOUT_SETTINGS_WITH_INFINITE_TIMEOUT))
when:
connection.receiveMessageAsync(1, operationContext, callback)
@@ -525,7 +525,7 @@ class InternalStreamConnectionSpecification extends Specification {
def connection = getOpenedConnection()
def callback = new FutureResultCallback()
- def operationContext = OPERATION_CONTEXT.withTimeoutContext(
+ def operationContext = createOperationContext().withTimeoutContext(
new TimeoutContext(TIMEOUT_SETTINGS_WITH_INFINITE_TIMEOUT))
when:
connection.receiveMessageAsync(1, operationContext, callback)
@@ -563,10 +563,10 @@ class InternalStreamConnectionSpecification extends Specification {
def connection = getOpenedConnection()
when:
- connection.sendMessageAsync(buffers1, messageId1, OPERATION_CONTEXT, sndCallbck1)
- connection.sendMessageAsync(buffers2, messageId2, OPERATION_CONTEXT, sndCallbck2)
- connection.receiveMessageAsync(messageId1, OPERATION_CONTEXT, rcvdCallbck1)
- connection.receiveMessageAsync(messageId2, OPERATION_CONTEXT, rcvdCallbck2)
+ connection.sendMessageAsync(buffers1, messageId1, createOperationContext(), sndCallbck1)
+ connection.sendMessageAsync(buffers2, messageId2, createOperationContext(), sndCallbck2)
+ connection.receiveMessageAsync(messageId1, createOperationContext(), rcvdCallbck1)
+ connection.receiveMessageAsync(messageId2, createOperationContext(), rcvdCallbck2)
rcvdCallbck1.get(1, SECONDS)
then:
@@ -588,14 +588,14 @@ class InternalStreamConnectionSpecification extends Specification {
def connection = getOpenedConnection()
when:
- connection.receiveMessage(1, OPERATION_CONTEXT)
+ connection.receiveMessage(1, createOperationContext())
then:
connection.isClosed()
thrown MongoSocketReadException
when:
- connection.receiveMessage(1, OPERATION_CONTEXT)
+ connection.receiveMessage(1, createOperationContext())
then:
thrown MongoSocketClosedException
@@ -620,9 +620,9 @@ class InternalStreamConnectionSpecification extends Specification {
def connection = getOpenedConnection()
when:
- connection.sendMessageAsync(buffers1, messageId1, OPERATION_CONTEXT, sndCallbck1)
- connection.sendMessageAsync(buffers2, messageId2, OPERATION_CONTEXT, sndCallbck2)
- connection.receiveMessageAsync(messageId1, OPERATION_CONTEXT, rcvdCallbck1)
+ connection.sendMessageAsync(buffers1, messageId1, createOperationContext(), sndCallbck1)
+ connection.sendMessageAsync(buffers2, messageId2, createOperationContext(), sndCallbck2)
+ connection.receiveMessageAsync(messageId1, createOperationContext(), rcvdCallbck1)
rcvdCallbck1.get(1, SECONDS)
then:
@@ -630,7 +630,7 @@ class InternalStreamConnectionSpecification extends Specification {
connection.isClosed()
when:
- connection.receiveMessageAsync(messageId2, OPERATION_CONTEXT, rcvdCallbck2)
+ connection.receiveMessageAsync(messageId2, createOperationContext(), rcvdCallbck2)
rcvdCallbck2.get(1, SECONDS)
then:
@@ -649,7 +649,7 @@ class InternalStreamConnectionSpecification extends Specification {
stream.read(_, _) >> helper.reply(response)
when:
- connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT)
+ connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), createOperationContext())
then:
thrown(MongoCommandException)
@@ -677,7 +677,7 @@ class InternalStreamConnectionSpecification extends Specification {
}
when:
- connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT, callback)
+ connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), createOperationContext(), callback)
callback.get()
then:
@@ -705,7 +705,7 @@ class InternalStreamConnectionSpecification extends Specification {
def callbacks = []
(1..numberOfOperations).each { n ->
def (buffers, messageId, sndCallbck, rcvdCallbck) = messages.pop()
- connection.sendMessageAsync(buffers, messageId, OPERATION_CONTEXT, sndCallbck)
+ connection.sendMessageAsync(buffers, messageId, createOperationContext(), sndCallbck)
callbacks.add(sndCallbck)
}
streamLatch.countDown()
@@ -730,7 +730,7 @@ class InternalStreamConnectionSpecification extends Specification {
stream.read(90, _) >> helper.defaultReply()
when:
- connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT)
+ connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), createOperationContext())
then:
commandListener.eventsWereDelivered([
@@ -753,7 +753,7 @@ class InternalStreamConnectionSpecification extends Specification {
when:
connection.sendAndReceive(commandMessage, {
BsonReader reader, DecoderContext decoderContext -> throw new CodecConfigurationException('')
- }, OPERATION_CONTEXT)
+ }, createOperationContext())
then:
thrown(CodecConfigurationException)
@@ -783,7 +783,7 @@ class InternalStreamConnectionSpecification extends Specification {
1 * advanceClusterTime(BsonDocument.parse(response).getDocument('$clusterTime'))
getReadConcern() >> ReadConcern.DEFAULT
}
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
when:
connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), operationContext)
@@ -819,7 +819,7 @@ class InternalStreamConnectionSpecification extends Specification {
1 * advanceClusterTime(BsonDocument.parse(response).getDocument('$clusterTime'))
getReadConcern() >> ReadConcern.DEFAULT
}
- def operationContext = OPERATION_CONTEXT.withSessionContext(sessionContext)
+ def operationContext = createOperationContext().withSessionContext(sessionContext)
when:
connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), operationContext, callback)
@@ -839,7 +839,7 @@ class InternalStreamConnectionSpecification extends Specification {
stream.write(_, _) >> { throw new MongoSocketWriteException('Failed to write', serverAddress, new IOException()) }
when:
- connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT)
+ connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), createOperationContext())
then:
def e = thrown(MongoSocketWriteException)
@@ -859,7 +859,7 @@ class InternalStreamConnectionSpecification extends Specification {
stream.read(16, _) >> { throw new MongoSocketReadException('Failed to read', serverAddress) }
when:
- connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT)
+ connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), createOperationContext())
then:
def e = thrown(MongoSocketReadException)
@@ -880,7 +880,7 @@ class InternalStreamConnectionSpecification extends Specification {
stream.read(90, _) >> { throw new MongoSocketReadException('Failed to read', serverAddress) }
when:
- connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT)
+ connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), createOperationContext())
then:
def e = thrown(MongoSocketException)
@@ -902,7 +902,7 @@ class InternalStreamConnectionSpecification extends Specification {
stream.read(_, _) >> helper.reply(response)
when:
- connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT)
+ connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), createOperationContext())
then:
def e = thrown(MongoCommandException)
@@ -923,7 +923,7 @@ class InternalStreamConnectionSpecification extends Specification {
stream.read(90, _) >> helper.defaultReply()
when:
- connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT)
+ connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), createOperationContext())
then:
commandListener.eventsWereDelivered([
@@ -959,7 +959,7 @@ class InternalStreamConnectionSpecification extends Specification {
stream.read(_, _) >> helper.reply('{ok : 0, errmsg : "failed"}')
when:
- connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT)
+ connection.sendAndReceive(commandMessage, new BsonDocumentCodec(), createOperationContext())
then:
thrown(MongoCommandException)
@@ -1005,7 +1005,7 @@ class InternalStreamConnectionSpecification extends Specification {
}
when:
- connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT, callback)
+ connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), createOperationContext(), callback)
callback.get()
then:
@@ -1038,7 +1038,7 @@ class InternalStreamConnectionSpecification extends Specification {
when:
connection.sendAndReceiveAsync(commandMessage, {
BsonReader reader, DecoderContext decoderContext -> throw new CodecConfigurationException('')
- }, OPERATION_CONTEXT, callback)
+ }, createOperationContext(), callback)
callback.get()
then:
@@ -1065,7 +1065,7 @@ class InternalStreamConnectionSpecification extends Specification {
}
when:
- connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT, callback)
+ connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), createOperationContext(), callback)
callback.get()
then:
@@ -1093,7 +1093,7 @@ class InternalStreamConnectionSpecification extends Specification {
}
when:
- connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT, callback)
+ connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), createOperationContext(), callback)
callback.get()
then:
@@ -1124,7 +1124,7 @@ class InternalStreamConnectionSpecification extends Specification {
}
when:
- connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT, callback)
+ connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), createOperationContext(), callback)
callback.get()
then:
@@ -1156,7 +1156,7 @@ class InternalStreamConnectionSpecification extends Specification {
}
when:
- connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT, callback)
+ connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), createOperationContext(), callback)
callback.get()
then:
@@ -1187,7 +1187,7 @@ class InternalStreamConnectionSpecification extends Specification {
}
when:
- connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), OPERATION_CONTEXT, callback)
+ connection.sendAndReceiveAsync(commandMessage, new BsonDocumentCodec(), createOperationContext(), callback)
callback.get()
then:
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/JMXConnectionPoolListenerSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/connection/JMXConnectionPoolListenerSpecification.groovy
index 374687f7d01..5a7bcd3e492 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/JMXConnectionPoolListenerSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/JMXConnectionPoolListenerSpecification.groovy
@@ -29,7 +29,7 @@ import spock.lang.Unroll
import javax.management.ObjectName
import java.lang.management.ManagementFactory
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.OPERATION_CONTEXT_FACTORY
class JMXConnectionPoolListenerSpecification extends Specification {
@@ -50,8 +50,8 @@ class JMXConnectionPoolListenerSpecification extends Specification {
provider.ready()
when:
- provider.get(OPERATION_CONTEXT)
- provider.get(OPERATION_CONTEXT).close()
+ provider.get(createOperationContext())
+ provider.get(createOperationContext()).close()
then:
with(jmxListener.getMBean(SERVER_ID)) {
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/LoadBalancedClusterTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/LoadBalancedClusterTest.java
index 7366a03b584..87dd1581045 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/LoadBalancedClusterTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/LoadBalancedClusterTest.java
@@ -16,6 +16,7 @@
package com.mongodb.internal.connection;
+import com.mongodb.ClusterFixture;
import com.mongodb.MongoClientException;
import com.mongodb.MongoConfigurationException;
import com.mongodb.MongoException;
@@ -52,7 +53,6 @@
import java.util.concurrent.atomic.AtomicReference;
import static com.mongodb.ClusterFixture.CLIENT_METADATA;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.TIMEOUT_SETTINGS;
import static com.mongodb.ClusterFixture.createOperationContext;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
@@ -96,14 +96,14 @@ public void shouldSelectServerWhenThereIsNoSRVLookup() {
mock(DnsSrvRecordMonitorFactory.class));
// when
- ServerTuple serverTuple = cluster.selectServer(mock(ServerSelector.class), OPERATION_CONTEXT);
+ ServerTuple serverTuple = cluster.selectServer(mock(ServerSelector.class), ClusterFixture.createOperationContext());
// then
assertServerTupleExpectations(serverAddress, expectedServer, serverTuple);
// when
FutureResultCallback callback = new FutureResultCallback<>();
- cluster.selectServerAsync(mock(ServerSelector.class), OPERATION_CONTEXT, callback);
+ cluster.selectServerAsync(mock(ServerSelector.class), ClusterFixture.createOperationContext(), callback);
serverTuple = callback.get();
// then
@@ -131,7 +131,7 @@ public void shouldSelectServerWhenThereIsSRVLookup() {
cluster = new LoadBalancedCluster(new ClusterId(), clusterSettings, serverFactory, CLIENT_METADATA, dnsSrvRecordMonitorFactory);
// when
- ServerTuple serverTuple = cluster.selectServer(mock(ServerSelector.class), OPERATION_CONTEXT);
+ ServerTuple serverTuple = cluster.selectServer(mock(ServerSelector.class), ClusterFixture.createOperationContext());
// then
assertServerTupleExpectations(resolvedServerAddress, expectedServer, serverTuple);
@@ -159,7 +159,7 @@ public void shouldSelectServerAsynchronouslyWhenThereIsSRVLookup() {
// when
FutureResultCallback callback = new FutureResultCallback<>();
- cluster.selectServerAsync(mock(ServerSelector.class), OPERATION_CONTEXT, callback);
+ cluster.selectServerAsync(mock(ServerSelector.class), ClusterFixture.createOperationContext(), callback);
ServerTuple serverTuple = callback.get();
// then
@@ -185,7 +185,7 @@ public void shouldFailSelectServerWhenThereIsSRVMisconfiguration() {
cluster = new LoadBalancedCluster(new ClusterId(), clusterSettings, serverFactory, CLIENT_METADATA, dnsSrvRecordMonitorFactory);
MongoClientException exception = assertThrows(MongoClientException.class, () -> cluster.selectServer(mock(ServerSelector.class),
- OPERATION_CONTEXT));
+ ClusterFixture.createOperationContext()));
assertEquals("In load balancing mode, the host must resolve to a single SRV record, but instead it resolved to multiple hosts",
exception.getMessage());
}
@@ -209,7 +209,7 @@ public void shouldFailSelectServerAsynchronouslyWhenThereIsSRVMisconfiguration()
cluster = new LoadBalancedCluster(new ClusterId(), clusterSettings, serverFactory, CLIENT_METADATA, dnsSrvRecordMonitorFactory);
FutureResultCallback callback = new FutureResultCallback<>();
- cluster.selectServerAsync(mock(ServerSelector.class), OPERATION_CONTEXT, callback);
+ cluster.selectServerAsync(mock(ServerSelector.class), ClusterFixture.createOperationContext(), callback);
MongoClientException exception = assertThrows(MongoClientException.class, callback::get);
assertEquals("In load balancing mode, the host must resolve to a single SRV record, but instead it resolved to multiple hosts",
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/LoggingCommandEventSenderSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/connection/LoggingCommandEventSenderSpecification.groovy
index e6f6afb02e0..de12c35af5e 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/LoggingCommandEventSenderSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/LoggingCommandEventSenderSpecification.groovy
@@ -39,7 +39,7 @@ import org.bson.BsonInt32
import org.bson.BsonString
import spock.lang.Specification
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.connection.ClusterConnectionMode.MULTIPLE
import static com.mongodb.connection.ClusterConnectionMode.SINGLE
import static com.mongodb.internal.operation.ServerVersionHelper.LATEST_WIRE_VERSION
@@ -63,7 +63,7 @@ class LoggingCommandEventSenderSpecification extends Specification {
def logger = Stub(Logger) {
isDebugEnabled() >> debugLoggingEnabled
}
- def operationContext = OPERATION_CONTEXT
+ def operationContext = createOperationContext()
def sender = new LoggingCommandEventSender([] as Set, [] as Set, connectionDescription, commandListener,
operationContext, message, message.getCommandDocument(bsonOutput),
new StructuredLogger(logger), LoggerSettings.builder().build())
@@ -109,7 +109,7 @@ class LoggingCommandEventSenderSpecification extends Specification {
def logger = Mock(Logger) {
isDebugEnabled() >> true
}
- def operationContext = OPERATION_CONTEXT
+ def operationContext = createOperationContext()
def sender = new LoggingCommandEventSender([] as Set, [] as Set, connectionDescription, commandListener,
operationContext, message, message.getCommandDocument(bsonOutput), new StructuredLogger(logger),
LoggerSettings.builder().build())
@@ -166,7 +166,7 @@ class LoggingCommandEventSenderSpecification extends Specification {
def logger = Mock(Logger) {
isDebugEnabled() >> true
}
- def operationContext = OPERATION_CONTEXT
+ def operationContext = createOperationContext()
def sender = new LoggingCommandEventSender([] as Set, [] as Set, connectionDescription, null, operationContext,
message, message.getCommandDocument(bsonOutput), new StructuredLogger(logger), LoggerSettings.builder().build())
@@ -200,7 +200,7 @@ class LoggingCommandEventSenderSpecification extends Specification {
def logger = Mock(Logger) {
isDebugEnabled() >> true
}
- def operationContext = OPERATION_CONTEXT
+ def operationContext = createOperationContext()
def sender = new LoggingCommandEventSender(['createUser'] as Set, [] as Set, connectionDescription, null,
operationContext, message, message.getCommandDocument(bsonOutput), new StructuredLogger(logger),
LoggerSettings.builder().build())
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/MultiServerClusterSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/connection/MultiServerClusterSpecification.groovy
index a3cf8104fd3..737aead0300 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/MultiServerClusterSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/MultiServerClusterSpecification.groovy
@@ -29,7 +29,7 @@ import org.bson.types.ObjectId
import spock.lang.Specification
import static com.mongodb.ClusterFixture.CLIENT_METADATA
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.connection.ClusterConnectionMode.MULTIPLE
import static com.mongodb.connection.ClusterType.REPLICA_SET
import static com.mongodb.connection.ClusterType.SHARDED
@@ -93,11 +93,12 @@ class MultiServerClusterSpecification extends Specification {
def cluster = new MultiServerCluster(CLUSTER_ID, ClusterSettings.builder().hosts(Arrays.asList(firstServer)).mode(MULTIPLE).build(),
factory, CLIENT_METADATA)
cluster.close()
+ def operationContext = createOperationContext()
when:
cluster.getServersSnapshot(
- OPERATION_CONTEXT.getTimeoutContext().computeServerSelectionTimeout(),
- OPERATION_CONTEXT.getTimeoutContext())
+ operationContext.getTimeoutContext().computeServerSelectionTimeout(),
+ operationContext.getTimeoutContext())
then:
thrown(IllegalStateException)
@@ -386,7 +387,7 @@ class MultiServerClusterSpecification extends Specification {
cluster.close()
when:
- cluster.selectServer(new WritableServerSelector(), OPERATION_CONTEXT)
+ cluster.selectServer(new WritableServerSelector(), createOperationContext())
then:
thrown(IllegalStateException)
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/PlainAuthenticatorUnitTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/PlainAuthenticatorUnitTest.java
index 12d8e9fa7c3..a535262b4b4 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/PlainAuthenticatorUnitTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/PlainAuthenticatorUnitTest.java
@@ -16,6 +16,7 @@
package com.mongodb.internal.connection;
+import com.mongodb.ClusterFixture;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.async.FutureResultCallback;
@@ -30,7 +31,6 @@
import java.util.List;
import java.util.concurrent.ExecutionException;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.getServerApi;
import static com.mongodb.internal.connection.MessageHelper.getApiVersionField;
import static com.mongodb.internal.connection.MessageHelper.getDbField;
@@ -54,7 +54,7 @@ public void before() {
public void testSuccessfulAuthentication() {
enqueueSuccessfulReply();
- subject.authenticate(connection, connectionDescription, OPERATION_CONTEXT);
+ subject.authenticate(connection, connectionDescription, ClusterFixture.createOperationContext());
validateMessages();
}
@@ -64,7 +64,7 @@ public void testSuccessfulAuthenticationAsync() throws ExecutionException, Inter
enqueueSuccessfulReply();
FutureResultCallback futureCallback = new FutureResultCallback<>();
- subject.authenticateAsync(connection, connectionDescription, OPERATION_CONTEXT, futureCallback);
+ subject.authenticateAsync(connection, connectionDescription, ClusterFixture.createOperationContext(), futureCallback);
futureCallback.get();
validateMessages();
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDeprioritizationTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDeprioritizationTest.java
index f1c8f69eb29..9ac2bbe7d40 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDeprioritizationTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDeprioritizationTest.java
@@ -16,6 +16,7 @@
package com.mongodb.internal.connection;
import com.mongodb.MongoConnectionPoolClearedException;
+import com.mongodb.MongoException;
import com.mongodb.ServerAddress;
import com.mongodb.connection.ClusterConnectionMode;
import com.mongodb.connection.ClusterDescription;
@@ -25,93 +26,237 @@
import com.mongodb.connection.ServerDescription;
import com.mongodb.connection.ServerId;
import com.mongodb.internal.connection.OperationContext.ServerDeprioritization;
+import com.mongodb.internal.mockito.MongoMockito;
+import com.mongodb.selector.ServerSelector;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.EnumSource;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Mockito;
import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
-import static com.mongodb.ClusterFixture.TIMEOUT_SETTINGS;
-import static com.mongodb.ClusterFixture.createOperationContext;
+import static java.lang.String.format;
import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
import static java.util.Collections.unmodifiableList;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.params.provider.EnumSource.Mode.EXCLUDE;
+import static org.junit.jupiter.params.provider.Arguments.of;
+import static org.mockito.ArgumentMatchers.any;
final class ServerDeprioritizationTest {
private static final ServerDescription SERVER_A = serverDescription("a");
private static final ServerDescription SERVER_B = serverDescription("b");
private static final ServerDescription SERVER_C = serverDescription("c");
private static final List ALL_SERVERS = unmodifiableList(asList(SERVER_A, SERVER_B, SERVER_C));
- private static final ClusterDescription REPLICA_SET = clusterDescription(ClusterType.REPLICA_SET);
- private static final ClusterDescription SHARDED_CLUSTER = clusterDescription(ClusterType.SHARDED);
-
+ private static final ClusterDescription REPLICA_SET_CLUSTER = multipleModeClusterDescription(ClusterType.REPLICA_SET);
+ private static final ClusterDescription SHARDED_CLUSTER = multipleModeClusterDescription(ClusterType.SHARDED);
+ private static final ClusterDescription UNKNOWN_CLUSTER = multipleModeClusterDescription(ClusterType.UNKNOWN);
+ private static final List CLUSTERS = asList(SHARDED_CLUSTER, REPLICA_SET_CLUSTER, UNKNOWN_CLUSTER);
+ private static final RuntimeException RUNTIME_EXCEPTION = new RuntimeException();
+ private static final MongoException MONGO_EXCEPTION_NO_LABEL = new MongoException(0, "test");
private ServerDeprioritization serverDeprioritization;
@BeforeEach
void beforeEach() {
- serverDeprioritization = createOperationContext(TIMEOUT_SETTINGS).getServerDeprioritization();
+ serverDeprioritization = new OperationContext.ServerDeprioritization(true);
}
- @Test
- void selectNoneDeprioritized() {
- assertAll(
- () -> assertEquals(ALL_SERVERS, serverDeprioritization.getServerSelector().select(SHARDED_CLUSTER)),
- () -> assertEquals(ALL_SERVERS, serverDeprioritization.getServerSelector().select(REPLICA_SET))
- );
+ private static Stream selectNoneDeprioritized() {
+ return CLUSTERS.stream().flatMap(clusterDescription ->
+ Stream.of(
+ namedArguments(clusterDescription),
+ namedArguments(clusterDescription, SERVER_A),
+ namedArguments(clusterDescription, SERVER_B),
+ namedArguments(clusterDescription, SERVER_C),
+ namedArguments(clusterDescription, SERVER_A, SERVER_B),
+ namedArguments(clusterDescription, SERVER_B, SERVER_A),
+ namedArguments(clusterDescription, SERVER_A, SERVER_C),
+ namedArguments(clusterDescription, SERVER_C, SERVER_A),
+ namedArguments(clusterDescription, SERVER_A, SERVER_B, SERVER_C)
+ ));
}
- @Test
- void selectSomeDeprioritized() {
- deprioritize(SERVER_B);
+ @ParameterizedTest
+ @MethodSource
+ void selectNoneDeprioritized(final ClusterDescription clusterDescription, final List selectorResult) {
+ ServerSelector wrappedSelector = createAssertingSelector(ALL_SERVERS, selectorResult);
+ assertEquals(selectorResult, serverDeprioritization.apply(wrappedSelector).select(clusterDescription));
+ }
+
+ @ParameterizedTest
+ @EnumSource(value = ClusterType.class, names = {"STANDALONE", "LOAD_BALANCED"})
+ void selectNoneDeprioritizedSingleServerCluster(final ClusterType clusterType) {
+ ClusterDescription cluster = singleModeClusterDescription(clusterType);
+ ServerSelector wrappedSelector = createAssertingSelector(singletonList(SERVER_A), singletonList(SERVER_A));
+ ServerSelector emptyListWrappedSelector = createAssertingSelector(singletonList(SERVER_A), emptyList());
assertAll(
- () -> assertEquals(asList(SERVER_A, SERVER_C), serverDeprioritization.getServerSelector().select(SHARDED_CLUSTER)),
- () -> assertEquals(ALL_SERVERS, serverDeprioritization.getServerSelector().select(REPLICA_SET))
+ () -> assertEquals(singletonList(SERVER_A), serverDeprioritization.apply(wrappedSelector).select(cluster)),
+ () -> assertEquals(emptyList(), serverDeprioritization.apply(emptyListWrappedSelector).select(cluster))
);
}
- @Test
- void selectAllDeprioritized() {
- deprioritize(SERVER_A);
- deprioritize(SERVER_B);
- deprioritize(SERVER_C);
- assertAll(
- () -> assertEquals(ALL_SERVERS, serverDeprioritization.getServerSelector().select(SHARDED_CLUSTER)),
- () -> assertEquals(ALL_SERVERS, serverDeprioritization.getServerSelector().select(REPLICA_SET))
+ private static Stream deprioritizableClusters() {
+ return Stream.of(
+ of(SHARDED_CLUSTER, RUNTIME_EXCEPTION),
+ of(SHARDED_CLUSTER, MONGO_EXCEPTION_NO_LABEL),
+ of(REPLICA_SET_CLUSTER, createSystemOverloadedError()),
+ of(UNKNOWN_CLUSTER, createSystemOverloadedError())
);
}
+ private static Stream selectSomeDeprioritized() {
+ return deprioritizableClusters().flatMap(args -> {
+ ClusterDescription clusterDescription = (ClusterDescription) args.get()[0];
+ Throwable exception = (Throwable) args.get()[1];
+ return Stream.of(
+ namedArguments(clusterDescription, exception, SERVER_A),
+ namedArguments(clusterDescription, exception, SERVER_C),
+ namedArguments(clusterDescription, exception, SERVER_A, SERVER_C),
+ namedArguments(clusterDescription, exception, SERVER_C, SERVER_A)
+ );
+ });
+ }
+
@ParameterizedTest
- @EnumSource(value = ClusterType.class, mode = EXCLUDE, names = {"SHARDED"})
- void serverSelectorSelectsAllIfNotShardedCluster(final ClusterType clusterType) {
- serverDeprioritization.updateCandidate(SERVER_A.getAddress());
- serverDeprioritization.onAttemptFailure(new RuntimeException());
- assertEquals(ALL_SERVERS, serverDeprioritization.getServerSelector().select(clusterDescription(clusterType)));
+ @MethodSource
+ void selectSomeDeprioritized(final ClusterDescription clusterDescription, final Throwable exception,
+ final List selectorResult) {
+ deprioritize(clusterDescription.getType(), exception, SERVER_B);
+ List expectedWrappedSelectorFilteredInput = asList(SERVER_A, SERVER_C);
+ ServerSelector wrappedSelector = createAssertingSelector(expectedWrappedSelectorFilteredInput, selectorResult);
+ assertEquals(selectorResult, serverDeprioritization.apply(wrappedSelector).select(clusterDescription));
+ }
+
+ private static Stream selectAllDeprioritized() {
+ return deprioritizableClusters().flatMap(args -> {
+ ClusterDescription clusterDescription = (ClusterDescription) args.get()[0];
+ Throwable exception = (Throwable) args.get()[1];
+ return Stream.of(
+ namedArguments(clusterDescription, exception),
+ namedArguments(clusterDescription, exception, SERVER_A),
+ namedArguments(clusterDescription, exception, SERVER_B),
+ namedArguments(clusterDescription, exception, SERVER_C),
+ namedArguments(clusterDescription, exception, SERVER_A, SERVER_B),
+ namedArguments(clusterDescription, exception, SERVER_B, SERVER_A),
+ namedArguments(clusterDescription, exception, SERVER_A, SERVER_C),
+ namedArguments(clusterDescription, exception, SERVER_C, SERVER_A),
+ namedArguments(clusterDescription, exception, SERVER_A, SERVER_B, SERVER_C)
+ );
+ });
+ }
+
+ @ParameterizedTest
+ @MethodSource
+ void selectAllDeprioritized(final ClusterDescription clusterDescription, final Throwable exception,
+ final List selectorResult) {
+ deprioritize(clusterDescription.getType(), exception, SERVER_A);
+ deprioritize(clusterDescription.getType(), exception, SERVER_B);
+ deprioritize(clusterDescription.getType(), exception, SERVER_C);
+ ServerSelector selector = createAssertingSelector(ALL_SERVERS, selectorResult);
+ assertEquals(selectorResult, serverDeprioritization.apply(selector).select(clusterDescription));
+ }
+
+ @ParameterizedTest
+ @EnumSource(value = ClusterType.class, names = {"STANDALONE", "LOAD_BALANCED"})
+ void selectAllDeprioritizedSingleServerCluster(final ClusterType clusterType) {
+ ClusterDescription cluster = singleModeClusterDescription(clusterType);
+ deprioritize(clusterType, createSystemOverloadedError(), SERVER_A);
+ ServerSelector selector = createAssertingSelector(singletonList(SERVER_A), singletonList(SERVER_A));
+ assertEquals(singletonList(SERVER_A), serverDeprioritization.apply(selector).select(cluster));
+ }
+
+ @ParameterizedTest
+ @MethodSource("selectSomeDeprioritized")
+ void selectWithRetryWhenWrappedReturnsEmpty(final ClusterDescription clusterDescription,
+ final Throwable exception,
+ final List selectorResult) {
+ deprioritize(clusterDescription.getType(), exception, SERVER_B);
+ ServerSelector selector = MongoMockito.mock(ServerSelector.class, tuner ->
+ Mockito.when(tuner.select(any(ClusterDescription.class)))
+ .thenAnswer(invocation -> {
+ assertEquals(asList(SERVER_A, SERVER_C), invocation.getArgument(0).getServerDescriptions());
+ return emptyList();
+ })
+ .thenAnswer(invocation -> {
+ assertEquals(ALL_SERVERS, invocation.getArgument(0).getServerDescriptions());
+ return selectorResult;
+ })
+ );
+ assertEquals(selectorResult, serverDeprioritization.apply(selector).select(clusterDescription));
}
@Test
void onAttemptFailureIgnoresIfPoolClearedException() {
- serverDeprioritization.updateCandidate(SERVER_A.getAddress());
+ serverDeprioritization.updateCandidate(SERVER_A.getAddress(), ClusterType.SHARDED);
serverDeprioritization.onAttemptFailure(
new MongoConnectionPoolClearedException(new ServerId(new ClusterId(), new ServerAddress()), null));
- assertEquals(ALL_SERVERS, serverDeprioritization.getServerSelector().select(SHARDED_CLUSTER));
+ ServerSelector selector = createAssertingSelector(ALL_SERVERS, ALL_SERVERS);
+ assertEquals(ALL_SERVERS, serverDeprioritization.apply(selector).select(SHARDED_CLUSTER));
}
@Test
void onAttemptFailureDoesNotThrowIfNoCandidate() {
- assertDoesNotThrow(() -> serverDeprioritization.onAttemptFailure(new RuntimeException()));
+ assertDoesNotThrow(() -> serverDeprioritization.onAttemptFailure(RUNTIME_EXCEPTION));
}
- private void deprioritize(final ServerDescription... serverDescriptions) {
+ @ParameterizedTest
+ @EnumSource(value = ClusterType.class, names = "SHARDED", mode = EnumSource.Mode.EXCLUDE)
+ void onAttemptFailureIgnoresIfNonShardedWithoutOverloadError(final ClusterType clusterType) {
+ ClusterDescription cluster = multipleModeClusterDescription(clusterType);
+ ServerSelector selector = createAssertingSelector(ALL_SERVERS, singletonList(SERVER_A));
+
+ assertAll(() -> {
+ deprioritize(clusterType, RUNTIME_EXCEPTION, SERVER_B);
+ assertEquals(singletonList(SERVER_A), serverDeprioritization.apply(selector).select(cluster),
+ format("Expected no deprioritization for %s with RuntimeException", clusterType));
+ },
+ () -> {
+ deprioritize(clusterType, MONGO_EXCEPTION_NO_LABEL, SERVER_B);
+ assertEquals(singletonList(SERVER_A), serverDeprioritization.apply(selector).select(cluster),
+ format("Expected no deprioritization for %s with MongoException without SystemOverloadedError", clusterType));
+ }
+ );
+ }
+
+ @ParameterizedTest
+ @EnumSource(value = ClusterType.class, names = "SHARDED", mode = EnumSource.Mode.EXCLUDE)
+ void onAttemptFailureIgnoresIfNonShardedWithOverloadErrorAndDisabledOverloadRetargeting(final ClusterType clusterType) {
+ ClusterDescription cluster = multipleModeClusterDescription(clusterType);
+ ServerSelector selector = createAssertingSelector(ALL_SERVERS, singletonList(SERVER_A));
+
+ ServerDeprioritization serverDeprioritization = new OperationContext.ServerDeprioritization(false);
+ serverDeprioritization.updateCandidate(SERVER_B.getAddress(), clusterType);
+ serverDeprioritization.onAttemptFailure(createSystemOverloadedError());
+
+ assertEquals(singletonList(SERVER_A), serverDeprioritization.apply(selector).select(cluster),
+ format("Expected no deprioritization when overloadRetargeting is disabled for %s with SystemOverloadedError", clusterType));
+ }
+
+ private void deprioritize(final ClusterType clusterType, final Throwable exception, final ServerDescription... serverDescriptions) {
for (ServerDescription serverDescription : serverDescriptions) {
- serverDeprioritization.updateCandidate(serverDescription.getAddress());
- serverDeprioritization.onAttemptFailure(new RuntimeException());
+ serverDeprioritization.updateCandidate(serverDescription.getAddress(), clusterType);
+ serverDeprioritization.onAttemptFailure(exception);
}
}
+ private static ServerSelector createAssertingSelector(
+ final List expectedInput,
+ final List selectorResult) {
+ return clusterDescription -> {
+ assertEquals(expectedInput, clusterDescription.getServerDescriptions());
+ return selectorResult;
+ };
+ }
+
private static ServerDescription serverDescription(final String host) {
return ServerDescription.builder()
.state(ServerConnectionState.CONNECTED)
@@ -120,7 +265,39 @@ private static ServerDescription serverDescription(final String host) {
.build();
}
- private static ClusterDescription clusterDescription(final ClusterType clusterType) {
+ private static ClusterDescription multipleModeClusterDescription(final ClusterType clusterType) {
return new ClusterDescription(ClusterConnectionMode.MULTIPLE, clusterType, ALL_SERVERS);
}
+
+ private static ClusterDescription singleModeClusterDescription(final ClusterType clusterType) {
+ return new ClusterDescription(ClusterConnectionMode.SINGLE, clusterType, singletonList(SERVER_A));
+ }
+
+ private static MongoException createSystemOverloadedError() {
+ MongoException e = new MongoException(6, "overloaded");
+ e.addLabel("SystemOverloadedError");
+ return e;
+ }
+
+ private static Arguments namedArguments(final ClusterDescription clusterDescription, final ServerDescription... serverDescriptions) {
+ return of(Named.of(generateArgumentName(clusterDescription), clusterDescription),
+ Named.of(generateArgumentName(asList(serverDescriptions)), asList(serverDescriptions)));
+ }
+
+ private static Arguments namedArguments(final ClusterDescription clusterDescription, final Throwable exception, final ServerDescription... serverDescriptions) {
+ return of(Named.of(generateArgumentName(clusterDescription), clusterDescription),
+ exception,
+ Named.of(generateArgumentName(asList(serverDescriptions)), asList(serverDescriptions)));
+ }
+
+ private static String generateArgumentName(final List servers) {
+ return "[" + servers.stream()
+ .map(ServerDescription::getAddress)
+ .map(ServerAddress::getHost)
+ .collect(Collectors.joining(", ")) + "]";
+ }
+
+ private static String generateArgumentName(final ClusterDescription clusterDescription) {
+ return "[" + clusterDescription.getType() + ", " + generateArgumentName(clusterDescription.getServerDescriptions()) + "]";
+ }
}
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDiscoveryAndMonitoringTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDiscoveryAndMonitoringTest.java
index dc81e5071e1..095372a6cee 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDiscoveryAndMonitoringTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerDiscoveryAndMonitoringTest.java
@@ -16,6 +16,7 @@
package com.mongodb.internal.connection;
+import com.mongodb.ClusterFixture;
import com.mongodb.ServerAddress;
import com.mongodb.connection.ClusterType;
import com.mongodb.connection.ServerDescription;
@@ -32,7 +33,6 @@
import java.util.Collection;
import java.util.stream.Collectors;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.getClusterDescription;
import static com.mongodb.internal.connection.ClusterDescriptionHelper.getPrimaries;
import static com.mongodb.internal.event.EventListenerHelper.NO_OP_CLUSTER_LISTENER;
@@ -154,9 +154,10 @@ private void assertServer(final String serverName, final BsonDocument expectedSe
if (expectedServerDescriptionDocument.isDocument("pool")) {
int expectedGeneration = expectedServerDescriptionDocument.getDocument("pool").getNumber("generation").intValue();
- Timeout serverSelectionTimeout = OPERATION_CONTEXT.getTimeoutContext().computeServerSelectionTimeout();
+ OperationContext operationContext = ClusterFixture.createOperationContext();
+ Timeout serverSelectionTimeout = operationContext.getTimeoutContext().computeServerSelectionTimeout();
DefaultServer server = (DefaultServer) getCluster()
- .getServersSnapshot(serverSelectionTimeout, OPERATION_CONTEXT.getTimeoutContext())
+ .getServersSnapshot(serverSelectionTimeout, operationContext.getTimeoutContext())
.getServer(new ServerAddress(serverName));
assertEquals(expectedGeneration, server.getConnectionPool().getGeneration());
}
diff --git a/driver-core/src/test/unit/com/mongodb/connection/ServerSelectionSelectionTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionSelectionTest.java
similarity index 55%
rename from driver-core/src/test/unit/com/mongodb/connection/ServerSelectionSelectionTest.java
rename to driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionSelectionTest.java
index 8b878fa77c5..5d6b5e0e1e3 100644
--- a/driver-core/src/test/unit/com/mongodb/connection/ServerSelectionSelectionTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionSelectionTest.java
@@ -14,19 +14,36 @@
* limitations under the License.
*/
-package com.mongodb.connection;
+package com.mongodb.internal.connection;
+import com.mongodb.ClusterFixture;
import com.mongodb.MongoConfigurationException;
+import com.mongodb.MongoException;
+import com.mongodb.MongoTimeoutException;
import com.mongodb.ReadPreference;
import com.mongodb.ServerAddress;
import com.mongodb.Tag;
import com.mongodb.TagSet;
-import com.mongodb.internal.selector.LatencyMinimizingServerSelector;
+import com.mongodb.assertions.Assertions;
+import com.mongodb.connection.ClusterConnectionMode;
+import com.mongodb.connection.ClusterDescription;
+import com.mongodb.connection.ClusterId;
+import com.mongodb.connection.ClusterSettings;
+import com.mongodb.connection.ClusterType;
+import com.mongodb.connection.ServerConnectionState;
+import com.mongodb.connection.ServerDescription;
+import com.mongodb.connection.ServerSettings;
+import com.mongodb.connection.ServerType;
+import com.mongodb.event.ServerDescriptionChangedEvent;
+import com.mongodb.internal.IgnorableRequestContext;
+import com.mongodb.internal.TimeoutContext;
+import com.mongodb.internal.mockito.MongoMockito;
+import com.mongodb.internal.observability.micrometer.TracingManager;
import com.mongodb.internal.selector.ReadPreferenceServerSelector;
import com.mongodb.internal.selector.WritableServerSelector;
+import com.mongodb.internal.time.Timeout;
import com.mongodb.lang.NonNull;
import com.mongodb.lang.Nullable;
-import com.mongodb.selector.CompositeServerSelector;
import com.mongodb.selector.ServerSelector;
import org.bson.BsonArray;
import org.bson.BsonBoolean;
@@ -34,36 +51,54 @@
import org.bson.BsonInt64;
import org.bson.BsonString;
import org.bson.BsonValue;
+import org.bson.json.JsonWriterSettings;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import util.JsonPoweredTestHelper;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
-import static java.util.Arrays.asList;
-import static org.junit.Assert.assertEquals;
+import static com.mongodb.ClusterFixture.TIMEOUT_SETTINGS;
+import static com.mongodb.connection.ServerDescription.MIN_DRIVER_WIRE_VERSION;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
+import static org.mockito.Mockito.when;
-// See https://github.com/mongodb/specifications/tree/master/source/server-selection/tests
+/**
+ * See Server Selection Tests .
+ */
@RunWith(Parameterized.class)
public class ServerSelectionSelectionTest {
private final String description;
private final BsonDocument definition;
private final ClusterDescription clusterDescription;
- private final long heartbeatFrequencyMS;
private final boolean error;
+ private static final Set TOPOLOGY_DESCRIPTION_FIELDS = new HashSet<>(Arrays.asList("type", "servers"));
+ private static final Set SERVER_DESCRIPTION_FIELDS = new HashSet<>(Arrays.asList(
+ "address", "type", "tags", "avg_rtt_ms", "lastWrite", "lastUpdateTime", "maxWireVersion"));
+ private static final Set READ_PREFERENCE_FIELDS = new HashSet<>(
+ Arrays.asList("mode", "tag_sets", "maxStalenessSeconds"));
+
public ServerSelectionSelectionTest(final String description, final BsonDocument definition) {
this.description = description;
this.definition = definition;
- this.heartbeatFrequencyMS = definition.getNumber("heartbeatFrequencyMS", new BsonInt64(10000)).longValue();
+
+ long heartbeatFrequencyMS = definition.getNumber("heartbeatFrequencyMS", new BsonInt64(10000)).longValue();
this.error = definition.getBoolean("error", BsonBoolean.FALSE).getValue();
this.clusterDescription = buildClusterDescription(definition.getDocument("topology_description"),
ServerSettings.builder().heartbeatFrequency(heartbeatFrequencyMS, TimeUnit.MILLISECONDS).build());
@@ -73,37 +108,38 @@ public ServerSelectionSelectionTest(final String description, final BsonDocument
public void shouldPassAllOutcomes() {
// skip this test because the driver prohibits maxStaleness or tagSets with mode of primary at a much lower level
assumeFalse(description.endsWith("/max-staleness/tests/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.json"));
- assumeFalse(description.contains("Deprioritized")); // TODO JAVA-6021 deprioritized server selection"
-
- ServerSelector serverSelector = null;
- List suitableServers = buildServerDescriptions(definition.getArray("suitable_servers", new BsonArray()));
- List selectedServers = null;
- try {
- serverSelector = getServerSelector();
- selectedServers = serverSelector.select(clusterDescription);
+ ServerTuple serverTuple;
+ ServerSelector serverSelector = getServerSelector();
+ OperationContext operationContext = createOperationContext();
+ Cluster.ServersSnapshot serversSnapshot = createServersSnapshot(clusterDescription);
+ List inLatencyWindowServers = buildServerDescriptions(definition.getArray("in_latency_window", new BsonArray()));
+
+ try (BaseCluster cluster = new TestCluster(clusterDescription, serversSnapshot)) {
+ serverTuple = cluster.selectServer(serverSelector, operationContext);
if (error) {
- fail("Should have thrown exception");
+ fail(format("Should have thrown exception"));
}
} catch (MongoConfigurationException e) {
if (!error) {
- fail("Should not have thrown exception: " + e);
+ fail(format("Should not have thrown exception: %s", e));
}
return;
+ } catch (MongoTimeoutException mongoTimeoutException) {
+ assertTrue(format("Expected empty but was %s", inLatencyWindowServers.size()),
+ inLatencyWindowServers.isEmpty());
+ return;
}
- assertServers(selectedServers, suitableServers);
-
- ServerSelector latencyBasedServerSelector = new CompositeServerSelector(asList(serverSelector,
- new LatencyMinimizingServerSelector(15, TimeUnit.MILLISECONDS)));
- List inLatencyWindowServers = buildServerDescriptions(definition.getArray("in_latency_window"));
- List latencyBasedSelectedServers = latencyBasedServerSelector.select(clusterDescription);
- assertServers(latencyBasedSelectedServers, inLatencyWindowServers);
+ assertNotNull(format("Server tuple should not be null"), serverTuple);
+ assertTrue(format("Selected server should be in latency window. Selected server: %s", serverTuple.getServerDescription()),
+ inLatencyWindowServers.stream().anyMatch(s -> s.equals(serverTuple.getServerDescription())));
}
@Parameterized.Parameters(name = "{0}")
public static Collection data() {
List data = new ArrayList<>();
for (BsonDocument testDocument : JsonPoweredTestHelper.getSpecTestDocuments("server-selection/tests/server_selection")) {
- data.add(new Object[]{testDocument.getString("resourcePath").getValue(), testDocument});
+ String resourcePath = testDocument.getString("resourcePath").getValue();
+ data.add(new Object[]{resourcePath, testDocument});
}
for (BsonDocument testDocument : JsonPoweredTestHelper.getSpecTestDocuments("max-staleness/tests")) {
data.add(new Object[]{testDocument.getString("resourcePath").getValue(), testDocument});
@@ -112,11 +148,12 @@ public static Collection data() {
}
public static ClusterDescription buildClusterDescription(final BsonDocument topologyDescription,
- @Nullable final ServerSettings serverSettings) {
+ @Nullable final ServerSettings serverSettings) {
+ validateTestDescriptionFields(topologyDescription.keySet(), TOPOLOGY_DESCRIPTION_FIELDS);
ClusterType clusterType = getClusterType(topologyDescription.getString("type").getValue());
ClusterConnectionMode connectionMode = getClusterConnectionMode(clusterType);
List servers = buildServerDescriptions(topologyDescription.getArray("servers"));
- return new ClusterDescription(connectionMode, clusterType, servers, null,
+ return new ClusterDescription(connectionMode, clusterType, servers, ClusterSettings.builder().build(),
serverSettings == null ? ServerSettings.builder().build() : serverSettings);
}
@@ -153,6 +190,7 @@ private static List buildServerDescriptions(final BsonArray s
}
private static ServerDescription buildServerDescription(final BsonDocument serverDescription) {
+ validateTestDescriptionFields(serverDescription.keySet(), SERVER_DESCRIPTION_FIELDS);
ServerDescription.Builder builder = ServerDescription.builder();
builder.address(new ServerAddress(serverDescription.getString("address").getValue()));
ServerType serverType = getServerType(serverDescription.getString("type").getValue());
@@ -175,6 +213,8 @@ private static ServerDescription buildServerDescription(final BsonDocument serve
}
if (serverDescription.containsKey("maxWireVersion")) {
builder.maxWireVersion(serverDescription.getNumber("maxWireVersion").intValue());
+ } else {
+ builder.maxWireVersion(MIN_DRIVER_WIRE_VERSION);
}
return builder.build();
}
@@ -229,6 +269,7 @@ private ServerSelector getServerSelector() {
return new WritableServerSelector();
} else {
BsonDocument readPreferenceDefinition = definition.getDocument("read_preference");
+ validateTestDescriptionFields(readPreferenceDefinition.keySet(), READ_PREFERENCE_FIELDS);
ReadPreference readPreference;
if (readPreferenceDefinition.getString("mode").getValue().equals("Primary")) {
readPreference = ReadPreference.valueOf("Primary");
@@ -244,8 +285,88 @@ private ServerSelector getServerSelector() {
}
}
- private void assertServers(final List actual, final List expected) {
- assertEquals(expected.size(), actual.size());
- assertTrue(actual.containsAll(expected));
+ private static List extractDeprioritizedServerAddresses(final BsonDocument definition) {
+ if (!definition.containsKey("deprioritized_servers")) {
+ return Collections.emptyList();
+ }
+ return definition.getArray("deprioritized_servers")
+ .stream()
+ .map(BsonValue::asDocument)
+ .map(ServerSelectionSelectionTest::buildServerDescription)
+ .map(ServerDescription::getAddress)
+ .collect(Collectors.toList());
+ }
+
+ private OperationContext createOperationContext() {
+ OperationContext operationContext =
+ new OperationContext(
+ IgnorableRequestContext.INSTANCE,
+ NoOpSessionContext.INSTANCE,
+ new TimeoutContext(TIMEOUT_SETTINGS.withServerSelectionTimeoutMS(0)),
+ TracingManager.NO_OP,
+ null,
+ null,
+ new OperationContext.ServerDeprioritization(true));
+ OperationContext.ServerDeprioritization serverDeprioritization = operationContext.getServerDeprioritization();
+ for (ServerAddress address : extractDeprioritizedServerAddresses(definition)) {
+ serverDeprioritization.updateCandidate(address, clusterDescription.getType());
+ // The spec defines deprioritized_servers as a pre-populated list to feed into the selection mechanism - not as "simulate the
+ // failure that caused deprioritization." Thus, SystemOverloadedError used unconditionally regardless of the cluster type.
+ MongoException error = new MongoException("test");
+ error.addLabel(MongoException.SYSTEM_OVERLOADED_ERROR_LABEL);
+ serverDeprioritization.onAttemptFailure(error);
+ }
+ return operationContext;
+ }
+
+ private static Cluster.ServersSnapshot createServersSnapshot(
+ final ClusterDescription clusterDescription) {
+ Map serverMap = new HashMap<>();
+ for (ServerDescription desc : clusterDescription.getServerDescriptions()) {
+ serverMap.put(desc.getAddress(), MongoMockito.mock(Server.class, server -> {
+ // `MinimumOperationCountServerSelector` should select any server since they all have 0 operation count.
+ when(server.operationCount()).thenReturn(0);
+ }));
+ }
+ return serverMap::get;
+ }
+
+ private static void validateTestDescriptionFields(final Set actualFields, final Set knownFields) {
+ Set unknownFields = new HashSet<>(actualFields);
+ unknownFields.removeAll(knownFields);
+ if (!unknownFields.isEmpty()) {
+ throw new UnsupportedOperationException("Unknown fields: " + unknownFields);
+ }
+ }
+
+ private static class TestCluster extends BaseCluster {
+ private final ServersSnapshot serversSnapshot;
+
+ TestCluster(final ClusterDescription clusterDescription, final ServersSnapshot serversSnapshot) {
+ super(new ClusterId(), clusterDescription.getClusterSettings(), new TestClusterableServerFactory(),
+ ClusterFixture.CLIENT_METADATA);
+ this.serversSnapshot = serversSnapshot;
+ updateDescription(clusterDescription);
+ }
+
+ @Override
+ protected void connect() {
+ // NOOP: this method may be invoked in test cases where no server is expected to be selected.
+ }
+
+ @Override
+ public ServersSnapshot getServersSnapshot(final Timeout serverSelectionTimeout, final TimeoutContext timeoutContext) {
+ return serversSnapshot;
+ }
+
+ @Override
+ public void onChange(final ServerDescriptionChangedEvent event) {
+ Assertions.fail();
+ }
+ }
+
+ private String format(final String messageFormat, final Object... args) {
+ String message = String.format(messageFormat, args);
+ return message + "\nTest Definition:\n" + definition.toJson(JsonWriterSettings.builder().indent(true).build());
}
}
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionWithinLatencyWindowTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionWithinLatencyWindowTest.java
index 14d6c59b0c6..23e1f59d3a7 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionWithinLatencyWindowTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/ServerSelectionWithinLatencyWindowTest.java
@@ -43,7 +43,7 @@
import static com.mongodb.ClusterFixture.TIMEOUT_SETTINGS;
import static com.mongodb.ClusterFixture.createOperationContext;
-import static com.mongodb.connection.ServerSelectionSelectionTest.buildClusterDescription;
+import static com.mongodb.internal.connection.ServerSelectionSelectionTest.buildClusterDescription;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toMap;
import static org.junit.Assert.assertEquals;
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/SingleServerClusterSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/connection/SingleServerClusterSpecification.groovy
index faa04a188f9..126cadce0c0 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/SingleServerClusterSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/SingleServerClusterSpecification.groovy
@@ -29,7 +29,7 @@ import com.mongodb.internal.selector.WritableServerSelector
import spock.lang.Specification
import static com.mongodb.ClusterFixture.CLIENT_METADATA
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.connection.ClusterConnectionMode.SINGLE
import static com.mongodb.connection.ClusterType.REPLICA_SET
import static com.mongodb.connection.ClusterType.UNKNOWN
@@ -78,10 +78,9 @@ class SingleServerClusterSpecification extends Specification {
sendNotification(firstServer, STANDALONE)
then:
- cluster.getServersSnapshot(OPERATION_CONTEXT
- .getTimeoutContext()
- .computeServerSelectionTimeout(),
- OPERATION_CONTEXT.getTimeoutContext()).getServer(firstServer) == factory.getServer(firstServer)
+ def operationContext = createOperationContext()
+ cluster.getServersSnapshot(operationContext.getTimeoutContext().computeServerSelectionTimeout(),
+ operationContext.getTimeoutContext()).getServer(firstServer) == factory.getServer(firstServer)
cleanup:
cluster?.close()
@@ -95,8 +94,9 @@ class SingleServerClusterSpecification extends Specification {
cluster.close()
when:
- cluster.getServersSnapshot(OPERATION_CONTEXT.getTimeoutContext().computeServerSelectionTimeout(),
- OPERATION_CONTEXT.getTimeoutContext())
+ def operationContext = createOperationContext()
+ cluster.getServersSnapshot(operationContext.getTimeoutContext().computeServerSelectionTimeout(),
+ operationContext.getTimeoutContext())
then:
thrown(IllegalStateException)
@@ -146,7 +146,7 @@ class SingleServerClusterSpecification extends Specification {
sendNotification(firstServer, getBuilder(firstServer).minWireVersion(1000).maxWireVersion(1000).build())
when:
- cluster.selectServer(new WritableServerSelector(), OPERATION_CONTEXT)
+ cluster.selectServer(new WritableServerSelector(), createOperationContext())
then:
thrown(MongoIncompatibleDriverException)
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/UsageTrackingConnectionSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/connection/UsageTrackingConnectionSpecification.groovy
index 78d79fba8b2..379d60a2fe7 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/UsageTrackingConnectionSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/UsageTrackingConnectionSpecification.groovy
@@ -26,7 +26,7 @@ import org.bson.BsonInt32
import org.bson.codecs.BsonDocumentCodec
import spock.lang.Specification
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ReadPreference.primary
import static com.mongodb.connection.ClusterConnectionMode.SINGLE
@@ -49,7 +49,7 @@ class UsageTrackingConnectionSpecification extends Specification {
connection.openedAt == Long.MAX_VALUE
when:
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
then:
connection.openedAt <= System.currentTimeMillis()
@@ -65,7 +65,7 @@ class UsageTrackingConnectionSpecification extends Specification {
connection.openedAt == Long.MAX_VALUE
when:
- connection.openAsync(OPERATION_CONTEXT, futureResultCallback)
+ connection.openAsync(createOperationContext(), futureResultCallback)
futureResultCallback.get()
then:
@@ -80,7 +80,7 @@ class UsageTrackingConnectionSpecification extends Specification {
connection.lastUsedAt == Long.MAX_VALUE
when:
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
then:
connection.lastUsedAt <= System.currentTimeMillis()
@@ -96,7 +96,7 @@ class UsageTrackingConnectionSpecification extends Specification {
connection.lastUsedAt == Long.MAX_VALUE
when:
- connection.openAsync(OPERATION_CONTEXT, futureResultCallback)
+ connection.openAsync(createOperationContext(), futureResultCallback)
futureResultCallback.get()
then:
@@ -106,11 +106,11 @@ class UsageTrackingConnectionSpecification extends Specification {
def 'lastUsedAt should be set on sendMessage'() {
given:
def connection = createConnection()
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
def openedLastUsedAt = connection.lastUsedAt
when:
- connection.sendMessage([], 1, OPERATION_CONTEXT)
+ connection.sendMessage([], 1, createOperationContext())
then:
connection.lastUsedAt >= openedLastUsedAt
@@ -121,12 +121,12 @@ class UsageTrackingConnectionSpecification extends Specification {
def 'lastUsedAt should be set on sendMessage asynchronously'() {
given:
def connection = createConnection()
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
def openedLastUsedAt = connection.lastUsedAt
def futureResultCallback = new FutureResultCallback()
when:
- connection.sendMessageAsync([], 1, OPERATION_CONTEXT, futureResultCallback)
+ connection.sendMessageAsync([], 1, createOperationContext(), futureResultCallback)
futureResultCallback.get()
then:
@@ -137,10 +137,10 @@ class UsageTrackingConnectionSpecification extends Specification {
def 'lastUsedAt should be set on receiveMessage'() {
given:
def connection = createConnection()
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
def openedLastUsedAt = connection.lastUsedAt
when:
- connection.receiveMessage(1, OPERATION_CONTEXT)
+ connection.receiveMessage(1, createOperationContext())
then:
connection.lastUsedAt >= openedLastUsedAt
@@ -150,12 +150,12 @@ class UsageTrackingConnectionSpecification extends Specification {
def 'lastUsedAt should be set on receiveMessage asynchronously'() {
given:
def connection = createConnection()
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
def openedLastUsedAt = connection.lastUsedAt
def futureResultCallback = new FutureResultCallback()
when:
- connection.receiveMessageAsync(1, OPERATION_CONTEXT, futureResultCallback)
+ connection.receiveMessageAsync(1, createOperationContext(), futureResultCallback)
futureResultCallback.get()
then:
@@ -166,13 +166,13 @@ class UsageTrackingConnectionSpecification extends Specification {
def 'lastUsedAt should be set on sendAndReceive'() {
given:
def connection = createConnection()
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
def openedLastUsedAt = connection.lastUsedAt
when:
connection.sendAndReceive(new CommandMessage('test',
new BsonDocument('ping', new BsonInt32(1)), NoOpFieldNameValidator.INSTANCE, primary(),
- MessageSettings.builder().build(), SINGLE, null), new BsonDocumentCodec(), OPERATION_CONTEXT)
+ MessageSettings.builder().build(), SINGLE, null), new BsonDocumentCodec(), createOperationContext())
then:
connection.lastUsedAt >= openedLastUsedAt
@@ -182,7 +182,7 @@ class UsageTrackingConnectionSpecification extends Specification {
def 'lastUsedAt should be set on sendAndReceive asynchronously'() {
given:
def connection = createConnection()
- connection.open(OPERATION_CONTEXT)
+ connection.open(createOperationContext())
def openedLastUsedAt = connection.lastUsedAt
def futureResultCallback = new FutureResultCallback()
@@ -190,7 +190,7 @@ class UsageTrackingConnectionSpecification extends Specification {
connection.sendAndReceiveAsync(new CommandMessage('test',
new BsonDocument('ping', new BsonInt32(1)), NoOpFieldNameValidator.INSTANCE, primary(),
MessageSettings.builder().build(), SINGLE, null),
- new BsonDocumentCodec(), OPERATION_CONTEXT, futureResultCallback)
+ new BsonDocumentCodec(), createOperationContext(), futureResultCallback)
futureResultCallback.get()
then:
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/X509AuthenticatorNoUserNameTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/X509AuthenticatorNoUserNameTest.java
index 5326c8c723d..0259b41930a 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/X509AuthenticatorNoUserNameTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/X509AuthenticatorNoUserNameTest.java
@@ -16,6 +16,7 @@
package com.mongodb.internal.connection;
+import com.mongodb.ClusterFixture;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.async.FutureResultCallback;
@@ -32,7 +33,6 @@
import java.util.List;
import java.util.concurrent.ExecutionException;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.getServerApi;
import static com.mongodb.connection.ClusterConnectionMode.MULTIPLE;
import static com.mongodb.internal.connection.MessageHelper.buildSuccessfulReply;
@@ -58,7 +58,7 @@ public void testSuccessfulAuthentication() {
enqueueSuccessfulAuthenticationReply();
new X509Authenticator(getCredentialWithCache(), MULTIPLE, getServerApi())
- .authenticate(connection, connectionDescriptionThreeSix, OPERATION_CONTEXT);
+ .authenticate(connection, connectionDescriptionThreeSix, ClusterFixture.createOperationContext());
validateMessages();
}
@@ -69,7 +69,7 @@ public void testSuccessfulAuthenticationAsync() throws ExecutionException, Inter
FutureResultCallback futureCallback = new FutureResultCallback<>();
new X509Authenticator(getCredentialWithCache(), MULTIPLE, getServerApi()).authenticateAsync(connection,
- connectionDescriptionThreeSix, OPERATION_CONTEXT, futureCallback);
+ connectionDescriptionThreeSix, ClusterFixture.createOperationContext(), futureCallback);
futureCallback.get();
diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/X509AuthenticatorUnitTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/X509AuthenticatorUnitTest.java
index a8b2d7b71d5..80d0b2c0411 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/connection/X509AuthenticatorUnitTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/connection/X509AuthenticatorUnitTest.java
@@ -16,6 +16,7 @@
package com.mongodb.internal.connection;
+import com.mongodb.ClusterFixture;
import com.mongodb.MongoCredential;
import com.mongodb.MongoSecurityException;
import com.mongodb.ServerAddress;
@@ -31,7 +32,6 @@
import java.util.List;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.getServerApi;
import static com.mongodb.internal.connection.MessageHelper.buildSuccessfulReply;
import static com.mongodb.internal.connection.MessageHelper.getApiVersionField;
@@ -58,7 +58,7 @@ public void testFailedAuthentication() {
enqueueFailedAuthenticationReply();
try {
- subject.authenticate(connection, connectionDescription, OPERATION_CONTEXT);
+ subject.authenticate(connection, connectionDescription, ClusterFixture.createOperationContext());
fail();
} catch (MongoSecurityException e) {
// all good
@@ -70,7 +70,7 @@ public void testFailedAuthenticationAsync() {
enqueueFailedAuthenticationReply();
FutureResultCallback futureCallback = new FutureResultCallback<>();
- subject.authenticateAsync(connection, connectionDescription, OPERATION_CONTEXT, futureCallback);
+ subject.authenticateAsync(connection, connectionDescription, ClusterFixture.createOperationContext(), futureCallback);
try {
futureCallback.get();
@@ -92,7 +92,7 @@ private void enqueueFailedAuthenticationReply() {
public void testSuccessfulAuthentication() {
enqueueSuccessfulAuthenticationReply();
- subject.authenticate(connection, connectionDescription, OPERATION_CONTEXT);
+ subject.authenticate(connection, connectionDescription, ClusterFixture.createOperationContext());
validateMessages();
}
@@ -102,7 +102,7 @@ public void testSuccessfulAuthenticationAsync() {
enqueueSuccessfulAuthenticationReply();
FutureResultCallback futureCallback = new FutureResultCallback<>();
- subject.authenticateAsync(connection, connectionDescription, OPERATION_CONTEXT, futureCallback);
+ subject.authenticateAsync(connection, connectionDescription, ClusterFixture.createOperationContext(), futureCallback);
futureCallback.get();
@@ -117,7 +117,7 @@ public void testSpeculativeAuthentication() {
+ "user: \"CN=client,OU=kerneluser,O=10Gen,L=New York City,ST=New York,C=US\", "
+ "mechanism: \"MONGODB-X509\", db: \"$external\"}");
subject.setSpeculativeAuthenticateResponse(BsonDocument.parse(speculativeAuthenticateResponse));
- subject.authenticate(connection, connectionDescription, OPERATION_CONTEXT);
+ subject.authenticate(connection, connectionDescription, ClusterFixture.createOperationContext());
assertEquals(connection.getSent().size(), 0);
assertEquals(expectedSpeculativeAuthenticateCommand, subject.createSpeculativeAuthenticateCommand(connection));
diff --git a/driver-core/src/test/unit/com/mongodb/internal/mockito/InsufficientStubbingDetectorDemoTest.java b/driver-core/src/test/unit/com/mongodb/internal/mockito/InsufficientStubbingDetectorDemoTest.java
index 5d8bd8e61b1..9142a097678 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/mockito/InsufficientStubbingDetectorDemoTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/mockito/InsufficientStubbingDetectorDemoTest.java
@@ -15,6 +15,7 @@
*/
package com.mongodb.internal.mockito;
+import com.mongodb.ClusterFixture;
import com.mongodb.internal.binding.ReadBinding;
import com.mongodb.internal.operation.ListCollectionsOperation;
import org.bson.BsonDocument;
@@ -24,7 +25,6 @@
import org.mockito.Mockito;
import org.mockito.internal.stubbing.answers.ThrowsException;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.when;
@@ -40,33 +40,33 @@ void beforeEach() {
@Test
void mockObjectWithDefaultAnswer() {
ReadBinding binding = Mockito.mock(ReadBinding.class);
- assertThrows(NullPointerException.class, () -> operation.execute(binding, OPERATION_CONTEXT));
+ assertThrows(NullPointerException.class, () -> operation.execute(binding, ClusterFixture.createOperationContext()));
}
@Test
void mockObjectWithThrowsException() {
ReadBinding binding = Mockito.mock(ReadBinding.class,
new ThrowsException(new AssertionError("Insufficient stubbing for " + ReadBinding.class)));
- assertThrows(AssertionError.class, () -> operation.execute(binding, OPERATION_CONTEXT));
+ assertThrows(AssertionError.class, () -> operation.execute(binding, ClusterFixture.createOperationContext()));
}
@Test
void mockObjectWithInsufficientStubbingDetector() {
ReadBinding binding = MongoMockito.mock(ReadBinding.class);
- assertThrows(AssertionError.class, () -> operation.execute(binding, OPERATION_CONTEXT));
+ assertThrows(AssertionError.class, () -> operation.execute(binding, ClusterFixture.createOperationContext()));
}
@Test
void stubbingWithThrowsException() {
ReadBinding binding = Mockito.mock(ReadBinding.class,
new ThrowsException(new AssertionError("Unfortunately, you cannot do stubbing")));
- assertThrows(AssertionError.class, () -> when(binding.getReadConnectionSource(OPERATION_CONTEXT)).thenReturn(null));
+ assertThrows(AssertionError.class, () -> when(binding.getReadConnectionSource(ClusterFixture.createOperationContext())).thenReturn(null));
}
@Test
void stubbingWithInsufficientStubbingDetector() {
MongoMockito.mock(ReadBinding.class, bindingMock ->
- when(bindingMock.getReadConnectionSource(OPERATION_CONTEXT)).thenReturn(null)
+ when(bindingMock.getReadConnectionSource(ClusterFixture.createOperationContext())).thenReturn(null)
);
}
}
diff --git a/driver-core/src/test/unit/com/mongodb/internal/operation/AsyncOperationHelperSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/operation/AsyncOperationHelperSpecification.groovy
index d573822cab7..6080f8bb727 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/operation/AsyncOperationHelperSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/operation/AsyncOperationHelperSpecification.groovy
@@ -36,7 +36,7 @@ import org.bson.codecs.BsonDocumentCodec
import org.bson.codecs.Decoder
import spock.lang.Specification
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ReadPreference.primary
import static com.mongodb.internal.operation.AsyncOperationHelper.CommandReadTransformerAsync
import static com.mongodb.internal.operation.AsyncOperationHelper.executeCommandAsync
@@ -74,7 +74,7 @@ class AsyncOperationHelperSpecification extends Specification {
_ * getDescription() >> connectionDescription
}
- def operationContext = OPERATION_CONTEXT.withSessionContext(
+ def operationContext = createOperationContext().withSessionContext(
Stub(SessionContext) {
hasSession() >> true
hasActiveTransaction() >> false
@@ -116,7 +116,7 @@ class AsyncOperationHelperSpecification extends Specification {
def connectionDescription = Stub(ConnectionDescription)
when:
- executeCommandAsync(asyncWriteBinding, OPERATION_CONTEXT, dbName, command, connection, { t, conn -> t }, callback)
+ executeCommandAsync(asyncWriteBinding, createOperationContext(), dbName, command, connection, { t, conn -> t }, callback)
then:
_ * connection.getDescription() >> connectionDescription
@@ -143,7 +143,7 @@ class AsyncOperationHelperSpecification extends Specification {
def connectionDescription = Stub(ConnectionDescription)
when:
- executeRetryableReadAsync(asyncReadBinding, OPERATION_CONTEXT, dbName, commandCreator, decoder, function, false, callback)
+ executeRetryableReadAsync(asyncReadBinding, createOperationContext(), dbName, commandCreator, decoder, function, false, callback)
then:
_ * connection.getDescription() >> connectionDescription
diff --git a/driver-core/src/test/unit/com/mongodb/internal/operation/ClientBulkWriteOperationTest.java b/driver-core/src/test/unit/com/mongodb/internal/operation/ClientBulkWriteOperationTest.java
index 5de1992b69d..18a66816abf 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/operation/ClientBulkWriteOperationTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/operation/ClientBulkWriteOperationTest.java
@@ -124,7 +124,7 @@ void shouldIgnoreSuccessfulCursorResultWhenVerboseResultIsFalse() {
false,
getDefaultCodecRegistry());
//when
- ClientBulkWriteResult result = op.execute(binding, ClusterFixture.OPERATION_CONTEXT);
+ ClientBulkWriteResult result = op.execute(binding, ClusterFixture.createOperationContext());
//then
assertEquals(
@@ -176,7 +176,7 @@ void shouldUseDefaultNumberOfModifiedDocumentsWhenMissingInCursor() {
false,
getDefaultCodecRegistry());
//when
- ClientBulkWriteResult result = op.execute(binding, ClusterFixture.OPERATION_CONTEXT);
+ ClientBulkWriteResult result = op.execute(binding, ClusterFixture.createOperationContext());
//then
assertEquals(1, result.getInsertedCount());
diff --git a/driver-core/src/test/unit/com/mongodb/internal/operation/CommitTransactionOperationUnitSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/operation/CommitTransactionOperationUnitSpecification.groovy
index 75ed9e6c5f3..aa4db2372ff 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/operation/CommitTransactionOperationUnitSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/operation/CommitTransactionOperationUnitSpecification.groovy
@@ -27,7 +27,7 @@ import com.mongodb.internal.binding.WriteBinding
import com.mongodb.internal.connection.OperationContext
import com.mongodb.internal.session.SessionContext
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
class CommitTransactionOperationUnitSpecification extends OperationUnitSpecification {
def 'should add UnknownTransactionCommitResult error label to MongoTimeoutException'() {
@@ -42,7 +42,7 @@ class CommitTransactionOperationUnitSpecification extends OperationUnitSpecifica
def operation = new CommitTransactionOperation(WriteConcern.ACKNOWLEDGED)
when:
- operation.execute(writeBinding, OPERATION_CONTEXT.withSessionContext(sessionContext))
+ operation.execute(writeBinding, createOperationContext().withSessionContext(sessionContext))
then:
def e = thrown(MongoTimeoutException)
@@ -64,7 +64,7 @@ class CommitTransactionOperationUnitSpecification extends OperationUnitSpecifica
def callback = new FutureResultCallback()
when:
- operation.executeAsync(writeBinding, OPERATION_CONTEXT.withSessionContext(sessionContext), callback)
+ operation.executeAsync(writeBinding, createOperationContext().withSessionContext(sessionContext), callback)
callback.get()
then:
diff --git a/driver-core/src/test/unit/com/mongodb/internal/operation/CursorResourceManagerTest.java b/driver-core/src/test/unit/com/mongodb/internal/operation/CursorResourceManagerTest.java
index 68b3bf7f606..26fd6e6eab5 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/operation/CursorResourceManagerTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/operation/CursorResourceManagerTest.java
@@ -15,6 +15,7 @@
*/
package com.mongodb.internal.operation;
+import com.mongodb.ClusterFixture;
import com.mongodb.MongoNamespace;
import com.mongodb.ServerCursor;
import com.mongodb.internal.binding.AsyncConnectionSource;
@@ -24,7 +25,6 @@
import com.mongodb.internal.mockito.MongoMockito;
import org.junit.jupiter.api.Test;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.mockito.Mockito.when;
@@ -50,12 +50,12 @@ void doClose(final OperationContext operationContext) {
cursorResourceManager.tryStartOperation();
try {
assertDoesNotThrow(() -> {
- cursorResourceManager.close(OPERATION_CONTEXT);
- cursorResourceManager.close(OPERATION_CONTEXT);
+ cursorResourceManager.close(ClusterFixture.createOperationContext());
+ cursorResourceManager.close(ClusterFixture.createOperationContext());
cursorResourceManager.setServerCursor(null);
});
} finally {
- cursorResourceManager.endOperation(OPERATION_CONTEXT);
+ cursorResourceManager.endOperation(ClusterFixture.createOperationContext());
}
}
}
diff --git a/driver-core/src/test/unit/com/mongodb/internal/operation/ListCollectionsOperationTest.java b/driver-core/src/test/unit/com/mongodb/internal/operation/ListCollectionsOperationTest.java
index de1bfe405ed..ca7730ff2b6 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/operation/ListCollectionsOperationTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/operation/ListCollectionsOperationTest.java
@@ -15,6 +15,7 @@
*/
package com.mongodb.internal.operation;
+import com.mongodb.ClusterFixture;
import com.mongodb.MongoNamespace;
import com.mongodb.ReadPreference;
import com.mongodb.ServerAddress;
@@ -39,7 +40,6 @@
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.assertions.Assertions.assertNotNull;
import static com.mongodb.internal.mockito.MongoMockito.mock;
import static java.util.Collections.emptyList;
@@ -99,7 +99,7 @@ void authorizedCollectionsIsFalseByDefault() {
}
private BsonDocument executeOperationAndCaptureCommand() {
- operation.execute(mocks.readBinding(), OPERATION_CONTEXT);
+ operation.execute(mocks.readBinding(), ClusterFixture.createOperationContext());
ArgumentCaptor commandCaptor = forClass(BsonDocument.class);
verify(mocks.connection()).command(any(), commandCaptor.capture(), any(), any(), any(), any());
return commandCaptor.getValue();
diff --git a/driver-core/src/test/unit/com/mongodb/internal/operation/OperationHelperSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/operation/OperationHelperSpecification.groovy
index fd9786e8dbf..ac51ebcede5 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/operation/OperationHelperSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/operation/OperationHelperSpecification.groovy
@@ -32,7 +32,7 @@ import org.bson.BsonArray
import org.bson.BsonDocument
import spock.lang.Specification
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.WriteConcern.ACKNOWLEDGED
import static com.mongodb.WriteConcern.UNACKNOWLEDGED
import static com.mongodb.connection.ServerConnectionState.CONNECTED
@@ -108,8 +108,8 @@ class OperationHelperSpecification extends Specification {
}
expect:
- canRetryRead(retryableServerDescription, OPERATION_CONTEXT.withSessionContext(noTransactionSessionContext))
- !canRetryRead(retryableServerDescription, OPERATION_CONTEXT.withSessionContext(activeTransactionSessionContext))
+ canRetryRead(retryableServerDescription, createOperationContext().withSessionContext(noTransactionSessionContext))
+ !canRetryRead(retryableServerDescription, createOperationContext().withSessionContext(activeTransactionSessionContext))
}
diff --git a/driver-core/src/test/unit/com/mongodb/internal/operation/OperationUnitSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/operation/OperationUnitSpecification.groovy
index ec5cb74156f..52934c3bfad 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/operation/OperationUnitSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/operation/OperationUnitSpecification.groovy
@@ -41,7 +41,7 @@ import spock.lang.Specification
import java.util.concurrent.TimeUnit
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
class OperationUnitSpecification extends Specification {
@@ -97,7 +97,7 @@ class OperationUnitSpecification extends Specification {
def testSyncOperation(operation, List serverVersion, result, Boolean checkCommand=true,
BsonDocument expectedCommand=null,
Boolean checkSecondaryOk=false, ReadPreference readPreference=ReadPreference.primary()) {
- def operationContext = OPERATION_CONTEXT
+ def operationContext = createOperationContext()
.withSessionContext(Stub(SessionContext) {
hasActiveTransaction() >> false
getReadConcern() >> ReadConcern.DEFAULT
@@ -151,7 +151,7 @@ class OperationUnitSpecification extends Specification {
Boolean checkCommand=true, BsonDocument expectedCommand=null,
Boolean checkSecondaryOk=false, ReadPreference readPreference=ReadPreference.primary()) {
- def operationContext = OPERATION_CONTEXT
+ def operationContext = createOperationContext()
.withSessionContext(Stub(SessionContext) {
hasActiveTransaction() >> false
getReadConcern() >> ReadConcern.DEFAULT
diff --git a/driver-core/src/test/unit/com/mongodb/internal/operation/SyncOperationHelperSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/operation/SyncOperationHelperSpecification.groovy
index bd9bd2f2578..8b66947c026 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/operation/SyncOperationHelperSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/operation/SyncOperationHelperSpecification.groovy
@@ -34,7 +34,7 @@ import org.bson.codecs.BsonDocumentCodec
import org.bson.codecs.Decoder
import spock.lang.Specification
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ReadPreference.primary
import static com.mongodb.internal.operation.OperationUnitSpecification.getMaxWireVersionForServerVersion
import static com.mongodb.internal.operation.SyncOperationHelper.CommandReadTransformer
@@ -61,7 +61,7 @@ class SyncOperationHelperSpecification extends Specification {
def connectionDescription = Stub(ConnectionDescription)
when:
- executeCommand(writeBinding, OPERATION_CONTEXT, dbName, command, decoder, function)
+ executeCommand(writeBinding, createOperationContext(), dbName, command, decoder, function)
then:
_ * connection.getDescription() >> connectionDescription
@@ -71,7 +71,7 @@ class SyncOperationHelperSpecification extends Specification {
def 'should retry with retryable exception'() {
given:
- def operationContext = OPERATION_CONTEXT
+ def operationContext = createOperationContext()
.withSessionContext(Stub(SessionContext) {
hasSession() >> true
hasActiveTransaction() >> false
@@ -132,7 +132,7 @@ class SyncOperationHelperSpecification extends Specification {
def connectionDescription = Stub(ConnectionDescription)
when:
- executeRetryableRead(readBinding, OPERATION_CONTEXT, dbName, commandCreator, decoder, function, false)
+ executeRetryableRead(readBinding, createOperationContext(), dbName, commandCreator, decoder, function, false)
then:
_ * connection.getDescription() >> connectionDescription
diff --git a/driver-core/src/test/unit/com/mongodb/internal/session/BaseClientSessionImplTest.java b/driver-core/src/test/unit/com/mongodb/internal/session/BaseClientSessionImplTest.java
index c7fc1d73e20..495523f90a3 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/session/BaseClientSessionImplTest.java
+++ b/driver-core/src/test/unit/com/mongodb/internal/session/BaseClientSessionImplTest.java
@@ -17,10 +17,10 @@
package com.mongodb.internal.session;
import com.mongodb.ClientSessionOptions;
+import com.mongodb.ClusterFixture;
import com.mongodb.session.ClientSession;
import org.junit.jupiter.api.Test;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.getCluster;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -28,7 +28,7 @@ class BaseClientSessionImplTest {
@Test
void shouldNotCheckoutServerSessionIfNeverRequested() {
- ServerSessionPool serverSessionPool = new ServerSessionPool(getCluster(), OPERATION_CONTEXT);
+ ServerSessionPool serverSessionPool = new ServerSessionPool(getCluster(), ClusterFixture.createOperationContext());
ClientSession clientSession = new BaseClientSessionImpl(serverSessionPool, new Object(), ClientSessionOptions.builder().build());
assertEquals(0, serverSessionPool.getInUseCount());
@@ -40,7 +40,7 @@ void shouldNotCheckoutServerSessionIfNeverRequested() {
@Test
void shouldDelayServerSessionCheckoutUntilRequested() {
- ServerSessionPool serverSessionPool = new ServerSessionPool(getCluster(), OPERATION_CONTEXT);
+ ServerSessionPool serverSessionPool = new ServerSessionPool(getCluster(), ClusterFixture.createOperationContext());
ClientSession clientSession = new BaseClientSessionImpl(serverSessionPool, new Object(), ClientSessionOptions.builder().build());
assertEquals(0, serverSessionPool.getInUseCount());
diff --git a/driver-core/src/test/unit/com/mongodb/internal/session/ServerSessionPoolSpecification.groovy b/driver-core/src/test/unit/com/mongodb/internal/session/ServerSessionPoolSpecification.groovy
index 19bfa994200..0fc4564d322 100644
--- a/driver-core/src/test/unit/com/mongodb/internal/session/ServerSessionPoolSpecification.groovy
+++ b/driver-core/src/test/unit/com/mongodb/internal/session/ServerSessionPoolSpecification.groovy
@@ -32,7 +32,7 @@ import org.bson.BsonDocument
import org.bson.codecs.BsonDocumentCodec
import spock.lang.Specification
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
import static com.mongodb.ClusterFixture.TIMEOUT_SETTINGS
import static com.mongodb.ClusterFixture.getServerApi
import static com.mongodb.ReadPreference.primaryPreferred
@@ -120,7 +120,7 @@ class ServerSessionPoolSpecification extends Specification {
millis() >>> [0, MINUTES.toMillis(29) + 1,
]
}
- def pool = new ServerSessionPool(cluster, OPERATION_CONTEXT, clock)
+ def pool = new ServerSessionPool(cluster, createOperationContext(), clock)
def sessionOne = pool.get()
when:
@@ -146,7 +146,7 @@ class ServerSessionPoolSpecification extends Specification {
def clock = Stub(ServerSessionPool.Clock) {
millis() >>> [0, 0, 0]
}
- def pool = new ServerSessionPool(cluster, OPERATION_CONTEXT, clock)
+ def pool = new ServerSessionPool(cluster, createOperationContext(), clock)
def session = pool.get()
when:
@@ -165,7 +165,7 @@ class ServerSessionPoolSpecification extends Specification {
def clock = Stub(ServerSessionPool.Clock) {
millis() >> 42
}
- def pool = new ServerSessionPool(cluster, OPERATION_CONTEXT, clock)
+ def pool = new ServerSessionPool(cluster, createOperationContext(), clock)
when:
def session = pool.get() as ServerSessionPool.ServerSessionImpl
@@ -187,7 +187,7 @@ class ServerSessionPoolSpecification extends Specification {
def clock = Stub(ServerSessionPool.Clock) {
millis() >> 42
}
- def pool = new ServerSessionPool(cluster, OPERATION_CONTEXT, clock)
+ def pool = new ServerSessionPool(cluster, createOperationContext(), clock)
when:
def session = pool.get() as ServerSessionPool.ServerSessionImpl
diff --git a/driver-legacy/src/main/com/mongodb/MongoClientOptions.java b/driver-legacy/src/main/com/mongodb/MongoClientOptions.java
index 1f19fba3484..2fcfba0c806 100644
--- a/driver-legacy/src/main/com/mongodb/MongoClientOptions.java
+++ b/driver-legacy/src/main/com/mongodb/MongoClientOptions.java
@@ -465,6 +465,18 @@ public boolean getRetryReads() {
return wrapped.getRetryReads();
}
+ /**
+ * Returns whether overload retargeting is enabled.
+ * See {@link MongoClientSettings.Builder#enableOverloadRetargeting(boolean)} for more information.
+ *
+ * @return the enableOverloadRetargeting value
+ * @see MongoClientSettings.Builder#enableOverloadRetargeting(boolean)
+ * @since 5.7
+ */
+ public boolean getEnableOverloadRetargeting() {
+ return wrapped.getEnableOverloadRetargeting();
+ }
+
/**
* The read concern to use.
*
@@ -1049,6 +1061,20 @@ public Builder retryReads(final boolean retryReads) {
return this;
}
+ /**
+ * Sets whether to enable overload retargeting.
+ * See {@link MongoClientSettings.Builder#enableOverloadRetargeting(boolean)} for more information.
+ *
+ * @param enableOverloadRetargeting whether to enable overload retargeting
+ * @return {@code this}
+ * @see #getEnableOverloadRetargeting()
+ * @since 5.7
+ */
+ public Builder enableOverloadRetargeting(final boolean enableOverloadRetargeting) {
+ wrapped.enableOverloadRetargeting(enableOverloadRetargeting);
+ return this;
+ }
+
/**
* Sets the read concern.
*
diff --git a/driver-legacy/src/main/com/mongodb/MongoClientURI.java b/driver-legacy/src/main/com/mongodb/MongoClientURI.java
index e471bbf1686..fc8f70651c8 100644
--- a/driver-legacy/src/main/com/mongodb/MongoClientURI.java
+++ b/driver-legacy/src/main/com/mongodb/MongoClientURI.java
@@ -151,6 +151,9 @@
* Defaults to false.
* {@code retryReads=true|false}. If true the driver will retry supported read operations if they fail due to a network error.
* Defaults to false.
+ * {@code enableOverloadRetargeting=true|false}. If true the driver may route a request to a different server on a subsequent
+ * retry attempt if the previously used server is overloaded. Does not take effect for
+ * {@linkplain com.mongodb.connection.ClusterType#SHARDED sharded clusters}. Defaults to false.
*
*
*
@@ -218,6 +221,9 @@
* Defaults to true.
* {@code retryReads=true|false}. If true the driver will retry supported read operations if they fail due to a network error.
* Defaults to true.
+ * {@code enableOverloadRetargeting=true|false}. If true the driver may route a request to a different server on a subsequent
+ * retry attempt if the previously used server is overloaded. Does not take effect for
+ * {@linkplain com.mongodb.connection.ClusterType#SHARDED sharded clusters}. Defaults to false.
* {@code uuidRepresentation=unspecified|standard|javaLegacy|csharpLegacy|pythonLegacy}. See
* {@link MongoClientOptions#getUuidRepresentation()} for documentation of semantics of this parameter. Defaults to "javaLegacy", but
* will change to "unspecified" in the next major release.
@@ -387,6 +393,11 @@ public MongoClientOptions getOptions() {
builder.retryReads(retryReads);
}
+ Boolean enableOverloadRetargeting = proxied.getEnableOverloadRetargeting();
+ if (enableOverloadRetargeting != null) {
+ builder.enableOverloadRetargeting(enableOverloadRetargeting);
+ }
+
Integer maxConnectionPoolSize = proxied.getMaxConnectionPoolSize();
if (maxConnectionPoolSize != null) {
builder.connectionsPerHost(maxConnectionPoolSize);
diff --git a/driver-legacy/src/test/functional/com/mongodb/DBTest.java b/driver-legacy/src/test/functional/com/mongodb/DBTest.java
index cf44573a2b4..b483e326081 100644
--- a/driver-legacy/src/test/functional/com/mongodb/DBTest.java
+++ b/driver-legacy/src/test/functional/com/mongodb/DBTest.java
@@ -31,7 +31,6 @@
import java.util.Locale;
import java.util.UUID;
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT;
import static com.mongodb.ClusterFixture.disableMaxTimeFailPoint;
import static com.mongodb.ClusterFixture.enableMaxTimeFailPoint;
import static com.mongodb.ClusterFixture.getBinding;
@@ -345,7 +344,7 @@ public void shouldApplyUuidRepresentationToCommandEncodingAndDecoding() {
BsonDocument getCollectionInfo(final String collectionName) {
return new ListCollectionsOperation<>(getDefaultDatabaseName(), new BsonDocumentCodec())
- .filter(new BsonDocument("name", new BsonString(collectionName))).execute(getBinding(), OPERATION_CONTEXT).next().get(0);
+ .filter(new BsonDocument("name", new BsonString(collectionName))).execute(getBinding(), ClusterFixture.createOperationContext()).next().get(0);
}
private boolean isCapped(final DBCollection collection) {
diff --git a/driver-legacy/src/test/functional/com/mongodb/LegacyMixedBulkWriteOperationSpecification.groovy b/driver-legacy/src/test/functional/com/mongodb/LegacyMixedBulkWriteOperationSpecification.groovy
index 6a9c511c3bc..2db1da67e22 100644
--- a/driver-legacy/src/test/functional/com/mongodb/LegacyMixedBulkWriteOperationSpecification.groovy
+++ b/driver-legacy/src/test/functional/com/mongodb/LegacyMixedBulkWriteOperationSpecification.groovy
@@ -184,7 +184,7 @@ class LegacyMixedBulkWriteOperationSpecification extends OperationFunctionalSpec
def insert = new InsertRequest(new BsonDocument('_id', new BsonInt32(1)))
def binding = getBinding()
createBulkWriteOperationForInsert(getNamespace(), true, ACKNOWLEDGED, false, asList(insert))
- .execute(binding, ClusterFixture.getOperationContext(binding.getReadPreference()))
+ .execute(binding, ClusterFixture.createOperationContext(binding.getReadPreference()))
def replacement = new UpdateRequest(new BsonDocument('_id', new BsonInt32(1)),
new BsonDocument('_id', new BsonInt32(1)).append('x', new BsonInt32(1)), REPLACE)
diff --git a/driver-legacy/src/test/unit/com/mongodb/MongoClientOptionsSpecification.groovy b/driver-legacy/src/test/unit/com/mongodb/MongoClientOptionsSpecification.groovy
index ae1d332674c..057a60cf65f 100644
--- a/driver-legacy/src/test/unit/com/mongodb/MongoClientOptionsSpecification.groovy
+++ b/driver-legacy/src/test/unit/com/mongodb/MongoClientOptionsSpecification.groovy
@@ -46,6 +46,7 @@ class MongoClientOptionsSpecification extends Specification {
options.getWriteConcern() == WriteConcern.ACKNOWLEDGED
options.getRetryWrites()
options.getRetryReads()
+ !options.getEnableOverloadRetargeting()
options.getCodecRegistry() == MongoClientSettings.defaultCodecRegistry
options.getUuidRepresentation() == UuidRepresentation.UNSPECIFIED
options.getMinConnectionsPerHost() == 0
@@ -116,6 +117,7 @@ class MongoClientOptionsSpecification extends Specification {
.readPreference(ReadPreference.secondary())
.retryWrites(true)
.retryReads(false)
+ .enableOverloadRetargeting(true)
.writeConcern(WriteConcern.JOURNALED)
.readConcern(ReadConcern.MAJORITY)
.minConnectionsPerHost(30)
@@ -162,6 +164,7 @@ class MongoClientOptionsSpecification extends Specification {
options.getServerSelector() == serverSelector
options.getRetryWrites()
!options.getRetryReads()
+ options.getEnableOverloadRetargeting()
options.getServerSelectionTimeout() == 150
options.getTimeout() == 10_000
options.getMaxWaitTime() == 200
@@ -318,6 +321,7 @@ class MongoClientOptionsSpecification extends Specification {
.applicationName('appName')
.readPreference(ReadPreference.secondary())
.retryReads(true)
+ .enableOverloadRetargeting(true)
.uuidRepresentation(UuidRepresentation.STANDARD)
.writeConcern(WriteConcern.JOURNALED)
.minConnectionsPerHost(30)
@@ -619,6 +623,7 @@ class MongoClientOptionsSpecification extends Specification {
.writeConcern(WriteConcern.JOURNALED)
.retryWrites(true)
.retryReads(true)
+ .enableOverloadRetargeting(true)
.uuidRepresentation(UuidRepresentation.STANDARD)
.minConnectionsPerHost(30)
.connectionsPerHost(500)
diff --git a/driver-legacy/src/test/unit/com/mongodb/MongoClientURISpecification.groovy b/driver-legacy/src/test/unit/com/mongodb/MongoClientURISpecification.groovy
index 241ac958c8a..1801b7c4749 100644
--- a/driver-legacy/src/test/unit/com/mongodb/MongoClientURISpecification.groovy
+++ b/driver-legacy/src/test/unit/com/mongodb/MongoClientURISpecification.groovy
@@ -131,6 +131,7 @@ class MongoClientURISpecification extends Specification {
+ 'heartbeatFrequencyMS=20000&'
+ 'retryWrites=true&'
+ 'retryReads=true&'
+ + 'enableOverloadRetargeting=true&'
+ 'uuidRepresentation=csharpLegacy&'
+ 'appName=app1&'
+ 'timeoutMS=10000')
@@ -158,6 +159,7 @@ class MongoClientURISpecification extends Specification {
options.getHeartbeatFrequency() == 20000
options.getRetryWrites()
options.getRetryReads()
+ options.getEnableOverloadRetargeting()
options.getUuidRepresentation() == UuidRepresentation.C_SHARP_LEGACY
options.getApplicationName() == 'app1'
}
@@ -178,6 +180,7 @@ class MongoClientURISpecification extends Specification {
!options.isSslEnabled()
options.getRetryWrites()
options.getRetryReads()
+ !options.getEnableOverloadRetargeting()
options.getUuidRepresentation() == UuidRepresentation.UNSPECIFIED
}
@@ -188,6 +191,7 @@ class MongoClientURISpecification extends Specification {
.readPreference(ReadPreference.secondary())
.retryWrites(true)
.retryReads(true)
+ .enableOverloadRetargeting(true)
.writeConcern(WriteConcern.JOURNALED)
.minConnectionsPerHost(30)
.connectionsPerHost(500)
@@ -220,6 +224,7 @@ class MongoClientURISpecification extends Specification {
options.getWriteConcern() == WriteConcern.JOURNALED
options.getRetryWrites()
options.getRetryReads()
+ options.getEnableOverloadRetargeting()
options.getTimeout() == 10_000
options.getServerSelectionTimeout() == 150
options.getMaxWaitTime() == 200
@@ -314,24 +319,33 @@ class MongoClientURISpecification extends Specification {
def 'should respect MongoClientOptions builder'() {
given:
- def uri = new MongoClientURI('mongodb://localhost/', MongoClientOptions.builder().connectionsPerHost(200))
+ def uri = new MongoClientURI('mongodb://localhost/', MongoClientOptions.builder()
+ .connectionsPerHost(200)
+ .enableOverloadRetargeting(true))
when:
def options = uri.getOptions()
then:
options.getConnectionsPerHost() == 200
+ options.getEnableOverloadRetargeting()
}
def 'should override MongoClientOptions builder'() {
given:
- def uri = new MongoClientURI('mongodb://localhost/?maxPoolSize=250', MongoClientOptions.builder().connectionsPerHost(200))
+ def uri = new MongoClientURI('mongodb://localhost/?'
+ + 'maxPoolSize=250'
+ + '&enableOverloadRetargeting=false',
+ MongoClientOptions.builder()
+ .connectionsPerHost(200)
+ .enableOverloadRetargeting(true))
when:
def options = uri.getOptions()
then:
options.getConnectionsPerHost() == 250
+ !options.getEnableOverloadRetargeting()
}
def 'should be equal to another MongoClientURI with the same string values'() {
diff --git a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/OperationExecutorImpl.java b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/OperationExecutorImpl.java
index ef18c2c6b1f..35ff27f79ec 100644
--- a/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/OperationExecutorImpl.java
+++ b/driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/OperationExecutorImpl.java
@@ -216,7 +216,8 @@ private OperationContext getOperationContext(final RequestContext requestContext
createTimeoutContext(session, timeoutSettings),
TracingManager.NO_OP,
mongoClient.getSettings().getServerApi(),
- commandName);
+ commandName,
+ new OperationContext.ServerDeprioritization(mongoClient.getSettings().getEnableOverloadRetargeting()));
}
private ReadPreference getReadPreferenceForBinding(final ReadPreference readPreference, @Nullable final ClientSession session) {
diff --git a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/RetryableReadsProseTest.java b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/RetryableReadsProseTest.java
index 84dd0d733bf..bb748f00601 100644
--- a/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/RetryableReadsProseTest.java
+++ b/driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/RetryableReadsProseTest.java
@@ -16,57 +16,14 @@
package com.mongodb.reactivestreams.client;
-import com.mongodb.client.MongoCursor;
-import com.mongodb.client.RetryableWritesProseTest;
+import com.mongodb.MongoClientSettings;
+import com.mongodb.client.AbstractRetryableReadsProseTest;
+import com.mongodb.client.MongoClient;
import com.mongodb.reactivestreams.client.syncadapter.SyncMongoClient;
-import org.bson.Document;
-import org.junit.jupiter.api.Test;
-import static com.mongodb.client.model.Filters.eq;
-
-/**
- *
- * Prose Tests .
- */
-final class RetryableReadsProseTest {
- /**
- *
- * 1. PoolClearedError Retryability Test .
- */
- @Test
- void poolClearedExceptionMustBeRetryable() throws Exception {
- RetryableWritesProseTest.poolClearedExceptionMustBeRetryable(
- SyncMongoClient::new,
- mongoCollection -> mongoCollection.find(eq(0)).iterator().hasNext(), "find", false);
- }
-
- /**
- *
- * 2.1 Retryable Reads Are Retried on a Different mongos When One is Available .
- */
- @Test
- void retriesOnDifferentMongosWhenAvailable() {
- RetryableWritesProseTest.retriesOnDifferentMongosWhenAvailable(
- SyncMongoClient::new,
- mongoCollection -> {
- try (MongoCursor cursor = mongoCollection.find().iterator()) {
- return cursor.hasNext();
- }
- }, "find", false);
- }
-
- /**
- *
- * 2.2 Retryable Reads Are Retried on the Same mongos When No Others are Available .
- */
- @Test
- void retriesOnSameMongosWhenAnotherNotAvailable() {
- RetryableWritesProseTest.retriesOnSameMongosWhenAnotherNotAvailable(
- SyncMongoClient::new,
- mongoCollection -> {
- try (MongoCursor cursor = mongoCollection.find().iterator()) {
- return cursor.hasNext();
- }
- }, "find", false);
+final class RetryableReadsProseTest extends AbstractRetryableReadsProseTest {
+ @Override
+ protected MongoClient createClient(final MongoClientSettings settings) {
+ return new SyncMongoClient(settings);
}
}
diff --git a/driver-reactive-streams/src/test/unit/com/mongodb/reactivestreams/client/internal/ClientSessionBindingSpecification.groovy b/driver-reactive-streams/src/test/unit/com/mongodb/reactivestreams/client/internal/ClientSessionBindingSpecification.groovy
index cfe66a8031f..0fcbb5ac31a 100644
--- a/driver-reactive-streams/src/test/unit/com/mongodb/reactivestreams/client/internal/ClientSessionBindingSpecification.groovy
+++ b/driver-reactive-streams/src/test/unit/com/mongodb/reactivestreams/client/internal/ClientSessionBindingSpecification.groovy
@@ -16,6 +16,7 @@
package com.mongodb.reactivestreams.client.internal
+import com.mongodb.ClusterFixture
import com.mongodb.ReadPreference
import com.mongodb.ServerAddress
import com.mongodb.async.FutureResultCallback
@@ -31,32 +32,34 @@ import com.mongodb.internal.connection.ServerTuple
import com.mongodb.reactivestreams.client.ClientSession
import spock.lang.Specification
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
+import static com.mongodb.ClusterFixture.createOperationContext
class ClientSessionBindingSpecification extends Specification {
def 'should return the session context from the connection source'() {
given:
def session = Stub(ClientSession)
+ def operationContext = ClusterFixture.createOperationContext()
def wrappedBinding = Mock(AsyncClusterAwareReadWriteBinding);
wrappedBinding.retain() >> wrappedBinding
def binding = new ClientSessionBinding(session, false, wrappedBinding)
when:
def futureResultCallback = new FutureResultCallback()
- binding.getReadConnectionSource(OPERATION_CONTEXT, futureResultCallback)
+
+ binding.getReadConnectionSource(operationContext, futureResultCallback)
then:
- 1 * wrappedBinding.getReadConnectionSource(OPERATION_CONTEXT, _) >> {
+ 1 * wrappedBinding.getReadConnectionSource(operationContext, _) >> {
it[1].onResult(Stub(AsyncConnectionSource), null)
}
when:
futureResultCallback = new FutureResultCallback()
- binding.getWriteConnectionSource(OPERATION_CONTEXT, futureResultCallback)
+ binding.getWriteConnectionSource(operationContext, futureResultCallback)
then:
- 1 * wrappedBinding.getWriteConnectionSource(OPERATION_CONTEXT, _) >> {
+ 1 * wrappedBinding.getWriteConnectionSource(operationContext, _) >> {
it[1].onResult(Stub(AsyncConnectionSource), null)
}
}
@@ -87,10 +90,10 @@ class ClientSessionBindingSpecification extends Specification {
def wrappedBinding = createStubBinding()
def binding = new ClientSessionBinding(session, true, wrappedBinding)
def futureResultCallback = new FutureResultCallback()
- binding.getReadConnectionSource(OPERATION_CONTEXT, futureResultCallback)
+ binding.getReadConnectionSource(createOperationContext(), futureResultCallback)
def readConnectionSource = futureResultCallback.get()
futureResultCallback = new FutureResultCallback()
- binding.getWriteConnectionSource(OPERATION_CONTEXT, futureResultCallback)
+ binding.getWriteConnectionSource(createOperationContext(), futureResultCallback)
def writeConnectionSource = futureResultCallback.get()
when:
diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java
index bbeb7419bc7..9ba2139f18c 100644
--- a/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java
+++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClientImpl.java
@@ -105,7 +105,7 @@ public MongoClientImpl(final Cluster cluster,
(SynchronousContextProvider) settings.getContextProvider(),
autoEncryptionSettings == null ? null : createCrypt(settings, autoEncryptionSettings), this,
operationExecutor, settings.getReadConcern(), settings.getReadPreference(), settings.getRetryReads(),
- settings.getRetryWrites(), settings.getServerApi(),
+ settings.getRetryWrites(), settings.getEnableOverloadRetargeting(), settings.getServerApi(),
new ServerSessionPool(cluster, TimeoutSettings.create(settings), settings.getServerApi()),
TimeoutSettings.create(settings), settings.getUuidRepresentation(),
settings.getWriteConcern(), new TracingManager(settings.getObservabilitySettings()));
diff --git a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java
index 920feb1f986..b5604a7a846 100644
--- a/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java
+++ b/driver-sync/src/main/com/mongodb/client/internal/MongoClusterImpl.java
@@ -104,6 +104,7 @@ final class MongoClusterImpl implements MongoCluster {
private final ReadPreference readPreference;
private final boolean retryReads;
private final boolean retryWrites;
+ private final boolean enableOverloadRetargeting;
@Nullable
private final ServerApi serverApi;
private final ServerSessionPool serverSessionPool;
@@ -117,10 +118,9 @@ final class MongoClusterImpl implements MongoCluster {
@Nullable final AutoEncryptionSettings autoEncryptionSettings, final Cluster cluster, final CodecRegistry codecRegistry,
@Nullable final SynchronousContextProvider contextProvider, @Nullable final Crypt crypt, final Object originator,
@Nullable final OperationExecutor operationExecutor, final ReadConcern readConcern, final ReadPreference readPreference,
- final boolean retryReads, final boolean retryWrites, @Nullable final ServerApi serverApi,
- final ServerSessionPool serverSessionPool, final TimeoutSettings timeoutSettings, final UuidRepresentation uuidRepresentation,
- final WriteConcern writeConcern,
- final TracingManager tracingManager) {
+ final boolean retryReads, final boolean retryWrites, final boolean enableOverloadRetargeting,
+ @Nullable final ServerApi serverApi, final ServerSessionPool serverSessionPool, final TimeoutSettings timeoutSettings,
+ final UuidRepresentation uuidRepresentation, final WriteConcern writeConcern, final TracingManager tracingManager) {
this.autoEncryptionSettings = autoEncryptionSettings;
this.cluster = cluster;
this.codecRegistry = codecRegistry;
@@ -132,6 +132,7 @@ final class MongoClusterImpl implements MongoCluster {
this.readPreference = readPreference;
this.retryReads = retryReads;
this.retryWrites = retryWrites;
+ this.enableOverloadRetargeting = enableOverloadRetargeting;
this.serverApi = serverApi;
this.serverSessionPool = serverSessionPool;
this.timeoutSettings = timeoutSettings;
@@ -180,35 +181,35 @@ public Long getTimeout(final TimeUnit timeUnit) {
@Override
public MongoCluster withCodecRegistry(final CodecRegistry codecRegistry) {
return new MongoClusterImpl(autoEncryptionSettings, cluster, codecRegistry, contextProvider, crypt, originator,
- operationExecutor, readConcern, readPreference, retryReads, retryWrites, serverApi, serverSessionPool, timeoutSettings,
+ operationExecutor, readConcern, readPreference, retryReads, retryWrites, enableOverloadRetargeting, serverApi, serverSessionPool, timeoutSettings,
uuidRepresentation, writeConcern, tracingManager);
}
@Override
public MongoCluster withReadPreference(final ReadPreference readPreference) {
return new MongoClusterImpl(autoEncryptionSettings, cluster, codecRegistry, contextProvider, crypt, originator,
- operationExecutor, readConcern, readPreference, retryReads, retryWrites, serverApi, serverSessionPool, timeoutSettings,
+ operationExecutor, readConcern, readPreference, retryReads, retryWrites, enableOverloadRetargeting, serverApi, serverSessionPool, timeoutSettings,
uuidRepresentation, writeConcern, tracingManager);
}
@Override
public MongoCluster withWriteConcern(final WriteConcern writeConcern) {
return new MongoClusterImpl(autoEncryptionSettings, cluster, codecRegistry, contextProvider, crypt, originator,
- operationExecutor, readConcern, readPreference, retryReads, retryWrites, serverApi, serverSessionPool, timeoutSettings,
+ operationExecutor, readConcern, readPreference, retryReads, retryWrites, enableOverloadRetargeting, serverApi, serverSessionPool, timeoutSettings,
uuidRepresentation, writeConcern, tracingManager);
}
@Override
public MongoCluster withReadConcern(final ReadConcern readConcern) {
return new MongoClusterImpl(autoEncryptionSettings, cluster, codecRegistry, contextProvider, crypt, originator,
- operationExecutor, readConcern, readPreference, retryReads, retryWrites, serverApi, serverSessionPool, timeoutSettings,
+ operationExecutor, readConcern, readPreference, retryReads, retryWrites, enableOverloadRetargeting, serverApi, serverSessionPool, timeoutSettings,
uuidRepresentation, writeConcern, tracingManager);
}
@Override
public MongoCluster withTimeout(final long timeout, final TimeUnit timeUnit) {
return new MongoClusterImpl(autoEncryptionSettings, cluster, codecRegistry, contextProvider, crypt, originator,
- operationExecutor, readConcern, readPreference, retryReads, retryWrites, serverApi, serverSessionPool,
+ operationExecutor, readConcern, readPreference, retryReads, retryWrites, enableOverloadRetargeting, serverApi, serverSessionPool,
timeoutSettings.withTimeout(timeout, timeUnit), uuidRepresentation, writeConcern, tracingManager);
}
@@ -530,7 +531,8 @@ private OperationContext getOperationContext(final ClientSession session, final
createTimeoutContext(session, executorTimeoutSettings),
tracingManager,
serverApi,
- commandName);
+ commandName,
+ new OperationContext.ServerDeprioritization(enableOverloadRetargeting));
}
private RequestContext getRequestContext() {
@@ -591,9 +593,9 @@ ClientSession getClientSession(@Nullable final ClientSession clientSessionFromOp
* Create a tracing span for the given operation, and set it on operation context.
*
* @param actualClientSession the session that the operation is part of
- * @param operationContext the operation context for the operation
- * @param commandName the name of the command
- * @param namespace the namespace of the command
+ * @param operationContext the operation context for the operation
+ * @param commandName the name of the command
+ * @param namespace the namespace of the command
* @return the created span, or null if tracing is not enabled
*/
@Nullable
diff --git a/driver-sync/src/test/functional/com/mongodb/client/AbstractRetryableReadsProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/AbstractRetryableReadsProseTest.java
new file mode 100644
index 00000000000..ede7b099662
--- /dev/null
+++ b/driver-sync/src/test/functional/com/mongodb/client/AbstractRetryableReadsProseTest.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2008-present MongoDB, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.mongodb.client;
+
+import com.mongodb.MongoClientSettings;
+import com.mongodb.ReadPreference;
+import com.mongodb.ServerAddress;
+import com.mongodb.client.test.CollectionHelper;
+import com.mongodb.event.CommandFailedEvent;
+import com.mongodb.event.CommandSucceededEvent;
+import com.mongodb.internal.connection.TestCommandListener;
+import org.bson.BsonDocument;
+import org.bson.Document;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static com.mongodb.ClusterFixture.isDiscoverableReplicaSet;
+import static com.mongodb.ClusterFixture.serverVersionAtLeast;
+import static com.mongodb.MongoException.RETRYABLE_ERROR_LABEL;
+import static com.mongodb.MongoException.SYSTEM_OVERLOADED_ERROR_LABEL;
+import static com.mongodb.client.Fixture.getDefaultDatabaseName;
+import static com.mongodb.client.Fixture.getMongoClientSettingsBuilder;
+import static com.mongodb.client.Fixture.getPrimary;
+import static com.mongodb.client.model.Filters.eq;
+import static java.lang.String.format;
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+/**
+ *
+ * Prose Tests .
+ */
+public abstract class AbstractRetryableReadsProseTest {
+
+ private static final String COLLECTION_NAME = "test";
+
+ protected abstract MongoClient createClient(MongoClientSettings settings);
+
+ @AfterEach
+ void afterEach() {
+ CollectionHelper.dropDatabase(getDefaultDatabaseName());
+ }
+
+ /**
+ *
+ * 1. PoolClearedError Retryability Test .
+ */
+ @Test
+ void poolClearedExceptionMustBeRetryable() throws Exception {
+ RetryableWritesProseTest.poolClearedExceptionMustBeRetryable(this::createClient,
+ mongoCollection -> mongoCollection.find(eq(0)).iterator().hasNext(), "find", false);
+ }
+
+ /**
+ *
+ * 2.1 Retryable Reads Are Retried on a Different mongos When One is Available .
+ */
+ @Test
+ void retriesOnDifferentMongosWhenAvailable() {
+ RetryableWritesProseTest.retriesOnDifferentMongosWhenAvailable(this::createClient,
+ mongoCollection -> {
+ try (MongoCursor cursor = mongoCollection.find().iterator()) {
+ return cursor.hasNext();
+ }
+ }, "find", false);
+ }
+
+ /**
+ *
+ * 2.2 Retryable Reads Are Retried on the Same mongos When No Others are Available .
+ */
+ @Test
+ void retriesOnSameMongosWhenAnotherNotAvailable() {
+ RetryableWritesProseTest.retriesOnSameMongosWhenAnotherNotAvailable(this::createClient,
+ mongoCollection -> {
+ try (MongoCursor cursor = mongoCollection.find().iterator()) {
+ return cursor.hasNext();
+ }
+ }, "find", false);
+ }
+
+ /**
+ *
+ * 3.1 Retryable Reads Caused by Overload Errors Are Retried on a Different Replicaset Server When One is Available and enableOverloadRetargeting is enabled .
+ */
+ @Test
+ void overloadErrorRetriedOnDifferentReplicaSetServer() throws InterruptedException {
+ //given
+ assumeTrue(serverVersionAtLeast(4, 4));
+ assumeTrue(isDiscoverableReplicaSet());
+ ServerAddress primaryServerAddress = getPrimary();
+ TestCommandListener commandListener = new TestCommandListener(asList("commandFailedEvent", "commandSucceededEvent"), emptyList());
+ BsonDocument configureFailPoint = BsonDocument.parse(
+ "{\n"
+ + " configureFailPoint: \"failCommand\",\n"
+ + " mode: { times: 1 },\n"
+ + " data: {\n"
+ + " failCommands: [\"find\"],\n"
+ + " errorLabels: ['" + RETRYABLE_ERROR_LABEL + "', '" + SYSTEM_OVERLOADED_ERROR_LABEL + "'],\n"
+ + " errorCode: 6\n"
+ + " }\n"
+ + "}\n");
+
+ try (FailPoint ignored = FailPoint.enable(configureFailPoint, primaryServerAddress);
+ MongoClient client = createClient(getMongoClientSettingsBuilder()
+ .retryReads(true)
+ .readPreference(ReadPreference.primaryPreferred())
+ .enableOverloadRetargeting(true)
+ .addCommandListener(commandListener)
+ .build())) {
+
+ MongoCollection collection = client.getDatabase(getDefaultDatabaseName())
+ .getCollection(COLLECTION_NAME);
+ commandListener.reset();
+
+ //when
+ collection.find().first();
+
+ //then
+ List commandFailedEvents = commandListener.getCommandFailedEvents();
+ assertEquals(1, commandFailedEvents.size());
+ List commandSucceededEvents = commandListener.getCommandSucceededEvents();
+ assertEquals(1, commandSucceededEvents.size());
+
+ ServerAddress failedServer = commandFailedEvents.get(0).getConnectionDescription().getServerAddress();
+ ServerAddress succeededServer = commandSucceededEvents.get(0).getConnectionDescription().getServerAddress();
+
+ assertNotEquals(failedServer, succeededServer,
+ format("Expected retry on different server but both were %s", failedServer));
+ }
+ }
+
+ /**
+ *
+ * 3.2 Retryable Reads Caused by Non-Overload Errors Are Retried on the Same Replicaset Server .
+ */
+ @Test
+ void nonOverloadErrorRetriedOnSameReplicaSetServer() throws InterruptedException {
+ BsonDocument configureFailPoint = BsonDocument.parse(
+ "{\n"
+ + " configureFailPoint: \"failCommand\",\n"
+ + " mode: { times: 1 },\n"
+ + " data: {\n"
+ + " failCommands: [\"find\"],\n"
+ + " errorLabels: ['" + RETRYABLE_ERROR_LABEL + "'],\n"
+ + " errorCode: 6\n"
+ + " }\n"
+ + "}\n");
+ testRetriedOnTheSameServer(configureFailPoint);
+ }
+
+ /**
+ *
+ * 3.3 Retryable Reads Caused by Overload Errors Are Retried on Same Replicaset Server When enableOverloadRetargeting is disabled .
+ */
+ @Test
+ void overloadErrorRetriedOnSameReplicaSetServerWhenRetargetingDisabled() throws InterruptedException {
+ BsonDocument configureFailPoint = BsonDocument.parse(
+ "{\n"
+ + " configureFailPoint: \"failCommand\",\n"
+ + " mode: { times: 1 },\n"
+ + " data: {\n"
+ + " failCommands: [\"find\"],\n"
+ + " errorLabels: ['" + RETRYABLE_ERROR_LABEL + "', '" + SYSTEM_OVERLOADED_ERROR_LABEL + "'],\n"
+ + " errorCode: 6\n"
+ + " }\n"
+ + "}\n");
+ testRetriedOnTheSameServer(configureFailPoint);
+ }
+
+ private void testRetriedOnTheSameServer(final BsonDocument configureFailPoint) throws InterruptedException {
+ //given
+ assumeTrue(serverVersionAtLeast(4, 4));
+ assumeTrue(isDiscoverableReplicaSet());
+ ServerAddress primaryServerAddress = getPrimary();
+ TestCommandListener commandListener = new TestCommandListener(asList("commandFailedEvent", "commandSucceededEvent"), emptyList());
+
+ try (FailPoint ignored = FailPoint.enable(configureFailPoint, primaryServerAddress);
+ MongoClient client = createClient(getMongoClientSettingsBuilder()
+ .retryReads(true)
+ .readPreference(ReadPreference.primaryPreferred())
+ .addCommandListener(commandListener)
+ .build())) {
+
+ MongoCollection collection = client.getDatabase(getDefaultDatabaseName())
+ .getCollection(COLLECTION_NAME);
+ commandListener.reset();
+
+ //when
+ collection.find().first();
+
+ //then
+ List commandFailedEvents = commandListener.getCommandFailedEvents();
+ assertEquals(1, commandFailedEvents.size());
+ List commandSucceededEvents = commandListener.getCommandSucceededEvents();
+ assertEquals(1, commandSucceededEvents.size());
+
+ ServerAddress failedServer = commandFailedEvents.get(0).getConnectionDescription().getServerAddress();
+ ServerAddress succeededServer = commandSucceededEvents.get(0).getConnectionDescription().getServerAddress();
+
+ assertEquals(failedServer, succeededServer,
+ format("Expected retry on same server but got %s and %s", failedServer, succeededServer));
+ }
+ }
+}
diff --git a/driver-sync/src/test/functional/com/mongodb/client/RetryableReadsProseTest.java b/driver-sync/src/test/functional/com/mongodb/client/RetryableReadsProseTest.java
index 59b6a9aad19..5ca0f75d56b 100644
--- a/driver-sync/src/test/functional/com/mongodb/client/RetryableReadsProseTest.java
+++ b/driver-sync/src/test/functional/com/mongodb/client/RetryableReadsProseTest.java
@@ -16,51 +16,11 @@
package com.mongodb.client;
-import org.bson.Document;
-import org.junit.jupiter.api.Test;
+import com.mongodb.MongoClientSettings;
-import static com.mongodb.client.model.Filters.eq;
-
-/**
- *
- * Prose Tests .
- */
-final class RetryableReadsProseTest {
- /**
- *
- * 1. PoolClearedError Retryability Test .
- */
- @Test
- void poolClearedExceptionMustBeRetryable() throws Exception {
- RetryableWritesProseTest.poolClearedExceptionMustBeRetryable(MongoClients::create,
- mongoCollection -> mongoCollection.find(eq(0)).iterator().hasNext(), "find", false);
- }
-
- /**
- *
- * 2.1 Retryable Reads Are Retried on a Different mongos When One is Available .
- */
- @Test
- void retriesOnDifferentMongosWhenAvailable() {
- RetryableWritesProseTest.retriesOnDifferentMongosWhenAvailable(MongoClients::create,
- mongoCollection -> {
- try (MongoCursor cursor = mongoCollection.find().iterator()) {
- return cursor.hasNext();
- }
- }, "find", false);
- }
-
- /**
- *
- * 2.2 Retryable Reads Are Retried on the Same mongos When No Others are Available .
- */
- @Test
- void retriesOnSameMongosWhenAnotherNotAvailable() {
- RetryableWritesProseTest.retriesOnSameMongosWhenAnotherNotAvailable(MongoClients::create,
- mongoCollection -> {
- try (MongoCursor cursor = mongoCollection.find().iterator()) {
- return cursor.hasNext();
- }
- }, "find", false);
+final class RetryableReadsProseTest extends AbstractRetryableReadsProseTest {
+ @Override
+ protected MongoClient createClient(final MongoClientSettings settings) {
+ return MongoClients.create(settings);
}
}
diff --git a/driver-sync/src/test/unit/com/mongodb/client/internal/ClientSessionBindingSpecification.groovy b/driver-sync/src/test/unit/com/mongodb/client/internal/ClientSessionBindingSpecification.groovy
index e2e664f324d..f2ecac0c170 100644
--- a/driver-sync/src/test/unit/com/mongodb/client/internal/ClientSessionBindingSpecification.groovy
+++ b/driver-sync/src/test/unit/com/mongodb/client/internal/ClientSessionBindingSpecification.groovy
@@ -16,7 +16,7 @@
package com.mongodb.client.internal
-
+import com.mongodb.ClusterFixture
import com.mongodb.ReadPreference
import com.mongodb.client.ClientSession
import com.mongodb.internal.binding.ClusterBinding
@@ -25,29 +25,28 @@ import com.mongodb.internal.binding.ReadWriteBinding
import com.mongodb.internal.connection.Cluster
import spock.lang.Specification
-import static com.mongodb.ClusterFixture.OPERATION_CONTEXT
-
class ClientSessionBindingSpecification extends Specification {
def 'should call underlying wrapped binding'() {
given:
def session = Stub(ClientSession)
+ def operationContext = ClusterFixture.createOperationContext()
def wrappedBinding = Mock(ClusterBinding);
def binding = new ClientSessionBinding(session, false, wrappedBinding)
when:
- binding.getReadConnectionSource(OPERATION_CONTEXT)
+ binding.getReadConnectionSource(operationContext)
then:
- 1 * wrappedBinding.getReadConnectionSource(OPERATION_CONTEXT) >> {
+ 1 * wrappedBinding.getReadConnectionSource(operationContext) >> {
Stub(ConnectionSource)
}
when:
- binding.getWriteConnectionSource(OPERATION_CONTEXT)
+ binding.getWriteConnectionSource(operationContext)
then:
- 1 * wrappedBinding.getWriteConnectionSource(OPERATION_CONTEXT) >> {
+ 1 * wrappedBinding.getWriteConnectionSource(operationContext) >> {
Stub(ConnectionSource)
}
}
@@ -77,8 +76,9 @@ class ClientSessionBindingSpecification extends Specification {
def session = Mock(ClientSession)
def wrappedBinding = createStubBinding()
def binding = new ClientSessionBinding(session, true, wrappedBinding)
- def readConnectionSource = binding.getReadConnectionSource(OPERATION_CONTEXT)
- def writeConnectionSource = binding.getWriteConnectionSource(OPERATION_CONTEXT)
+ def operationContext = ClusterFixture.createOperationContext()
+ def readConnectionSource = binding.getReadConnectionSource(operationContext)
+ def writeConnectionSource = binding.getWriteConnectionSource(operationContext)
when:
binding.release()
diff --git a/driver-sync/src/test/unit/com/mongodb/client/internal/CryptConnectionSpecification.groovy b/driver-sync/src/test/unit/com/mongodb/client/internal/CryptConnectionSpecification.groovy
index 8a38f966754..3ec9a889e29 100644
--- a/driver-sync/src/test/unit/com/mongodb/client/internal/CryptConnectionSpecification.groovy
+++ b/driver-sync/src/test/unit/com/mongodb/client/internal/CryptConnectionSpecification.groovy
@@ -61,7 +61,7 @@ class CryptConnectionSpecification extends Specification {
def cryptConnection = new CryptConnection(wrappedConnection, crypt)
def codec = new DocumentCodec()
def timeoutContext = Mock(TimeoutContext)
- def operationContext = ClusterFixture.OPERATION_CONTEXT.withTimeoutContext(timeoutContext)
+ def operationContext = ClusterFixture.createOperationContext().withTimeoutContext(timeoutContext)
def operationTimeout = Mock(Timeout)
timeoutContext.getTimeout() >> operationTimeout
@@ -127,7 +127,7 @@ class CryptConnectionSpecification extends Specification {
def encryptedResponse = toRaw(new BsonDocument('ok', new BsonInt32(1)))
def decryptedResponse = encryptedResponse
def timeoutContext = Mock(TimeoutContext)
- def operationContext = ClusterFixture.OPERATION_CONTEXT.withTimeoutContext(timeoutContext)
+ def operationContext = ClusterFixture.createOperationContext().withTimeoutContext(timeoutContext)
def operationTimeout = Mock(Timeout)
timeoutContext.getTimeout() >> operationTimeout
@@ -183,7 +183,7 @@ class CryptConnectionSpecification extends Specification {
def encryptedResponse = toRaw(new BsonDocument('ok', new BsonInt32(1)))
def decryptedResponse = encryptedResponse
def timeoutContext = Mock(TimeoutContext)
- def operationContext = ClusterFixture.OPERATION_CONTEXT.withTimeoutContext(timeoutContext)
+ def operationContext = ClusterFixture.createOperationContext().withTimeoutContext(timeoutContext)
def operationTimeout = Mock(Timeout)
timeoutContext.getTimeout() >> operationTimeout
diff --git a/driver-sync/src/test/unit/com/mongodb/client/internal/MongoClusterSpecification.groovy b/driver-sync/src/test/unit/com/mongodb/client/internal/MongoClusterSpecification.groovy
index c75a4255595..34f46e7b007 100644
--- a/driver-sync/src/test/unit/com/mongodb/client/internal/MongoClusterSpecification.groovy
+++ b/driver-sync/src/test/unit/com/mongodb/client/internal/MongoClusterSpecification.groovy
@@ -259,7 +259,7 @@ class MongoClusterSpecification extends Specification {
MongoClusterImpl createMongoCluster(final MongoClientSettings settings, final OperationExecutor operationExecutor) {
new MongoClusterImpl(null, cluster, settings.codecRegistry, null, null,
originator, operationExecutor, settings.readConcern, settings.readPreference, settings.retryReads, settings.retryWrites,
- null, serverSessionPool, TimeoutSettings.create(settings), settings.uuidRepresentation,
+ settings.enableOverloadRetargeting, null, serverSessionPool, TimeoutSettings.create(settings), settings.uuidRepresentation,
settings.writeConcern, TracingManager.NO_OP)
}
}
diff --git a/testing/resources/specifications b/testing/resources/specifications
index bb9dddd8176..1b15cd29901 160000
--- a/testing/resources/specifications
+++ b/testing/resources/specifications
@@ -1 +1 @@
-Subproject commit bb9dddd8176eddbb9424f9bebedfe8c6bbf28c3a
+Subproject commit 1b15cd299011172f941893cbe3c9d4737cb2ee5d