diff --git a/pom.xml b/pom.xml
index a5d3a47ec6..8b64370059 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-redis
- 2.5.0-SNAPSHOT
+ 2.5.0-DATAREDIS-1955-SNAPSHOT
Spring Data Redis
diff --git a/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java b/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java
index 832231c667..28d9c8e204 100644
--- a/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java
+++ b/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java
@@ -99,6 +99,7 @@
*
* @author Christoph Strobl
* @author Mark Paluch
+ * @author Andrey Muchnik
* @since 1.7
*/
public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
@@ -248,6 +249,11 @@ public Object put(Object id, Object item, String keyspace) {
}
}
+ boolean isNoExpire = rdo.getTimeToLive() == null || rdo.getTimeToLive() != null && rdo.getTimeToLive() < 0;
+ if (isNoExpire && !isNew && keepShadowCopy()){
+ connection.del(ByteUtils.concat(objectKey, BinaryKeyspaceIdentifier.PHANTOM_SUFFIX));
+ }
+
connection.sAdd(toBytes(rdo.getKeyspace()), key);
IndexWriter indexWriter = new IndexWriter(connection, converter);
@@ -492,7 +498,7 @@ public void update(PartialUpdate> update) {
} else {
connection.persist(redisKey);
- connection.persist(ByteUtils.concat(redisKey, BinaryKeyspaceIdentifier.PHANTOM_SUFFIX));
+ connection.del(ByteUtils.concat(redisKey, BinaryKeyspaceIdentifier.PHANTOM_SUFFIX));
}
}
diff --git a/src/test/java/org/springframework/data/redis/core/RedisKeyValueAdapterTests.java b/src/test/java/org/springframework/data/redis/core/RedisKeyValueAdapterTests.java
index 48330cd237..60903098b6 100644
--- a/src/test/java/org/springframework/data/redis/core/RedisKeyValueAdapterTests.java
+++ b/src/test/java/org/springframework/data/redis/core/RedisKeyValueAdapterTests.java
@@ -54,6 +54,7 @@
*
* @author Christoph Strobl
* @author Mark Paluch
+ * @author Andrey Muchnik
*/
@ExtendWith(LettuceConnectionFactoryExtension.class)
public class RedisKeyValueAdapterTests {
@@ -705,6 +706,41 @@ void phantomKeyInsertedOnPutWhenShadowCopyIsInDefaultAndKeyspaceNotificationEnab
assertThat(template.hasKey("persons:1:phantom")).isTrue();
}
+ @Test // DATAREDIS-1955
+ void phantomKeyIsDeletedWhenPutWithNegativeTimeToLiveAndOldEntryTimeToLiveWasPositiveAndWhenShadowCopyIsTurnedOn() {
+ ExpiringPerson rand = new ExpiringPerson();
+ rand.id = "1";
+ rand.ttl = 3000L;
+
+ adapter.put("1", rand, "persons");
+
+ assertThat(template.getExpire("persons:1:phantom")).isPositive();
+
+ rand.ttl = -1L;
+
+ adapter.put("1", rand, "persons");
+
+ assertThat(template.hasKey("persons:1:phantom")).isFalse();
+ }
+
+ @Test // DATAREDIS-1955
+ void updateWithRefreshTtlAndWithoutPositiveTtlShouldDeletePhantomKey() {
+ ExpiringPerson person = new ExpiringPerson();
+ person.id = "1";
+ person.ttl = 100L;
+
+ adapter.put("1", person, "persons");
+
+ assertThat(template.getExpire("persons:1:phantom")).isPositive();
+
+ PartialUpdate update = new PartialUpdate<>("1", ExpiringPerson.class) //
+ .refreshTtl(true);
+
+ adapter.update(update);
+
+ assertThat(template.hasKey("persons:1:phantom")).isFalse();
+ }
+
/**
* Wait up to 5 seconds until {@code key} is no longer available in Redis.
*