Skip to content

Commit 682c2e3

Browse files
committed
Normalize single write handling of Write Concern errors
JAVA-6111
1 parent 81fc5e6 commit 682c2e3

5 files changed

Lines changed: 109 additions & 67 deletions

File tree

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,21 @@ public MongoServerException(final int code, @Nullable final String errorCodeName
7171
this.serverAddress = serverAddress;
7272
}
7373

74+
/**
75+
* Construct a new instance.
76+
*
77+
* @param code the error code from the server
78+
* @param message the message from the server
79+
* @param t the throwable cause
80+
* @param serverAddress the address of the server
81+
* @since 5.7
82+
*/
83+
public MongoServerException(final int code, final String message, final Throwable t, final ServerAddress serverAddress) {
84+
super(code, message, t);
85+
this.errorCodeName = null;
86+
this.serverAddress = serverAddress;
87+
}
88+
7489
/**
7590
* Gets the address of the server.
7691
*

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,24 @@ public MongoWriteConcernException(final WriteConcernError writeConcernError, @Nu
8282
addLabels(errorLabels);
8383
}
8484

85+
/**
86+
* Construct an instance.
87+
*
88+
* @param writeConcernError the non-null write concern error
89+
* @param writeConcernResult the write result
90+
* @param serverAddress the non-null server address
91+
* @param errorLabels the server errorLabels
92+
* @param t the throwable cause
93+
* @since 5.7
94+
*/
95+
public MongoWriteConcernException(final WriteConcernError writeConcernError, @Nullable final WriteConcernResult writeConcernResult,
96+
final ServerAddress serverAddress, final Collection<String> errorLabels, final Throwable t) {
97+
super(writeConcernError.getCode(), writeConcernError.getMessage(), t, serverAddress);
98+
this.writeConcernResult = writeConcernResult;
99+
this.writeConcernError = notNull("writeConcernError", writeConcernError);
100+
addLabels(errorLabels);
101+
}
102+
85103

86104
/**
87105
* Gets the write concern error.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.mongodb.internal.operation;
17+
18+
import com.mongodb.MongoBulkWriteException;
19+
import com.mongodb.MongoException;
20+
import com.mongodb.MongoInternalException;
21+
import com.mongodb.MongoWriteConcernException;
22+
import com.mongodb.MongoWriteException;
23+
import com.mongodb.WriteConcernResult;
24+
import com.mongodb.WriteError;
25+
import com.mongodb.bulk.BulkWriteResult;
26+
import com.mongodb.internal.bulk.WriteRequest;
27+
import org.bson.BsonDocument;
28+
29+
/**
30+
* <p>This class is not part of the public API and may be removed or changed at any time</p>
31+
*/
32+
public class MongoBulkWriteExceptionHelper {
33+
34+
public static MongoException translateSingleOperationBulkWriteResultException(
35+
final WriteRequest.Type type, final MongoBulkWriteException e) {
36+
MongoException exception;
37+
if (e.getWriteConcernError() != null) {
38+
exception = new MongoWriteConcernException(e.getWriteConcernError(),
39+
translateBulkWriteResult(type, e.getWriteResult()), e.getServerAddress(), e.getErrorLabels(), e);
40+
} else if (!e.getWriteErrors().isEmpty()) {
41+
exception = new MongoWriteException(new WriteError(e.getWriteErrors().get(0)), e.getServerAddress(),
42+
e.getErrorLabels());
43+
} else {
44+
exception = new MongoWriteException(new WriteError(-1, "Unknown write error", new BsonDocument()),
45+
e.getServerAddress(), e.getErrorLabels());
46+
}
47+
48+
return exception;
49+
}
50+
51+
private static WriteConcernResult translateBulkWriteResult(final WriteRequest.Type type, final BulkWriteResult writeResult) {
52+
switch (type) {
53+
case INSERT:
54+
return WriteConcernResult.acknowledged(writeResult.getInsertedCount(), false, null);
55+
case DELETE:
56+
return WriteConcernResult.acknowledged(writeResult.getDeletedCount(), false, null);
57+
case UPDATE:
58+
case REPLACE:
59+
return WriteConcernResult.acknowledged(writeResult.getMatchedCount() + writeResult.getUpserts().size(),
60+
writeResult.getMatchedCount() > 0,
61+
writeResult.getUpserts().isEmpty()
62+
? null : writeResult.getUpserts().get(0).getId());
63+
default:
64+
throw new MongoInternalException("Unhandled write request type: " + type);
65+
}
66+
}
67+
68+
69+
private MongoBulkWriteExceptionHelper() {
70+
}
71+
}

driver-reactive-streams/src/main/com/mongodb/reactivestreams/client/internal/MongoOperationPublisher.java

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,11 @@
1818
import com.mongodb.AutoEncryptionSettings;
1919
import com.mongodb.MongoBulkWriteException;
2020
import com.mongodb.MongoClientException;
21-
import com.mongodb.MongoException;
2221
import com.mongodb.MongoNamespace;
23-
import com.mongodb.MongoWriteConcernException;
24-
import com.mongodb.MongoWriteException;
2522
import com.mongodb.ReadConcern;
2623
import com.mongodb.ReadPreference;
2724
import com.mongodb.WriteConcern;
28-
import com.mongodb.WriteConcernResult;
29-
import com.mongodb.WriteError;
3025
import com.mongodb.bulk.BulkWriteResult;
31-
import com.mongodb.bulk.WriteConcernError;
3226
import com.mongodb.client.model.BulkWriteOptions;
3327
import com.mongodb.client.model.CountOptions;
3428
import com.mongodb.client.model.CreateCollectionOptions;
@@ -66,7 +60,6 @@
6660
import com.mongodb.internal.operation.WriteOperation;
6761
import com.mongodb.lang.Nullable;
6862
import com.mongodb.reactivestreams.client.ClientSession;
69-
import org.bson.BsonDocument;
7063
import org.bson.BsonValue;
7164
import org.bson.UuidRepresentation;
7265
import org.bson.codecs.configuration.CodecRegistry;
@@ -86,6 +79,7 @@
8679
import static com.mongodb.assertions.Assertions.assertNotNull;
8780
import static com.mongodb.assertions.Assertions.isTrue;
8881
import static com.mongodb.assertions.Assertions.notNull;
82+
import static com.mongodb.internal.operation.MongoBulkWriteExceptionHelper.translateSingleOperationBulkWriteResultException;
8983
import static java.util.Collections.singletonList;
9084
import static org.bson.codecs.configuration.CodecRegistries.withUuidRepresentation;
9185

@@ -530,34 +524,7 @@ private Mono<BulkWriteResult> createSingleWriteRequestMono(
530524
@Nullable final ClientSession clientSession,
531525
final WriteRequest.Type type) {
532526
return createWriteOperationMono(operations::getTimeoutSettings, operation, clientSession)
533-
.onErrorMap(MongoBulkWriteException.class, e -> {
534-
MongoException exception;
535-
WriteConcernError writeConcernError = e.getWriteConcernError();
536-
if (e.getWriteErrors().isEmpty() && writeConcernError != null) {
537-
WriteConcernResult writeConcernResult;
538-
if (type == WriteRequest.Type.INSERT) {
539-
writeConcernResult = WriteConcernResult.acknowledged(e.getWriteResult().getInsertedCount(), false, null);
540-
} else if (type == WriteRequest.Type.DELETE) {
541-
writeConcernResult = WriteConcernResult.acknowledged(e.getWriteResult().getDeletedCount(), false, null);
542-
} else {
543-
writeConcernResult = WriteConcernResult
544-
.acknowledged(e.getWriteResult().getMatchedCount() + e.getWriteResult().getUpserts().size(),
545-
e.getWriteResult().getMatchedCount() > 0,
546-
e.getWriteResult().getUpserts().isEmpty()
547-
? null : e.getWriteResult().getUpserts().get(0).getId());
548-
}
549-
exception = new MongoWriteConcernException(writeConcernError, writeConcernResult, e.getServerAddress(),
550-
e.getErrorLabels());
551-
} else if (!e.getWriteErrors().isEmpty()) {
552-
exception = new MongoWriteException(new WriteError(e.getWriteErrors().get(0)), e.getServerAddress(),
553-
e.getErrorLabels());
554-
} else {
555-
exception = new MongoWriteException(new WriteError(-1, "Unknown write error", new BsonDocument()),
556-
e.getServerAddress(), e.getErrorLabels());
557-
}
558-
559-
return exception;
560-
});
527+
.onErrorMap(MongoBulkWriteException.class, e -> translateSingleOperationBulkWriteResultException(type, e));
561528
}
562529

563530
private OperationExecutor getExecutor(final TimeoutSettings timeoutSettings) {

driver-sync/src/main/com/mongodb/client/internal/MongoCollectionImpl.java

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,10 @@
1818

1919
import com.mongodb.AutoEncryptionSettings;
2020
import com.mongodb.MongoBulkWriteException;
21-
import com.mongodb.MongoInternalException;
2221
import com.mongodb.MongoNamespace;
23-
import com.mongodb.MongoWriteConcernException;
24-
import com.mongodb.MongoWriteException;
2522
import com.mongodb.ReadConcern;
2623
import com.mongodb.ReadPreference;
2724
import com.mongodb.WriteConcern;
28-
import com.mongodb.WriteConcernResult;
29-
import com.mongodb.WriteError;
3025
import com.mongodb.bulk.BulkWriteResult;
3126
import com.mongodb.client.AggregateIterable;
3227
import com.mongodb.client.ChangeStreamIterable;
@@ -85,6 +80,7 @@
8580
import static com.mongodb.internal.bulk.WriteRequest.Type.INSERT;
8681
import static com.mongodb.internal.bulk.WriteRequest.Type.REPLACE;
8782
import static com.mongodb.internal.bulk.WriteRequest.Type.UPDATE;
83+
import static com.mongodb.internal.operation.MongoBulkWriteExceptionHelper.translateSingleOperationBulkWriteResultException;
8884
import static java.util.Collections.singletonList;
8985
import static java.util.concurrent.TimeUnit.MILLISECONDS;
9086
import static org.bson.codecs.configuration.CodecRegistries.withUuidRepresentation;
@@ -1113,34 +1109,9 @@ private BulkWriteResult executeSingleWriteRequest(@Nullable final ClientSession
11131109
final WriteOperation<BulkWriteResult> writeOperation,
11141110
final WriteRequest.Type type) {
11151111
try {
1116-
return getExecutor(timeoutSettings)
1117-
.execute(writeOperation, readConcern, clientSession);
1112+
return getExecutor(timeoutSettings).execute(writeOperation, readConcern, clientSession);
11181113
} catch (MongoBulkWriteException e) {
1119-
if (e.getWriteErrors().isEmpty()) {
1120-
throw new MongoWriteConcernException(e.getWriteConcernError(),
1121-
translateBulkWriteResult(type, e.getWriteResult()),
1122-
e.getServerAddress(), e.getErrorLabels());
1123-
} else {
1124-
throw new MongoWriteException(new WriteError(e.getWriteErrors().get(0)), e.getServerAddress(), e.getErrorLabels());
1125-
}
1126-
1127-
}
1128-
}
1129-
1130-
private WriteConcernResult translateBulkWriteResult(final WriteRequest.Type type, final BulkWriteResult writeResult) {
1131-
switch (type) {
1132-
case INSERT:
1133-
return WriteConcernResult.acknowledged(writeResult.getInsertedCount(), false, null);
1134-
case DELETE:
1135-
return WriteConcernResult.acknowledged(writeResult.getDeletedCount(), false, null);
1136-
case UPDATE:
1137-
case REPLACE:
1138-
return WriteConcernResult.acknowledged(writeResult.getMatchedCount() + writeResult.getUpserts().size(),
1139-
writeResult.getMatchedCount() > 0,
1140-
writeResult.getUpserts().isEmpty()
1141-
? null : writeResult.getUpserts().get(0).getId());
1142-
default:
1143-
throw new MongoInternalException("Unhandled write request type: " + type);
1114+
throw translateSingleOperationBulkWriteResultException(type, e);
11441115
}
11451116
}
11461117

0 commit comments

Comments
 (0)