Skip to content
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

Centralize appending of maxTimeMS #1333

Merged
merged 19 commits into from
Mar 26, 2024
Merged

Centralize appending of maxTimeMS #1333

merged 19 commits into from
Mar 26, 2024

Conversation

vbabanin
Copy link
Member

@vbabanin vbabanin commented Mar 12, 2024

Description:

This PR tackles the challenge identified in JAVA-4055 related to the handling of maxTimeMS in the context of Client-Side Field Level Encryption (CSFLE) by moving appending of maxTimeMS to a centralized and lower level within the driver, specifically to the CommandMessage.

Implementation details

Operations handle maxTimeMS differently:

  • A majority append maxTimeMS when it is non-zero.
  • Some read operations check if cursor is tailable or non-tailable.
  • Tailable await cursors append maxAwaitTimeMS as maxTimeMS to a command.

Therefore, this PR introduces MaxTimeMsSupplier in TimeoutContext. This ensures CommandMessage remains agnostic to the operation's logic, allowing operations to dictate it.

JAVA-5322
JAVA-5327

@@ -319,4 +324,15 @@ public Timeout getTimeout() {
return timeout;
}

public void addExtraElements(final List<BsonElement> extraElements) {
long maxTimeMS = maxTimeSupplier.get();
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Long maxTimeMS

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

# Conflicts:
#	driver-core/src/main/com/mongodb/internal/operation/OperationHelper.java
} else if (timeoutMS == 0) {
return timeoutMS;
} else {
return timeoutRemainingMS();
}
Copy link
Member Author

@vbabanin vbabanin Mar 16, 2024

Choose a reason for hiding this comment

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

else if (timeoutMS == 0) is removed due to an issue where using an original infinite timeout (timeoutMS = 0) incorrectly led to always returning 0 from TimeoutSettings in timeoutOrAlternative, regardless of actual computedServerSelectionTimeout time left.

timeoutRemainingMS() handles both infinite and finite timeouts, checking against the timeout object itself:

For the reference:

  private long timeoutRemainingMS() {
        assertNotNull(timeout);
        if (timeout.hasExpired()) {
            throw createMongoTimeoutException("The operation timeout has expired.");
        }
        return timeout.isInfinite() ? 0 : timeout.remaining(MILLISECONDS);
    }

Copy link
Member

Choose a reason for hiding this comment

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

Note: I added timeoutRemainingMS for review in JAVA-5351 as it can incorrectly return 0. (Nothing to fix in this ticket).

List<BsonElement> extraElements = new ArrayList<>();
if (!getSettings().isCryptd()) {
Copy link
Member Author

Choose a reason for hiding this comment

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

From the spec:

When sending a command to mongocryptd, drivers MUST NOT append a maxTimeMS field. This is to ensure that a maxTimeMS field can be safely appended to the command after it has been marked by mongocryptd and encrypted by libmongocrypt. To determine whether or not the server is a mongocryptd, drivers MUST check that the iscryptd field in the server's description is true.

Rationale: https://github.com/mongodb/specifications/blob/master/source/client-side-operations-timeout/client-side-operations-timeout.md#maxtimems-is-not-added-for-mongocryptd

@vbabanin vbabanin marked this pull request as ready for review March 16, 2024 02:53
Copy link
Member

@rozza rozza left a comment

Choose a reason for hiding this comment

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

Its looking good and is much cleaner than I initially thought it would be.

Found a couple of nits but I also recommend a couple of minor changes to the API:

A):

Have TimeoutContext.getMaxTimeMS() be the thing that consumes the supplier eg:

    public Long getMaxTimeMS() {
       return notNull("Should never be null", maxTimeoutSupplier.get());
    }

Convert the current getMaxTimeMS to be protected and used internally eg: rename it to defaultMaxTimeMS.

Add a timeoutContext.resetSupplier() that resets the supplier to the default. Rather than doing: timeoutContext.setMaxTimeSupplier(timeoutContext::getMaxTimeMS);

B):

Remove TimeoutContext#addTimeoutElements put the logic in command message.

C):

I think CommandOperationHelper#appendMaxTimeMs can now be removed.

What do you think?

} else if (timeoutMS == 0) {
return timeoutMS;
} else {
return timeoutRemainingMS();
}
Copy link
Member

Choose a reason for hiding this comment

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

Note: I added timeoutRemainingMS for review in JAVA-5351 as it can incorrectly return 0. (Nothing to fix in this ticket).

- Introduce reset method for MaxTimeMsSupplier.

JAVA-5322
@vbabanin
Copy link
Member Author

vbabanin commented Mar 20, 2024

Its looking good and is much cleaner than I initially thought it would be.

Found a couple of nits but I also recommend a couple of minor changes to the API:

A):

Have TimeoutContext.getMaxTimeMS() be the thing that consumes the supplier eg:

    public Long getMaxTimeMS() {
       return notNull("Should never be null", maxTimeoutSupplier.get());
    }

Convert the current getMaxTimeMS to be protected and used internally eg: rename it to defaultMaxTimeMS.

Add a timeoutContext.resetSupplier() that resets the supplier to the default. Rather than doing: timeoutContext.setMaxTimeSupplier(timeoutContext::getMaxTimeMS);

B):

Remove TimeoutContext#addTimeoutElements put the logic in command message.

C):

I think CommandOperationHelper#appendMaxTimeMs can now be removed.

What do you think?

Thank you for the suggestions @rozza!

A) Agreed. This change will maintain consistency in the TimeoutContext API with other methods. Implemented.

B) Implemented as suggested.

C) Agreed and removed.

@vbabanin vbabanin requested a review from rozza March 20, 2024 04:59
@rozza
Copy link
Member

rozza commented Mar 20, 2024

@vbabanin I think one of the mocks needs updating as its causing all the tests to fail.

JAVA-5322
# Conflicts:
#	driver-core/src/main/com/mongodb/internal/TimeoutContext.java
#	driver-core/src/test/unit/com/mongodb/internal/TimeoutContextTest.java
vbabanin and others added 5 commits March 22, 2024 13:52
…est.java

Co-authored-by: Valentin Kovalenko <valentin.male.kovalenko@gmail.com>
…andMessageTest.java

Co-authored-by: Valentin Kovalenko <valentin.male.kovalenko@gmail.com>
…andMessageTest.java

Co-authored-by: Valentin Kovalenko <valentin.male.kovalenko@gmail.com>
JAVA-5322
@vbabanin vbabanin requested a review from stIncMale March 22, 2024 22:13
@vbabanin vbabanin self-assigned this Mar 22, 2024
@stIncMale stIncMale mentioned this pull request Mar 24, 2024
@rozza rozza merged commit b89ce8e into mongodb:CSOT Mar 26, 2024
50 of 58 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants