-
Notifications
You must be signed in to change notification settings - Fork 1.5k
ClientMetaData refactoring #1807
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
Conversation
Avoid appending duplicate metadata JAVA-5955
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR refactors the ClientMetadata implementation to avoid appending duplicate metadata to the MongoDB driver information. The changes introduce a new internal DriverInformation class and modify the metadata handling to check for duplicates before appending, addressing issue JAVA-5955.
Key changes:
- Introduces new internal classes
DriverInformationandDriverInformationHelperfor managing driver information - Updates
ClientMetadatato use a list-based approach with duplicate checking - Refactors tests to use the new infrastructure and adds comprehensive test coverage for duplicate metadata scenarios
Reviewed Changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| AbstractClientMetadataProseTest.java | Extensively refactored test methods to use new DriverInformation class and added multiple new test cases for duplicate metadata scenarios |
| MongoDriverInformationSpec.scala | Updated exclusions list to include new synthetic method |
| MongoDriverInformationSpecification.groovy | Updated test comments to reflect "append" vs "prepend" behavior |
| ClientMetadataTest.java | Modified test expectations to align with new metadata building approach |
| ClientMetadata.java | Core refactoring to use DriverInformation list with duplicate checking |
| package-info.java | Added package documentation for internal client classes |
| DriverInformationHelper.java | New utility class for extracting driver information fields |
| DriverInformation.java | New data class representing driver information with proper equals/hashCode |
| Internal.java | New annotation for marking internal APIs |
| MongoDriverInformation.java | Refactored to use DriverInformation internally while maintaining public API |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
driver-core/src/main/com/mongodb/internal/client/package-info.java
Outdated
Show resolved
Hide resolved
…java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| ElementType.TYPE }) | ||
| @Documented | ||
| @Alpha(Reason.CLIENT) | ||
| public @interface Internal { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had to add an internal method MongoDriverInformation#getDriverInformationList to get the list of DriverInformation and added this annotation as a way to highlight things for internal use only.
If this ok, then I'll add a ticket to annotation each of the internal packages in their package-info.java
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have VisibleForTesting should we try to unify all these in a similar fashion to ApiStatus
(already supported in IntelliJ ~)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didnt want to misuse that as it's not for testing. It's needed for the ClientMetaData API as well. This all stems from MongoDriverInformation being lossy, I need the combined information of name, version and platform.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have other places where methods are exposed in the public API but intended for internal use. For example:
Lines 37 to 55 in 5e4e96a
| /** | |
| * Notify the client session that a message has been sent. | |
| * <p> | |
| * For internal use only | |
| * </p> | |
| * | |
| * @return true if this is the first message sent, false otherwise | |
| * @since 4.0 | |
| */ | |
| boolean notifyMessageSent(); | |
| /** | |
| * Notify the client session that command execution is being initiated. This should be called before server selection occurs. | |
| * <p> | |
| * For internal use only | |
| * </p> | |
| * @param operation the operation | |
| */ | |
| void notifyOperationInitiated(Object operation); |
Since we’ve introduced a new annotation here, should we make it consistent with those cases by adding the annotation there as well? We could do this in a separate ticket.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added JAVA-5975
|
|
||
| import java.util.Objects; | ||
|
|
||
| public final class DriverInformation { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes required by the spec ensure that driver information as a whole can be checked for equality - so that duplicates aren't appended.
| driverInformationList.add(driverInformation); | ||
| } | ||
| } | ||
| if (hasAddedNewData) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only recalculate the clientMetadataBsonDocument if there has been a real change.
| tryWithLimit(client, d -> { | ||
| putAtPath(d, "driver.name", driverInformation.getInitialDriverName()); | ||
| putAtPath(d, "driver.version", driverInformation.getInitialDriverVersion()); | ||
| tryWithLimit(clientMetadata, d -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We add the initial driver information - if there is room. Then later we add the full driver information (eg the extended libraries that use the driver) if there is room.
This behavior is defined by the spec.
| * @mongodb.server.release 3.4 | ||
| */ | ||
| public final class MongoDriverInformation { | ||
| private final List<String> driverNames; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using lists of Strings, no longer works for the new test cases - as it meant we couldn't check for duplicates effectively.
| } | ||
|
|
||
| def 'should not prepend data if none has been added'() { | ||
| def 'should not append data if none has been added'() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We never prepended the data - so these tests needed some tweaking to make sense.
| options.getDriverPlatforms() == ['Java oracle64-1.8.0.31'] | ||
| } | ||
|
|
||
| def 'should error if trying to set a version without setting a name'() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a specific new test from the spec that actually tests we can do this. So removed the check and this test.
| } | ||
|
|
||
| @ParameterizedTest | ||
| @DisplayName("Test 1: Test that the driver updates metadata") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new prose tests. I renamed the existing ones to make it easier for future changes / adding new tests.
driver-core/src/main/com/mongodb/internal/connection/ClientMetadata.java
Show resolved
Hide resolved
driver-sync/src/test/functional/com/mongodb/client/AbstractClientMetadataProseTest.java
Show resolved
Hide resolved
| ElementType.TYPE }) | ||
| @Documented | ||
| @Alpha(Reason.CLIENT) | ||
| public @interface Internal { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have VisibleForTesting should we try to unify all these in a similar fashion to ApiStatus
(already supported in IntelliJ ~)
|
I used I think there is a ticket to move away from our own null annotations, to a more standardized one. Perhaps we should also look to adopt |
driver-core/src/main/com/mongodb/internal/client/DriverInformationHelper.java
Outdated
Show resolved
Hide resolved
…tionHelper.java Co-authored-by: Viacheslav Babanin <frest0512@gmail.com>
nhachicha
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it's outside the scope of this PR, we can create a ticket to consider folding the @Internal annotation underAPIStatus 👍
| ElementType.TYPE }) | ||
| @Documented | ||
| @Alpha(Reason.CLIENT) | ||
| public @interface Internal { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have other places where methods are exposed in the public API but intended for internal use. For example:
Lines 37 to 55 in 5e4e96a
| /** | |
| * Notify the client session that a message has been sent. | |
| * <p> | |
| * For internal use only | |
| * </p> | |
| * | |
| * @return true if this is the first message sent, false otherwise | |
| * @since 4.0 | |
| */ | |
| boolean notifyMessageSent(); | |
| /** | |
| * Notify the client session that command execution is being initiated. This should be called before server selection occurs. | |
| * <p> | |
| * For internal use only | |
| * </p> | |
| * @param operation the operation | |
| */ | |
| void notifyOperationInitiated(Object operation); |
Since we’ve introduced a new annotation here, should we make it consistent with those cases by adding the annotation there as well? We could do this in a separate ticket.
Avoid appending duplicate metadata Added new @internal annotation for non public / public apis JAVA-5955 --------- Co-authored-by: Viacheslav Babanin <frest0512@gmail.com>
Avoid appending duplicate metadata
JAVA-5955