From 571c9df9a6ab1613ea61311ad80be39fe41ff8ec Mon Sep 17 00:00:00 2001 From: Bhaskar Mallapragada Date: Thu, 30 Apr 2020 01:48:36 -0700 Subject: [PATCH 1/7] Autoscale/Autopilot support - Added ThroughputProperties class which contains factories for creating autoscaled or fixed throughput - Added ThroughputResponse class to fetch relevant details of offer response - Added overloads for database and container to create using throughput properties - Added read and replace overloads for database and container to read or replace throughput response --- .../com/azure/cosmos/CosmosAsyncClient.java | 14 +++ .../azure/cosmos/CosmosAsyncContainer.java | 65 ++++++++++++ .../com/azure/cosmos/CosmosAsyncDatabase.java | 85 +++++++++++++++ .../com/azure/cosmos/CosmosContainer.java | 20 ++++ .../java/com/azure/cosmos/CosmosDatabase.java | 41 ++++++- .../cosmos/implementation/Constants.java | 5 + .../cosmos/implementation/HttpConstants.java | 3 + .../azure/cosmos/implementation/Offer.java | 93 +++++++++++++++- .../OfferAutoscaleAutoUpgradeProperties.java | 42 ++++++++ .../OfferAutoscaleSettings.java | 55 ++++++++++ .../cosmos/implementation/RequestOptions.java | 10 ++ .../implementation/RxDocumentClientImpl.java | 25 +++++ .../models/CosmosContainerRequestOptions.java | 7 ++ .../models/CosmosDatabaseRequestOptions.java | 8 ++ .../azure/cosmos/models/CosmosResponse.java | 2 +- .../cosmos/models/ModelBridgeInternal.java | 24 +++++ .../cosmos/models/ThroughputProperties.java | 100 ++++++++++++++++++ .../cosmos/models/ThroughputResponse.java | 52 +++++++++ .../azure/cosmos/CosmosResponseValidator.java | 4 +- .../azure/cosmos/rx/CollectionCrudTest.java | 30 ++++++ .../com/azure/cosmos/rx/DatabaseCrudTest.java | 25 +++++ 21 files changed, 706 insertions(+), 4 deletions(-) create mode 100644 sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/OfferAutoscaleAutoUpgradeProperties.java create mode 100644 sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/OfferAutoscaleSettings.java create mode 100644 sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java create mode 100644 sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputResponse.java diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncClient.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncClient.java index e30ff232cd61..860338890e9b 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncClient.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncClient.java @@ -16,6 +16,7 @@ import com.azure.cosmos.models.FeedOptions; import com.azure.cosmos.models.ModelBridgeInternal; import com.azure.cosmos.models.SqlQuerySpec; +import com.azure.cosmos.models.ThroughputProperties; import com.azure.cosmos.util.CosmosPagedFlux; import com.azure.cosmos.util.UtilBridgeInternal; import io.micrometer.core.instrument.MeterRegistry; @@ -323,6 +324,19 @@ public Mono createDatabase(String id, int throughpu return createDatabase(new CosmosDatabaseProperties(id), options); } + /** + * Creates a database. + * + * @param id the id + * @param throughputProperties the throughputProperties + * @return the mono + */ + public Mono createDatabase(String id, ThroughputProperties throughputProperties) { + CosmosDatabaseRequestOptions options = new CosmosDatabaseRequestOptions(); + ModelBridgeInternal.setOfferProperties(options, throughputProperties); + return createDatabase(new CosmosDatabaseProperties(id), options); + } + /** * Reads all databases. *

diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java index f33665cdbc54..d3245fad83b7 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java @@ -19,6 +19,8 @@ import com.azure.cosmos.models.ModelBridgeInternal; import com.azure.cosmos.models.PartitionKey; import com.azure.cosmos.models.SqlQuerySpec; +import com.azure.cosmos.models.ThroughputProperties; +import com.azure.cosmos.models.ThroughputResponse; import com.azure.cosmos.util.CosmosPagedFlux; import com.azure.cosmos.util.UtilBridgeInternal; import reactor.core.publisher.Flux; @@ -661,6 +663,69 @@ public Mono replaceProvisionedThroughput(int requestUnitsPerSecond) { }).map(offerResourceResponse -> offerResourceResponse.getResource().getThroughput()); } + /** + * Replace the throughput . + * + * @param throughputProperties the throughput properties + * @return the mono containing throughput response + */ + public Mono replaceThroughput(ThroughputProperties throughputProperties) { + return this.read() + .flatMap(response -> this.database.getDocClientWrapper() + .queryOffers("select * from c where c.offerResourceId = '" + + response.getProperties() + .getResourceId() + + "'", new FeedOptions()) + .single() + .flatMap(offerFeedResponse -> { + if (offerFeedResponse.getResults().isEmpty()) { + return Mono.error(BridgeInternal + .createCosmosClientException( + HttpConstants.StatusCodes.BADREQUEST, + "No offers found for the " + + "resource")); + } + + Offer existingOffer = offerFeedResponse.getResults().get(0); + ModelBridgeInternal.updateOfferFromProperties(existingOffer, + throughputProperties); + return this.database.getDocClientWrapper() + .replaceOffer(existingOffer) + .single(); + }).map(ModelBridgeInternal::createThroughputRespose)); + } + + /** + * Read the throughput throughput . + * + * @return the mono containing throughput response + */ + public Mono readThroughput() { + return this.read() + .flatMap(response -> this.database.getDocClientWrapper() + .queryOffers("select * from c where c.offerResourceId = '" + + response + .getProperties() + .getResourceId() + "'", + new FeedOptions()) + .single() + .flatMap(offerFeedResponse -> { + if (offerFeedResponse.getResults().isEmpty()) { + return Mono.error(BridgeInternal + .createCosmosClientException( + HttpConstants.StatusCodes.BADREQUEST, + "No offers found for the resource")); + } + return this.database.getDocClientWrapper() + .readOffer(offerFeedResponse.getResults() + .get(0) + .getSelfLink()) + .single(); + }) + .map(ModelBridgeInternal::createThroughputRespose)); + } + + /** * Gets the parent Database * diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java index f84535a1ee77..e88a6ece137a 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java @@ -11,12 +11,15 @@ import com.azure.cosmos.models.CosmosAsyncUserResponse; import com.azure.cosmos.models.CosmosContainerProperties; import com.azure.cosmos.models.CosmosContainerRequestOptions; +import com.azure.cosmos.models.CosmosDatabaseProperties; import com.azure.cosmos.models.CosmosDatabaseRequestOptions; import com.azure.cosmos.models.CosmosUserProperties; import com.azure.cosmos.models.FeedOptions; import com.azure.cosmos.models.ModelBridgeInternal; import com.azure.cosmos.models.SqlQuerySpec; import com.azure.cosmos.implementation.apachecommons.lang.StringUtils; +import com.azure.cosmos.models.ThroughputProperties; +import com.azure.cosmos.models.ThroughputResponse; import com.azure.cosmos.util.CosmosPagedFlux; import com.azure.cosmos.util.UtilBridgeInternal; import reactor.core.Exceptions; @@ -154,6 +157,22 @@ public Mono createContainer( return createContainer(containerProperties, options); } + /** + * Creates a container. + * + * @param containerProperties the container properties + * @param throughputProperties the throughput properties + * @param options the request options + * @return the mono + */ + public Mono createContainer( + CosmosContainerProperties containerProperties, + ThroughputProperties throughputProperties, + CosmosContainerRequestOptions options){ + ModelBridgeInternal.setOfferProperties(options, throughputProperties); + return createContainer(containerProperties, options); + } + /** * Creates a document container. *

@@ -663,6 +682,72 @@ public Mono replaceProvisionedThroughput(int requestUnitsPerSecond) { .getThroughput())); } + /** + * Sets throughput provisioned for a container in measurement of + * Requests-per-Unit in the Azure Cosmos service. + * + * @param throughputProperties the throughput properties + * @return the mono + */ + public Mono replaceThroughput(ThroughputProperties throughputProperties) { + return this.read() + .flatMap(response -> this.getDocClientWrapper() + .queryOffers("select * from c where c.offerResourceId = '" + + response.getProperties() + .getResourceId() + + "'", new FeedOptions()) + .single() + .flatMap(offerFeedResponse -> { + if (offerFeedResponse.getResults().isEmpty()) { + return Mono.error(BridgeInternal + .createCosmosClientException( + HttpConstants.StatusCodes.BADREQUEST, + "No offers found for the " + + "resource")); + } + + Offer existingOffer = offerFeedResponse.getResults().get(0); + ModelBridgeInternal.updateOfferFromProperties(existingOffer, + throughputProperties); + + return this.getDocClientWrapper() + .replaceOffer(existingOffer) + .single(); + }) + .map(ModelBridgeInternal::createThroughputRespose)); + } + + /** + * Gets the throughput of the database + * + * @return the mono containing throughput response + */ + public Mono readThroughput() { + return this.read() + .flatMap(response -> getDocClientWrapper() + .queryOffers("select * from c where c.offerResourceId = '" + + response + .getProperties() + .getResourceId() + "'", + new FeedOptions()) + .single() + .flatMap(offerFeedResponse -> { + if (offerFeedResponse.getResults().isEmpty()) { + return Mono.error(BridgeInternal + .createCosmosClientException( + HttpConstants.StatusCodes.BADREQUEST, + "No offers found for the " + + "resource")); + } + return getDocClientWrapper() + .readOffer(offerFeedResponse.getResults() + .get(0) + .getSelfLink()) + .single(); + }) + .map(ModelBridgeInternal::createThroughputRespose)); + } + CosmosAsyncClient getClient() { return client; } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosContainer.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosContainer.java index bb9c874f3d44..06002438b337 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosContainer.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosContainer.java @@ -13,6 +13,8 @@ import com.azure.cosmos.models.ModelBridgeInternal; import com.azure.cosmos.models.PartitionKey; import com.azure.cosmos.models.SqlQuerySpec; +import com.azure.cosmos.models.ThroughputProperties; +import com.azure.cosmos.models.ThroughputResponse; import com.azure.cosmos.util.CosmosPagedFlux; import com.azure.cosmos.util.CosmosPagedIterable; import com.azure.cosmos.util.UtilBridgeInternal; @@ -140,6 +142,24 @@ public Integer replaceProvisionedThroughput(int requestUnitsPerSecond) throws Co .replaceProvisionedThroughput(requestUnitsPerSecond)); } + /** + * Sets the throughput. + * + * @param throughputProperties the throughput properties + * @return the throughput response + */ + public ThroughputResponse replaceThroughput(ThroughputProperties throughputProperties) { + return database.throughputResponseToBlock(this.asyncContainer.replaceThroughput(throughputProperties)); + } + + /** + * Gets the throughput. + * + * @return the throughput response + */ + public ThroughputResponse readThroughput() { + return database.throughputResponseToBlock(this.asyncContainer.readThroughput()); + } /* CosmosAsyncItem operations */ diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosDatabase.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosDatabase.java index 9fee11c726be..cf9fd465ed70 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosDatabase.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosDatabase.java @@ -15,6 +15,8 @@ import com.azure.cosmos.models.FeedOptions; import com.azure.cosmos.models.ModelBridgeInternal; import com.azure.cosmos.models.SqlQuerySpec; +import com.azure.cosmos.models.ThroughputProperties; +import com.azure.cosmos.models.ThroughputResponse; import com.azure.cosmos.util.CosmosPagedFlux; import com.azure.cosmos.util.CosmosPagedIterable; import com.azure.cosmos.util.UtilBridgeInternal; @@ -155,6 +157,24 @@ public CosmosContainerResponse createContainer( options)); } + /** + * Creates a cosmos container. + * + * @param containerProperties the container properties + * @param throughputProperties the throughput properties + * @param options the options + * @return the cosmos container response + * @throws CosmosClientException the cosmos client exception + */ + public CosmosContainerResponse createContainer( + CosmosContainerProperties containerProperties, + ThroughputProperties throughputProperties, + CosmosContainerRequestOptions options) throws CosmosClientException { + return this.mapContainerResponseAndBlock(databaseWrapper.createContainer(containerProperties, + throughputProperties, + options)); + } + /** * Create container cosmos sync container response. * @@ -479,7 +499,26 @@ public Integer replaceProvisionedThroughput(int requestUnitsPerSecond) throws Co return throughputResponseToBlock(databaseWrapper.replaceProvisionedThroughput(requestUnitsPerSecond)); } - Integer throughputResponseToBlock(Mono throughputResponse) throws CosmosClientException { + /** + * Sets the throughput. + * + * @param throughputProperties the throughput properties + * @return the throughput response + */ + public ThroughputResponse replaceThroughput(ThroughputProperties throughputProperties) { + return throughputResponseToBlock(databaseWrapper.replaceThroughput(throughputProperties)); + } + + /** + * Gets the throughput of the database + * + * @return the throughput response + */ + public ThroughputResponse readThroughput() { + return throughputResponseToBlock(databaseWrapper.readThroughput()); + } + + T throughputResponseToBlock(Mono throughputResponse) throws CosmosClientException { try { return throughputResponse.block(); } catch (Exception ex) { diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Constants.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Constants.java index 5e1fac067138..fea6a976cb21 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Constants.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Constants.java @@ -50,6 +50,11 @@ public static final class Properties { public static final String DOCUMENTS_LINK = "_docs"; public static final String RESOURCE_LINK = "resource"; public static final String MEDIA_LINK = "media"; + public static final String AUTOPILOT_MAX_THROUGHPUT = "maxThroughput"; + public static final String AUTOPILOT_AUTO_UPGRADE_POLICY = "autoUpgradePolicy"; + public static final String AUTOPILOT_AUTO_THROUGHPUT_POLICY = "throughputPolicy"; + public static final String AUTOPILOT_THROUGHPUT_POLICY_INCREMENT_PERCENT = "incrementPercent"; + public static final String AUTOPILOT_SETTINGS = "offerAutopilotSettings"; public static final String PERMISSION_MODE = "permissionMode"; public static final String RESOURCE_KEY = "key"; 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 6b85e9cfc80d..3a37d5bcad7c 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 @@ -171,6 +171,9 @@ public static class HttpHeaders { public static final String OFFER_TYPE = "x-ms-offer-type"; public static final String OFFER_THROUGHPUT = "x-ms-offer-throughput"; public static final String OFFER_IS_RU_PER_MINUTE_THROUGHPUT_ENABLED = "x-ms-offer-is-ru-per-minute-throughput-enabled"; + public static final String OFFER_MIN_THROUGHPUT = "x-ms-cosmos-min-throughput"; + public static final String OFFER_AUTOPILOT_SETTINGS = "x-ms-cosmos-offer-autopilot-settings"; + public static final String OFFER_REPLACE_PENDING = "x-ms-offer-replace-pending"; // Upsert header public static final String IS_UPSERT = "x-ms-documentdb-is-upsert"; diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java index 0364a22f11b6..3190be775365 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java @@ -4,6 +4,7 @@ package com.azure.cosmos.implementation; import com.azure.cosmos.BridgeInternal; +import com.azure.cosmos.models.ModelBridgeInternal; import com.azure.cosmos.models.Resource; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -26,6 +27,18 @@ public Offer(int offerThroughput) { this.setContent(content); } + Offer(OfferAutoscaleSettings offerAutoscaleSettings) { + super(); + this.setOfferVersion(Constants.Properties.OFFER_VERSION_V2); + this.setOfferType(""); + ObjectNode content = Utils.getSimpleObjectMapper().createObjectNode(); +// content.put(Constants.Properties.OFFER_THROUGHPUT, null); + content.replace(Constants.Properties.AUTOPILOT_SETTINGS, ModelBridgeInternal + .getPropertyBagFromJsonSerializable(offerAutoscaleSettings)); + this.setContent(content); + } + + /** * Initialize an offer object from json string. * @@ -34,7 +47,71 @@ public Offer(int offerThroughput) { public Offer(String jsonString) { super(jsonString); } - + + /** + * Create fixed offer offer. + * + * @param throughput the throughput + * @return the offer + */ + public static Offer createFixedOffer(int throughput) { + return new Offer(throughput); + } + + /** + * Create autoscale offer offer. + * + * @param startingMaxThroughput the starting max throughput + * @param autoUpgradeMaxThroughputIncrementPercentage the auto upgrade max throughput increment percentage + * @return the offer + */ + public static Offer createAutoscaleOffer( + int startingMaxThroughput, + int autoUpgradeMaxThroughputIncrementPercentage) { + return new Offer(new OfferAutoscaleSettings(startingMaxThroughput, + autoUpgradeMaxThroughputIncrementPercentage)); + } + + /** + * Gets offer auto scale settings. + * + * @return the offer auto scale settings + */ + public OfferAutoscaleSettings getOfferAutoScaleSettings() { + if (this.getContent().hasNonNull(Constants.Properties.AUTOPILOT_SETTINGS)) { + return new OfferAutoscaleSettings((ObjectNode) this.getContent() + .get(Constants.Properties.AUTOPILOT_SETTINGS)); + } else { + return null; + } + } + + /** + * Gets max autoscale throughput. + * + * @return the max autoscale throughput + */ + public int getMaxAutoscaleThroughput() { + OfferAutoscaleSettings offerAutoscaleSettings = this.getOfferAutoScaleSettings(); + if (offerAutoscaleSettings != null) { + return offerAutoscaleSettings.getMaxThroughput(); + } else { + return 0; + } + } + + /** + * Sets max autoscale throughput. + * + * @param maxAutoscaleThroughput the max autoscale throughput + */ + public void setMaxAutoscaleThroughput(int maxAutoscaleThroughput) { + OfferAutoscaleSettings offerAutoscaleSettings = this.getOfferAutoScaleSettings(); + if (offerAutoscaleSettings != null) { + offerAutoscaleSettings.setMaxThroughput(maxAutoscaleThroughput); + } + } + /** * Gets the self-link of a resource to which the resource offer applies. * @@ -116,6 +193,15 @@ public int getThroughput() { return this.getContent().get(Constants.Properties.OFFER_THROUGHPUT).asInt(); } + /** + * Has offer throughput. + * + * @return the if the offer has throughput + */ + public boolean hasOfferThroughput(){ + return this.getContent().hasNonNull(Constants.Properties.OFFER_THROUGHPUT); + } + /** * Sets the offer throughput for this offer. * @@ -142,4 +228,9 @@ public String getString(String propertyName) { public Integer getInt(String propertyName) { return super.getInt(propertyName); } + + public void updateAutoscaleThroughput(int maxAutoscaleThroughput) { + this.getOfferAutoScaleSettings().setMaxThroughput(maxAutoscaleThroughput); + } + } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/OfferAutoscaleAutoUpgradeProperties.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/OfferAutoscaleAutoUpgradeProperties.java new file mode 100644 index 000000000000..13f7671c5778 --- /dev/null +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/OfferAutoscaleAutoUpgradeProperties.java @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.cosmos.implementation; + +import com.azure.cosmos.models.JsonSerializable; +import com.azure.cosmos.models.ModelBridgeInternal; +import com.fasterxml.jackson.databind.node.ObjectNode; + +public class OfferAutoscaleAutoUpgradeProperties extends JsonSerializable { + + private AutoscaleThroughputProperties autoscaleThroughputProperties; + + OfferAutoscaleAutoUpgradeProperties(int maxThroughputIncrementPercentage) { + this.autoscaleThroughputProperties = new AutoscaleThroughputProperties(maxThroughputIncrementPercentage); + super.set(Constants.Properties.AUTOPILOT_AUTO_THROUGHPUT_POLICY, autoscaleThroughputProperties); + } + + OfferAutoscaleAutoUpgradeProperties(ObjectNode objectNode) { + super(objectNode); + } + + AutoscaleThroughputProperties getAutoscaleThroughputProperties() { + return autoscaleThroughputProperties; + } + + public static class AutoscaleThroughputProperties extends JsonSerializable { + + AutoscaleThroughputProperties(int maxThroughputIncrementPercentage) { + super.set(Constants.Properties.AUTOPILOT_THROUGHPUT_POLICY_INCREMENT_PERCENT, + maxThroughputIncrementPercentage); + } + + /** + * Getter for property 'incrementPercent'. + * + * @return Value for property 'incrementPercent'. + */ + int getIncrementPercent() { + return this.getInt(Constants.Properties.AUTOPILOT_THROUGHPUT_POLICY_INCREMENT_PERCENT); + } + } +} diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/OfferAutoscaleSettings.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/OfferAutoscaleSettings.java new file mode 100644 index 000000000000..d53a6f2688b6 --- /dev/null +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/OfferAutoscaleSettings.java @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.cosmos.implementation; + +import com.azure.cosmos.models.JsonSerializable; +import com.azure.cosmos.models.ModelBridgeInternal; +import com.fasterxml.jackson.databind.node.ObjectNode; + + +public class OfferAutoscaleSettings extends JsonSerializable { + OfferAutoscaleAutoUpgradeProperties offerAutoscaleAutoUpgradeProperties; + + OfferAutoscaleSettings(final int maxThroughput, int maxThroughputIncrementPercentage) { + super(); + offerAutoscaleAutoUpgradeProperties = new OfferAutoscaleAutoUpgradeProperties(maxThroughputIncrementPercentage); + super.set(Constants.Properties.AUTOPILOT_MAX_THROUGHPUT, maxThroughput); + super.set(Constants.Properties.AUTOPILOT_AUTO_UPGRADE_POLICY, offerAutoscaleAutoUpgradeProperties); + } + + OfferAutoscaleSettings(String json) { + super(json); + } + + OfferAutoscaleSettings(ObjectNode objectNode) { + super(objectNode); + } + + /** + * Getter for property 'maxThroughput'. + * + * @return Value for property 'maxThroughput'. + */ + int getMaxThroughput() { + return this.getInt(Constants.Properties.AUTOPILOT_MAX_THROUGHPUT); + } + + void setMaxThroughput(int maxAutoscaleThroughput) { + super.set(Constants.Properties.AUTOPILOT_MAX_THROUGHPUT, maxAutoscaleThroughput); + } + + /** + * Getter for property 'autoscaleAutoUpgradeProperties'. + * + * @return Value for property 'autoscaleAutoUpgradeProperties'. + */ + OfferAutoscaleAutoUpgradeProperties getAutoscaleAutoUpgradeProperties() { + if (offerAutoscaleAutoUpgradeProperties == null) { + if (this.has(Constants.Properties.AUTOPILOT_AUTO_UPGRADE_POLICY)) + offerAutoscaleAutoUpgradeProperties = + new OfferAutoscaleAutoUpgradeProperties((ObjectNode) this.get(Constants.Properties + .AUTOPILOT_AUTO_UPGRADE_POLICY)); + } + return offerAutoscaleAutoUpgradeProperties; + } +} diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RequestOptions.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RequestOptions.java index 62b7a14154cc..31cc4e95ec4e 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RequestOptions.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RequestOptions.java @@ -7,6 +7,7 @@ import com.azure.cosmos.ConsistencyLevel; import com.azure.cosmos.models.IndexingDirective; import com.azure.cosmos.models.PartitionKey; +import com.azure.cosmos.models.ThroughputProperties; import java.util.HashMap; import java.util.List; @@ -31,6 +32,7 @@ public class RequestOptions { private boolean scriptLoggingEnabled; private boolean populateQuotaInfo; private Map properties; + private ThroughputProperties throughputProperties; /** * Gets the triggers to be invoked before the operation. @@ -194,6 +196,14 @@ public void setOfferThroughput(Integer offerThroughput) { this.offerThroughput = offerThroughput; } + public void setThroughputProperties(ThroughputProperties throughputProperties) { + this.throughputProperties = throughputProperties; + } + + public ThroughputProperties getThroughputProperties() { + return this.throughputProperties; + } + /** * Gets the partition key used to identify the current request's target partition. * diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java index 9f3f52ffffbe..88fadc3d5116 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java @@ -904,6 +904,31 @@ private Map getRequestHeaders(RequestOptions options) { headers.put(HttpConstants.HttpHeaders.OFFER_TYPE, options.getOfferType()); } + if (options.getOfferThroughput() == null) { + if (options.getThroughputProperties() != null) { + Offer offer = ModelBridgeInternal.getOfferFromThroughputProperties(options.getThroughputProperties()); + final OfferAutoscaleAutoUpgradeProperties autoscaleAutoUpgradeProperties + = offer.getOfferAutoScaleSettings().getAutoscaleAutoUpgradeProperties(); + if (offer.hasOfferThroughput() && + (offer.getOfferAutoScaleSettings().getMaxThroughput() >= 0 || + autoscaleAutoUpgradeProperties != null && + autoscaleAutoUpgradeProperties + .getAutoscaleThroughputProperties() + .getIncrementPercent() >= 0)) { + throw new IllegalArgumentException("Autoscale provisioned throughput can not be configured with " + + "fixed offer"); + } + + if (offer.hasOfferThroughput()) { + headers.put(HttpConstants.HttpHeaders.OFFER_THROUGHPUT, options.getOfferThroughput().toString()); + } else if (offer.getOfferAutoScaleSettings() != null) { + headers.put(HttpConstants.HttpHeaders.OFFER_AUTOPILOT_SETTINGS, + ModelBridgeInternal.toJsonFromJsonSerializable(offer.getOfferAutoScaleSettings())); + } + } + } + + if (options.isPopulateQuotaInfo()) { headers.put(HttpConstants.HttpHeaders.POPULATE_QUOTA_INFO, String.valueOf(true)); } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosContainerRequestOptions.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosContainerRequestOptions.java index 80e2fcc74c62..331184db2f1e 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosContainerRequestOptions.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosContainerRequestOptions.java @@ -14,6 +14,7 @@ public final class CosmosContainerRequestOptions { private ConsistencyLevel consistencyLevel; private String sessionToken; private AccessCondition accessCondition; + private ThroughputProperties throughputProperties; /** * Gets the throughput in the form of Request Units per second when creating a cosmos container. @@ -119,6 +120,11 @@ public CosmosContainerRequestOptions setAccessCondition(AccessCondition accessCo return this; } + CosmosContainerRequestOptions setThroughputProperties(ThroughputProperties throughputProperties) { + this.throughputProperties = throughputProperties; + return this; + } + RequestOptions toRequestOptions() { RequestOptions options = new RequestOptions(); options.setAccessCondition(accessCondition); @@ -126,6 +132,7 @@ RequestOptions toRequestOptions() { options.setPopulateQuotaInfo(populateQuotaInfo); options.setSessionToken(sessionToken); options.setConsistencyLevel(consistencyLevel); + options.setThroughputProperties(this.throughputProperties); return options; } } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosDatabaseRequestOptions.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosDatabaseRequestOptions.java index 3fe4b1d5d976..f810e57cfd21 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosDatabaseRequestOptions.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosDatabaseRequestOptions.java @@ -2,6 +2,7 @@ // Licensed under the MIT License. package com.azure.cosmos.models; +import com.azure.cosmos.implementation.Offer; import com.azure.cosmos.implementation.RequestOptions; /** @@ -10,6 +11,7 @@ public final class CosmosDatabaseRequestOptions { private Integer offerThroughput; private AccessCondition accessCondition; + private ThroughputProperties throughputProperties; /** * Gets the conditions associated with the request. @@ -51,10 +53,16 @@ CosmosDatabaseRequestOptions setOfferThroughput(Integer offerThroughput) { return this; } + CosmosDatabaseRequestOptions setThroughputProperties(ThroughputProperties throughputProperties) { + this.throughputProperties = throughputProperties; + return this; + } + RequestOptions toRequestOptions() { RequestOptions options = new RequestOptions(); options.setAccessCondition(accessCondition); options.setOfferThroughput(offerThroughput); + options.setThroughputProperties(this.throughputProperties); return options; } } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosResponse.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosResponse.java index d81f04396180..cded9a4d3b3a 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosResponse.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosResponse.java @@ -13,7 +13,7 @@ * The cosmos response * @param the type of resource */ -public class CosmosResponse { +public class CosmosResponse { private T properties; protected final ResourceResponse resourceResponseWrapper; diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ModelBridgeInternal.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ModelBridgeInternal.java index 4f2280c979cd..c978c8fbac9a 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ModelBridgeInternal.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ModelBridgeInternal.java @@ -20,6 +20,7 @@ import com.azure.cosmos.implementation.Document; import com.azure.cosmos.implementation.DocumentCollection; import com.azure.cosmos.implementation.HttpConstants; +import com.azure.cosmos.implementation.Offer; import com.azure.cosmos.implementation.PartitionKeyRange; import com.azure.cosmos.implementation.Permission; import com.azure.cosmos.implementation.QueryMetrics; @@ -226,6 +227,22 @@ public static CosmosDatabaseRequestOptions setOfferThroughput(CosmosDatabaseRequ return cosmosDatabaseRequestOptions.setOfferThroughput(offerThroughput); } + public static CosmosDatabaseRequestOptions setOfferProperties( + CosmosDatabaseRequestOptions cosmosDatabaseRequestOptions, + ThroughputProperties throughputProperties) { + return cosmosDatabaseRequestOptions.setThroughputProperties(throughputProperties); + } + + public static CosmosContainerRequestOptions setOfferProperties( + CosmosContainerRequestOptions containerRequestOptions, + ThroughputProperties throughputProperties) { + return containerRequestOptions.setThroughputProperties(throughputProperties); + } + + public static Offer updateOfferFromProperties(Offer offer, ThroughputProperties properties) { + return properties.updateOfferFromProperties(offer); + } + public static CosmosItemRequestOptions setPartitionKey(CosmosItemRequestOptions cosmosItemRequestOptions, PartitionKey partitionKey) { return cosmosItemRequestOptions.setPartitionKey(partitionKey); @@ -483,4 +500,11 @@ public static void setFeedOptionsMaxItemCount(FeedOptions feedOptions, Integer m feedOptions.setMaxItemCount(maxItemCount); } + public static Offer getOfferFromThroughputProperties(ThroughputProperties properties) { + return properties.getOffer(); + } + + public static ThroughputResponse createThroughputRespose(ResourceResponse offerResourceResponse) { + return new ThroughputResponse(offerResourceResponse); + } } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java new file mode 100644 index 000000000000..ef4aa3a50b96 --- /dev/null +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.cosmos.models; + +import com.azure.cosmos.implementation.Offer; +import com.azure.cosmos.implementation.OfferAutoscaleSettings; + +/** + * Represents throughput of the resources in the Azure Cosmos DB service. + */ +public class ThroughputProperties { + private final Offer offer; + + ThroughputProperties(Offer offer) { + this.offer = offer; + } + + /** + * Create fixed throughput properties. + * + * @param throughput the throughput + * @return the throughput properties + */ + public static ThroughputProperties createFixedThroughput(int throughput) { + return new ThroughputProperties(Offer.createFixedOffer(throughput)); + } + + /** + * Create auto scale throughput properties. + * + * @param maxAutoScaleThroughput the max auto scale throughput + * @param autoUpgradethroughputIncrementPercentage the auto upgrade max throughput increment percentage + * @return the throughput properties + */ + public static ThroughputProperties createAutoScaledProvisionedThroughput( + int maxAutoScaleThroughput, + int autoUpgradethroughputIncrementPercentage) { + return new ThroughputProperties(Offer.createAutoscaleOffer(maxAutoScaleThroughput, + autoUpgradethroughputIncrementPercentage)); + } + + /** + * Create auto scaled provisioned throughput throughput properties. + * + * @param maxAutoScaleThroughput the max auto scale throughput + * @return the throughput properties + */ + public static ThroughputProperties createAutoScaledProvisionedThroughput(int maxAutoScaleThroughput) { + return new ThroughputProperties(Offer.createAutoscaleOffer(maxAutoScaleThroughput, + 0)); + } + + /** + * Gets offer throughput. + * + * @return the offer throughput + */ + public Integer getOfferThroughput() { + return offer.getThroughput(); + } + + /** + * Gets offer autoscale properties. + * + * @return the offer autoscale properties + */ + public OfferAutoscaleSettings getOfferAutoscaleProperties() { + return this.offer.getOfferAutoScaleSettings(); + } + + /** + * Gets max autoscale throughput. + * + * @return the max autoscale throughput + */ + public int getMaxAutoscaleThroughput() { + return this.offer.getMaxAutoscaleThroughput(); + } + + + Offer getOffer() { + return this.offer; + } + + /** + * Get an updated offer based on the properties. + */ + Offer updateOfferFromProperties(Offer offer) { + /* + if autoscale is set then update autoscale values + else update fixedthroughput + */ + + if (this.getMaxAutoscaleThroughput() > 0) { + offer.updateAutoscaleThroughput(this.getMaxAutoscaleThroughput()); + } + return offer; + } + +} diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputResponse.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputResponse.java new file mode 100644 index 000000000000..f709dc7db0cb --- /dev/null +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputResponse.java @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.cosmos.models; + +import com.azure.cosmos.implementation.HttpConstants; +import com.azure.cosmos.implementation.Offer; +import com.azure.cosmos.implementation.ResourceResponse; + +/** + * The cosmos throughput response. + */ +public class ThroughputResponse extends CosmosResponse { + + private ResourceResponse offerResourceResponse; + private ThroughputProperties throughputProperties; + + ThroughputResponse(ResourceResponse offerResourceResponse) { + super(offerResourceResponse); + this.offerResourceResponse = offerResourceResponse; + } + + @Override + public ThroughputProperties getProperties(){ + if (throughputProperties == null){ + throughputProperties = new ThroughputProperties(offerResourceResponse.getResource()); + } + return throughputProperties; + } + + /** + * Gets minimum throughput in measurement of request units per second in the Azure Cosmos service. + * + * @return the minimun throughput + */ + public int getMinThroughput(){ + return Integer.parseInt(offerResourceResponse + .getResponseHeaders() + .get(HttpConstants.HttpHeaders.OFFER_MIN_THROUGHPUT)); + } + + /** + * Gets the status whether offer replace is successful or pending. + * + * @return the boolean representing the status + */ + public boolean isReplacePending(){ + return Boolean.parseBoolean(offerResourceResponse + .getResponseHeaders() + .get(HttpConstants.HttpHeaders.OFFER_REPLACE_PENDING)); + } + +} diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/CosmosResponseValidator.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/CosmosResponseValidator.java index b332307829a6..a4425c48d211 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/CosmosResponseValidator.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/CosmosResponseValidator.java @@ -226,7 +226,9 @@ public Builder notNullEtag() { @Override public void validate(T resourceResponse) { assertThat(resourceResponse.getProperties()).isNotNull(); - assertThat(resourceResponse.getProperties().getETag()).isNotNull(); + if (resourceResponse.getProperties() instanceof Resource) { + assertThat(((Resource)resourceResponse.getProperties()).getETag()).isNotNull(); + } } }); return this; diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java index 585bf91db842..274161295016 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java @@ -3,6 +3,7 @@ package com.azure.cosmos.rx; import com.azure.cosmos.BridgeInternal; +import com.azure.cosmos.CosmosContainer; import com.azure.cosmos.models.CompositePath; import com.azure.cosmos.models.CompositePathSortOrder; import com.azure.cosmos.CosmosAsyncClient; @@ -27,6 +28,8 @@ import com.azure.cosmos.implementation.Database; import com.azure.cosmos.implementation.FailureValidator; import com.azure.cosmos.implementation.RetryAnalyzer; +import com.azure.cosmos.models.ThroughputProperties; +import com.azure.cosmos.models.ThroughputResponse; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; @@ -367,6 +370,33 @@ public void sessionTokenConsistencyCollectionDeleteCreateSameName() { } } + @Test(groups = { "emulator" }, timeOut = TIMEOUT) + public void readReplaceAutoscaleThroughput() throws Exception { + safeDeleteDatabase(client.getDatabase("newTestDatabase")); + int initalThroughput = 5000; + ThroughputProperties throughputProperties = + ThroughputProperties.createAutoScaledProvisionedThroughput(initalThroughput, 50); + CosmosAsyncDatabase database = client.createDatabase("newTestDatabase") + .block() + .getDatabase(); + + CosmosContainerProperties containerProperties = new CosmosContainerProperties("testCol", "/myPk"); + CosmosAsyncContainer container = database.createContainer(containerProperties, throughputProperties, + new CosmosContainerRequestOptions()) + .block() + .getContainer(); + + // Read + ThroughputResponse readThroughputResponse = container.readThroughput().block(); + assertThat(readThroughputResponse.getProperties().getMaxAutoscaleThroughput()).isEqualTo(initalThroughput); + + // Replace + int tagetThroughput = 6000; + throughputProperties = ThroughputProperties.createAutoScaledProvisionedThroughput(tagetThroughput); + ThroughputResponse replaceResponse = container.replaceThroughput(throughputProperties).block(); + assertThat(replaceResponse.getProperties().getMaxAutoscaleThroughput()).isEqualTo(tagetThroughput); + } + @BeforeClass(groups = { "emulator" }, timeOut = SETUP_TIMEOUT) public void before_CollectionCrudTest() { client = getClientBuilder().buildAsyncClient(); diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java index acbbecede623..e37ee6bacca4 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java @@ -4,6 +4,8 @@ import com.azure.cosmos.CosmosAsyncClient; import com.azure.cosmos.CosmosAsyncDatabase; +import com.azure.cosmos.implementation.Offer; +import com.azure.cosmos.implementation.RequestOptions; import com.azure.cosmos.models.CosmosAsyncDatabaseResponse; import com.azure.cosmos.CosmosClientBuilder; import com.azure.cosmos.CosmosDatabaseForTest; @@ -11,6 +13,8 @@ import com.azure.cosmos.models.CosmosDatabaseRequestOptions; import com.azure.cosmos.CosmosResponseValidator; import com.azure.cosmos.implementation.FailureValidator; +import com.azure.cosmos.models.ThroughputProperties; +import com.azure.cosmos.models.ThroughputResponse; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Factory; @@ -20,6 +24,8 @@ import java.util.ArrayList; import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; + public class DatabaseCrudTest extends TestSuiteBase { private final String preExistingDatabaseId = CosmosDatabaseForTest.generateId(); private final List databases = new ArrayList<>(); @@ -108,6 +114,25 @@ public void deleteDatabase_DoesntExist() throws Exception { validateFailure(deleteObservable, validator); } + @Test(groups = { "emulator" }, timeOut = TIMEOUT) + public void readReplaceAutoscaleThroughput() throws Exception { + safeDeleteDatabase(client.getDatabase("newTestDatabase")); + int initalThroughput = 5000; + ThroughputProperties properties = ThroughputProperties.createAutoScaledProvisionedThroughput(initalThroughput, + 50); + CosmosAsyncDatabase database = client.createDatabase("newTestDatabase", properties) + .block() + .getDatabase(); + + ThroughputResponse readThroughputResponse = database.readThroughput().block(); + assertThat(readThroughputResponse.getProperties().getMaxAutoscaleThroughput()).isEqualTo(initalThroughput); + database.createContainer("testCol", "/myPk").block(); + int tagetThroughput = 6000; + properties = ThroughputProperties.createAutoScaledProvisionedThroughput(tagetThroughput); + ThroughputResponse replaceResponse = database.replaceThroughput(properties).block(); + assertThat(replaceResponse.getProperties().getMaxAutoscaleThroughput()).isEqualTo(tagetThroughput); + } + @BeforeClass(groups = { "emulator" }, timeOut = SETUP_TIMEOUT) public void before_DatabaseCrudTest() { client = getClientBuilder().buildAsyncClient(); From 6c76f5bcce71d4282c02576af722d2d2197d70bf Mon Sep 17 00:00:00 2001 From: Bhaskar Mallapragada Date: Thu, 30 Apr 2020 19:10:48 -0700 Subject: [PATCH 2/7] Fixing spotbug issue --- .../main/java/com/azure/cosmos/implementation/Offer.java | 9 +++++++++ .../java/com/azure/cosmos/models/ThroughputResponse.java | 4 +++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java index 3190be775365..1cc85c0743ba 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java @@ -48,6 +48,15 @@ public Offer(String jsonString) { super(jsonString); } + /** + * Instantiates a new Offer from object node. + * + * @param objectNode the object node + */ + public Offer(ObjectNode objectNode) { + super(objectNode); + } + /** * Create fixed offer offer. * diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputResponse.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputResponse.java index f709dc7db0cb..199d0882da82 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputResponse.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputResponse.java @@ -22,7 +22,9 @@ public class ThroughputResponse extends CosmosResponse { @Override public ThroughputProperties getProperties(){ if (throughputProperties == null){ - throughputProperties = new ThroughputProperties(offerResourceResponse.getResource()); + Offer offer = + new Offer(ModelBridgeInternal.getPropertyBagFromJsonSerializable(offerResourceResponse.getResource())); + throughputProperties = new ThroughputProperties(offer); } return throughputProperties; } From 2be9d9426979f3e2e8e5926077b6bcb4ded060de Mon Sep 17 00:00:00 2001 From: Bhaskar Mallapragada Date: Fri, 1 May 2020 16:08:19 -0700 Subject: [PATCH 3/7] Adressing PR comments Adding additional tests --- .../azure/cosmos/CosmosAsyncContainer.java | 17 ++++---- .../com/azure/cosmos/CosmosAsyncDatabase.java | 26 +++++++---- .../azure/cosmos/implementation/Offer.java | 10 ++--- .../implementation/RxDocumentClientImpl.java | 13 +++--- .../cosmos/models/ThroughputProperties.java | 36 ++++++++-------- .../azure/cosmos/rx/CollectionCrudTest.java | 43 ++++++++++++++++--- .../com/azure/cosmos/rx/DatabaseCrudTest.java | 39 +++++++++++++---- 7 files changed, 122 insertions(+), 62 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java index d3245fad83b7..f493e58cb1aa 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java @@ -672,10 +672,10 @@ public Mono replaceProvisionedThroughput(int requestUnitsPerSecond) { public Mono replaceThroughput(ThroughputProperties throughputProperties) { return this.read() .flatMap(response -> this.database.getDocClientWrapper() - .queryOffers("select * from c where c.offerResourceId = '" - + response.getProperties() - .getResourceId() - + "'", new FeedOptions()) + .queryOffers(database.getOfferQuerySpecFromResourceId(response + .getProperties() + .getResourceId()) + , new FeedOptions()) .single() .flatMap(offerFeedResponse -> { if (offerFeedResponse.getResults().isEmpty()) { @@ -703,11 +703,10 @@ public Mono replaceThroughput(ThroughputProperties throughpu public Mono readThroughput() { return this.read() .flatMap(response -> this.database.getDocClientWrapper() - .queryOffers("select * from c where c.offerResourceId = '" - + response - .getProperties() - .getResourceId() + "'", - new FeedOptions()) + .queryOffers(database.getOfferQuerySpecFromResourceId(response + .getProperties() + .getResourceId()) + , new FeedOptions()) .single() .flatMap(offerFeedResponse -> { if (offerFeedResponse.getResults().isEmpty()) { diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java index e88a6ece137a..d15a9efce00f 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java @@ -16,6 +16,7 @@ import com.azure.cosmos.models.CosmosUserProperties; import com.azure.cosmos.models.FeedOptions; import com.azure.cosmos.models.ModelBridgeInternal; +import com.azure.cosmos.models.SqlParameter; import com.azure.cosmos.models.SqlQuerySpec; import com.azure.cosmos.implementation.apachecommons.lang.StringUtils; import com.azure.cosmos.models.ThroughputProperties; @@ -25,6 +26,9 @@ import reactor.core.Exceptions; import reactor.core.publisher.Mono; +import java.util.Collections; +import java.util.List; + import static com.azure.cosmos.implementation.Utils.setContinuationTokenAndMaxItemCount; /** @@ -692,10 +696,9 @@ public Mono replaceProvisionedThroughput(int requestUnitsPerSecond) { public Mono replaceThroughput(ThroughputProperties throughputProperties) { return this.read() .flatMap(response -> this.getDocClientWrapper() - .queryOffers("select * from c where c.offerResourceId = '" - + response.getProperties() - .getResourceId() - + "'", new FeedOptions()) + .queryOffers(getOfferQuerySpecFromResourceId(response.getProperties() + .getResourceId()), + new FeedOptions()) .single() .flatMap(offerFeedResponse -> { if (offerFeedResponse.getResults().isEmpty()) { @@ -725,10 +728,8 @@ public Mono replaceThroughput(ThroughputProperties throughpu public Mono readThroughput() { return this.read() .flatMap(response -> getDocClientWrapper() - .queryOffers("select * from c where c.offerResourceId = '" - + response - .getProperties() - .getResourceId() + "'", + .queryOffers(getOfferQuerySpecFromResourceId(response.getProperties() + .getResourceId()), new FeedOptions()) .single() .flatMap(offerFeedResponse -> { @@ -748,6 +749,15 @@ public Mono readThroughput() { .map(ModelBridgeInternal::createThroughputRespose)); } + SqlQuerySpec getOfferQuerySpecFromResourceId(String resourceId) { + String queryText = "select * from c where c.offerResourceId = @resourceId"; + SqlQuerySpec querySpec = new SqlQuerySpec(queryText); + List parameters = Collections + .singletonList(new SqlParameter("@resourceId", resourceId)); + querySpec.setParameters(parameters); + return querySpec; + } + CosmosAsyncClient getClient() { return client; } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java index 1cc85c0743ba..72da6316295a 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java @@ -63,7 +63,7 @@ public Offer(ObjectNode objectNode) { * @param throughput the throughput * @return the offer */ - public static Offer createFixedOffer(int throughput) { + public static Offer createManualOffer(int throughput) { return new Offer(throughput); } @@ -100,7 +100,7 @@ public OfferAutoscaleSettings getOfferAutoScaleSettings() { * * @return the max autoscale throughput */ - public int getMaxAutoscaleThroughput() { + public int getAutoscaleMaxThroughput() { OfferAutoscaleSettings offerAutoscaleSettings = this.getOfferAutoScaleSettings(); if (offerAutoscaleSettings != null) { return offerAutoscaleSettings.getMaxThroughput(); @@ -112,12 +112,12 @@ public int getMaxAutoscaleThroughput() { /** * Sets max autoscale throughput. * - * @param maxAutoscaleThroughput the max autoscale throughput + * @param autoscaleMaxThroughput the max autoscale throughput */ - public void setMaxAutoscaleThroughput(int maxAutoscaleThroughput) { + public void setAutoscaleMaxThroughput(int autoscaleMaxThroughput) { OfferAutoscaleSettings offerAutoscaleSettings = this.getOfferAutoScaleSettings(); if (offerAutoscaleSettings != null) { - offerAutoscaleSettings.setMaxThroughput(maxAutoscaleThroughput); + offerAutoscaleSettings.setMaxThroughput(autoscaleMaxThroughput); } } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java index 88fadc3d5116..41d07af59892 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/RxDocumentClientImpl.java @@ -907,10 +907,14 @@ private Map getRequestHeaders(RequestOptions options) { if (options.getOfferThroughput() == null) { if (options.getThroughputProperties() != null) { Offer offer = ModelBridgeInternal.getOfferFromThroughputProperties(options.getThroughputProperties()); - final OfferAutoscaleAutoUpgradeProperties autoscaleAutoUpgradeProperties - = offer.getOfferAutoScaleSettings().getAutoscaleAutoUpgradeProperties(); + final OfferAutoscaleSettings offerAutoscaleSettings = offer.getOfferAutoScaleSettings(); + OfferAutoscaleAutoUpgradeProperties autoscaleAutoUpgradeProperties = null; + if (offerAutoscaleSettings != null) { + autoscaleAutoUpgradeProperties + = offer.getOfferAutoScaleSettings().getAutoscaleAutoUpgradeProperties(); + } if (offer.hasOfferThroughput() && - (offer.getOfferAutoScaleSettings().getMaxThroughput() >= 0 || + (offerAutoscaleSettings != null && offerAutoscaleSettings.getMaxThroughput() >= 0 || autoscaleAutoUpgradeProperties != null && autoscaleAutoUpgradeProperties .getAutoscaleThroughputProperties() @@ -920,7 +924,7 @@ private Map getRequestHeaders(RequestOptions options) { } if (offer.hasOfferThroughput()) { - headers.put(HttpConstants.HttpHeaders.OFFER_THROUGHPUT, options.getOfferThroughput().toString()); + headers.put(HttpConstants.HttpHeaders.OFFER_THROUGHPUT, String.valueOf(offer.getThroughput())); } else if (offer.getOfferAutoScaleSettings() != null) { headers.put(HttpConstants.HttpHeaders.OFFER_AUTOPILOT_SETTINGS, ModelBridgeInternal.toJsonFromJsonSerializable(offer.getOfferAutoScaleSettings())); @@ -928,7 +932,6 @@ private Map getRequestHeaders(RequestOptions options) { } } - if (options.isPopulateQuotaInfo()) { headers.put(HttpConstants.HttpHeaders.POPULATE_QUOTA_INFO, String.valueOf(true)); } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java index ef4aa3a50b96..03da2e8db19c 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java @@ -21,32 +21,32 @@ public class ThroughputProperties { * @param throughput the throughput * @return the throughput properties */ - public static ThroughputProperties createFixedThroughput(int throughput) { - return new ThroughputProperties(Offer.createFixedOffer(throughput)); + public static ThroughputProperties createManualThroughput(int throughput) { + return new ThroughputProperties(Offer.createManualOffer(throughput)); } /** * Create auto scale throughput properties. * - * @param maxAutoScaleThroughput the max auto scale throughput + * @param autoScaleMaxThroughput the max auto scale throughput * @param autoUpgradethroughputIncrementPercentage the auto upgrade max throughput increment percentage * @return the throughput properties */ - public static ThroughputProperties createAutoScaledProvisionedThroughput( - int maxAutoScaleThroughput, + static ThroughputProperties createAutoScaledThroughput( + int autoScaleMaxThroughput, int autoUpgradethroughputIncrementPercentage) { - return new ThroughputProperties(Offer.createAutoscaleOffer(maxAutoScaleThroughput, + return new ThroughputProperties(Offer.createAutoscaleOffer(autoScaleMaxThroughput, autoUpgradethroughputIncrementPercentage)); } /** * Create auto scaled provisioned throughput throughput properties. * - * @param maxAutoScaleThroughput the max auto scale throughput + * @param autoScaleMaxThroughput the max auto scale throughput * @return the throughput properties */ - public static ThroughputProperties createAutoScaledProvisionedThroughput(int maxAutoScaleThroughput) { - return new ThroughputProperties(Offer.createAutoscaleOffer(maxAutoScaleThroughput, + public static ThroughputProperties createAutoScaledThroughput(int autoScaleMaxThroughput) { + return new ThroughputProperties(Offer.createAutoscaleOffer(autoScaleMaxThroughput, 0)); } @@ -55,7 +55,7 @@ public static ThroughputProperties createAutoScaledProvisionedThroughput(int max * * @return the offer throughput */ - public Integer getOfferThroughput() { + public Integer getManualThroughput() { return offer.getThroughput(); } @@ -64,7 +64,7 @@ public Integer getOfferThroughput() { * * @return the offer autoscale properties */ - public OfferAutoscaleSettings getOfferAutoscaleProperties() { + OfferAutoscaleSettings getOfferAutoscaleProperties() { return this.offer.getOfferAutoScaleSettings(); } @@ -73,8 +73,8 @@ public OfferAutoscaleSettings getOfferAutoscaleProperties() { * * @return the max autoscale throughput */ - public int getMaxAutoscaleThroughput() { - return this.offer.getMaxAutoscaleThroughput(); + public int getAutoscaleMaxThroughput() { + return this.offer.getAutoscaleMaxThroughput(); } @@ -86,13 +86,11 @@ Offer getOffer() { * Get an updated offer based on the properties. */ Offer updateOfferFromProperties(Offer offer) { - /* - if autoscale is set then update autoscale values - else update fixedthroughput - */ - if (this.getMaxAutoscaleThroughput() > 0) { - offer.updateAutoscaleThroughput(this.getMaxAutoscaleThroughput()); + if (this.getAutoscaleMaxThroughput() > 0) { + offer.updateAutoscaleThroughput(this.getAutoscaleMaxThroughput()); + } else { + offer.setThroughput(this.getManualThroughput()); } return offer; } diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java index 274161295016..f22557f47e37 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java @@ -3,7 +3,6 @@ package com.azure.cosmos.rx; import com.azure.cosmos.BridgeInternal; -import com.azure.cosmos.CosmosContainer; import com.azure.cosmos.models.CompositePath; import com.azure.cosmos.models.CompositePathSortOrder; import com.azure.cosmos.CosmosAsyncClient; @@ -372,11 +371,11 @@ public void sessionTokenConsistencyCollectionDeleteCreateSameName() { @Test(groups = { "emulator" }, timeOut = TIMEOUT) public void readReplaceAutoscaleThroughput() throws Exception { - safeDeleteDatabase(client.getDatabase("newTestDatabase")); + final String databaseName = CosmosDatabaseForTest.generateId(); int initalThroughput = 5000; ThroughputProperties throughputProperties = - ThroughputProperties.createAutoScaledProvisionedThroughput(initalThroughput, 50); - CosmosAsyncDatabase database = client.createDatabase("newTestDatabase") + ThroughputProperties.createAutoScaledThroughput(initalThroughput); + CosmosAsyncDatabase database = client.createDatabase(databaseName) .block() .getDatabase(); @@ -388,13 +387,43 @@ public void readReplaceAutoscaleThroughput() throws Exception { // Read ThroughputResponse readThroughputResponse = container.readThroughput().block(); - assertThat(readThroughputResponse.getProperties().getMaxAutoscaleThroughput()).isEqualTo(initalThroughput); + assertThat(readThroughputResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(initalThroughput); // Replace int tagetThroughput = 6000; - throughputProperties = ThroughputProperties.createAutoScaledProvisionedThroughput(tagetThroughput); + throughputProperties = ThroughputProperties.createAutoScaledThroughput(tagetThroughput); ThroughputResponse replaceResponse = container.replaceThroughput(throughputProperties).block(); - assertThat(replaceResponse.getProperties().getMaxAutoscaleThroughput()).isEqualTo(tagetThroughput); + assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); + safeDeleteDatabase(client.getDatabase(databaseName)); + } + + @Test(groups = {"emulator"}, timeOut = TIMEOUT) + public void readReplaceManualThroughput() throws Exception { + final String databaseName = CosmosDatabaseForTest.generateId(); + int initalThroughput = 5000; + ThroughputProperties throughputProperties = + ThroughputProperties.createManualThroughput(initalThroughput); + CosmosAsyncDatabase database = client.createDatabase(databaseName) + .block() + .getDatabase(); + + CosmosContainerProperties containerProperties = new CosmosContainerProperties("testCol", "/myPk"); + CosmosAsyncContainer container = database.createContainer(containerProperties, throughputProperties, + new CosmosContainerRequestOptions()) + .block() + .getContainer(); + + // Read + ThroughputResponse readThroughputResponse = container.readThroughput().block(); + assertThat(readThroughputResponse.getProperties().getManualThroughput()).isEqualTo(initalThroughput); + + // Replace + int tagetThroughput = 6000; + throughputProperties = ThroughputProperties.createManualThroughput(tagetThroughput); + ThroughputResponse replaceResponse = container.replaceThroughput(throughputProperties).block(); + assertThat(replaceResponse.getProperties().getManualThroughput()).isEqualTo(tagetThroughput); + safeDeleteDatabase(client.getDatabase(databaseName)); + } @BeforeClass(groups = { "emulator" }, timeOut = SETUP_TIMEOUT) diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java index e37ee6bacca4..d6d0fcf4c1aa 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java @@ -4,8 +4,6 @@ import com.azure.cosmos.CosmosAsyncClient; import com.azure.cosmos.CosmosAsyncDatabase; -import com.azure.cosmos.implementation.Offer; -import com.azure.cosmos.implementation.RequestOptions; import com.azure.cosmos.models.CosmosAsyncDatabaseResponse; import com.azure.cosmos.CosmosClientBuilder; import com.azure.cosmos.CosmosDatabaseForTest; @@ -116,23 +114,46 @@ public void deleteDatabase_DoesntExist() throws Exception { @Test(groups = { "emulator" }, timeOut = TIMEOUT) public void readReplaceAutoscaleThroughput() throws Exception { - safeDeleteDatabase(client.getDatabase("newTestDatabase")); + final String databaseName = CosmosDatabaseForTest.generateId(); int initalThroughput = 5000; - ThroughputProperties properties = ThroughputProperties.createAutoScaledProvisionedThroughput(initalThroughput, - 50); - CosmosAsyncDatabase database = client.createDatabase("newTestDatabase", properties) + ThroughputProperties properties = ThroughputProperties.createAutoScaledThroughput(initalThroughput); + CosmosAsyncDatabase database = client.createDatabase(databaseName, properties) .block() .getDatabase(); ThroughputResponse readThroughputResponse = database.readThroughput().block(); - assertThat(readThroughputResponse.getProperties().getMaxAutoscaleThroughput()).isEqualTo(initalThroughput); + assertThat(readThroughputResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(initalThroughput); database.createContainer("testCol", "/myPk").block(); int tagetThroughput = 6000; - properties = ThroughputProperties.createAutoScaledProvisionedThroughput(tagetThroughput); + properties = ThroughputProperties.createAutoScaledThroughput(tagetThroughput); ThroughputResponse replaceResponse = database.replaceThroughput(properties).block(); - assertThat(replaceResponse.getProperties().getMaxAutoscaleThroughput()).isEqualTo(tagetThroughput); + assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); + safeDeleteDatabase(client.getDatabase(databaseName)); + } + @Test(groups = { "emulator" }, timeOut = TIMEOUT) + public void readReplaceManualThroughput() throws Exception { + final String databaseName = CosmosDatabaseForTest.generateId(); + int initalThroughput = 5000; + ThroughputProperties properties = ThroughputProperties.createManualThroughput(initalThroughput); + CosmosAsyncDatabase database = client.createDatabase(databaseName, properties) + .block() + .getDatabase(); + + ThroughputResponse readThroughputResponse = database.readThroughput().block(); + assertThat(readThroughputResponse.getProperties().getManualThroughput()).isEqualTo(initalThroughput); + database.createContainer("testCol", "/myPk").block(); + int tagetThroughput = 6000; + properties = ThroughputProperties.createManualThroughput(tagetThroughput); + ThroughputResponse replaceResponse = database.replaceThroughput(properties).block(); + assertThat(replaceResponse.getProperties().getManualThroughput()).isEqualTo(tagetThroughput); + safeDeleteDatabase(client.getDatabase(databaseName)); + + } + + + @BeforeClass(groups = { "emulator" }, timeOut = SETUP_TIMEOUT) public void before_DatabaseCrudTest() { client = getClientBuilder().buildAsyncClient(); From bf77a32aca2da6fa5d53553ebb42ec3647bc5aff Mon Sep 17 00:00:00 2001 From: Bhaskar Mallapragada Date: Tue, 5 May 2020 00:35:19 -0700 Subject: [PATCH 4/7] Implementing PR comments --- .../azure/cosmos/CosmosAsyncContainer.java | 5 +++-- .../com/azure/cosmos/CosmosAsyncDatabase.java | 4 ++-- .../azure/cosmos/implementation/Offer.java | 4 ++-- .../cosmos/models/ThroughputProperties.java | 4 ++-- .../ThroughputPropertiesCodeSnippet.java | 20 +++++++++++++++++++ .../azure/cosmos/rx/CollectionCrudTest.java | 9 +++++---- .../com/azure/cosmos/rx/DatabaseCrudTest.java | 9 +++++---- 7 files changed, 39 insertions(+), 16 deletions(-) create mode 100644 sdk/cosmos/azure-cosmos/src/samples/java/com/azure/cosmos/ThroughputPropertiesCodeSnippet.java diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java index f493e58cb1aa..5b2065010ad5 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java @@ -683,7 +683,7 @@ public Mono replaceThroughput(ThroughputProperties throughpu .createCosmosClientException( HttpConstants.StatusCodes.BADREQUEST, "No offers found for the " + - "resource")); + "resource " + this.getId())); } Offer existingOffer = offerFeedResponse.getResults().get(0); @@ -713,7 +713,8 @@ public Mono readThroughput() { return Mono.error(BridgeInternal .createCosmosClientException( HttpConstants.StatusCodes.BADREQUEST, - "No offers found for the resource")); + "No offers found for the resource " + + this.getId())); } return this.database.getDocClientWrapper() .readOffer(offerFeedResponse.getResults() diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java index d15a9efce00f..261feb53c01d 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java @@ -706,7 +706,7 @@ public Mono replaceThroughput(ThroughputProperties throughpu .createCosmosClientException( HttpConstants.StatusCodes.BADREQUEST, "No offers found for the " + - "resource")); + "resource " + this.getId())); } Offer existingOffer = offerFeedResponse.getResults().get(0); @@ -738,7 +738,7 @@ public Mono readThroughput() { .createCosmosClientException( HttpConstants.StatusCodes.BADREQUEST, "No offers found for the " + - "resource")); + "resource " + this.getId())); } return getDocClientWrapper() .readOffer(offerFeedResponse.getResults() diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java index 72da6316295a..641ed99da5f9 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java @@ -58,7 +58,7 @@ public Offer(ObjectNode objectNode) { } /** - * Create fixed offer offer. + * Create fixed offer. * * @param throughput the throughput * @return the offer @@ -68,7 +68,7 @@ public static Offer createManualOffer(int throughput) { } /** - * Create autoscale offer offer. + * Create autoscale offer. * * @param startingMaxThroughput the starting max throughput * @param autoUpgradeMaxThroughputIncrementPercentage the auto upgrade max throughput increment percentage diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java index 03da2e8db19c..9b9a15fac0ca 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java @@ -32,7 +32,7 @@ public static ThroughputProperties createManualThroughput(int throughput) { * @param autoUpgradethroughputIncrementPercentage the auto upgrade max throughput increment percentage * @return the throughput properties */ - static ThroughputProperties createAutoScaledThroughput( + static ThroughputProperties createAutoscaledThroughput( int autoScaleMaxThroughput, int autoUpgradethroughputIncrementPercentage) { return new ThroughputProperties(Offer.createAutoscaleOffer(autoScaleMaxThroughput, @@ -45,7 +45,7 @@ static ThroughputProperties createAutoScaledThroughput( * @param autoScaleMaxThroughput the max auto scale throughput * @return the throughput properties */ - public static ThroughputProperties createAutoScaledThroughput(int autoScaleMaxThroughput) { + public static ThroughputProperties createAutoscaledThroughput(int autoScaleMaxThroughput) { return new ThroughputProperties(Offer.createAutoscaleOffer(autoScaleMaxThroughput, 0)); } diff --git a/sdk/cosmos/azure-cosmos/src/samples/java/com/azure/cosmos/ThroughputPropertiesCodeSnippet.java b/sdk/cosmos/azure-cosmos/src/samples/java/com/azure/cosmos/ThroughputPropertiesCodeSnippet.java new file mode 100644 index 000000000000..91200638154c --- /dev/null +++ b/sdk/cosmos/azure-cosmos/src/samples/java/com/azure/cosmos/ThroughputPropertiesCodeSnippet.java @@ -0,0 +1,20 @@ +package com.azure.cosmos; + +import com.azure.cosmos.implementation.TestConfigurations; +import com.azure.cosmos.models.ThroughputProperties; + +public class ThroughputPropertiesCodeSnippet { + public static void main(String[] args) throws Exception { + + CosmosAsyncClient client = new CosmosClientBuilder() + .endpoint(TestConfigurations.HOST) + .key(TestConfigurations.MASTER_KEY) + .buildAsyncClient(); + + final String databaseName = "testDB"; + int throughput = 5000; + ThroughputProperties properties = ThroughputProperties.createAutoscaledThroughput(throughput); + client.createDatabase(databaseName, properties).block(); + client.close(); + } +} diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java index f22557f47e37..749d539f08a0 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java @@ -374,7 +374,7 @@ public void readReplaceAutoscaleThroughput() throws Exception { final String databaseName = CosmosDatabaseForTest.generateId(); int initalThroughput = 5000; ThroughputProperties throughputProperties = - ThroughputProperties.createAutoScaledThroughput(initalThroughput); + ThroughputProperties.createAutoscaledThroughput(initalThroughput); CosmosAsyncDatabase database = client.createDatabase(databaseName) .block() .getDatabase(); @@ -391,9 +391,10 @@ public void readReplaceAutoscaleThroughput() throws Exception { // Replace int tagetThroughput = 6000; - throughputProperties = ThroughputProperties.createAutoScaledThroughput(tagetThroughput); - ThroughputResponse replaceResponse = container.replaceThroughput(throughputProperties).block(); - assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); + throughputProperties = ThroughputProperties.createAutoscaledThroughput(tagetThroughput); + // Enable later +// ThroughputResponse replaceResponse = container.replaceThroughput(throughputProperties).block(); +// assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); safeDeleteDatabase(client.getDatabase(databaseName)); } diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java index d6d0fcf4c1aa..0db35a21a077 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java @@ -116,7 +116,7 @@ public void deleteDatabase_DoesntExist() throws Exception { public void readReplaceAutoscaleThroughput() throws Exception { final String databaseName = CosmosDatabaseForTest.generateId(); int initalThroughput = 5000; - ThroughputProperties properties = ThroughputProperties.createAutoScaledThroughput(initalThroughput); + ThroughputProperties properties = ThroughputProperties.createAutoscaledThroughput(initalThroughput); CosmosAsyncDatabase database = client.createDatabase(databaseName, properties) .block() .getDatabase(); @@ -125,9 +125,10 @@ public void readReplaceAutoscaleThroughput() throws Exception { assertThat(readThroughputResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(initalThroughput); database.createContainer("testCol", "/myPk").block(); int tagetThroughput = 6000; - properties = ThroughputProperties.createAutoScaledThroughput(tagetThroughput); - ThroughputResponse replaceResponse = database.replaceThroughput(properties).block(); - assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); + properties = ThroughputProperties.createAutoscaledThroughput(tagetThroughput); + // Enable later +// ThroughputResponse replaceResponse = database.replaceThroughput(properties).block(); +// assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); safeDeleteDatabase(client.getDatabase(databaseName)); } From 7258a7e6d43871be75cde97f736bb00917de1608 Mon Sep 17 00:00:00 2001 From: Bhaskar Mallapragada Date: Tue, 5 May 2020 18:00:12 -0700 Subject: [PATCH 5/7] Rebasing master. Changing autopilot tests from emulator to simple --- .../src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java | 2 +- .../src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java index 749d539f08a0..911b36855617 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java @@ -369,7 +369,7 @@ public void sessionTokenConsistencyCollectionDeleteCreateSameName() { } } - @Test(groups = { "emulator" }, timeOut = TIMEOUT) + @Test(groups = { "simple" }, timeOut = TIMEOUT) public void readReplaceAutoscaleThroughput() throws Exception { final String databaseName = CosmosDatabaseForTest.generateId(); int initalThroughput = 5000; diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java index 0db35a21a077..254213c24957 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java @@ -112,7 +112,7 @@ public void deleteDatabase_DoesntExist() throws Exception { validateFailure(deleteObservable, validator); } - @Test(groups = { "emulator" }, timeOut = TIMEOUT) + @Test(groups = { "simple" }, timeOut = TIMEOUT) public void readReplaceAutoscaleThroughput() throws Exception { final String databaseName = CosmosDatabaseForTest.generateId(); int initalThroughput = 5000; From c9c999e2ed99614f9739b1f86105eaea8f18cfaa Mon Sep 17 00:00:00 2001 From: Bhaskar Mallapragada Date: Thu, 7 May 2020 14:38:15 -0700 Subject: [PATCH 6/7] Refactoring some implementation --- .../java/com/azure/cosmos/CosmosAsyncContainer.java | 5 +++-- .../java/com/azure/cosmos/CosmosAsyncDatabase.java | 5 +++-- .../java/com/azure/cosmos/implementation/Offer.java | 3 +++ .../com/azure/cosmos/models/ThroughputProperties.java | 11 +++-------- .../java/com/azure/cosmos/rx/CollectionCrudTest.java | 8 ++++---- .../java/com/azure/cosmos/rx/DatabaseCrudTest.java | 10 ++++++---- 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java index 5b2065010ad5..9e416dc328a7 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncContainer.java @@ -687,10 +687,11 @@ public Mono replaceThroughput(ThroughputProperties throughpu } Offer existingOffer = offerFeedResponse.getResults().get(0); - ModelBridgeInternal.updateOfferFromProperties(existingOffer, + Offer updatedOffer = + ModelBridgeInternal.updateOfferFromProperties(existingOffer, throughputProperties); return this.database.getDocClientWrapper() - .replaceOffer(existingOffer) + .replaceOffer(updatedOffer) .single(); }).map(ModelBridgeInternal::createThroughputRespose)); } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java index 261feb53c01d..e0352ec3893d 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosAsyncDatabase.java @@ -710,11 +710,12 @@ public Mono replaceThroughput(ThroughputProperties throughpu } Offer existingOffer = offerFeedResponse.getResults().get(0); - ModelBridgeInternal.updateOfferFromProperties(existingOffer, + Offer updatedOffer = + ModelBridgeInternal.updateOfferFromProperties(existingOffer, throughputProperties); return this.getDocClientWrapper() - .replaceOffer(existingOffer) + .replaceOffer(updatedOffer) .single(); }) .map(ModelBridgeInternal::createThroughputRespose)); diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java index 641ed99da5f9..c5c5db127928 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/Offer.java @@ -242,4 +242,7 @@ public void updateAutoscaleThroughput(int maxAutoscaleThroughput) { this.getOfferAutoScaleSettings().setMaxThroughput(maxAutoscaleThroughput); } + public void updateContent(Offer offer) { + this.setContent(offer.getContent()); + } } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java index 9b9a15fac0ca..503f17b9958e 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/ThroughputProperties.java @@ -85,14 +85,9 @@ Offer getOffer() { /** * Get an updated offer based on the properties. */ - Offer updateOfferFromProperties(Offer offer) { - - if (this.getAutoscaleMaxThroughput() > 0) { - offer.updateAutoscaleThroughput(this.getAutoscaleMaxThroughput()); - } else { - offer.setThroughput(this.getManualThroughput()); - } - return offer; + Offer updateOfferFromProperties(Offer oldOffer) { + oldOffer.updateContent(this.offer); + return oldOffer; } } diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java index 911b36855617..42a879f5f9d3 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java @@ -378,8 +378,9 @@ public void readReplaceAutoscaleThroughput() throws Exception { CosmosAsyncDatabase database = client.createDatabase(databaseName) .block() .getDatabase(); + String collectionId = UUID.randomUUID().toString(); - CosmosContainerProperties containerProperties = new CosmosContainerProperties("testCol", "/myPk"); + CosmosContainerProperties containerProperties = new CosmosContainerProperties(collectionId, "/myPk"); CosmosAsyncContainer container = database.createContainer(containerProperties, throughputProperties, new CosmosContainerRequestOptions()) .block() @@ -392,9 +393,8 @@ public void readReplaceAutoscaleThroughput() throws Exception { // Replace int tagetThroughput = 6000; throughputProperties = ThroughputProperties.createAutoscaledThroughput(tagetThroughput); - // Enable later -// ThroughputResponse replaceResponse = container.replaceThroughput(throughputProperties).block(); -// assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); + ThroughputResponse replaceResponse = container.replaceThroughput(throughputProperties).block(); + assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); safeDeleteDatabase(client.getDatabase(databaseName)); } diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java index 254213c24957..de83fa1c7410 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; @@ -123,12 +124,13 @@ public void readReplaceAutoscaleThroughput() throws Exception { ThroughputResponse readThroughputResponse = database.readThroughput().block(); assertThat(readThroughputResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(initalThroughput); - database.createContainer("testCol", "/myPk").block(); + String collectionId = UUID.randomUUID().toString(); + database.createContainer(collectionId, "/myPk").block(); + // Replace int tagetThroughput = 6000; properties = ThroughputProperties.createAutoscaledThroughput(tagetThroughput); - // Enable later -// ThroughputResponse replaceResponse = database.replaceThroughput(properties).block(); -// assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); + ThroughputResponse replaceResponse = database.replaceThroughput(properties).block(); + assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); safeDeleteDatabase(client.getDatabase(databaseName)); } From 191d86f5c2fa3094c5024c985a63ef132913aa62 Mon Sep 17 00:00:00 2001 From: Bhaskar Mallapragada Date: Thu, 7 May 2020 17:24:08 -0700 Subject: [PATCH 7/7] Moving throughput tests to a new test class. --- .../azure/cosmos/rx/CollectionCrudTest.java | 52 +------ .../com/azure/cosmos/rx/DatabaseCrudTest.java | 44 ------ .../com/azure/cosmos/rx/ThroughputTests.java | 142 ++++++++++++++++++ 3 files changed, 149 insertions(+), 89 deletions(-) create mode 100644 sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/ThroughputTests.java diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java index 42a879f5f9d3..f3f226492ec8 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/CollectionCrudTest.java @@ -369,64 +369,26 @@ public void sessionTokenConsistencyCollectionDeleteCreateSameName() { } } - @Test(groups = { "simple" }, timeOut = TIMEOUT) - public void readReplaceAutoscaleThroughput() throws Exception { - final String databaseName = CosmosDatabaseForTest.generateId(); - int initalThroughput = 5000; - ThroughputProperties throughputProperties = - ThroughputProperties.createAutoscaledThroughput(initalThroughput); - CosmosAsyncDatabase database = client.createDatabase(databaseName) - .block() - .getDatabase(); - String collectionId = UUID.randomUUID().toString(); - - CosmosContainerProperties containerProperties = new CosmosContainerProperties(collectionId, "/myPk"); - CosmosAsyncContainer container = database.createContainer(containerProperties, throughputProperties, - new CosmosContainerRequestOptions()) - .block() - .getContainer(); - - // Read - ThroughputResponse readThroughputResponse = container.readThroughput().block(); - assertThat(readThroughputResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(initalThroughput); - - // Replace - int tagetThroughput = 6000; - throughputProperties = ThroughputProperties.createAutoscaledThroughput(tagetThroughput); - ThroughputResponse replaceResponse = container.replaceThroughput(throughputProperties).block(); - assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); - safeDeleteDatabase(client.getDatabase(databaseName)); - } - @Test(groups = {"emulator"}, timeOut = TIMEOUT) - public void readReplaceManualThroughput() throws Exception { + public void replaceProvisionedThroughput(){ final String databaseName = CosmosDatabaseForTest.generateId(); - int initalThroughput = 5000; - ThroughputProperties throughputProperties = - ThroughputProperties.createManualThroughput(initalThroughput); CosmosAsyncDatabase database = client.createDatabase(databaseName) .block() .getDatabase(); - CosmosContainerProperties containerProperties = new CosmosContainerProperties("testCol", "/myPk"); - CosmosAsyncContainer container = database.createContainer(containerProperties, throughputProperties, + CosmosAsyncContainer container = database.createContainer(containerProperties, 1000, new CosmosContainerRequestOptions()) .block() .getContainer(); + Integer throughput = container.readProvisionedThroughput().block(); - // Read - ThroughputResponse readThroughputResponse = container.readThroughput().block(); - assertThat(readThroughputResponse.getProperties().getManualThroughput()).isEqualTo(initalThroughput); - - // Replace - int tagetThroughput = 6000; - throughputProperties = ThroughputProperties.createManualThroughput(tagetThroughput); - ThroughputResponse replaceResponse = container.replaceThroughput(throughputProperties).block(); - assertThat(replaceResponse.getProperties().getManualThroughput()).isEqualTo(tagetThroughput); - safeDeleteDatabase(client.getDatabase(databaseName)); + assertThat(throughput).isEqualTo(1000); + throughput = container.replaceProvisionedThroughput(2000).block(); + assertThat(throughput).isEqualTo(2000); } + @BeforeClass(groups = { "emulator" }, timeOut = SETUP_TIMEOUT) public void before_CollectionCrudTest() { client = getClientBuilder().buildAsyncClient(); diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java index de83fa1c7410..05c25605466e 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/DatabaseCrudTest.java @@ -113,50 +113,6 @@ public void deleteDatabase_DoesntExist() throws Exception { validateFailure(deleteObservable, validator); } - @Test(groups = { "simple" }, timeOut = TIMEOUT) - public void readReplaceAutoscaleThroughput() throws Exception { - final String databaseName = CosmosDatabaseForTest.generateId(); - int initalThroughput = 5000; - ThroughputProperties properties = ThroughputProperties.createAutoscaledThroughput(initalThroughput); - CosmosAsyncDatabase database = client.createDatabase(databaseName, properties) - .block() - .getDatabase(); - - ThroughputResponse readThroughputResponse = database.readThroughput().block(); - assertThat(readThroughputResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(initalThroughput); - String collectionId = UUID.randomUUID().toString(); - database.createContainer(collectionId, "/myPk").block(); - // Replace - int tagetThroughput = 6000; - properties = ThroughputProperties.createAutoscaledThroughput(tagetThroughput); - ThroughputResponse replaceResponse = database.replaceThroughput(properties).block(); - assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); - safeDeleteDatabase(client.getDatabase(databaseName)); - - } - - @Test(groups = { "emulator" }, timeOut = TIMEOUT) - public void readReplaceManualThroughput() throws Exception { - final String databaseName = CosmosDatabaseForTest.generateId(); - int initalThroughput = 5000; - ThroughputProperties properties = ThroughputProperties.createManualThroughput(initalThroughput); - CosmosAsyncDatabase database = client.createDatabase(databaseName, properties) - .block() - .getDatabase(); - - ThroughputResponse readThroughputResponse = database.readThroughput().block(); - assertThat(readThroughputResponse.getProperties().getManualThroughput()).isEqualTo(initalThroughput); - database.createContainer("testCol", "/myPk").block(); - int tagetThroughput = 6000; - properties = ThroughputProperties.createManualThroughput(tagetThroughput); - ThroughputResponse replaceResponse = database.replaceThroughput(properties).block(); - assertThat(replaceResponse.getProperties().getManualThroughput()).isEqualTo(tagetThroughput); - safeDeleteDatabase(client.getDatabase(databaseName)); - - } - - - @BeforeClass(groups = { "emulator" }, timeOut = SETUP_TIMEOUT) public void before_DatabaseCrudTest() { client = getClientBuilder().buildAsyncClient(); diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/ThroughputTests.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/ThroughputTests.java new file mode 100644 index 000000000000..9d31248e760e --- /dev/null +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/rx/ThroughputTests.java @@ -0,0 +1,142 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +package com.azure.cosmos.rx; + +import com.azure.cosmos.CosmosAsyncClient; +import com.azure.cosmos.CosmosAsyncContainer; +import com.azure.cosmos.CosmosAsyncDatabase; +import com.azure.cosmos.CosmosClientBuilder; +import com.azure.cosmos.CosmosDatabaseForTest; +import com.azure.cosmos.models.CosmosContainerProperties; +import com.azure.cosmos.models.CosmosContainerRequestOptions; +import com.azure.cosmos.models.ThroughputProperties; +import com.azure.cosmos.models.ThroughputResponse; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; + +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ThroughputTests extends TestSuiteBase{ + + private CosmosAsyncClient client; + + @Factory(dataProvider = "clientBuilders") + public ThroughputTests(CosmosClientBuilder clientBuilder) { + super(clientBuilder); + } + + @BeforeClass(groups = { "simple" }, timeOut = SETUP_TIMEOUT) + public void before_ThroughputTests() { + client = getClientBuilder().buildAsyncClient(); + } + + @Test(groups = { "simple" }, timeOut = TIMEOUT) + public void readReplaceAutoscaleThroughputDb() throws Exception { + final String databaseName = CosmosDatabaseForTest.generateId(); + int initalThroughput = 5000; + ThroughputProperties properties = ThroughputProperties.createAutoscaledThroughput(initalThroughput); + CosmosAsyncDatabase database = client.createDatabase(databaseName, properties) + .block() + .getDatabase(); + + ThroughputResponse readThroughputResponse = database.readThroughput().block(); + assertThat(readThroughputResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(initalThroughput); + String collectionId = UUID.randomUUID().toString(); + database.createContainer(collectionId, "/myPk").block(); + // Replace + int tagetThroughput = 6000; + properties = ThroughputProperties.createAutoscaledThroughput(tagetThroughput); + ThroughputResponse replaceResponse = database.replaceThroughput(properties).block(); + assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); + safeDeleteDatabase(client.getDatabase(databaseName)); + + } + + @Test(groups = { "simple" }, timeOut = TIMEOUT) + public void readReplaceManualThroughputDb() throws Exception { + final String databaseName = CosmosDatabaseForTest.generateId(); + int initalThroughput = 5000; + ThroughputProperties properties = ThroughputProperties.createManualThroughput(initalThroughput); + CosmosAsyncDatabase database = client.createDatabase(databaseName, properties) + .block() + .getDatabase(); + + ThroughputResponse readThroughputResponse = database.readThroughput().block(); + assertThat(readThroughputResponse.getProperties().getManualThroughput()).isEqualTo(initalThroughput); + database.createContainer("testCol", "/myPk").block(); + int tagetThroughput = 6000; + properties = ThroughputProperties.createManualThroughput(tagetThroughput); + ThroughputResponse replaceResponse = database.replaceThroughput(properties).block(); + assertThat(replaceResponse.getProperties().getManualThroughput()).isEqualTo(tagetThroughput); + safeDeleteDatabase(client.getDatabase(databaseName)); + + } + + @Test(groups = {"simple"}, timeOut = TIMEOUT) + public void readReplaceManualThroughputCollection() throws Exception { + final String databaseName = CosmosDatabaseForTest.generateId(); + int initalThroughput = 5000; + ThroughputProperties throughputProperties = + ThroughputProperties.createManualThroughput(initalThroughput); + CosmosAsyncDatabase database = client.createDatabase(databaseName) + .block() + .getDatabase(); + + CosmosContainerProperties containerProperties = new CosmosContainerProperties("testCol", "/myPk"); + CosmosAsyncContainer container = database.createContainer(containerProperties, throughputProperties, + new CosmosContainerRequestOptions()) + .block() + .getContainer(); + + // Read + ThroughputResponse readThroughputResponse = container.readThroughput().block(); + assertThat(readThroughputResponse.getProperties().getManualThroughput()).isEqualTo(initalThroughput); + + // Replace + int tagetThroughput = 6000; + throughputProperties = ThroughputProperties.createManualThroughput(tagetThroughput); + ThroughputResponse replaceResponse = container.replaceThroughput(throughputProperties).block(); + assertThat(replaceResponse.getProperties().getManualThroughput()).isEqualTo(tagetThroughput); + safeDeleteDatabase(client.getDatabase(databaseName)); + + } + + @Test(groups = { "simple" }, timeOut = TIMEOUT) + public void readReplaceAutoscaleThroughputCollection() throws Exception { + final String databaseName = CosmosDatabaseForTest.generateId(); + int initalThroughput = 5000; + ThroughputProperties throughputProperties = + ThroughputProperties.createAutoscaledThroughput(initalThroughput); + CosmosAsyncDatabase database = client.createDatabase(databaseName) + .block() + .getDatabase(); + String collectionId = UUID.randomUUID().toString(); + + CosmosContainerProperties containerProperties = new CosmosContainerProperties(collectionId, "/myPk"); + CosmosAsyncContainer container = database.createContainer(containerProperties, throughputProperties, + new CosmosContainerRequestOptions()) + .block() + .getContainer(); + + // Read + ThroughputResponse readThroughputResponse = container.readThroughput().block(); + assertThat(readThroughputResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(initalThroughput); + + // Replace + int tagetThroughput = 6000; + throughputProperties = ThroughputProperties.createAutoscaledThroughput(tagetThroughput); + ThroughputResponse replaceResponse = container.replaceThroughput(throughputProperties).block(); + assertThat(replaceResponse.getProperties().getAutoscaleMaxThroughput()).isEqualTo(tagetThroughput); + safeDeleteDatabase(client.getDatabase(databaseName)); + } + + @AfterClass(groups = { "simple" }, timeOut = SHUTDOWN_TIMEOUT, alwaysRun = true) + public void afterClass() { + assertThat(this.client).isNotNull(); + this.client.close(); + } +}