Skip to content

Commit 44d40c3

Browse files
committed
JAVA-2682: Don't retry writes unless all writes in the list are retryable
1 parent d719076 commit 44d40c3

File tree

3 files changed

+62
-4
lines changed

3 files changed

+62
-4
lines changed

driver-core/src/main/com/mongodb/operation/BulkWriteBatch.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@
3131
import com.mongodb.connection.BulkWriteBatchCombiner;
3232
import com.mongodb.connection.ConnectionDescription;
3333
import com.mongodb.connection.ServerDescription;
34-
import com.mongodb.session.SessionContext;
3534
import com.mongodb.connection.SplittablePayload;
3635
import com.mongodb.internal.connection.IndexMap;
3736
import com.mongodb.internal.validator.CollectibleDocumentFieldNameValidator;
3837
import com.mongodb.internal.validator.MappedFieldNameValidator;
3938
import com.mongodb.internal.validator.NoOpFieldNameValidator;
4039
import com.mongodb.internal.validator.UpdateFieldNameValidator;
40+
import com.mongodb.session.SessionContext;
4141
import org.bson.BsonArray;
4242
import org.bson.BsonBoolean;
4343
import org.bson.BsonDocument;
@@ -101,7 +101,7 @@ public static BulkWriteBatch createBulkWriteBatch(final MongoNamespace namespace
101101
boolean writeRequestsAreRetryable = true;
102102
for (int i = 0; i < writeRequests.size(); i++) {
103103
WriteRequest writeRequest = writeRequests.get(i);
104-
writeRequestsAreRetryable = isRetryable(writeRequest);
104+
writeRequestsAreRetryable = writeRequestsAreRetryable && isRetryable(writeRequest);
105105
writeRequestsWithIndex.add(new WriteRequestWithIndex(writeRequest, i));
106106
}
107107
if (canRetryWrites && !writeRequestsAreRetryable) {

driver-core/src/test/functional/com/mongodb/operation/MixedBulkWriteOperationSpecification.groovy

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import static com.mongodb.client.model.Filters.gte
6464
import static com.mongodb.connection.ServerType.REPLICA_SET_PRIMARY
6565
import static com.mongodb.connection.ServerType.STANDALONE
6666

67+
@SuppressWarnings('ClassSize')
6768
class MixedBulkWriteOperationSpecification extends OperationFunctionalSpecification {
6869

6970
def 'should throw IllegalArgumentException for empty list of requests'() {
@@ -999,6 +1000,45 @@ class MixedBulkWriteOperationSpecification extends OperationFunctionalSpecificat
9991000
async << [true, false]
10001001
}
10011002

1003+
@IgnoreIf({ !serverVersionAtLeast(3, 6) })
1004+
def 'should not request retryable write for multi updates or deletes'() {
1005+
given:
1006+
def operation = new MixedBulkWriteOperation(getNamespace(),
1007+
writes, true, ACKNOWLEDGED, true)
1008+
1009+
when:
1010+
executeWithSession(operation, async)
1011+
1012+
then:
1013+
noExceptionThrown()
1014+
1015+
where:
1016+
[async, writes] << [
1017+
[true, false],
1018+
// Test scenarios where the multi:true request is at the beginning and at the end of the list
1019+
[
1020+
[
1021+
new DeleteRequest(new BsonDocument()).multi(true),
1022+
new InsertRequest(new BsonDocument())
1023+
],
1024+
[
1025+
new UpdateRequest(new BsonDocument('_id', new BsonInt32(1)),
1026+
new BsonDocument('$set', new BsonDocument('_id', new BsonInt32(1))), UPDATE).multi(true),
1027+
new InsertRequest(new BsonDocument())
1028+
],
1029+
[
1030+
new InsertRequest(new BsonDocument()),
1031+
new DeleteRequest(new BsonDocument()).multi(true)
1032+
],
1033+
[
1034+
new InsertRequest(new BsonDocument()),
1035+
new UpdateRequest(new BsonDocument('_id', new BsonInt32(1)),
1036+
new BsonDocument('$set', new BsonDocument('_id', new BsonInt32(1))), UPDATE).multi(true)
1037+
]
1038+
]
1039+
].combinations()
1040+
}
1041+
10021042
@IgnoreIf({ !serverVersionAtLeast(3, 6) })
10031043
def 'should support array filters'() {
10041044
given:

driver-core/src/test/unit/com/mongodb/operation/BulkWriteBatchSpecification.groovy

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ import com.mongodb.bulk.WriteRequest
2828
import com.mongodb.client.model.Collation
2929
import com.mongodb.connection.ClusterId
3030
import com.mongodb.connection.ConnectionDescription
31+
import com.mongodb.connection.ConnectionId
3132
import com.mongodb.connection.ServerDescription
3233
import com.mongodb.connection.ServerId
34+
import com.mongodb.connection.ServerType
35+
import com.mongodb.connection.ServerVersion
3336
import com.mongodb.internal.connection.NoOpSessionContext
3437
import org.bson.BsonDocument
3538
import org.bson.BsonInt32
@@ -41,8 +44,13 @@ import static com.mongodb.connection.ServerConnectionState.CONNECTED
4144

4245
class BulkWriteBatchSpecification extends Specification {
4346
def namespace = new MongoNamespace('db.coll')
44-
def serverDescription = ServerDescription.builder().address(new ServerAddress()).state(CONNECTED).build()
45-
def connectionDescription = new ConnectionDescription(new ServerId(new ClusterId(), serverDescription.getAddress()))
47+
def serverDescription = ServerDescription.builder().address(new ServerAddress()).state(CONNECTED)
48+
.version(new ServerVersion(3, 6))
49+
.logicalSessionTimeoutMinutes(30)
50+
.build()
51+
def connectionDescription = new ConnectionDescription(
52+
new ConnectionId(new ServerId(new ClusterId(), serverDescription.getAddress())), new ServerVersion(3, 6),
53+
ServerType.REPLICA_SET_PRIMARY, 1000, 16000, 48000, [])
4654
def sessionContext = new NoOpSessionContext()
4755

4856
def 'should split payloads by type when ordered'() {
@@ -221,6 +229,16 @@ class BulkWriteBatchSpecification extends Specification {
221229
!bulkWriteBatch.hasAnotherBatch()
222230
}
223231

232+
def 'should not retry when at least one write is not retryable'() {
233+
when:
234+
def bulkWriteBatch = BulkWriteBatch.createBulkWriteBatch(namespace, serverDescription, connectionDescription, false,
235+
WriteConcern.ACKNOWLEDGED, null, true,
236+
[new DeleteRequest(new BsonDocument()).multi(true), new InsertRequest(new BsonDocument())], sessionContext)
237+
238+
then:
239+
!bulkWriteBatch.getRetryWrites()
240+
}
241+
224242
def 'should handle operation responses'() {
225243
given:
226244
def bulkWriteBatch = BulkWriteBatch.createBulkWriteBatch(namespace, serverDescription, connectionDescription, true,

0 commit comments

Comments
 (0)