diff --git a/sdk/cosmos/azure-cosmos-test/src/main/java/module-info.java b/sdk/cosmos/azure-cosmos-test/src/main/java/module-info.java deleted file mode 100644 index ccaaf699f81e..000000000000 --- a/sdk/cosmos/azure-cosmos-test/src/main/java/module-info.java +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -module com.azure.cosmos.test { - - requires transitive com.azure.cosmos; - - exports com.azure.cosmos.test.faultinjection; -} diff --git a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConsistencyTestsStrong.java b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConsistencyTestsStrong.java new file mode 100644 index 000000000000..745177f3f7ce --- /dev/null +++ b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/ConsistencyTestsStrong.java @@ -0,0 +1,109 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.cosmos.implementation; + +import com.azure.cosmos.*; +import com.azure.cosmos.implementation.clienttelemetry.ClientTelemetry; +import com.azure.cosmos.implementation.directconnectivity.ReflectionUtils; +import com.azure.cosmos.implementation.directconnectivity.WFConstants; +import com.azure.cosmos.implementation.routing.PartitionKeyInternal; +import com.azure.cosmos.models.CosmosClientTelemetryConfig; +import com.azure.cosmos.models.CosmosQueryRequestOptions; +import com.azure.cosmos.models.FeedResponse; +import com.azure.cosmos.models.PartitionKey; +import com.azure.cosmos.test.faultinjection.*; +import org.apache.commons.lang3.Range; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ConsistencyTestsStrong { + + @Test(groups = {"direct"}) + public void injectTooManyRequestsFaultAndVerify429Count(boolean shouldRegionScopedSessionContainerEnabled) throws InterruptedException { + string databaseName = "newdatabase"; + + // Create a fault injection rule for TooManyRequests (429) in direct mode + FaultInjectionRule tooManyRequestsRule = new FaultInjectionRuleBuilder( + id: "TooManyRequestsRule-" + Guid.NewGuid(), + condition: new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.ReadItem) + .Build(), + result: FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.TooManyRequests) + .Build()) + .Build(); + + // inject 404/1002 into all regions + FaultInjectionRule tooManyRequestsRule = new FaultInjectionRuleBuilder("tooManyRequestsRule-" + UUID.randomUUID()) + .condition(new FaultInjectionConditionBuilder()) + .withOperationType(FaultInjectionOperationType.READ_ITEM) + .result( + FaultInjectionResultBuilders + .getResultBuilder(FaultInjectionServerErrorType.READ_SESSION_NOT_AVAILABLE) + .build()) + .build(); + + // Initialize the fault injector + FaultInjector faultInjector = new FaultInjector(new List { tooManyRequestsRule }); + + CosmosClient cosmosClient = new CosmosClientBuilder( + connectionString: "") + .WithConnectionModeDirect().WithFaultInjection(faultInjector) + .WithConsistencyLevel(Cosmos.ConsistencyLevel.Eventual) + .WithThrottlingRetryOptions( + maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(5), // Maximum wait time for retries + maxRetryAttemptsOnThrottledRequests: 2) // Maximum retry attempts + .Build(); + + + ContainerProperties containerProperties = new ContainerProperties( + id: "test", + partitionKeyPath: "/id"); + + + // Create database and container + await cosmosClient.CreateDatabaseIfNotExistsAsync(databaseName); + Container container = await cosmosClient.GetDatabase(databaseName).CreateContainerIfNotExistsAsync(containerProperties); + + dynamic testObject = new + { + id = Guid.NewGuid().ToString(), + Company = "Microsoft", + State = "WA" + + }; + + + await container.CreateItemAsync(testObject); + try + { + // Attempt to read the item + ItemResponse itemResponse = await container.ReadItemAsync( + testObject.id, + new Cosmos.PartitionKey(testObject.id)); + + // Print diagnostics + Console.WriteLine("Diagnostics:"); + Console.WriteLine(itemResponse.Diagnostics.ToString()); + } + + catch (CosmosException ex) + { + // Handle other Cosmos exceptions + Console.WriteLine($"CosmosException: {ex.StatusCode} - {ex.Message}"); + Console.WriteLine("Diagnostics:"); + Console.WriteLine(ex.Diagnostics.ToString()); + } + long hitCount = tooManyRequestsRule.GetHitCount(); + Console.WriteLine($"Total 429 responses: {hitCount}"); + } + +} diff --git a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/directconnectivity/ConsistencyWriterTest.java b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/directconnectivity/ConsistencyWriterTest.java index 9ede1c281219..28cd24f1eca7 100644 --- a/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/directconnectivity/ConsistencyWriterTest.java +++ b/sdk/cosmos/azure-cosmos-tests/src/test/java/com/azure/cosmos/implementation/directconnectivity/ConsistencyWriterTest.java @@ -5,6 +5,7 @@ import com.azure.cosmos.BridgeInternal; import com.azure.cosmos.ConsistencyLevel; +import com.azure.cosmos.CosmosClientBuilder; import com.azure.cosmos.implementation.ClientSideRequestStatistics; import com.azure.cosmos.implementation.DiagnosticsClientContext; import com.azure.cosmos.implementation.FailureValidator; @@ -21,11 +22,13 @@ import com.azure.cosmos.implementation.StoreResponseBuilder; import com.azure.cosmos.implementation.Utils; import com.azure.cosmos.implementation.guava25.collect.ImmutableList; +import com.azure.cosmos.rx.TestSuiteBase; import io.reactivex.subscribers.TestSubscriber; import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.testng.annotations.DataProvider; +import org.testng.annotations.Factory; import org.testng.annotations.Test; import reactor.core.publisher.DirectProcessor; import reactor.core.publisher.Mono; @@ -46,6 +49,7 @@ import static com.azure.cosmos.implementation.TestUtils.mockDiagnosticsClientContext; import static com.azure.cosmos.implementation.TestUtils.mockDocumentServiceRequest; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; public class ConsistencyWriterTest { private final static DiagnosticsClientContext clientContext = mockDiagnosticsClientContext(); @@ -77,6 +81,19 @@ public Object[][] storeResponseArgProvider() { }; } + /*@Test(groups = "unit") + public void ConsistencyWriter_BarrierRetriesExhaustedWith429_Throws408Async() { + int barrierRequestCount = 0; + + sessionContainer = Mockito.mock(ISessionContainer.class); + + transportClient = Mockito.mock(TransportClient.class); + when(transportClient.invokeStoreAsync( + Mockito.any(Uri.class), + Mockito.any(RxDocumentServiceRequest.class)) + .thenAnswer(i -> i.getArguments()[0])); + }*/ + @Test(groups = "unit", dataProvider = "exceptionArgProvider") public void exception(Exception ex, Class klass, int expectedStatusCode, Integer expectedSubStatusCode) { TransportClientWrapper transportClientWrapper = new TransportClientWrapper.Builder.ReplicaResponseBuilder diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/HttpConstants.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/HttpConstants.java index 63c238f0e6ab..d52d636b396f 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/HttpConstants.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/HttpConstants.java @@ -480,6 +480,7 @@ public static class SubStatusCodes { public static final int NO_VALID_STORE_RESPONSE = 21009; public static final int SERVER_GENERATED_408 = 21010; public static final int FAILED_TO_PARSE_SERVER_RESPONSE = 21011; + public static final int SERVER_WRITE_BARRIER_THROTTLED = 21013; } public static class HeaderValues { diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RequestTimeoutException.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RequestTimeoutException.java index e89cb494ab84..3ce08cf7d807 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RequestTimeoutException.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RequestTimeoutException.java @@ -17,6 +17,13 @@ */ public class RequestTimeoutException extends CosmosException { + /** + * Instantiates a new Request timeout exception. + */ + public RequestTimeoutException(int subStatusCode) { + this(RMResources.RequestTimeout, null, subStatusCode); + } + /** * Instantiates a new Request timeout exception. */ diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/ConsistencyWriter.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/ConsistencyWriter.java index 92a781cf071c..e08ba5fb6973 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/ConsistencyWriter.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/ConsistencyWriter.java @@ -27,7 +27,6 @@ import com.azure.cosmos.implementation.Strings; import com.azure.cosmos.implementation.Utils; import com.azure.cosmos.implementation.apachecommons.collections.ComparatorUtils; -import com.azure.cosmos.implementation.directconnectivity.rntbd.ClosedClientTransportException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import reactor.core.Exceptions; @@ -46,6 +45,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; @@ -386,6 +386,7 @@ Mono barrierForGlobalStrong(RxDocumentServiceRequest request, Sto private Mono waitForWriteBarrierAsync(RxDocumentServiceRequest barrierRequest, long selectedGlobalCommittedLsn) { AtomicInteger writeBarrierRetryCount = new AtomicInteger(ConsistencyWriter.MAX_NUMBER_OF_WRITE_BARRIER_READ_RETRIES); + AtomicBoolean lastAttemptWasThrottled = new AtomicBoolean(false); AtomicLong maxGlobalCommittedLsnReceived = new AtomicLong(0); return Flux.defer(() -> { if (barrierRequest.requestContext.timeoutHelper.isElapsed()) { @@ -403,8 +404,35 @@ private Mono waitForWriteBarrierAsync(RxDocumentServiceRequest barrierR false /*forceReadAll*/); return storeResultListObs.flatMap( responses -> { - if (responses != null && responses.stream().anyMatch(response -> response.globalCommittedLSN >= selectedGlobalCommittedLsn)) { - return Mono.just(Boolean.TRUE); + //if (responses != null && responses.stream().anyMatch(response -> response.globalCommittedLSN >= selectedGlobalCommittedLsn)) { + // return Mono.just(Boolean.TRUE); + //} + + if (responses != null) { + // Check if all replicas returned 429, but don't exit early. + if (responses.stream().count() > 0 && responses.stream().allMatch(response -> response.getStoreResponse().getStatus() == HttpConstants.StatusCodes.TOO_MANY_REQUESTS)) { + if (logger.isDebugEnabled()) { + logger.debug("waitForWriteBarrierAsync: All replicas returned 429 Too Many Requests. Continuing retries." + + "StatusCode: {}, SubStatusCode: {}, PkRangeId :{}.", + responses.get(0).getStoreResponse().getStatus(), + responses.get(0).getStoreResponse().getSubStatusCode(), + responses.get(0).getStoreResponse().getPartitionKeyRangeId()); + } + lastAttemptWasThrottled.set(true); + } else { + lastAttemptWasThrottled.set(false); + } + + // Check if any response satisfies the barrier condition + if (responses.stream().anyMatch(response -> response.globalCommittedLSN >= selectedGlobalCommittedLsn)) { + if (logger.isDebugEnabled()) { + logger.debug("ConsistencyWriter: WaitForWriteBarrierAsync - Barrier met. Responses: {}", + responses.stream().map(StoreResult::toString).collect(Collectors.joining("; "))); + } + return Mono.just(Boolean.TRUE); + } + } else { + lastAttemptWasThrottled.set(false); } //get max global committed lsn from current batch of responses, then update if greater than max of all batches. @@ -416,6 +444,14 @@ private Mono waitForWriteBarrierAsync(RxDocumentServiceRequest barrierR //only refresh on first barrier call, set to false for subsequent attempts. barrierRequest.requestContext.forceRefreshAddressCache = false; + if (lastAttemptWasThrottled.get()) + { + if (logger.isDebugEnabled()) { + logger.debug("ConsistencyWriter: Write barrier failed after all retries due to consistent throttling (429). Throwing RequestTimeoutException (408)."); + } + throw new RequestTimeoutException(HttpConstants.SubStatusCodes.SERVER_WRITE_BARRIER_THROTTLED); + } + //get max global committed lsn from current batch of responses, then update if greater than max of all batches. if (writeBarrierRetryCount.getAndDecrement() == 0) { if (logger.isDebugEnabled() && responses != null) { diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/QuorumReader.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/QuorumReader.java index 1f01e66076d6..3a6808e0fee9 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/QuorumReader.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/QuorumReader.java @@ -155,6 +155,14 @@ public Mono readStrongAsync( secondaryQuorumReadResult -> { switch (secondaryQuorumReadResult.quorumResult) { + case QuorumThrottled: + try { + logger.warn("QuorumThrottled: ReadQuorumResult StoreResponses: {}", + String.join(";", secondaryQuorumReadResult.storeResponses)); + return Flux.just(secondaryQuorumReadResult.getResponse()); + } catch (CosmosException e) { + return Flux.error(e); + } case QuorumNotPossibleInCurrentRegion: try { logger.warn("QuorumNotPossibleInCurrentRegion: ReadQuorumResult StoreResponses: {}", @@ -179,7 +187,7 @@ public Mono readStrongAsync( secondaryQuorumReadResult.globalCommittedSelectedLsn); return barrierRequestObs.flux().flatMap(barrierRequest -> { - Mono readBarrierObs = this.waitForReadBarrierAsync( + Mono readBarrierObs = this.waitForReadBarrierAsync( barrierRequest, true /* include primary */, readQuorumValue, @@ -190,9 +198,14 @@ public Mono readStrongAsync( return readBarrierObs.flux().flatMap( readBarrier -> { - if (readBarrier) { + if (readBarrier.throttledResponse != null) { + // handle throttling by delegating to ResourceThrottleRetryPolicy + return Flux.just(readBarrier.throttledResponse); + } + + if (readBarrier.isSuccess) { try { - return Flux.just(secondaryQuorumReadResult.getResponse()); + return Flux.just(secondaryQuorumReadResult.getResponse()); } catch (Exception e) { return Flux.error(e); } @@ -327,10 +340,10 @@ private Mono readQuorumAsync( Mono barrierRequestObs = BarrierRequestHelper.createAsync(this.diagnosticsClientContext, entity, this.authorizationTokenProvider, readLsn, globalCommittedLSN); return barrierRequestObs.flatMap( barrierRequest -> { - Mono waitForObs = this.waitForReadBarrierAsync(barrierRequest, false, readQuorum, readLsn, globalCommittedLSN, readMode); + Mono waitForObs = this.waitForReadBarrierAsync(barrierRequest, false, readQuorum, readLsn, globalCommittedLSN, readMode); return waitForObs.flatMap( waitFor -> { - if (!waitFor) { + if (waitFor.isSuccess) { return Mono.just(new ReadQuorumResult( entity.requestContext.requestChargeTracker, ReadQuorumResultKind.QuorumSelected, @@ -610,7 +623,7 @@ private Mono waitForPrimaryLsnAsync( } - private Mono waitForReadBarrierAsync( + private Mono waitForReadBarrierAsync( RxDocumentServiceRequest barrierRequest, boolean allowPrimary, final int readQuorum, @@ -641,7 +654,7 @@ private Mono waitForReadBarrierAsync( if ((responses.stream().filter(response -> response.lsn >= readBarrierLsn).count() >= readQuorum) && (!(targetGlobalCommittedLSN > 0) || maxGlobalCommittedLsnInResponses >= targetGlobalCommittedLSN)) { - return Flux.just(true); + return Flux.just(new WaitForReadBarrierResult(true, null)); } maxGlobalCommittedLsn.set(Math.max(maxGlobalCommittedLsn.get(), maxGlobalCommittedLsnInResponses)); @@ -655,7 +668,7 @@ private Mono waitForReadBarrierAsync( JavaStreamUtils.toString(responses, "; ")); } // retries exhausted - return Flux.just(false); + return Flux.just(new WaitForReadBarrierResult(false, null)); } else { // delay @@ -673,8 +686,8 @@ private Mono waitForReadBarrierAsync( .flatMap(barrierRequestSucceeded -> Flux.defer(() -> { - if (barrierRequestSucceeded) { - return Flux.just(true); + if (barrierRequestSucceeded.isSuccess) { + return Flux.just(barrierRequestSucceeded); } // we will go into global strong read barrier mode for global strong requests after regular barrier calls have been exhausted. @@ -696,7 +709,7 @@ private Mono waitForReadBarrierAsync( if ((responses.stream().filter(response -> response.lsn >= readBarrierLsn).count() >= readQuorum) && maxGlobalCommittedLsnInResponses >= targetGlobalCommittedLSN) { - return Flux.just(true); + return Flux.just(new WaitForReadBarrierResult(true, null)); } maxGlobalCommittedLsn.set( @@ -708,7 +721,7 @@ private Mono waitForReadBarrierAsync( logger.debug("QuorumReader: waitForReadBarrierAsync - Last barrier for mult-region strong requests. Responses: {}", JavaStreamUtils.toString(responses, "; ")); } - return Flux.just(false); + return Flux.just(new WaitForReadBarrierResult(false, null)); } else { return Flux.empty(); } @@ -737,11 +750,11 @@ private Mono waitForReadBarrierAsync( // In case the above flux returns empty (which it will after all the retries have been exhausted), // We will just return false .switchIfEmpty( - Flux.defer(() -> { - logger.debug("QuorumReader: waitForReadBarrierAsync - TargetGlobalCommittedLsn: {}, MaxGlobalCommittedLsn: {}.", targetGlobalCommittedLSN, maxGlobalCommittedLsn); - return Flux.just(false); - }) - ).take(1).single(); + Flux.defer(() -> { + logger.debug("QuorumReader: waitForReadBarrierAsync - TargetGlobalCommittedLsn: {}, MaxGlobalCommittedLsn: {}.", targetGlobalCommittedLSN, maxGlobalCommittedLsn); + return Flux.just(new WaitForReadBarrierResult(false, null)); + }) + ).take(1).single(); } private boolean isQuorumMet( @@ -827,7 +840,18 @@ private enum ReadQuorumResultKind { QuorumMet, QuorumSelected, QuorumNotSelected, - QuorumNotPossibleInCurrentRegion + QuorumNotPossibleInCurrentRegion, + QuorumThrottled + } + + private class WaitForReadBarrierResult { + private final boolean isSuccess; + private final StoreResponse throttledResponse; + + private WaitForReadBarrierResult(boolean isSuccess, StoreResponse throttledResponse) { + this.isSuccess = isSuccess; + this.throttledResponse = throttledResponse; + } } private abstract class ReadResult { diff --git a/sdk/cosmos/azure-cosmos/src/main/java/module-info.java b/sdk/cosmos/azure-cosmos/src/main/java/module-info.java deleted file mode 100644 index f69228ebe38b..000000000000 --- a/sdk/cosmos/azure-cosmos/src/main/java/module-info.java +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - - -module com.azure.cosmos { - - requires transitive com.azure.core; - - requires com.fasterxml.jackson.datatype.jsr310; - requires io.netty.transport; - requires io.netty.handler; - requires io.netty.common; - requires io.netty.buffer; - requires io.netty.codec; - requires io.netty.resolver; - requires io.netty.codec.http; - requires io.netty.codec.http2; - requires io.netty.transport.classes.epoll; - requires io.netty.handler.proxy; - requires reactor.netty.core; - requires reactor.netty.http; - requires com.codahale.metrics; - requires java.management; - requires jdk.management; - requires micrometer.core; - // This is only required by guava shaded libraries - requires java.logging; - requires HdrHistogram; - - // public API surface area - exports com.azure.cosmos; - exports com.azure.cosmos.models; - exports com.azure.cosmos.util; - - // export packages for multiple different modules - exports com.azure.cosmos.implementation to com.azure.cosmos.encryption, com.azure.cosmos.test, com.azure.cosmos.kafka.connect; - exports com.azure.cosmos.implementation.caches to com.azure.cosmos.encryption, com.azure.cosmos.test; - exports com.azure.cosmos.implementation.feedranges to com.azure.cosmos.encryption, com.azure.cosmos.test; - exports com.azure.cosmos.implementation.apachecommons.lang to com.azure.cosmos.encryption, com.azure.cosmos.test, com.azure.cosmos.kafka.connect; - exports com.azure.cosmos.implementation.guava25.base to com.azure.cosmos.encryption, com.azure.cosmos.test, com.azure.cosmos.kafka.connect; - exports com.azure.cosmos.implementation.guava25.collect to com.azure.cosmos.encryption, com.azure.cosmos.test, com.azure.cosmos.kafka.connect; - exports com.azure.cosmos.implementation.guava27 to com.azure.cosmos.encryption, com.azure.cosmos.test, com.azure.cosmos.kafka.connect; - exports com.azure.cosmos.implementation.directconnectivity to com.azure.cosmos.encryption, com.azure.cosmos.test; - opens com.azure.cosmos.implementation to com.fasterxml.jackson.databind, java.logging, com.fasterxml.jackson.module.afterburner; - - // exporting implementation packages specifically for cosmos encryption - exports com.azure.cosmos.implementation.batch to com.azure.cosmos.encryption; - exports com.azure.cosmos.implementation.patch to com.azure.cosmos.encryption; - exports com.azure.cosmos.implementation.query to com.azure.cosmos.encryption; - exports com.azure.cosmos.implementation.apachecommons.lang.tuple to com.azure.cosmos.encryption, com.azure.cosmos.kafka.connect; - - // exporting some packages specifically for Jackson - opens com.azure.cosmos.implementation.caches to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.changefeed to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.changefeed.common to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.changefeed.pkversion to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.changefeed.epkversion to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.feedranges to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.changefeed.exceptions to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.directconnectivity to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.directconnectivity.rntbd to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.http to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.query to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.query.aggregation to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.query.metrics to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.query.orderbyquery to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.query.hybridsearch to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.routing to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.clienttelemetry to com.fasterxml.jackson.databind; - opens com.azure.cosmos.util to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.throughputControl to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.throughputControl.sdk.controller.group.global to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.perPartitionCircuitBreaker to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.perPartitionAutomaticFailover to com.fasterxml.jackson.databind; - - // exporting packages specifically for cosmos test - exports com.azure.cosmos.implementation.faultinjection to com.azure.cosmos.test; - exports com.azure.cosmos.implementation.directconnectivity.rntbd to com.azure.cosmos.test; - exports com.azure.cosmos.implementation.routing to com.azure.cosmos.test; - opens com.azure.cosmos to com.azure.cosmos.test, com.azure.spring.data.cosmos, com.fasterxml.jackson.databind, com.fasterxml.jackson.module.afterburner, java.logging; - opens com.azure.cosmos.models to com.azure.cosmos.test, com.azure.spring.data.cosmos, com.fasterxml.jackson.databind, com.fasterxml.jackson.module.afterburner, java.logging; - opens com.azure.cosmos.implementation.throughputControl.sdk to com.fasterxml.jackson.databind; - opens com.azure.cosmos.implementation.throughputControl.sdk.config to com.fasterxml.jackson.databind; - - exports com.azure.cosmos.implementation.interceptor to com.azure.cosmos.test; - - uses com.azure.cosmos.implementation.guava25.base.PatternCompiler; - uses com.azure.core.util.tracing.Tracer; -}