diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosContainerProperties.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosContainerProperties.java
index c6d2d22fb88c..695d1bb38694 100644
--- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosContainerProperties.java
+++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosContainerProperties.java
@@ -196,6 +196,46 @@ public CosmosContainerProperties setConflictResolutionPolicy(ConflictResolutionP
return this;
}
+ /**
+ * Gets the collection's default time-to-live value.
+ *
+ * @return the default time-to-live value in seconds.
+ */
+ public Integer getDefaultTimeToLiveInSeconds() {
+ if (super.has(Constants.Properties.DEFAULT_TTL)) {
+ return super.getInt(Constants.Properties.DEFAULT_TTL);
+ }
+
+ return null;
+ }
+
+ /**
+ * Sets the collection's default time-to-live value.
+ *
+ * The default time-to-live value on a collection is an optional property. If set, the documents within the collection
+ * expires after the specified number of seconds since their last write time. The value of this property should be one of the following:
+ *
+ * null - indicates evaluation of time-to-live is disabled and documents within the collection will never expire, regardless whether
+ * individual documents have their time-to-live set.
+ *
+ * nonzero positive integer - indicates the default time-to-live value for all documents within the collection. This value can be overridden
+ * by individual documents' time-to-live value.
+ *
+ * -1 - indicates by default all documents within the collection never expire. This value can be overridden by individual documents'
+ * time-to-live value.
+ *
+ * @param timeToLive the default time-to-live value in seconds.
+ */
+ public void setDefaultTimeToLiveInSeconds(Integer timeToLive) {
+ // a "null" value is represented as a missing element on the wire.
+ // setting timeToLive to null should remove the property from the property bag.
+ if (timeToLive != null) {
+ super.set(Constants.Properties.DEFAULT_TTL, timeToLive);
+ } else if (super.has(Constants.Properties.DEFAULT_TTL)) {
+ super.remove(Constants.Properties.DEFAULT_TTL);
+ }
+ }
+
DocumentCollection getV2Collection() {
DocumentCollection collection = new DocumentCollection(this.toJson());
collection.setPartitionKey(this.getPartitionKeyDefinition());
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 cefed5a6f9a2..f5af62385c78 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
@@ -88,6 +88,19 @@ public void validate(CosmosAsyncContainerResponse resourceResponse) {
return this;
}
+ public Builder withDefaultTimeToLive(Integer timeToLive) {
+ validators.add(new CosmosResponseValidator() {
+
+ @Override
+ public void validate(CosmosAsyncContainerResponse resourceResponse) {
+ assertThat(resourceResponse.getProperties()).isNotNull();
+ assertThat(resourceResponse.getProperties().getDefaultTimeToLiveInSeconds()).isNotNull();
+ assertThat(resourceResponse.getProperties().getDefaultTimeToLiveInSeconds()).isEqualTo(timeToLive);
+ }
+ });
+ return this;
+ }
+
public Builder withProperty(String propertyName, String value) {
validators.add(new CosmosResponseValidator() {
@Override
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 28c4b7e48d10..709e7250daf9 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
@@ -95,6 +95,23 @@ public void createCollection(String collectionName) throws InterruptedException
safeDeleteAllCollections(database);
}
+ @Test(groups = { "emulator" }, timeOut = TIMEOUT, dataProvider = "collectionCrudArgProvider")
+ public void createCollectionWithTTL(String collectionName) throws InterruptedException {
+ CosmosContainerProperties collectionDefinition = getCollectionDefinition(collectionName);
+
+ Integer defaultTimeToLive = 300;
+ collectionDefinition.setDefaultTimeToLiveInSeconds(defaultTimeToLive);
+
+ Mono createObservable = database
+ .createContainer(collectionDefinition);
+
+ CosmosResponseValidator validator = new CosmosResponseValidator.Builder()
+ .withId(collectionDefinition.getId()).withDefaultTimeToLive(defaultTimeToLive).build();
+
+ validateSuccess(createObservable, validator);
+ safeDeleteAllCollections(database);
+ }
+
@Test(groups = { "emulator" }, timeOut = TIMEOUT)
public void createCollectionWithCompositeIndexAndSpatialSpec() throws InterruptedException {
PartitionKeyDefinition partitionKeyDef = new PartitionKeyDefinition();
@@ -188,6 +205,24 @@ public void readCollection(String collectionName) throws InterruptedException {
safeDeleteAllCollections(database);
}
+ @Test(groups = { "emulator" }, timeOut = TIMEOUT, dataProvider = "collectionCrudArgProvider")
+ public void readCollectionWithTTL(String collectionName) throws InterruptedException {
+ CosmosContainerProperties collectionDefinition = getCollectionDefinition(collectionName);
+
+ Integer defaultTimeToLive = 200;
+ collectionDefinition.setDefaultTimeToLiveInSeconds(defaultTimeToLive);
+
+ Mono createObservable = database.createContainer(collectionDefinition);
+ CosmosAsyncContainer collection = createObservable.block().getContainer();
+
+ Mono readObservable = collection.read();
+
+ CosmosResponseValidator validator = new CosmosResponseValidator.Builder()
+ .withId(collection.getId()).withDefaultTimeToLive(defaultTimeToLive).build();
+ validateSuccess(readObservable, validator);
+ safeDeleteAllCollections(database);
+ }
+
@Test(groups = { "emulator" }, timeOut = TIMEOUT, dataProvider = "collectionCrudArgProvider")
public void readCollection_DoesntExist(String collectionName) throws Exception {
@@ -235,6 +270,34 @@ public void replaceCollection(String collectionName) throws InterruptedException
safeDeleteAllCollections(database);
}
+ @Test(groups = { "emulator" }, timeOut = TIMEOUT, dataProvider = "collectionCrudArgProvider")
+ public void replaceCollectionWithTTL(String collectionName) throws InterruptedException {
+ // create a collection
+ CosmosContainerProperties collectionDefinition = getCollectionDefinition(collectionName);
+ Integer defaultTimeToLive = 120;
+ collectionDefinition.setDefaultTimeToLiveInSeconds(defaultTimeToLive);
+ Mono createObservable = database.createContainer(collectionDefinition);
+ CosmosAsyncContainer collection = createObservable.block().getContainer();
+ CosmosContainerProperties collectionSettings = collection.read().block().getProperties();
+ // sanity check
+ assertThat(collectionSettings.getIndexingPolicy().getIndexingMode()).isEqualTo(IndexingMode.CONSISTENT);
+ assertThat(collectionSettings.getDefaultTimeToLiveInSeconds()).isEqualTo(defaultTimeToLive);
+
+ // replace indexing mode
+ IndexingPolicy indexingMode = new IndexingPolicy();
+ indexingMode.setIndexingMode(IndexingMode.LAZY);
+ collectionSettings.setIndexingPolicy(indexingMode);
+ collectionSettings.setDefaultTimeToLiveInSeconds(defaultTimeToLive * 2);
+ Mono readObservable = collection.replace(collectionSettings, new CosmosContainerRequestOptions());
+
+ // validate
+ CosmosResponseValidator validator = new CosmosResponseValidator.Builder()
+ .indexingMode(IndexingMode.LAZY).withDefaultTimeToLive(defaultTimeToLive * 2).build();
+ validateSuccess(readObservable, validator);
+ safeDeleteAllCollections(database);
+ }
+
+
@Test(groups = { "emulator" }, timeOut = 10 * TIMEOUT, retryAnalyzer = RetryAnalyzer.class)
public void sessionTokenConsistencyCollectionDeleteCreateSameName() {
CosmosAsyncClient client1 = clientBuilder().buildAsyncClient();