From a879d0b4e3b464e3c1f50b32cd2a4278a336fcab Mon Sep 17 00:00:00 2001 From: Michael Reiche <48999328+mikereiche@users.noreply.github.com> Date: Tue, 14 Sep 2021 09:49:12 -0700 Subject: [PATCH] Use expiry(duration) with duration. (#1223) Also adds test for exceptions thrown during events - with validator. Closes #1204. --- .../convert/MappingCouchbaseConverter.java | 2 +- .../BasicCouchbasePersistentEntity.java | 46 ++++++++++++++++++- .../mapping/CouchbasePersistentEntity.java | 23 ++++++++++ ...hbaseTemplateKeyValueIntegrationTests.java | 24 +++++++--- ...hbaseTemplateKeyValueIntegrationTests.java | 17 +++++-- .../BasicCouchbasePersistentEntityTests.java | 12 ++--- .../query/StringN1qlQueryCreatorTests.java | 6 +-- 7 files changed, 107 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/springframework/data/couchbase/core/convert/MappingCouchbaseConverter.java b/src/main/java/org/springframework/data/couchbase/core/convert/MappingCouchbaseConverter.java index 65ee20c6..05b6b448 100644 --- a/src/main/java/org/springframework/data/couchbase/core/convert/MappingCouchbaseConverter.java +++ b/src/main/java/org/springframework/data/couchbase/core/convert/MappingCouchbaseConverter.java @@ -503,7 +503,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter implem final TreeMap suffixes = new TreeMap<>(); final TreeMap idAttributes = new TreeMap<>(); - target.setExpiration(entity.getExpiry()); + target.setExpiration((int)(entity.getExpiryDuration().getSeconds())); entity.doWithProperties(new PropertyHandler() { @Override diff --git a/src/main/java/org/springframework/data/couchbase/core/mapping/BasicCouchbasePersistentEntity.java b/src/main/java/org/springframework/data/couchbase/core/mapping/BasicCouchbasePersistentEntity.java index 3aa10ca5..057cbc6b 100644 --- a/src/main/java/org/springframework/data/couchbase/core/mapping/BasicCouchbasePersistentEntity.java +++ b/src/main/java/org/springframework/data/couchbase/core/mapping/BasicCouchbasePersistentEntity.java @@ -16,6 +16,8 @@ package org.springframework.data.couchbase.core.mapping; +import java.time.Duration; +import java.time.Instant; import java.util.Calendar; import java.util.TimeZone; import java.util.concurrent.TimeUnit; @@ -101,8 +103,9 @@ public class BasicCouchbasePersistentEntity extends BasicPersistentEntity extends BasicPersistentEntity extends PersistentEntity + * The Couchbase format for expiration time is: - for TTL < 31 days (<= 30 * 24 * 60 * 60): expressed as a TTL in + * seconds - for TTL > 30 days: expressed as Unix UTC time of expiry (number of SECONDS since the Epoch) + * + * @return the expiration time Duration + */ + Duration getExpiryDuration(); + + /** + * Returns the expiration time of the entity. + *

+ * The Couchbase format for expiration time is: - for TTL < 31 days (<= 30 * 24 * 60 * 60): expressed as a TTL in + * seconds - for TTL > 30 days: expressed as Unix UTC time of expiry (number of SECONDS since the Epoch) + * + * @return the expiration time Instant + */ + Instant getExpiryInstant(); + /** * Flag for using getAndTouch operations for reads, resetting the expiration (if one was set) when the entity is * directly read (eg. findOne, findById). diff --git a/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java index ff3356c7..66bf472a 100644 --- a/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java @@ -27,14 +27,15 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.time.Duration; +import java.time.Instant; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.UUID; -import com.couchbase.client.core.error.CouchbaseException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.dao.DataIntegrityViolationException; @@ -47,7 +48,6 @@ import org.springframework.data.couchbase.core.support.OneAndAllId; import org.springframework.data.couchbase.core.support.WithDurability; import org.springframework.data.couchbase.core.support.WithExpiry; import org.springframework.data.couchbase.domain.Address; -import org.springframework.data.couchbase.domain.Course; import org.springframework.data.couchbase.domain.NaiveAuditorAware; import org.springframework.data.couchbase.domain.PersonValue; import org.springframework.data.couchbase.domain.Submission; @@ -60,6 +60,7 @@ import org.springframework.data.couchbase.util.ClusterType; import org.springframework.data.couchbase.util.IgnoreWhen; import org.springframework.data.couchbase.util.JavaIntegrationTests; +import com.couchbase.client.core.error.CouchbaseException; import com.couchbase.client.java.kv.PersistTo; import com.couchbase.client.java.kv.ReplicateTo; import com.couchbase.client.java.query.QueryOptions; @@ -84,6 +85,7 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests { couchbaseTemplate.removeByQuery(UserAnnotated.class).all(); couchbaseTemplate.removeByQuery(UserAnnotated2.class).all(); couchbaseTemplate.removeByQuery(UserAnnotated3.class).all(); + couchbaseTemplate.removeByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all(); } @Test @@ -179,8 +181,8 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests { user.setSubmissions( Arrays.asList(new Submission(UUID.randomUUID().toString(), user.getId(), "tid", "status", 123))); couchbaseTemplate.upsertById(UserSubmission.class).one(user); - assertThrows(CouchbaseException.class, () -> couchbaseTemplate.findByQuery(UserSubmission.class).project(new String[] { "address.street" }) - .withConsistency(QueryScanConsistency.REQUEST_PLUS).all()); + assertThrows(CouchbaseException.class, () -> couchbaseTemplate.findByQuery(UserSubmission.class) + .project(new String[] { "address.street" }).withConsistency(QueryScanConsistency.REQUEST_PLUS).all()); List found = couchbaseTemplate.findByQuery(UserSubmission.class).project(new String[] { "address" }) .withConsistency(QueryScanConsistency.REQUEST_PLUS).all(); @@ -282,15 +284,23 @@ class CouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationTests { } // check that they are gone after a few seconds. sleepSecs(4); + List errorList = new LinkedList(); for (User user : users) { User found = couchbaseTemplate.findById(user.getClass()).one(user.getId()); - if (found instanceof UserAnnotated3) { - assertNotNull(found, "found should be non null as it was set to have no expiry"); + if (user.getId().endsWith(UserAnnotated3.class.getSimpleName())) { + if (found == null) { + errorList.add("\nfound should be non null as it was set to have no expiry " + user.getId() ); + } } else { - assertNull(found, "found should have been null as document should be expired"); + if (found != null) { + errorList.add("\nfound should have been null as document should be expired " + user.getId()); + } } } + if (!errorList.isEmpty()) { + throw new RuntimeException(errorList.toString()); + } } @Test diff --git a/src/test/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateKeyValueIntegrationTests.java b/src/test/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateKeyValueIntegrationTests.java index 2729470d..379e76fc 100644 --- a/src/test/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/ReactiveCouchbaseTemplateKeyValueIntegrationTests.java @@ -30,6 +30,7 @@ import java.time.Duration; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.UUID; @@ -72,7 +73,7 @@ class ReactiveCouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationT @Override public void beforeEach() { super.beforeEach(); - List r1 = reactiveCouchbaseTemplate.removeByQuery(User.class).all().collectList().block(); + List r1 = reactiveCouchbaseTemplate.removeByQuery(User.class).all().collectList().block(); List r2 = reactiveCouchbaseTemplate.removeByQuery(UserAnnotated.class).all().collectList().block(); List r3 = reactiveCouchbaseTemplate.removeByQuery(UserAnnotated2.class).all().collectList().block(); } @@ -219,15 +220,23 @@ class ReactiveCouchbaseTemplateKeyValueIntegrationTests extends JavaIntegrationT } // check that they are gone after a few seconds. sleepSecs(4); + List errorList = new LinkedList(); for (User user : users) { User found = reactiveCouchbaseTemplate.findById(user.getClass()).one(user.getId()).block(); - if (found instanceof UserAnnotated3) { - assertNotNull(found, "found should be non null as it was set to have no expiry"); + if (user.getId().endsWith(UserAnnotated3.class.getSimpleName())) { + if (found == null) { + errorList.add("\nfound should be non null as it was set to have no expiry " + user.getId()); + } } else { - assertNull(found, "found should have been null as document should be expired"); + if (found != null) { + errorList.add("\nfound should have been null as document should be expired " + user.getId()); + } } } + if (!errorList.isEmpty()) { + throw new RuntimeException(errorList.toString()); + } } @Test diff --git a/src/test/java/org/springframework/data/couchbase/core/mapping/BasicCouchbasePersistentEntityTests.java b/src/test/java/org/springframework/data/couchbase/core/mapping/BasicCouchbasePersistentEntityTests.java index f3f7d5cc..a87eba4d 100644 --- a/src/test/java/org/springframework/data/couchbase/core/mapping/BasicCouchbasePersistentEntityTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/mapping/BasicCouchbasePersistentEntityTests.java @@ -43,7 +43,7 @@ public class BasicCouchbasePersistentEntityTests { CouchbasePersistentEntity entity = new BasicCouchbasePersistentEntity<>( ClassTypeInformation.from(DefaultExpiry.class)); - assertThat(entity.getExpiry()).isEqualTo(0); + assertThat(entity.getExpiryDuration().getSeconds()).isEqualTo(0); } @Test @@ -51,14 +51,14 @@ public class BasicCouchbasePersistentEntityTests { CouchbasePersistentEntity entity = new BasicCouchbasePersistentEntity<>( ClassTypeInformation.from(DefaultExpiryUnit.class)); - assertThat(entity.getExpiry()).isEqualTo(78); + assertThat(entity.getExpiryDuration().getSeconds()).isEqualTo(78); } @Test void testLargeExpiry30DaysStillInSeconds() { CouchbasePersistentEntity entityUnder = new BasicCouchbasePersistentEntity<>( ClassTypeInformation.from(LimitDaysExpiry.class)); - assertThat(entityUnder.getExpiry()).isEqualTo(30 * 24 * 60 * 60); + assertThat(entityUnder.getExpiryDuration().getSeconds()).isEqualTo(30 * 24 * 60 * 60); } @Test @@ -66,7 +66,7 @@ public class BasicCouchbasePersistentEntityTests { CouchbasePersistentEntity entityOver = new BasicCouchbasePersistentEntity<>( ClassTypeInformation.from(OverLimitDaysExpiry.class)); - int expiryOver = entityOver.getExpiry(); + int expiryOver = (int)entityOver.getExpiryInstant().getEpochSecond(); Calendar expected = Calendar.getInstance(TimeZone.getTimeZone("UTC")); expected.add(Calendar.DAY_OF_YEAR, 31); @@ -87,7 +87,7 @@ public class BasicCouchbasePersistentEntityTests { ClassTypeInformation.from(OverLimitDaysExpiryExpression.class)); entityOver.setEnvironment(environment); - int expiryOver = entityOver.getExpiry(); + int expiryOver = (int)entityOver.getExpiryInstant().getEpochSecond(); Calendar expected = Calendar.getInstance(TimeZone.getTimeZone("UTC")); expected.add(Calendar.DAY_OF_YEAR, 31); @@ -107,7 +107,7 @@ public class BasicCouchbasePersistentEntityTests { CouchbasePersistentEntity entityOver = new BasicCouchbasePersistentEntity<>( ClassTypeInformation.from(OverLimitSecondsExpiry.class)); - int expiryOver = entityOver.getExpiry(); + int expiryOver = (int)entityOver.getExpiryInstant().getEpochSecond(); Calendar expected = Calendar.getInstance(TimeZone.getTimeZone("UTC")); expected.add(Calendar.DAY_OF_YEAR, 31); diff --git a/src/test/java/org/springframework/data/couchbase/repository/query/StringN1qlQueryCreatorTests.java b/src/test/java/org/springframework/data/couchbase/repository/query/StringN1qlQueryCreatorTests.java index bf611098..72f657d2 100644 --- a/src/test/java/org/springframework/data/couchbase/repository/query/StringN1qlQueryCreatorTests.java +++ b/src/test/java/org/springframework/data/couchbase/repository/query/StringN1qlQueryCreatorTests.java @@ -23,6 +23,7 @@ import java.util.Optional; import java.util.Properties; import java.util.UUID; +import com.couchbase.client.java.query.QueryScanConsistency; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; @@ -98,11 +99,8 @@ class StringN1qlQueryCreatorTests extends ClusterAwareIntegrationTests { Query query = creator.createQuery(); - try { - Thread.sleep(3000); - } catch (Exception e) {} ExecutableFindByQuery q = (ExecutableFindByQuery) couchbaseTemplate - .findByQuery(Airline.class).matching(query); + .findByQuery(Airline.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).matching(query); Optional al = q.one(); assertEquals(airline.toString(), al.get().toString());