-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Dedicatedgateway shardkey request option #47796
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
base: main
Are you sure you want to change the base?
Conversation
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 pull request adds support for the sharding feature in the Dedicated Gateway by introducing a new shardKey field to DedicatedGatewayRequestOptions. This optional field allows customers to specify a shard key to route requests to instances with cached data for that shard, or bypass the SQLx cache if the correlated instance is down. Without a shard key, the request falls back to random instance selection.
Changes:
- Added a
shardKeystring field toDedicatedGatewayRequestOptionswith validation for alphanumeric characters and hyphens - Added the HTTP header constant
DEDICATED_GATEWAY_PER_REQUEST_SHARD_KEYfor propagating the shard key to the service - Updated request header logic in
DocumentQueryExecutionContextBaseandRxDocumentClientImplto include the shard key header when specified - Added integration tests to verify the shard key header is correctly propagated for both query and read item operations
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/DedicatedGatewayRequestOptions.java | Added shardKey field with getter/setter and validation logic for character set constraints |
| sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/HttpConstants.java | Added new HTTP header constant for dedicated gateway shard key |
| sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/query/DocumentQueryExecutionContextBase.java | Updated query request header creation to include shard key when present |
| sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java | Updated request header creation to include shard key when present |
| sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/RequestHeadersSpyWireTest.java | Added tests for shard key header propagation and updated validation method to support both query and read item operations |
| requestHeaders.put(HttpConstants.HttpHeaders.DEDICATED_GATEWAY_PER_REQUEST_BYPASS_CACHE, | ||
| String.valueOf(cosmosQueryRequestOptions.getDedicatedGatewayRequestOptions().isIntegratedCacheBypassed())); | ||
| } | ||
| if(cosmosQueryRequestOptions.getDedicatedGatewayRequestOptions().getShardKey() != null) { |
Copilot
AI
Jan 23, 2026
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.
Missing space after the 'if' keyword. The codebase consistently uses 'if (' with a space (e.g., lines 276, 280 in this file, and lines 2014, 2018 in RxDocumentClientImpl.java). This should be 'if (' instead of 'if('.
| if(cosmosQueryRequestOptions.getDedicatedGatewayRequestOptions().getShardKey() != null) { | |
| if (cosmosQueryRequestOptions.getDedicatedGatewayRequestOptions().getShardKey() != null) { |
| headers.put(HttpConstants.HttpHeaders.DEDICATED_GATEWAY_PER_REQUEST_BYPASS_CACHE, | ||
| String.valueOf(options.getDedicatedGatewayRequestOptions().isIntegratedCacheBypassed())); | ||
| } | ||
| if(options.getDedicatedGatewayRequestOptions().getShardKey() != null) { |
Copilot
AI
Jan 23, 2026
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.
Missing space after the 'if' keyword. The codebase consistently uses 'if (' with a space (e.g., lines 2014, 2018 in this file, and lines 276, 280 in DocumentQueryExecutionContextBase.java). This should be 'if (' instead of 'if('.
| if(options.getDedicatedGatewayRequestOptions().getShardKey() != null) { | |
| if (options.getDedicatedGatewayRequestOptions().getShardKey() != null) { |
| DedicatedGatewayRequestOptions options) { | ||
| Map<String, String> headers = httpRequest.headers().toMap(); | ||
| if (headers.get(HttpConstants.HttpHeaders.IS_QUERY) != null) { | ||
| if (headers.get(HttpConstants.HttpHeaders.IS_QUERY) != null || headers.get(HttpConstants.HttpHeaders.CONSISTENCY_LEVEL) != null) { |
Copilot
AI
Jan 23, 2026
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 are two spaces between CONSISTENCY_LEVEL and the comparison operator. This should be a single space for consistency with the rest of the codebase.
| if (headers.get(HttpConstants.HttpHeaders.IS_QUERY) != null || headers.get(HttpConstants.HttpHeaders.CONSISTENCY_LEVEL) != null) { | |
| if (headers.get(HttpConstants.HttpHeaders.IS_QUERY) != null || headers.get(HttpConstants.HttpHeaders.CONSISTENCY_LEVEL) != null) { |
| @Test(groups = { "fast" }, timeOut = TIMEOUT) | ||
| public void readItemWithDedicatedGatewayShardKeyHeader() { | ||
| DedicatedGatewayRequestOptions dedicatedOptions = new DedicatedGatewayRequestOptions(); | ||
| dedicatedOptions.setMaxIntegratedCacheStaleness(Duration.ofMinutes(1)); | ||
| dedicatedOptions.setIntegratedCacheBypassed(true); | ||
| dedicatedOptions.setShardKey("shard-456"); | ||
| CosmosItemRequestOptions cosmosItemRequestOptions = new CosmosItemRequestOptions(); | ||
| cosmosItemRequestOptions.setDedicatedGatewayRequestOptions(dedicatedOptions); | ||
| cosmosItemRequestOptions.setCustomItemSerializer(CosmosItemSerializer.DEFAULT_SERIALIZER); | ||
| String documentLink = getDocumentLink(); | ||
| client.clearCapturedRequests(); | ||
| RequestOptions requestOptions = itemOptionsAccessor.toRequestOptions(cosmosItemRequestOptions); | ||
| requestOptions.setPartitionKey(new PartitionKey(DOCUMENT_ID)); | ||
| client.readDocument(documentLink, requestOptions).block(); | ||
| List<HttpRequest> requests = client.getCapturedRequests(); | ||
| for (HttpRequest httpRequest : requests) { | ||
| validateRequestHasDedicatedGatewayHeaders(httpRequest, cosmosItemRequestOptions.getDedicatedGatewayRequestOptions()); | ||
| } | ||
| } |
Copilot
AI
Jan 23, 2026
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.
Test coverage is needed for the validation logic in setShardKey. Consider adding tests for edge cases such as: null or empty string (should throw IllegalArgumentException), invalid characters (e.g., special characters, spaces), and maximum length validation (if the 36 character/72 byte limit mentioned in the PR description is implemented). This follows the pattern seen in the existing test file where validation tests exist for other fields (e.g., readItemWithMaxIntegratedCacheStalenessInNegative).
| import java.time.Duration; | ||
|
|
||
| import static com.azure.cosmos.implementation.guava25.base.Preconditions.checkArgument; | ||
| import static com.azure.cosmos.implementation.guava25.base.Preconditions.checkNotNull; |
Copilot
AI
Jan 23, 2026
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 import checkNotNull is not used anywhere in this file. Consider removing this unused import to keep the code clean.
| import static com.azure.cosmos.implementation.guava25.base.Preconditions.checkNotNull; |
| public DedicatedGatewayRequestOptions setShardKey(String shardKey) { | ||
| checkArgument(StringUtils.isNotEmpty(shardKey), "shardKey must not be null or empty"); | ||
| checkArgument(validateShardKey(shardKey), "shardKey contains invalid characters. Only alphanumeric and hyphen (-) are allowed."); | ||
| this.shardKey = shardKey; | ||
| return this; |
Copilot
AI
Jan 23, 2026
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 PR description mentions a size validation requirement: "Max Size = 72 bytes (size of GUID) or 36 characters (length of GUID)". However, the implementation only validates the character set but does not enforce the maximum length constraint. Consider adding a length check to ensure the shardKey does not exceed 36 characters or 72 bytes.
| return this; | ||
| } | ||
|
|
||
| private boolean validateShardKey(String shardKey){ |
Copilot
AI
Jan 23, 2026
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.
Missing space after the 'if' keyword. The codebase consistently uses 'if (' with a space, as seen throughout the file and in similar code (e.g., lines 276, 280 in DocumentQueryExecutionContextBase.java, and lines 2014, 2018 in RxDocumentClientImpl.java). This should be 'if (' instead of 'if('.
| private boolean validateShardKey(String shardKey){ | |
| private boolean validateShardKey(String shardKey) { |
| /** | ||
| * Gets the shard key value associated with the request in the Azure CosmosDB service to optionally specify a shard key | ||
| * to use the new sharding feature in dedicated gateway. | ||
| * | ||
| * @return shard key value | ||
| */ | ||
| public String getShardKey() { | ||
| return shardKey; | ||
| } | ||
|
|
||
| /** | ||
| * Sets the shard key value associated with the request in the Azure CosmosDB service to optionally specify a shard key | ||
| * to use the new sharding feature in dedicated gateway. | ||
| * | ||
| * @param shardKey shard key value | ||
| * @return this DedicatedGatewayRequestOptions | ||
| */ |
Copilot
AI
Jan 23, 2026
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 JavaDoc for the getter and setter methods should include a default value section, consistent with the pattern used for other methods in this class. For example, getMaxIntegratedCacheStaleness() and setMaxIntegratedCacheStaleness() both include "<p>Default value is null</p>". The shardKey field should follow the same pattern.
API Change CheckAPIView identified API level changes in this PR and created the following API reviews |
Introduction
To support sharding for SQLx, Dedicatedgateway team introduced a new request option called “ShardKey”. This should be enabled in the existing “DedicatedGatewayRequestOptions”. This will allow the customer to optionally specify a shard key to use the new sharding feature.
Specifying the shard key will help route the request to an instance that has cached data for this shard or bypass the SQLx cache if correlated instance is down. If the shard key is not specified, it will fall back to the default behavior, which is randomly selecting an instance to serve the request.
Changes
Added string field shardKey to DedicatedGatewayRequestOptions
validation:
Max Size = 72 bytes (size of GUID) or 36 characters (length of GUID)
Character Set Limitations: accepts alphanumeric and hyphen(-) charaters
This field will be passed as the header “x-ms-dedicatedgateway-shard-key” to the service.
Testing
Note:
HTTP2 is required for the sharding feature. If HTTP1 and shard key are both set, shard key will be ignored.
Please add an informative description that covers that changes made by the pull request and link all relevant issues.
If an SDK is being regenerated based on a new swagger spec, a link to the pull request containing these swagger spec changes has been included above.
All SDK Contribution checklist:
General Guidelines and Best Practices
Testing Guidelines