From a5875ae9f66ddc66fdac54ee2e82ab01f44a67fd Mon Sep 17 00:00:00 2001 From: mikereiche Date: Wed, 11 Jan 2023 12:29:29 -0800 Subject: [PATCH] Use getAndTouch only when annotation attribute touchOnRead=true. Closes #1634. --- .../ReactiveFindByIdOperationSupport.java | 11 ++-- ...hbaseTemplateKeyValueIntegrationTests.java | 51 ++++++++++++++++--- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByIdOperationSupport.java b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByIdOperationSupport.java index beae803d9..ddb7358ae 100644 --- a/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByIdOperationSupport.java +++ b/src/main/java/org/springframework/data/couchbase/core/ReactiveFindByIdOperationSupport.java @@ -182,13 +182,12 @@ private CommonOptions initGetOptions() { CommonOptions getOptions; final CouchbasePersistentEntity entity = template.getConverter().getMappingContext() .getRequiredPersistentEntity(domainType); - Duration entityExpiryAnnotation = entity.getExpiryDuration(); - if (expiry != null || entityExpiryAnnotation == null || !entityExpiryAnnotation.isZero() - || options instanceof GetAndTouchOptions) { + Boolean isTouchOnRead = entity.isTouchOnRead(); + if (expiry != null || isTouchOnRead || options instanceof GetAndTouchOptions) { if (expiry != null) { expiryToUse = expiry; - } else if (entityExpiryAnnotation == null || !entityExpiryAnnotation.isZero()) { - expiryToUse = entityExpiryAnnotation; + } else if (isTouchOnRead) { + expiryToUse = entity.getExpiryDuration(); } else { expiryToUse = Duration.ZERO; } @@ -209,7 +208,7 @@ private CommonOptions initGetOptions() { } return getOptions; } - + } } 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 0741dce6f..59eb29017 100644 --- a/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java +++ b/src/test/java/org/springframework/data/couchbase/core/CouchbaseTemplateKeyValueIntegrationTests.java @@ -56,6 +56,7 @@ import org.springframework.data.couchbase.domain.UserAnnotated; import org.springframework.data.couchbase.domain.UserAnnotated2; import org.springframework.data.couchbase.domain.UserAnnotated3; +import org.springframework.data.couchbase.domain.UserAnnotatedTouchOnRead; import org.springframework.data.couchbase.domain.UserSubmission; import org.springframework.data.couchbase.util.ClusterType; import org.springframework.data.couchbase.util.IgnoreWhen; @@ -136,24 +137,60 @@ void findByIdWithExpiryAnnotation() { assertEquals(user2, foundUser2); // now set user1 expiration back to 1 second with getAndTouch using the @Document(expiry=1) annotation + // This will have no effect as UserAnnotated does not have touchOnGet foundUser1 = couchbaseTemplate.findById(UserAnnotated.class).one(user1.getId()); user1.setVersion(foundUser1.getVersion());// version will have changed assertEquals(user1, foundUser1); // user1 should be gone, user2 should still be there int tries = 0; - Collection foundUsers; + Collection foundUsers; do { - sleepSecs(1); - foundUsers = (Collection) couchbaseTemplate.findById(User.class) + sleepSecs(3); + foundUsers = (Collection) couchbaseTemplate.findById(UserAnnotated.class) .all(Arrays.asList(user1.getId(), user2.getId())); - } while (tries++ < 7 && foundUsers.size() != 1 && !user2.equals(foundUsers.iterator().next())); - assertEquals(1, foundUsers.size(), "should have found exactly 1 user"); - assertEquals(user2, foundUsers.iterator().next()); + } while (tries++ < 7 && foundUsers.size() != 2 && !user2.equals(foundUsers.iterator().next())); + assertEquals(2, foundUsers.size(), "should have found exactly 2 users"); } finally { - couchbaseTemplate.removeByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all(); + couchbaseTemplate.removeByQuery(UserAnnotated.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all(); } + } + + @Test + void findByIdWithExpiryAnnotationTouchOnRead() { + try { + UserAnnotatedTouchOnRead user1 = new UserAnnotatedTouchOnRead(UUID.randomUUID().toString(), "user1", "user1"); + UserAnnotatedTouchOnRead user2 = new UserAnnotatedTouchOnRead(UUID.randomUUID().toString(), "user2", "user2"); + + Collection upserts = (Collection) couchbaseTemplate.upsertById(UserAnnotatedTouchOnRead.class) + .all(Arrays.asList(user1, user2)); + + // explicitly set expiry to 10 seconds + UserAnnotatedTouchOnRead foundUser1 = couchbaseTemplate.findById(UserAnnotatedTouchOnRead.class).withExpiry(Duration.ofSeconds(10)).one(user1.getId()); + user1.setVersion(foundUser1.getVersion());// version will have changed + assertEquals(user1, foundUser1); + UserAnnotatedTouchOnRead foundUser2 = couchbaseTemplate.findById(UserAnnotatedTouchOnRead.class).withExpiry(Duration.ofSeconds(10)).one(user2.getId()); + user2.setVersion(foundUser2.getVersion());// version will have changed + assertEquals(user2, foundUser2); + + // now set user1 expiration back to 1 second with getAndTouch using the @Document(expiry=1) annotation + foundUser1 = couchbaseTemplate.findById(UserAnnotatedTouchOnRead.class).one(user1.getId()); + user1.setVersion(foundUser1.getVersion());// version will have changed + assertEquals(user1, foundUser1); + // user1 should be gone, user2 should still be there + int tries = 0; + Collection foundUsers; + do { + sleepSecs(3); + foundUsers = (Collection) couchbaseTemplate.findById(UserAnnotatedTouchOnRead.class) + .all(Arrays.asList(user1.getId(), user2.getId())); + } while (tries++ < 7 && foundUsers.size() != 1 && !user2.equals(foundUsers.iterator().next())); + assertEquals(1, foundUsers.size(), "should have found exactly 1 user1"); + assertEquals(user2.getId(), foundUsers.iterator().next().getId()); + } finally { + couchbaseTemplate.removeByQuery(UserAnnotatedTouchOnRead.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all(); + } } @Test void upsertAndFindById() {