Skip to content

Commit 2fa9f49

Browse files
stIncMalekatcharov
andauthored
Add durations to connection pool events (#1166)
JAVA-5076 --------- Co-authored-by: Maxim Katcharov <[email protected]>
1 parent c4662b1 commit 2fa9f49

File tree

13 files changed

+376
-53
lines changed

13 files changed

+376
-53
lines changed

driver-core/src/main/com/mongodb/ConnectionString.java

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
import com.mongodb.connection.ClusterSettings;
2020
import com.mongodb.connection.ConnectionPoolSettings;
2121
import com.mongodb.connection.SocketSettings;
22+
import com.mongodb.event.ConnectionCheckOutStartedEvent;
23+
import com.mongodb.event.ConnectionCheckedInEvent;
24+
import com.mongodb.event.ConnectionCheckedOutEvent;
25+
import com.mongodb.event.ConnectionCreatedEvent;
26+
import com.mongodb.event.ConnectionReadyEvent;
2227
import com.mongodb.internal.diagnostics.logging.Logger;
2328
import com.mongodb.internal.diagnostics.logging.Loggers;
2429
import com.mongodb.internal.dns.DefaultDnsResolver;
@@ -132,8 +137,10 @@
132137
* <ul>
133138
* <li>{@code maxPoolSize=n}: The maximum number of connections in the connection pool.</li>
134139
* <li>{@code minPoolSize=n}: The minimum number of connections in the connection pool.</li>
135-
* <li>{@code waitQueueTimeoutMS=ms}: The maximum wait time in milliseconds that a thread may wait for a connection to
136-
* become available.</li>
140+
* <li>{@code waitQueueTimeoutMS=ms}: The maximum duration to wait until either:
141+
* an {@linkplain ConnectionCheckedOutEvent in-use connection} becomes {@linkplain ConnectionCheckedInEvent available},
142+
* or a {@linkplain ConnectionCreatedEvent connection is created} and begins to be {@linkplain ConnectionReadyEvent established}.
143+
* See {@link #getMaxWaitTime()} for more details.</li>
137144
* <li>{@code maxConnecting=n}: The maximum number of connections a pool may be establishing concurrently.</li>
138145
* </ul>
139146
* <p>Write concern configuration:</p>
@@ -1366,15 +1373,42 @@ public Integer getMinConnectionPoolSize() {
13661373
/**
13671374
* Gets the maximum connection pool size specified in the connection string.
13681375
* @return the maximum connection pool size
1376+
* @see ConnectionPoolSettings#getMaxSize()
13691377
*/
13701378
@Nullable
13711379
public Integer getMaxConnectionPoolSize() {
13721380
return maxConnectionPoolSize;
13731381
}
13741382

13751383
/**
1376-
* Gets the maximum wait time of a thread waiting for a connection specified in the connection string.
1377-
* @return the maximum wait time of a thread waiting for a connection
1384+
* The maximum duration to wait until either:
1385+
* <ul>
1386+
* <li>
1387+
* an {@linkplain ConnectionCheckedOutEvent in-use connection} becomes {@linkplain ConnectionCheckedInEvent available}; or
1388+
* </li>
1389+
* <li>
1390+
* a {@linkplain ConnectionCreatedEvent connection is created} and begins to be {@linkplain ConnectionReadyEvent established}.
1391+
* The time between {@linkplain ConnectionCheckOutStartedEvent requesting} a connection
1392+
* and it being created is limited by this maximum duration.
1393+
* The maximum time between it being created and {@linkplain ConnectionCheckedOutEvent successfully checked out},
1394+
* which includes the time to {@linkplain ConnectionReadyEvent establish} the created connection,
1395+
* is affected by {@link SocketSettings#getConnectTimeout(TimeUnit)}, {@link SocketSettings#getReadTimeout(TimeUnit)}
1396+
* among others, and is not affected by this maximum duration.
1397+
* </li>
1398+
* </ul>
1399+
* The reasons it is not always possible to create and start establishing a connection
1400+
* whenever there is no available connection:
1401+
* <ul>
1402+
* <li>
1403+
* the number of connections per pool is limited by {@link #getMaxConnectionPoolSize()};
1404+
* </li>
1405+
* <li>
1406+
* the number of connections a pool may be establishing concurrently is limited by {@link #getMaxConnecting()}.
1407+
* </li>
1408+
* </ul>
1409+
*
1410+
* @return The value of the {@code waitQueueTimeoutMS} option, if specified.
1411+
* @see ConnectionPoolSettings#getMaxWaitTime(TimeUnit)
13781412
*/
13791413
@Nullable
13801414
public Integer getMaxWaitTime() {

driver-core/src/main/com/mongodb/connection/ConnectionPoolSettings.java

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
import com.mongodb.ConnectionString;
2020
import com.mongodb.annotations.Immutable;
2121
import com.mongodb.annotations.NotThreadSafe;
22+
import com.mongodb.event.ConnectionCheckOutStartedEvent;
23+
import com.mongodb.event.ConnectionCheckedInEvent;
24+
import com.mongodb.event.ConnectionCheckedOutEvent;
2225
import com.mongodb.event.ConnectionCreatedEvent;
2326
import com.mongodb.event.ConnectionPoolListener;
2427
import com.mongodb.event.ConnectionReadyEvent;
@@ -119,6 +122,8 @@ public Builder applySettings(final ConnectionPoolSettings connectionPoolSettings
119122
*
120123
* @param maxSize the maximum number of connections in the pool; if 0, then there is no limit.
121124
* @return this
125+
* @see #getMaxSize()
126+
* @see #getMaxWaitTime(TimeUnit)
122127
*/
123128
public Builder maxSize(final int maxSize) {
124129
this.maxSize = maxSize;
@@ -140,13 +145,38 @@ public Builder minSize(final int minSize) {
140145
}
141146

142147
/**
143-
* <p>The maximum time that a thread may wait for a connection to become available.</p>
148+
* The maximum duration to wait until either:
149+
* <ul>
150+
* <li>
151+
* an {@linkplain ConnectionCheckedOutEvent in-use connection} becomes {@linkplain ConnectionCheckedInEvent available}; or
152+
* </li>
153+
* <li>
154+
* a {@linkplain ConnectionCreatedEvent connection is created} and begins to be {@linkplain ConnectionReadyEvent established}.
155+
* The time between {@linkplain ConnectionCheckOutStartedEvent requesting} a connection
156+
* and it being created is limited by this maximum duration.
157+
* The maximum time between it being created and {@linkplain ConnectionCheckedOutEvent successfully checked out},
158+
* which includes the time to {@linkplain ConnectionReadyEvent establish} the created connection,
159+
* is affected by {@link SocketSettings#getConnectTimeout(TimeUnit)}, {@link SocketSettings#getReadTimeout(TimeUnit)}
160+
* among others, and is not affected by this maximum duration.
161+
* </li>
162+
* </ul>
163+
* The reasons it is not always possible to create and start establishing a connection
164+
* whenever there is no available connection:
165+
* <ul>
166+
* <li>
167+
* the number of connections per pool is limited by {@link #getMaxSize()};
168+
* </li>
169+
* <li>
170+
* the number of connections a pool may be establishing concurrently is limited by {@link #getMaxConnecting()}.
171+
* </li>
172+
* </ul>
144173
*
145174
* <p>Default is 2 minutes. A value of 0 means that it will not wait. A negative value means it will wait indefinitely.</p>
146175
*
147176
* @param maxWaitTime the maximum amount of time to wait
148177
* @param timeUnit the TimeUnit for this wait period
149178
* @return this
179+
* @see #getMaxWaitTime(TimeUnit)
150180
*/
151181
public Builder maxWaitTime(final long maxWaitTime, final TimeUnit timeUnit) {
152182
this.maxWaitTimeMS = MILLISECONDS.convert(maxWaitTime, timeUnit);
@@ -234,6 +264,7 @@ public Builder connectionPoolListenerList(final List<ConnectionPoolListener> con
234264
* @param maxConnecting The maximum number of connections a pool may be establishing concurrently. Must be positive.
235265
* @return {@code this}.
236266
* @see ConnectionPoolSettings#getMaxConnecting()
267+
* @see #getMaxWaitTime(TimeUnit)
237268
* @since 4.4
238269
*/
239270
public Builder maxConnecting(final int maxConnecting) {
@@ -298,6 +329,9 @@ public Builder applyConnectionString(final ConnectionString connectionString) {
298329
* <p>Default is 100.</p>
299330
*
300331
* @return the maximum number of connections in the pool; if 0, then there is no limit.
332+
* @see Builder#maxSize(int)
333+
* @see ConnectionString#getMaxConnectionPoolSize()
334+
* @see #getMaxWaitTime(TimeUnit)
301335
*/
302336
public int getMaxSize() {
303337
return maxSize;
@@ -316,12 +350,38 @@ public int getMinSize() {
316350
}
317351

318352
/**
319-
* <p>The maximum time that a thread may wait for a connection to become available.</p>
353+
* The maximum duration to wait until either:
354+
* <ul>
355+
* <li>
356+
* an {@linkplain ConnectionCheckedOutEvent in-use connection} becomes {@linkplain ConnectionCheckedInEvent available}; or
357+
* </li>
358+
* <li>
359+
* a {@linkplain ConnectionCreatedEvent connection is created} and begins to be {@linkplain ConnectionReadyEvent established}.
360+
* The time between {@linkplain ConnectionCheckOutStartedEvent requesting} a connection
361+
* and it being created is limited by this maximum duration.
362+
* The maximum time between it being created and {@linkplain ConnectionCheckedOutEvent successfully checked out},
363+
* which includes the time to {@linkplain ConnectionReadyEvent establish} the created connection,
364+
* is affected by {@link SocketSettings#getConnectTimeout(TimeUnit)}, {@link SocketSettings#getReadTimeout(TimeUnit)}
365+
* among others, and is not affected by this maximum duration.
366+
* </li>
367+
* </ul>
368+
* The reasons it is not always possible to create and start establishing a connection
369+
* whenever there is no available connection:
370+
* <ul>
371+
* <li>
372+
* the number of connections per pool is limited by {@link #getMaxSize()};
373+
* </li>
374+
* <li>
375+
* the number of connections a pool may be establishing concurrently is limited by {@link #getMaxConnecting()}.
376+
* </li>
377+
* </ul>
320378
*
321379
* <p>Default is 2 minutes. A value of 0 means that it will not wait. A negative value means it will wait indefinitely.</p>
322380
*
323381
* @param timeUnit the TimeUnit for this wait period
324382
* @return the maximum amount of time to wait in the given TimeUnits
383+
* @see Builder#maxWaitTime(long, TimeUnit)
384+
* @see ConnectionString#getMaxWaitTime()
325385
*/
326386
public long getMaxWaitTime(final TimeUnit timeUnit) {
327387
return timeUnit.convert(maxWaitTimeMS, MILLISECONDS);
@@ -388,6 +448,8 @@ public List<ConnectionPoolListener> getConnectionPoolListeners() {
388448
*
389449
* @return The maximum number of connections a pool may be establishing concurrently.
390450
* @see Builder#maxConnecting(int)
451+
* @see ConnectionString#getMaxConnecting()
452+
* @see #getMaxWaitTime(TimeUnit)
391453
* @since 4.4
392454
*/
393455
public int getMaxConnecting() {

driver-core/src/main/com/mongodb/event/ConnectionCheckOutFailedEvent.java

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@
1616

1717
package com.mongodb.event;
1818

19+
import com.mongodb.connection.ConnectionPoolSettings;
1920
import com.mongodb.connection.ServerId;
2021

22+
import java.util.concurrent.TimeUnit;
23+
24+
import static com.mongodb.assertions.Assertions.isTrueArgument;
2125
import static com.mongodb.assertions.Assertions.notNull;
2226

2327
/**
@@ -54,8 +58,25 @@ public enum Reason {
5458

5559
private final ServerId serverId;
5660
private final long operationId;
57-
5861
private final Reason reason;
62+
private final long elapsedTimeNanos;
63+
64+
/**
65+
* Constructs an instance.
66+
*
67+
* @param serverId The server ID. See {@link #getServerId()}.
68+
* @param operationId The operation ID. See {@link #getOperationId()}.
69+
* @param reason The reason the connection check out failed. See {@link #getReason()}.
70+
* @param elapsedTimeNanos The time it took while trying to check out the connection. See {@link #getElapsedTime(TimeUnit)}.
71+
* @since 4.11
72+
*/
73+
public ConnectionCheckOutFailedEvent(final ServerId serverId, final long operationId, final Reason reason, final long elapsedTimeNanos) {
74+
this.serverId = notNull("serverId", serverId);
75+
this.operationId = operationId;
76+
this.reason = notNull("reason", reason);
77+
isTrueArgument("waited time is not negative", elapsedTimeNanos >= 0);
78+
this.elapsedTimeNanos = elapsedTimeNanos;
79+
}
5980

6081
/**
6182
* Construct an instance
@@ -64,11 +85,12 @@ public enum Reason {
6485
* @param operationId the operation id
6586
* @param reason the reason the connection check out failed
6687
* @since 4.10
88+
* @deprecated Prefer {@link ConnectionCheckOutFailedEvent#ConnectionCheckOutFailedEvent(ServerId, long, Reason, long)}.
89+
* If this constructor is used, then {@link #getElapsedTime(TimeUnit)} is 0.
6790
*/
91+
@Deprecated
6892
public ConnectionCheckOutFailedEvent(final ServerId serverId, final long operationId, final Reason reason) {
69-
this.serverId = notNull("serverId", serverId);
70-
this.operationId = operationId;
71-
this.reason = notNull("reason", reason);
93+
this(serverId, operationId, reason, 0);
7294
}
7395

7496
/**
@@ -77,6 +99,7 @@ public ConnectionCheckOutFailedEvent(final ServerId serverId, final long operati
7799
* @param serverId the server id
78100
* @param reason the reason the connection check out failed
79101
* @deprecated Prefer {@link #ConnectionCheckOutFailedEvent(ServerId, long, Reason)}
102+
* If this constructor is used, then {@link #getOperationId()} is -1.
80103
*/
81104
@Deprecated
82105
public ConnectionCheckOutFailedEvent(final ServerId serverId, final Reason reason) {
@@ -112,13 +135,35 @@ public Reason getReason() {
112135
return reason;
113136
}
114137

138+
/**
139+
* The time it took to check out the connection.
140+
* More specifically, the time elapsed between the {@link ConnectionCheckOutStartedEvent} emitted by the same checking out and this event.
141+
* <p>
142+
* Naturally, if a new connection was not {@linkplain ConnectionCreatedEvent created}
143+
* and {@linkplain ConnectionReadyEvent established} as part of checking out,
144+
* this duration is usually not greater than {@link ConnectionPoolSettings#getMaxWaitTime(TimeUnit)},
145+
* but may occasionally be greater than that, because the driver does not provide hard real-time guarantees.</p>
146+
* <p>
147+
* This duration does not currently include the time to deliver the {@link ConnectionCheckOutStartedEvent}.
148+
* Subject to change.</p>
149+
*
150+
* @param timeUnit The time unit of the result.
151+
* {@link TimeUnit#convert(long, TimeUnit)} specifies how the conversion from nanoseconds to {@code timeUnit} is done.
152+
* @return The time it took to establish the connection.
153+
* @since 4.11
154+
*/
155+
public long getElapsedTime(final TimeUnit timeUnit) {
156+
return timeUnit.convert(elapsedTimeNanos, TimeUnit.NANOSECONDS);
157+
}
158+
115159
@Override
116160
public String toString() {
117161
return "ConnectionCheckOutFailedEvent{"
118162
+ "server=" + serverId.getAddress()
119163
+ ", clusterId=" + serverId.getClusterId()
120164
+ ", operationId=" + operationId
121165
+ ", reason=" + reason
166+
+ ", elapsedTimeNanos=" + elapsedTimeNanos
122167
+ '}';
123168
}
124169
}

driver-core/src/main/com/mongodb/event/ConnectionCheckedInEvent.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
/**
2424
* An event for checking in a connection to the pool.
25+
* Such a connection is considered available until it becomes {@linkplain ConnectionCheckedOutEvent in use}
26+
* or {@linkplain ConnectionClosedEvent closed}.
2527
*
2628
* @since 3.5
2729
*/

0 commit comments

Comments
 (0)