Move expires check to dedicated method.

Introduce helper method to unify expiry check and simplify control flow.

Original Pull Request: #1961
This commit is contained in:
Christoph Strobl
2021-02-10 12:47:41 +01:00
parent 8933e026f5
commit 9b18e0cea1
2 changed files with 43 additions and 23 deletions

View File

@@ -235,23 +235,27 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
connection.hMSet(objectKey, rdo.getBucket().rawMap());
if (rdo.getTimeToLive() != null && rdo.getTimeToLive() > 0) {
if(isNew) {
connection.sAdd(toBytes(rdo.getKeyspace()), key);
}
if (expires(rdo)) {
connection.expire(objectKey, rdo.getTimeToLive());
}
if (keepShadowCopy()) { // add phantom key so values can be restored
// add phantom key so values can be restored
byte[] phantomKey = ByteUtils.concat(objectKey, BinaryKeyspaceIdentifier.PHANTOM_SUFFIX);
connection.del(phantomKey);
connection.hMSet(phantomKey, rdo.getBucket().rawMap());
connection.expire(phantomKey, rdo.getTimeToLive() + PHANTOM_KEY_TTL);
}
boolean isNoExpire = rdo.getTimeToLive() == null || rdo.getTimeToLive() != null && rdo.getTimeToLive() < 0;
if (isNoExpire && !isNew && keepShadowCopy()) {
connection.del(ByteUtils.concat(objectKey, BinaryKeyspaceIdentifier.PHANTOM_SUFFIX));
}
if (expires(rdo)) {
connection.sAdd(toBytes(rdo.getKeyspace()), key);
connection.del(phantomKey);
connection.hMSet(phantomKey, rdo.getBucket().rawMap());
connection.expire(phantomKey, rdo.getTimeToLive() + PHANTOM_KEY_TTL);
} else if (!isNew) {
connection.del(phantomKey);
}
}
IndexWriter indexWriter = new IndexWriter(connection, converter);
if (isNew) {
@@ -346,11 +350,14 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
connection.sRem(binKeyspace, binId);
new IndexWriter(connection, converter).removeKeyFromIndexes(asString(keyspace), binId);
RedisPersistentEntity<?> persistentEntity = converter.getMappingContext().getPersistentEntity(type);
if (persistentEntity != null && persistentEntity.isExpiring()) {
if(RedisKeyValueAdapter.this.keepShadowCopy()) {
byte[] phantomKey = ByteUtils.concat(keyToDelete, BinaryKeyspaceIdentifier.PHANTOM_SUFFIX);
connection.del(phantomKey);
RedisPersistentEntity<?> persistentEntity = converter.getMappingContext().getPersistentEntity(type);
if (persistentEntity != null && persistentEntity.isExpiring()) {
byte[] phantomKey = ByteUtils.concat(keyToDelete, BinaryKeyspaceIdentifier.PHANTOM_SUFFIX);
connection.del(phantomKey);
}
}
return null;
});
@@ -481,7 +488,7 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
if (update.isRefreshTtl()) {
if (rdo.getTimeToLive() != null && rdo.getTimeToLive() > 0) {
if (expires(rdo)) {
connection.expire(redisKey, rdo.getTimeToLive());
@@ -493,7 +500,10 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
} else {
connection.persist(redisKey);
connection.del(ByteUtils.concat(redisKey, BinaryKeyspaceIdentifier.PHANTOM_SUFFIX));
if(keepShadowCopy()) {
connection.del(ByteUtils.concat(redisKey, BinaryKeyspaceIdentifier.PHANTOM_SUFFIX));
}
}
}
@@ -650,6 +660,16 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
return target;
}
/**
* @return {@literal true} if {@link RedisData#getTimeToLive()} has a positive value.
*
* @param data must not be {@literal null}.
* @since 2.3.7
*/
private boolean expires(RedisData data) {
return data.getTimeToLive() != null && data.getTimeToLive() > 0;
}
/**
* Configure usage of {@link KeyExpirationEventMessageListener}.
*

View File

@@ -688,10 +688,10 @@ public class RedisKeyValueAdapterTests {
assertThat(updatedLocation.getY()).isCloseTo(18D, offset(0.005));
}
@Test // DATAREDIS-1955
@Test // GH-1955
public void phantomKeyIsDeletedWhenPutWithNegativeTimeToLiveAndOldEntryTimeToLiveWasPositiveAndWhenShadowCopyIsTurnedOn() {
ExpiringPerson rand = new ExpiringPerson();
rand.id = "1";
rand.ttl = 3000L;
adapter.put("1", rand, "persons");
@@ -705,21 +705,21 @@ public class RedisKeyValueAdapterTests {
assertThat(template.hasKey("persons:1:phantom")).isFalse();
}
@Test // DATAREDIS-1955
@Test // GH-1955
public 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<ExpiringPerson> update = new PartialUpdate<>("1", ExpiringPerson.class) //
.refreshTtl(true);
.set("ttl", -1L).refreshTtl(true);
adapter.update(update);
assertThat(template.getExpire("persons:1")).isNotPositive();
assertThat(template.hasKey("persons:1:phantom")).isFalse();
}