From 182d16bc77606adaafdf965d2165ed470f25d8e5 Mon Sep 17 00:00:00 2001 From: Abhijeet Mohanty Date: Mon, 8 Jun 2026 16:22:41 -0400 Subject: [PATCH 1/5] Allow overriding HTTP/2 maxFrameSize via system property / env var Adds COSMOS.HTTP2_MAX_FRAME_SIZE_IN_KB system property and COSMOS_HTTP2_MAX_FRAME_SIZE_IN_KB environment variable to override the HTTP/2 SETTINGS_MAX_FRAME_SIZE advertised by ReactorNettyClient. Value is expressed in KB and clamped to [64 KB, 16 MB]; unparseable values fall back to the 64 KB default. Adds unit tests for default, valid override, lower/upper clamp, and unparseable fallback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../cosmos/implementation/ConfigsTests.java | 61 +++++++++++++++++++ .../azure/cosmos/implementation/Configs.java | 58 ++++++++++++++++++ .../http/ReactorNettyClient.java | 2 +- 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConfigsTests.java b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConfigsTests.java index a04a474faccf..3eff4318c6c4 100644 --- a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConfigsTests.java +++ b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConfigsTests.java @@ -169,6 +169,67 @@ public void http2MaxConcurrentStreams() { } } + @Test(groups = { "unit" }) + public void http2MaxFrameSizeInBytes() { + final String propName = "COSMOS.HTTP2_MAX_FRAME_SIZE_IN_KB"; + final int defaultBytes = 64 * 1024; + final int minBytes = 64 * 1024; + final int maxBytes = 16 * 1024 * 1024; + + System.clearProperty(propName); + + // Default (64 KB) + assertThat(Configs.getHttp2MaxFrameSizeInBytes()).isEqualTo(defaultBytes); + + // Valid value at lower bound + System.setProperty(propName, "64"); + try { + assertThat(Configs.getHttp2MaxFrameSizeInBytes()).isEqualTo(minBytes); + } finally { + System.clearProperty(propName); + } + + // Valid value at upper bound (16 MB) + System.setProperty(propName, String.valueOf(16 * 1024)); + try { + assertThat(Configs.getHttp2MaxFrameSizeInBytes()).isEqualTo(maxBytes); + } finally { + System.clearProperty(propName); + } + + // Valid value within range (1 MB) + System.setProperty(propName, "1024"); + try { + assertThat(Configs.getHttp2MaxFrameSizeInBytes()).isEqualTo(1024 * 1024); + } finally { + System.clearProperty(propName); + } + + // Below lower bound -> clamped up to 64 KB + System.setProperty(propName, "32"); + try { + assertThat(Configs.getHttp2MaxFrameSizeInBytes()).isEqualTo(minBytes); + } finally { + System.clearProperty(propName); + } + + // Above upper bound -> clamped down to 16 MB + System.setProperty(propName, String.valueOf(32 * 1024)); + try { + assertThat(Configs.getHttp2MaxFrameSizeInBytes()).isEqualTo(maxBytes); + } finally { + System.clearProperty(propName); + } + + // Unparseable -> falls back to default + System.setProperty(propName, "not-a-number"); + try { + assertThat(Configs.getHttp2MaxFrameSizeInBytes()).isEqualTo(defaultBytes); + } finally { + System.clearProperty(propName); + } + } + @Test(groups = { "emulator" }) public void thinClientEnabledTest() { assertThat(isThinClientEnabled()).isFalse(); diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java index 18eef0544e18..c9730e4629bf 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java @@ -396,6 +396,16 @@ public class Configs { private static final String HTTP2_MAX_CONCURRENT_STREAMS = "COSMOS.HTTP2_MAX_CONCURRENT_STREAMS"; private static final String HTTP2_MAX_CONCURRENT_STREAMS_VARIABLE = "COSMOS_HTTP2_MAX_CONCURRENT_STREAMS"; + // Config to indicate the SETTINGS_MAX_FRAME_SIZE advertised by the HTTP/2 client to the remote peer. + // The value is expressed in kilobytes (KB) and is clamped to [64 KB, 16 MB] — the lower bound matches + // the SDK's historical default so users can only grow the frame size, and the upper bound is the + // hard maximum permitted by the HTTP/2 spec (RFC 7540: 2^24 - 1 bytes, rounded down to 16 MB). + private static final int MIN_HTTP2_MAX_FRAME_SIZE_IN_KB = 64; // 64 KB + private static final int MAX_HTTP2_MAX_FRAME_SIZE_IN_KB = 16 * 1024; // 16 MB + private static final int DEFAULT_HTTP2_MAX_FRAME_SIZE_IN_KB = 64; // 64 KB + private static final String HTTP2_MAX_FRAME_SIZE_IN_KB = "COSMOS.HTTP2_MAX_FRAME_SIZE_IN_KB"; + private static final String HTTP2_MAX_FRAME_SIZE_IN_KB_VARIABLE = "COSMOS_HTTP2_MAX_FRAME_SIZE_IN_KB"; + private static final boolean DEFAULT_IS_NON_PARSEABLE_DOCUMENT_LOGGING_ENABLED = false; private static final String IS_NON_PARSEABLE_DOCUMENT_LOGGING_ENABLED = "COSMOS.IS_NON_PARSEABLE_DOCUMENT_LOGGING_ENABLED"; private static final String IS_NON_PARSEABLE_DOCUMENT_LOGGING_ENABLED_VARIABLE = "COSMOS_IS_NON_PARSEABLE_DOCUMENT_LOGGING_ENABLED"; @@ -1390,6 +1400,54 @@ public static int getHttp2MaxConcurrentStreams() { return Integer.parseInt(http2MaxConcurrentStreams); } + /** + * Returns the HTTP/2 SETTINGS_MAX_FRAME_SIZE to advertise to the remote peer, in bytes. + * + * The customer-facing configuration is expressed in kilobytes (KB) via system property + * {@code COSMOS.HTTP2_MAX_FRAME_SIZE_IN_KB} or environment variable + * {@code COSMOS_HTTP2_MAX_FRAME_SIZE_IN_KB}. Resolution order is system property, then environment + * variable, then the SDK default of 64 KB. The configured value is clamped to the inclusive range + * [64 KB, 16 MB]; an unparseable or out-of-range value falls back to the default (or is clamped) + * and a warning is logged. The returned value is converted to bytes for downstream Netty + * consumption. + */ + public static int getHttp2MaxFrameSizeInBytes() { + String configuredValue = System.getProperty( + HTTP2_MAX_FRAME_SIZE_IN_KB, + firstNonNull( + emptyToNull(System.getenv().get(HTTP2_MAX_FRAME_SIZE_IN_KB_VARIABLE)), + String.valueOf(DEFAULT_HTTP2_MAX_FRAME_SIZE_IN_KB))); + + int parsedInKb; + try { + parsedInKb = Integer.parseInt(configuredValue); + } catch (NumberFormatException ex) { + logger.warn( + "Invalid value '{}' for {} / {}; falling back to default {} KB.", + configuredValue, + HTTP2_MAX_FRAME_SIZE_IN_KB, + HTTP2_MAX_FRAME_SIZE_IN_KB_VARIABLE, + DEFAULT_HTTP2_MAX_FRAME_SIZE_IN_KB); + return DEFAULT_HTTP2_MAX_FRAME_SIZE_IN_KB * 1024; + } + + if (parsedInKb < MIN_HTTP2_MAX_FRAME_SIZE_IN_KB || parsedInKb > MAX_HTTP2_MAX_FRAME_SIZE_IN_KB) { + int clampedInKb = Math.min( + MAX_HTTP2_MAX_FRAME_SIZE_IN_KB, + Math.max(MIN_HTTP2_MAX_FRAME_SIZE_IN_KB, parsedInKb)); + logger.warn( + "Configured HTTP/2 max frame size {} KB is outside the allowed range [{}, {}] KB; " + + "clamping to {} KB.", + parsedInKb, + MIN_HTTP2_MAX_FRAME_SIZE_IN_KB, + MAX_HTTP2_MAX_FRAME_SIZE_IN_KB, + clampedInKb); + return clampedInKb * 1024; + } + + return parsedInKb * 1024; + } + public static boolean isEmulatorServerCertValidationDisabled() { String certVerificationDisabledConfig = System.getProperty( EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED, diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java index 2e362eadc084..65bc4cb76bee 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java @@ -152,7 +152,7 @@ private void configureChannelPipelineHandlers() { .protocol(HttpProtocol.H2, HttpProtocol.HTTP11) .http2Settings(settings -> settings .initialWindowSize(1024 * 1024) // 1MB initial window size - .maxFrameSize(64 * 1024) // 64KB max frame size + .maxFrameSize(Configs.getHttp2MaxFrameSizeInBytes()) // 64KB default; overridable via COSMOS.HTTP2_MAX_FRAME_SIZE_IN_KB / COSMOS_HTTP2_MAX_FRAME_SIZE_IN_KB (clamped to [64KB, 16MB]) .maxConcurrentStreams(httpCfgAccessor().getEffectiveMaxConcurrentStreams(http2Cfg)) // Increased from default 30 ) .doOnConnected((connection -> { From 5e673892229f545e0f2727f9b040c8beb290986f Mon Sep 17 00:00:00 2001 From: Abhijeet Mohanty Date: Mon, 8 Jun 2026 16:43:04 -0400 Subject: [PATCH 2/5] Cap HTTP/2 max frame size at 16383 KB Use 16383 KB as the customer-facing upper bound so the converted byte value remains below the HTTP/2 SETTINGS_MAX_FRAME_SIZE spec maximum of 2^24 - 1 bytes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../com/azure/cosmos/implementation/ConfigsTests.java | 8 ++++---- .../java/com/azure/cosmos/implementation/Configs.java | 8 ++++---- .../cosmos/implementation/http/ReactorNettyClient.java | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConfigsTests.java b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConfigsTests.java index 3eff4318c6c4..c814714ce2ee 100644 --- a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConfigsTests.java +++ b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConfigsTests.java @@ -174,7 +174,7 @@ public void http2MaxFrameSizeInBytes() { final String propName = "COSMOS.HTTP2_MAX_FRAME_SIZE_IN_KB"; final int defaultBytes = 64 * 1024; final int minBytes = 64 * 1024; - final int maxBytes = 16 * 1024 * 1024; + final int maxBytes = 16_383 * 1024; System.clearProperty(propName); @@ -189,8 +189,8 @@ public void http2MaxFrameSizeInBytes() { System.clearProperty(propName); } - // Valid value at upper bound (16 MB) - System.setProperty(propName, String.valueOf(16 * 1024)); + // Valid value at upper bound (16383 KB) + System.setProperty(propName, "16383"); try { assertThat(Configs.getHttp2MaxFrameSizeInBytes()).isEqualTo(maxBytes); } finally { @@ -213,7 +213,7 @@ public void http2MaxFrameSizeInBytes() { System.clearProperty(propName); } - // Above upper bound -> clamped down to 16 MB + // Above upper bound -> clamped down to 16383 KB System.setProperty(propName, String.valueOf(32 * 1024)); try { assertThat(Configs.getHttp2MaxFrameSizeInBytes()).isEqualTo(maxBytes); diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java index c9730e4629bf..c7d544971ee5 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Configs.java @@ -397,11 +397,11 @@ public class Configs { private static final String HTTP2_MAX_CONCURRENT_STREAMS_VARIABLE = "COSMOS_HTTP2_MAX_CONCURRENT_STREAMS"; // Config to indicate the SETTINGS_MAX_FRAME_SIZE advertised by the HTTP/2 client to the remote peer. - // The value is expressed in kilobytes (KB) and is clamped to [64 KB, 16 MB] — the lower bound matches + // The value is expressed in kilobytes (KB) and is clamped to [64 KB, 16383 KB] — the lower bound matches // the SDK's historical default so users can only grow the frame size, and the upper bound is the - // hard maximum permitted by the HTTP/2 spec (RFC 7540: 2^24 - 1 bytes, rounded down to 16 MB). + // largest whole-KB value below the HTTP/2 spec max (RFC 7540: 2^24 - 1 bytes). private static final int MIN_HTTP2_MAX_FRAME_SIZE_IN_KB = 64; // 64 KB - private static final int MAX_HTTP2_MAX_FRAME_SIZE_IN_KB = 16 * 1024; // 16 MB + private static final int MAX_HTTP2_MAX_FRAME_SIZE_IN_KB = 16_383; // 16383 KB private static final int DEFAULT_HTTP2_MAX_FRAME_SIZE_IN_KB = 64; // 64 KB private static final String HTTP2_MAX_FRAME_SIZE_IN_KB = "COSMOS.HTTP2_MAX_FRAME_SIZE_IN_KB"; private static final String HTTP2_MAX_FRAME_SIZE_IN_KB_VARIABLE = "COSMOS_HTTP2_MAX_FRAME_SIZE_IN_KB"; @@ -1407,7 +1407,7 @@ public static int getHttp2MaxConcurrentStreams() { * {@code COSMOS.HTTP2_MAX_FRAME_SIZE_IN_KB} or environment variable * {@code COSMOS_HTTP2_MAX_FRAME_SIZE_IN_KB}. Resolution order is system property, then environment * variable, then the SDK default of 64 KB. The configured value is clamped to the inclusive range - * [64 KB, 16 MB]; an unparseable or out-of-range value falls back to the default (or is clamped) + * [64 KB, 16383 KB]; an unparseable or out-of-range value falls back to the default (or is clamped) * and a warning is logged. The returned value is converted to bytes for downstream Netty * consumption. */ diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java index 65bc4cb76bee..99e475c51849 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java @@ -152,7 +152,7 @@ private void configureChannelPipelineHandlers() { .protocol(HttpProtocol.H2, HttpProtocol.HTTP11) .http2Settings(settings -> settings .initialWindowSize(1024 * 1024) // 1MB initial window size - .maxFrameSize(Configs.getHttp2MaxFrameSizeInBytes()) // 64KB default; overridable via COSMOS.HTTP2_MAX_FRAME_SIZE_IN_KB / COSMOS_HTTP2_MAX_FRAME_SIZE_IN_KB (clamped to [64KB, 16MB]) + .maxFrameSize(Configs.getHttp2MaxFrameSizeInBytes()) // 64KB default; overridable via COSMOS.HTTP2_MAX_FRAME_SIZE_IN_KB / COSMOS_HTTP2_MAX_FRAME_SIZE_IN_KB (clamped to [64KB, 16383KB]) .maxConcurrentStreams(httpCfgAccessor().getEffectiveMaxConcurrentStreams(http2Cfg)) // Increased from default 30 ) .doOnConnected((connection -> { From 97902209d7b784385c47975fd6ecc939eb9ebf79 Mon Sep 17 00:00:00 2001 From: Abhijeet Mohanty Date: Mon, 8 Jun 2026 16:49:14 -0400 Subject: [PATCH 3/5] Fix HTTP/2 config accessor usage Use the local http2CfgAccessor helper when applying effective HTTP/2 max concurrent streams settings. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../azure/cosmos/implementation/http/ReactorNettyClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java index 581cf6a06200..f62082edaacc 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/http/ReactorNettyClient.java @@ -185,7 +185,7 @@ private void configureChannelPipelineHandlers() { .http2Settings(settings -> settings .initialWindowSize(1024 * 1024) // 1MB initial window size .maxFrameSize(Configs.getHttp2MaxFrameSizeInBytes()) // 64KB default; overridable via COSMOS.HTTP2_MAX_FRAME_SIZE_IN_KB / COSMOS_HTTP2_MAX_FRAME_SIZE_IN_KB (clamped to [64KB, 16383KB]) - .maxConcurrentStreams(httpCfgAccessor().getEffectiveMaxConcurrentStreams(http2Cfg)) // Increased from default 30 + .maxConcurrentStreams(http2CfgAccessor().getEffectiveMaxConcurrentStreams(http2Cfg)) // Increased from default 30 ) .doOnConnected((connection -> { // The response header clean up pipeline is being added due to an error getting when calling gateway: From 0496177e1571c265fa90d4e1e7161d2c19e4a352 Mon Sep 17 00:00:00 2001 From: Abhijeet Mohanty Date: Mon, 8 Jun 2026 17:07:07 -0400 Subject: [PATCH 4/5] Rename GSI query definition getter Rename CosmosGlobalSecondaryIndexDefinition.getDefinition to getQueryDefinition so the method name matches the documented query definition purpose. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../rx/GlobalSecondaryIndexContainerCrudTest.java | 10 +++++----- .../azure/cosmos/rx/GlobalSecondaryIndexTest.java | 12 ++++++------ .../models/CosmosGlobalSecondaryIndexDefinition.java | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexContainerCrudTest.java b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexContainerCrudTest.java index 91a516ed5c15..70aa92652b5c 100644 --- a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexContainerCrudTest.java +++ b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexContainerCrudTest.java @@ -96,7 +96,7 @@ public void createGsiContainer() { CosmosGlobalSecondaryIndexDefinition gsiDef = createResponse.getProperties().getGlobalSecondaryIndexDefinition(); assertThat(gsiDef).isNotNull(); assertThat(gsiDef.getSourceContainerId()).isEqualTo(sourceContainerId); - assertThat(gsiDef.getDefinition()).isEqualTo(GSI_QUERY_DEFINITION); + assertThat(gsiDef.getQueryDefinition()).isEqualTo(GSI_QUERY_DEFINITION); assertThat(gsiDef.getSourceContainerRid()).isNotNull().isNotEmpty(); } finally { safeDeleteAllCollections(database); @@ -133,7 +133,7 @@ public void readGsiContainer() { CosmosGlobalSecondaryIndexDefinition gsiDef = readResponse.getProperties().getGlobalSecondaryIndexDefinition(); assertThat(gsiDef).isNotNull(); assertThat(gsiDef.getSourceContainerId()).isEqualTo(sourceContainerId); - assertThat(gsiDef.getDefinition()).isEqualTo(GSI_QUERY_DEFINITION); + assertThat(gsiDef.getQueryDefinition()).isEqualTo(GSI_QUERY_DEFINITION); assertThat(gsiDef.getSourceContainerRid()).isNotNull().isNotEmpty(); } finally { safeDeleteAllCollections(database); @@ -211,7 +211,7 @@ public void createGsiContainerWithCustomIndexingPolicy() { CosmosGlobalSecondaryIndexDefinition gsiDef = createResponse.getProperties().getGlobalSecondaryIndexDefinition(); assertThat(gsiDef).isNotNull(); assertThat(gsiDef.getSourceContainerId()).isEqualTo(sourceContainerId); - assertThat(gsiDef.getDefinition()).isEqualTo(GSI_QUERY_DEFINITION); + assertThat(gsiDef.getQueryDefinition()).isEqualTo(GSI_QUERY_DEFINITION); assertThat(gsiDef.getSourceContainerRid()).isNotNull().isNotEmpty(); } finally { safeDeleteAllCollections(database); @@ -259,7 +259,7 @@ public void replaceGsiContainer() { CosmosGlobalSecondaryIndexDefinition gsiDef = replaceResponse.getProperties().getGlobalSecondaryIndexDefinition(); assertThat(gsiDef).isNotNull(); assertThat(gsiDef.getSourceContainerId()).isEqualTo(sourceContainerId); - assertThat(gsiDef.getDefinition()).isEqualTo(GSI_QUERY_DEFINITION); + assertThat(gsiDef.getQueryDefinition()).isEqualTo(GSI_QUERY_DEFINITION); } finally { safeDeleteAllCollections(database); } @@ -361,7 +361,7 @@ public void createGsiContainer_ridResolvedFromSourceContainer() { .isNotNull() .isNotEmpty() .isEqualTo(expectedSourceRid); - assertThat(gsiDef.getDefinition()).isEqualTo(GSI_QUERY_DEFINITION); + assertThat(gsiDef.getQueryDefinition()).isEqualTo(GSI_QUERY_DEFINITION); } finally { safeDeleteAllCollections(database); } diff --git a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexTest.java b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexTest.java index a3e83178b42b..29bbf0b1720d 100644 --- a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexTest.java +++ b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexTest.java @@ -52,7 +52,7 @@ public void containerProperties_setAndGetGlobalSecondaryIndexDefinition() { CosmosGlobalSecondaryIndexDefinition retrieved = containerProperties.getGlobalSecondaryIndexDefinition(); assertThat(retrieved).isNotNull(); assertThat(retrieved.getSourceContainerId()).isEqualTo("gsi-src"); - assertThat(retrieved.getDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); + assertThat(retrieved.getQueryDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); } @Test(groups = {"unit"}, timeOut = TIMEOUT) @@ -161,7 +161,7 @@ public void globalSecondaryIndexDefinition_deserializesFromJson() { CosmosGlobalSecondaryIndexDefinition definition = containerProperties.getGlobalSecondaryIndexDefinition(); assertThat(definition).isNotNull(); assertThat(definition.getSourceContainerId()).isEqualTo("gsi-src"); - assertThat(definition.getDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); + assertThat(definition.getQueryDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); assertThat(definition.getSourceContainerRid()).isEqualTo("TughAMEOdUI="); // No status field in the JSON, so the accessor returns null. assertThat(definition.getStatus()).isNull(); @@ -213,7 +213,7 @@ public void globalSecondaryIndexDefinition_deserializesFromNewWireFormat() { assertThat(definition).isNotNull(); assertThat(definition.getSourceContainerId()).isEqualTo("gsi-src"); assertThat(definition.getSourceContainerRid()).isEqualTo("TughAMEOdUI="); - assertThat(definition.getDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); + assertThat(definition.getQueryDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); assertThat(definition.getStatus()).isEqualTo(CosmosGlobalSecondaryIndexBuildStatus.ACTIVE); } @@ -243,7 +243,7 @@ public void globalSecondaryIndexDefinition_newWireFormatTakesPrecedenceOverLegac .as("New wire format should take precedence when both are present") .isEqualTo("gsi-new"); assertThat(definition.getSourceContainerRid()).isEqualTo("NewRid="); - assertThat(definition.getDefinition()).isEqualTo("SELECT c.id FROM c"); + assertThat(definition.getQueryDefinition()).isEqualTo("SELECT c.id FROM c"); } @Test(groups = {"unit"}, timeOut = TIMEOUT) @@ -269,7 +269,7 @@ public void GlobalSecondaryIndexDefinition_fullRoundTrip() throws Exception { CosmosGlobalSecondaryIndexDefinition deserializedDef = deserialized.getGlobalSecondaryIndexDefinition(); assertThat(deserializedDef).isNotNull(); assertThat(deserializedDef.getSourceContainerId()).isEqualTo("gsi-src"); - assertThat(deserializedDef.getDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); + assertThat(deserializedDef.getQueryDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); // Verify the RID round-tripped correctly through the wire format ObjectNode jsonNode = (ObjectNode) simpleObjectMapper.readTree(json); @@ -301,7 +301,7 @@ public void globalSecondaryIndexDefinition_nullSourceContainerId_fallsThroughToN // The GSI definition itself should be non-null (the JSON node exists) CosmosGlobalSecondaryIndexDefinition gsiDef = containerProperties.getGlobalSecondaryIndexDefinition(); assertThat(gsiDef).isNotNull(); - assertThat(gsiDef.getDefinition()).isEqualTo("SELECT c.customerId FROM c"); + assertThat(gsiDef.getQueryDefinition()).isEqualTo("SELECT c.customerId FROM c"); // But sourceContainerId should be null assertThat(gsiDef.getSourceContainerId()) diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosGlobalSecondaryIndexDefinition.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosGlobalSecondaryIndexDefinition.java index 299a28458921..e949bb4de7d7 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosGlobalSecondaryIndexDefinition.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosGlobalSecondaryIndexDefinition.java @@ -106,7 +106,7 @@ public CosmosGlobalSecondaryIndexBuildStatus getStatus() { * @return the query definition. */ @Beta(value = Beta.SinceVersion.V4_81_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) - public String getDefinition() { + public String getQueryDefinition() { return this.jsonSerializable.getString(Constants.Properties.GLOBAL_SECONDARY_INDEX_QUERY_DEFINITION); } From 8fb36fb596ba22b71dad6e87f32b48e1950893f9 Mon Sep 17 00:00:00 2001 From: Abhijeet Mohanty Date: Mon, 8 Jun 2026 18:08:16 -0400 Subject: [PATCH 5/5] Revert GSI query definition getter rename Restore CosmosGlobalSecondaryIndexDefinition.getDefinition and related test references. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../rx/GlobalSecondaryIndexContainerCrudTest.java | 10 +++++----- .../azure/cosmos/rx/GlobalSecondaryIndexTest.java | 12 ++++++------ .../models/CosmosGlobalSecondaryIndexDefinition.java | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexContainerCrudTest.java b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexContainerCrudTest.java index 70aa92652b5c..91a516ed5c15 100644 --- a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexContainerCrudTest.java +++ b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexContainerCrudTest.java @@ -96,7 +96,7 @@ public void createGsiContainer() { CosmosGlobalSecondaryIndexDefinition gsiDef = createResponse.getProperties().getGlobalSecondaryIndexDefinition(); assertThat(gsiDef).isNotNull(); assertThat(gsiDef.getSourceContainerId()).isEqualTo(sourceContainerId); - assertThat(gsiDef.getQueryDefinition()).isEqualTo(GSI_QUERY_DEFINITION); + assertThat(gsiDef.getDefinition()).isEqualTo(GSI_QUERY_DEFINITION); assertThat(gsiDef.getSourceContainerRid()).isNotNull().isNotEmpty(); } finally { safeDeleteAllCollections(database); @@ -133,7 +133,7 @@ public void readGsiContainer() { CosmosGlobalSecondaryIndexDefinition gsiDef = readResponse.getProperties().getGlobalSecondaryIndexDefinition(); assertThat(gsiDef).isNotNull(); assertThat(gsiDef.getSourceContainerId()).isEqualTo(sourceContainerId); - assertThat(gsiDef.getQueryDefinition()).isEqualTo(GSI_QUERY_DEFINITION); + assertThat(gsiDef.getDefinition()).isEqualTo(GSI_QUERY_DEFINITION); assertThat(gsiDef.getSourceContainerRid()).isNotNull().isNotEmpty(); } finally { safeDeleteAllCollections(database); @@ -211,7 +211,7 @@ public void createGsiContainerWithCustomIndexingPolicy() { CosmosGlobalSecondaryIndexDefinition gsiDef = createResponse.getProperties().getGlobalSecondaryIndexDefinition(); assertThat(gsiDef).isNotNull(); assertThat(gsiDef.getSourceContainerId()).isEqualTo(sourceContainerId); - assertThat(gsiDef.getQueryDefinition()).isEqualTo(GSI_QUERY_DEFINITION); + assertThat(gsiDef.getDefinition()).isEqualTo(GSI_QUERY_DEFINITION); assertThat(gsiDef.getSourceContainerRid()).isNotNull().isNotEmpty(); } finally { safeDeleteAllCollections(database); @@ -259,7 +259,7 @@ public void replaceGsiContainer() { CosmosGlobalSecondaryIndexDefinition gsiDef = replaceResponse.getProperties().getGlobalSecondaryIndexDefinition(); assertThat(gsiDef).isNotNull(); assertThat(gsiDef.getSourceContainerId()).isEqualTo(sourceContainerId); - assertThat(gsiDef.getQueryDefinition()).isEqualTo(GSI_QUERY_DEFINITION); + assertThat(gsiDef.getDefinition()).isEqualTo(GSI_QUERY_DEFINITION); } finally { safeDeleteAllCollections(database); } @@ -361,7 +361,7 @@ public void createGsiContainer_ridResolvedFromSourceContainer() { .isNotNull() .isNotEmpty() .isEqualTo(expectedSourceRid); - assertThat(gsiDef.getQueryDefinition()).isEqualTo(GSI_QUERY_DEFINITION); + assertThat(gsiDef.getDefinition()).isEqualTo(GSI_QUERY_DEFINITION); } finally { safeDeleteAllCollections(database); } diff --git a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexTest.java b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexTest.java index 29bbf0b1720d..a3e83178b42b 100644 --- a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexTest.java +++ b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/rx/GlobalSecondaryIndexTest.java @@ -52,7 +52,7 @@ public void containerProperties_setAndGetGlobalSecondaryIndexDefinition() { CosmosGlobalSecondaryIndexDefinition retrieved = containerProperties.getGlobalSecondaryIndexDefinition(); assertThat(retrieved).isNotNull(); assertThat(retrieved.getSourceContainerId()).isEqualTo("gsi-src"); - assertThat(retrieved.getQueryDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); + assertThat(retrieved.getDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); } @Test(groups = {"unit"}, timeOut = TIMEOUT) @@ -161,7 +161,7 @@ public void globalSecondaryIndexDefinition_deserializesFromJson() { CosmosGlobalSecondaryIndexDefinition definition = containerProperties.getGlobalSecondaryIndexDefinition(); assertThat(definition).isNotNull(); assertThat(definition.getSourceContainerId()).isEqualTo("gsi-src"); - assertThat(definition.getQueryDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); + assertThat(definition.getDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); assertThat(definition.getSourceContainerRid()).isEqualTo("TughAMEOdUI="); // No status field in the JSON, so the accessor returns null. assertThat(definition.getStatus()).isNull(); @@ -213,7 +213,7 @@ public void globalSecondaryIndexDefinition_deserializesFromNewWireFormat() { assertThat(definition).isNotNull(); assertThat(definition.getSourceContainerId()).isEqualTo("gsi-src"); assertThat(definition.getSourceContainerRid()).isEqualTo("TughAMEOdUI="); - assertThat(definition.getQueryDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); + assertThat(definition.getDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); assertThat(definition.getStatus()).isEqualTo(CosmosGlobalSecondaryIndexBuildStatus.ACTIVE); } @@ -243,7 +243,7 @@ public void globalSecondaryIndexDefinition_newWireFormatTakesPrecedenceOverLegac .as("New wire format should take precedence when both are present") .isEqualTo("gsi-new"); assertThat(definition.getSourceContainerRid()).isEqualTo("NewRid="); - assertThat(definition.getQueryDefinition()).isEqualTo("SELECT c.id FROM c"); + assertThat(definition.getDefinition()).isEqualTo("SELECT c.id FROM c"); } @Test(groups = {"unit"}, timeOut = TIMEOUT) @@ -269,7 +269,7 @@ public void GlobalSecondaryIndexDefinition_fullRoundTrip() throws Exception { CosmosGlobalSecondaryIndexDefinition deserializedDef = deserialized.getGlobalSecondaryIndexDefinition(); assertThat(deserializedDef).isNotNull(); assertThat(deserializedDef.getSourceContainerId()).isEqualTo("gsi-src"); - assertThat(deserializedDef.getQueryDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); + assertThat(deserializedDef.getDefinition()).isEqualTo("SELECT c.customerId, c.emailAddress FROM c"); // Verify the RID round-tripped correctly through the wire format ObjectNode jsonNode = (ObjectNode) simpleObjectMapper.readTree(json); @@ -301,7 +301,7 @@ public void globalSecondaryIndexDefinition_nullSourceContainerId_fallsThroughToN // The GSI definition itself should be non-null (the JSON node exists) CosmosGlobalSecondaryIndexDefinition gsiDef = containerProperties.getGlobalSecondaryIndexDefinition(); assertThat(gsiDef).isNotNull(); - assertThat(gsiDef.getQueryDefinition()).isEqualTo("SELECT c.customerId FROM c"); + assertThat(gsiDef.getDefinition()).isEqualTo("SELECT c.customerId FROM c"); // But sourceContainerId should be null assertThat(gsiDef.getSourceContainerId()) diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosGlobalSecondaryIndexDefinition.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosGlobalSecondaryIndexDefinition.java index e949bb4de7d7..299a28458921 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosGlobalSecondaryIndexDefinition.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosGlobalSecondaryIndexDefinition.java @@ -106,7 +106,7 @@ public CosmosGlobalSecondaryIndexBuildStatus getStatus() { * @return the query definition. */ @Beta(value = Beta.SinceVersion.V4_81_0, warningText = Beta.PREVIEW_SUBJECT_TO_CHANGE_WARNING) - public String getQueryDefinition() { + public String getDefinition() { return this.jsonSerializable.getString(Constants.Properties.GLOBAL_SECONDARY_INDEX_QUERY_DEFINITION); }