Skip to content

Remove RTT check before reading a response from the server. #1391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,6 @@ public <T> T sendAndReceive(final CommandMessage message, final Decoder<T> decod
CommandEventSender commandEventSender;

try (ByteBufferBsonOutput bsonOutput = new ByteBufferBsonOutput(this)) {
Timeout.onExistsAndExpired(operationContext.getTimeoutContext().timeoutIncludingRoundTrip(), () -> {
Copy link
Member Author

@vbabanin vbabanin May 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the specification:

After wire message construction, drivers MUST check for timeout before writing the message to the server.

I have removed this check from its previous position as it was occurring before the wire message was constructed, not after, which is contrary to the spec. We still perform this necessary timeout check later in the code within the trySendMessage method, just before writing the message to the socket.

throw TimeoutContext.createMongoRoundTripTimeoutException();
});
message.encode(bsonOutput, operationContext);
commandEventSender = createCommandEventSender(message, bsonOutput, operationContext);
commandEventSender.sendStartedEvent();
Expand Down Expand Up @@ -432,10 +429,6 @@ private void trySendMessage(final CommandMessage message, final ByteBufferBsonOu

private <T> T receiveCommandMessageResponse(final Decoder<T> decoder, final CommandEventSender commandEventSender,
final OperationContext operationContext) {
Timeout.onExistsAndExpired(operationContext.getTimeoutContext().timeoutIncludingRoundTrip(), () -> {
throw createMongoOperationTimeoutExceptionAndClose(commandEventSender);
});

boolean commandSuccessful = false;
try (ResponseBuffers responseBuffers = receiveResponseBuffers(operationContext)) {
updateSessionContext(operationContext.getSessionContext(), responseBuffers);
Expand Down Expand Up @@ -509,6 +502,16 @@ private <T> void sendCommandMessageAsync(final int messageId, final Decoder<T> d
final SingleResultCallback<T> callback, final ByteBufferBsonOutput bsonOutput,
final CommandEventSender commandEventSender, final boolean responseExpected) {
List<ByteBuf> byteBuffers = bsonOutput.getByteBuffers();

boolean[] shouldReturn = {false};
Copy link
Member Author

@vbabanin vbabanin May 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved this check from "after the write is complete" to "before a message is send."

According to the CSOT spec:

After wire message construction, drivers MUST check for timeout before writing the message to the server.

Timeout.onExistsAndExpired(operationContext.getTimeoutContext().timeoutIncludingRoundTrip(), () -> {
callback.onResult(null, createMongoOperationTimeoutExceptionAndClose(commandEventSender));
shouldReturn[0] = true;
});
if (shouldReturn[0]) {
return;
}

sendMessageAsync(byteBuffers, messageId, operationContext, (result, t) -> {
ResourceUtil.release(byteBuffers);
bsonOutput.close();
Expand All @@ -519,15 +522,6 @@ private <T> void sendCommandMessageAsync(final int messageId, final Decoder<T> d
commandEventSender.sendSucceededEventForOneWayCommand();
callback.onResult(null, null);
} else {
boolean[] shouldReturn = {false};
Timeout.onExistsAndExpired(operationContext.getTimeoutContext().timeoutIncludingRoundTrip(), () -> {
callback.onResult(null, createMongoOperationTimeoutExceptionAndClose(commandEventSender));
shouldReturn[0] = true;
});
if (shouldReturn[0]) {
return;
}

readAsync(MESSAGE_HEADER_LENGTH, operationContext, new MessageHeaderCallback(operationContext, (responseBuffers, t1) -> {
if (t1 != null) {
commandEventSender.sendFailedEvent(t1);
Expand Down