DATAREDIS-589 - Move secondary index cleanup to MappingExpirationListener.

We now no longer rely on ApplicationEvents captured in the RedisKeyValueAdapter for performing cleanup operations for expired keys, but do this along with the phantom key removal. This removes a flaw when initializing a non repository related KeyspaceEventListener publishing events that actually are unrelated to the Adapter.

Additionally upgraded test infrastructure to utilize Redis 3.2.6 with disabled protected-mode and enabled keyspace-events.

Original pull request: #232.
This commit is contained in:
Christoph Strobl
2017-01-10 13:33:47 +01:00
committed by Mark Paluch
parent 253c281205
commit 639b1e2b55
5 changed files with 114 additions and 32 deletions

View File

@@ -24,6 +24,7 @@ import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.AfterClass;
@@ -43,6 +44,7 @@ import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisKeyValueAdapter.EnableKeyspaceEvents;
import org.springframework.data.redis.core.convert.Bucket;
import org.springframework.data.redis.core.convert.KeyspaceConfiguration;
import org.springframework.data.redis.core.convert.MappingConfiguration;
@@ -92,6 +94,7 @@ public class RedisKeyValueAdapterTests {
mappingContext.afterPropertiesSet();
adapter = new RedisKeyValueAdapter(template, mappingContext);
adapter.setEnableKeyspaceEvents(EnableKeyspaceEvents.ON_STARTUP);
adapter.afterPropertiesSet();
template.execute(new RedisCallback<Void>() {
@@ -239,26 +242,67 @@ public class RedisKeyValueAdapterTests {
assertThat(template.opsForSet().members("persons:firstname:rand"), not(hasItem("1")));
}
@Test // DATAREDIS-425
public void keyExpiredEventShouldRemoveHelperStructures() {
/**
* @see DATAREDIS-425
*/
@Test
public void keyExpiredEventShouldRemoveHelperStructures() throws InterruptedException {
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("_class", Person.class.getName());
map.put("firstname", "rand");
map.put("address.country", "Andor");
template.opsForHash().putAll("persons:1", map);
template.expire("persons:1", 1, TimeUnit.SECONDS);
template.opsForSet().add("persons", "1");
template.opsForSet().add("persons:firstname:rand", "1");
template.opsForSet().add("persons:1:idx", "persons:firstname:rand");
adapter.onApplicationEvent(new RedisKeyExpiredEvent("persons:1".getBytes(Bucket.CHARSET)));
int iterationCount = 0;
while (template.hasKey("persons:1") && iterationCount++ < 3) { // ci might be a little slow
Thread.sleep(2000);
}
assertThat(template.hasKey("persons:1"), is(false));
assertThat(template.hasKey("persons:firstname:rand"), is(false));
assertThat(template.hasKey("persons:1:idx"), is(false));
assertThat(template.opsForSet().members("persons"), not(hasItem("1")));
}
@Test // DATAREDIS-512
/**
* @see DATAREDIS-589
*/
@Test
public void keyExpiredEventWithoutKeyspaceShouldBeIgnored() throws InterruptedException {
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("_class", Person.class.getName());
map.put("firstname", "rand");
map.put("address.country", "Andor");
template.opsForHash().putAll("persons:1", map);
template.opsForHash().putAll("1", map);
template.expire("1", 1, TimeUnit.SECONDS);
template.opsForSet().add("persons", "1");
template.opsForSet().add("persons:firstname:rand", "1");
template.opsForSet().add("persons:1:idx", "persons:firstname:rand");
Thread.sleep(2000);
assertThat(template.hasKey("persons:1"), is(true));
assertThat(template.hasKey("persons:firstname:rand"), is(true));
assertThat(template.hasKey("persons:1:idx"), is(true));
assertThat(template.opsForSet().members("persons"), hasItem("1"));
}
/**
* @see DATAREDIS-512
*/
@Test
public void putWritesIndexDataCorrectly() {
Person rand = new Person();