DATAREDIS-744 - Support Redis hashes with colon in their id.
We now support Redis hashes via Repository support that contain colon in their id. We're using colons to split a composite id string into keyspace and id parts. Previously, we partially rejected processing of id's that don't exactly match the number of parts delimited by colon. This caused leftovers in secondary indexes. Original Pull Request: #298
This commit is contained in:
committed by
Christoph Strobl
parent
323cb32861
commit
5de73903c1
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis.core;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link RedisKeyExpiredEvent}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class RedisKeyExpiredEventUnitTests {
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void shouldReturnKeyspace() {
|
||||
|
||||
assertThat(new RedisKeyExpiredEvent<Object>("foo".getBytes(), "").getKeyspace(), is(nullValue()));
|
||||
assertThat(new RedisKeyExpiredEvent<Object>("foo:bar".getBytes(), "").getKeyspace(), is(equalTo("foo")));
|
||||
assertThat(new RedisKeyExpiredEvent<Object>("foo:bar:baz".getBytes(), "").getKeyspace(), is(equalTo("foo")));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void shouldReturnId() {
|
||||
|
||||
assertThat(new RedisKeyExpiredEvent<Object>("foo".getBytes(), "").getId(), is(equalTo("foo".getBytes())));
|
||||
assertThat(new RedisKeyExpiredEvent<Object>("foo:bar".getBytes(), "").getId(), is(equalTo("bar".getBytes())));
|
||||
assertThat(new RedisKeyExpiredEvent<Object>("foo:bar:baz".getBytes(), "").getId(),
|
||||
is(equalTo("bar:baz".getBytes())));
|
||||
}
|
||||
}
|
||||
@@ -146,6 +146,20 @@ public class RedisKeyValueAdapterTests {
|
||||
assertThat(template.opsForHash().entries("persons:1").size(), is(2));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void putWritesDataWithColonCorrectly() {
|
||||
|
||||
Person rand = new Person();
|
||||
rand.age = 24;
|
||||
|
||||
adapter.put("1:a", rand, "persons");
|
||||
|
||||
assertThat(template.keys("persons*"), hasItems("persons", "persons:1:a"));
|
||||
assertThat(template.opsForSet().size("persons"), is(1L));
|
||||
assertThat(template.opsForSet().members("persons"), hasItems("1:a"));
|
||||
assertThat(template.opsForHash().entries("persons:1:a").size(), is(2));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-425
|
||||
public void putWritesSimpleIndexDataCorrectly() {
|
||||
|
||||
@@ -158,6 +172,18 @@ public class RedisKeyValueAdapterTests {
|
||||
assertThat(template.opsForSet().members("persons:firstname:rand"), hasItems("1"));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void putWritesSimpleIndexDataWithColonCorrectly() {
|
||||
|
||||
Person rand = new Person();
|
||||
rand.firstname = "rand";
|
||||
|
||||
adapter.put("1:a", rand, "persons");
|
||||
|
||||
assertThat(template.keys("persons*"), hasItem("persons:firstname:rand"));
|
||||
assertThat(template.opsForSet().members("persons:firstname:rand"), hasItems("1:a"));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-425
|
||||
public void putWritesNestedDataCorrectly() {
|
||||
|
||||
@@ -184,15 +210,15 @@ public class RedisKeyValueAdapterTests {
|
||||
assertThat(template.opsForSet().members("persons:address.country:Andor"), hasItems("1"));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-425
|
||||
@Test // DATAREDIS-425, DATAREDIS-744
|
||||
public void getShouldReadSimpleObjectCorrectly() {
|
||||
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
map.put("_class", Person.class.getName());
|
||||
map.put("age", "24");
|
||||
template.opsForHash().putAll("persons:load-1", map);
|
||||
template.opsForHash().putAll("persons:load-1:a", map);
|
||||
|
||||
Object loaded = adapter.get("load-1", "persons");
|
||||
Object loaded = adapter.get("load-1:a", "persons");
|
||||
|
||||
assertThat(loaded, instanceOf(Person.class));
|
||||
assertThat(((Person) loaded).age, is(24));
|
||||
@@ -257,7 +283,7 @@ public class RedisKeyValueAdapterTests {
|
||||
assertThat(template.opsForSet().members("persons:firstname:rand"), not(hasItem("1")));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-425
|
||||
@Test // DATAREDIS-425, DATAREDIS-744
|
||||
public void keyExpiredEventShouldRemoveHelperStructures() throws Exception {
|
||||
|
||||
assumeTrue(RedisTestProfileValueSource.matches("runLongTests", "true"));
|
||||
@@ -267,22 +293,22 @@ public class RedisKeyValueAdapterTests {
|
||||
map.put("firstname", "rand");
|
||||
map.put("address.country", "Andor");
|
||||
|
||||
template.opsForHash().putAll("persons:1", map);
|
||||
template.opsForHash().putAll("persons:1:b", map);
|
||||
|
||||
template.opsForSet().add("persons", "1");
|
||||
template.opsForSet().add("persons:firstname:rand", "1");
|
||||
template.opsForSet().add("persons:1:idx", "persons:firstname:rand");
|
||||
template.opsForSet().add("persons:firstname:rand", "1:b");
|
||||
template.opsForSet().add("persons:1:b:idx", "persons:firstname:rand");
|
||||
|
||||
template.expire("persons:1", 100, TimeUnit.MILLISECONDS);
|
||||
template.expire("persons:1:b", 100, TimeUnit.MILLISECONDS);
|
||||
|
||||
waitUntilKeyIsGone(template, "persons:1");
|
||||
waitUntilKeyIsGone(template, "persons:1:phantom");
|
||||
waitUntilKeyIsGone(template, "persons:1:b");
|
||||
waitUntilKeyIsGone(template, "persons:1:b:phantom");
|
||||
waitUntilKeyIsGone(template, "persons:firstname:rand");
|
||||
|
||||
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")));
|
||||
assertThat(template.hasKey("persons:1:b:idx"), is(false));
|
||||
assertThat(template.opsForSet().members("persons"), not(hasItem("1:b")));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-589
|
||||
@@ -348,17 +374,17 @@ public class RedisKeyValueAdapterTests {
|
||||
assertThat(template.opsForSet().isMember("persons:mat:idx", "persons:firstname:mat"), is(true));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-471
|
||||
@Test // DATAREDIS-471, DATAREDIS-744
|
||||
public void updateShouldAlterIndexDataCorrectly() {
|
||||
|
||||
Person rand = new Person();
|
||||
rand.firstname = "rand";
|
||||
|
||||
adapter.put("1", rand, "persons");
|
||||
adapter.put("1:a", rand, "persons");
|
||||
|
||||
assertThat(template.hasKey("persons:firstname:rand"), is(true));
|
||||
|
||||
PartialUpdate<Person> update = new PartialUpdate<>("1", Person.class) //
|
||||
PartialUpdate<Person> update = new PartialUpdate<>("1:a", Person.class) //
|
||||
.set("firstname", "mat");
|
||||
|
||||
adapter.update(update);
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis.core.convert;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.redis.core.convert.MappingRedisConverter.BinaryKeyspaceIdentifier;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link BinaryKeyspaceIdentifier}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class BinaryKeyspaceIdentifierUnitTests {
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void shouldReturnIfKeyIsValid() {
|
||||
|
||||
assertThat(BinaryKeyspaceIdentifier.isValid(null), is(false));
|
||||
assertThat(BinaryKeyspaceIdentifier.isValid("foo".getBytes()), is(false));
|
||||
assertThat(BinaryKeyspaceIdentifier.isValid("".getBytes()), is(false));
|
||||
assertThat(BinaryKeyspaceIdentifier.isValid("foo:bar".getBytes()), is(true));
|
||||
assertThat(BinaryKeyspaceIdentifier.isValid("foo:bar:baz".getBytes()), is(true));
|
||||
assertThat(BinaryKeyspaceIdentifier.isValid("foo:bar:baz:phantom".getBytes()), is(true));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void shouldReturnKeyspace() {
|
||||
|
||||
assertThat(BinaryKeyspaceIdentifier.of("foo:bar".getBytes()).getKeyspace(), is(equalTo("foo".getBytes())));
|
||||
assertThat(BinaryKeyspaceIdentifier.of("foo:bar:baz".getBytes()).getKeyspace(), is(equalTo("foo".getBytes())));
|
||||
assertThat(BinaryKeyspaceIdentifier.of("foo:bar:baz:phantom".getBytes()).getKeyspace(),
|
||||
is(equalTo("foo".getBytes())));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void shouldReturnId() {
|
||||
|
||||
assertThat(BinaryKeyspaceIdentifier.of("foo:bar".getBytes()).getId(), is(equalTo("bar".getBytes())));
|
||||
assertThat(BinaryKeyspaceIdentifier.of("foo:bar:baz".getBytes()).getId(), is(equalTo("bar:baz".getBytes())));
|
||||
assertThat(BinaryKeyspaceIdentifier.of("foo:bar:baz:phantom".getBytes()).getId(),
|
||||
is(equalTo("bar:baz".getBytes())));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void shouldReturnPhantomKey() {
|
||||
|
||||
assertThat(BinaryKeyspaceIdentifier.of("foo:bar".getBytes()).isPhantomKey(), is(false));
|
||||
assertThat(BinaryKeyspaceIdentifier.of("foo:bar:baz".getBytes()).isPhantomKey(), is(false));
|
||||
assertThat(BinaryKeyspaceIdentifier.of("foo:bar:baz:phantom".getBytes()).isPhantomKey(), is(true));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.redis.core.convert;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.redis.core.convert.MappingRedisConverter.KeyspaceIdentifier;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link KeyspaceIdentifier}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class KeyspaceIdentifierUnitTests {
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void shouldReturnIfKeyIsValid() {
|
||||
|
||||
assertThat(KeyspaceIdentifier.isValid(null), is(false));
|
||||
assertThat(KeyspaceIdentifier.isValid("foo"), is(false));
|
||||
assertThat(KeyspaceIdentifier.isValid(""), is(false));
|
||||
assertThat(KeyspaceIdentifier.isValid("foo:bar"), is(true));
|
||||
assertThat(KeyspaceIdentifier.isValid("foo:bar:baz"), is(true));
|
||||
assertThat(KeyspaceIdentifier.isValid("foo:bar:baz:phantom"), is(true));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void shouldReturnKeyspace() {
|
||||
|
||||
assertThat(KeyspaceIdentifier.of("foo:bar").getKeyspace(), is("foo"));
|
||||
assertThat(KeyspaceIdentifier.of("foo:bar:baz").getKeyspace(), is("foo"));
|
||||
assertThat(KeyspaceIdentifier.of("foo:bar:baz:phantom").getKeyspace(), is("foo"));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void shouldReturnId() {
|
||||
|
||||
assertThat(KeyspaceIdentifier.of("foo:bar").getId(), is("bar"));
|
||||
assertThat(KeyspaceIdentifier.of("foo:bar:baz").getId(), is("bar:baz"));
|
||||
assertThat(KeyspaceIdentifier.of("foo:bar:baz:phantom").getId(), is("bar:baz"));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-744
|
||||
public void shouldReturnPhantomKey() {
|
||||
|
||||
assertThat(KeyspaceIdentifier.of("foo:bar").isPhantomKey(), is(false));
|
||||
assertThat(KeyspaceIdentifier.of("foo:bar:baz").isPhantomKey(), is(false));
|
||||
assertThat(KeyspaceIdentifier.of("foo:bar:baz:phantom").isPhantomKey(), is(true));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user