Skip to content

Commit c6ad238

Browse files
mp911dechristophstrobl
authored andcommitted
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
1 parent 8e481f4 commit c6ad238

File tree

7 files changed

+438
-53
lines changed

7 files changed

+438
-53
lines changed

src/main/java/org/springframework/data/redis/core/RedisKeyExpiredEvent.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015 the original author or authors.
2+
* Copyright 2015-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,13 +18,14 @@
1818
import java.nio.charset.Charset;
1919

2020
import org.springframework.context.ApplicationEvent;
21-
import org.springframework.data.redis.util.ByteUtils;
21+
import org.springframework.data.redis.core.convert.MappingRedisConverter.BinaryKeyspaceIdentifier;
2222

2323
/**
2424
* {@link RedisKeyExpiredEvent} is Redis specific {@link ApplicationEvent} published when a specific key in Redis
2525
* expires. It might but must not hold the expired value itself next to the key.
26-
*
26+
*
2727
* @author Christoph Strobl
28+
* @author Mark Paluch
2829
* @since 1.7
2930
*/
3031
public class RedisKeyExpiredEvent<T> extends RedisKeyspaceEvent {
@@ -34,12 +35,12 @@ public class RedisKeyExpiredEvent<T> extends RedisKeyspaceEvent {
3435
*/
3536
public static final Charset CHARSET = Charset.forName("UTF-8");
3637

37-
private final byte[][] args;
38+
private final BinaryKeyspaceIdentifier objectId;
3839
private final Object value;
3940

4041
/**
4142
* Creates new {@link RedisKeyExpiredEvent}.
42-
*
43+
*
4344
* @param key
4445
*/
4546
public RedisKeyExpiredEvent(byte[] key) {
@@ -67,36 +68,36 @@ public RedisKeyExpiredEvent(byte[] key, Object value) {
6768
public RedisKeyExpiredEvent(String channel, byte[] key, Object value) {
6869
super(channel, key);
6970

70-
args = ByteUtils.split(key, ':');
71+
if (BinaryKeyspaceIdentifier.isValid(key)) {
72+
this.objectId = BinaryKeyspaceIdentifier.of(key);
73+
} else {
74+
this.objectId = null;
75+
}
76+
7177
this.value = value;
7278
}
7379

7480
/**
7581
* Gets the keyspace in which the expiration occured.
76-
*
82+
*
7783
* @return {@literal null} if it could not be determined.
7884
*/
7985
public String getKeyspace() {
80-
81-
if (args.length >= 2) {
82-
return new String(args[0], CHARSET);
83-
}
84-
85-
return null;
86+
return objectId != null ? new String(objectId.getKeyspace(), CHARSET) : null;
8687
}
8788

8889
/**
8990
* Get the expired objects id;
90-
*
91+
*
9192
* @return
9293
*/
9394
public byte[] getId() {
94-
return args.length == 2 ? args[1] : args[0];
95+
return objectId != null ? objectId.getId() : getSource();
9596
}
9697

9798
/**
9899
* Get the expired Object
99-
*
100+
*
100101
* @return {@literal null} if not present.
101102
*/
102103
public Object getValue() {

src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
import java.util.concurrent.TimeUnit;
2828
import java.util.concurrent.atomic.AtomicReference;
2929

30-
import org.slf4j.Logger;
31-
import org.slf4j.LoggerFactory;
3230
import org.springframework.beans.BeansException;
3331
import org.springframework.beans.factory.InitializingBean;
3432
import org.springframework.context.ApplicationContext;
@@ -52,6 +50,8 @@
5250
import org.springframework.data.redis.core.convert.GeoIndexedPropertyValue;
5351
import org.springframework.data.redis.core.convert.KeyspaceConfiguration;
5452
import org.springframework.data.redis.core.convert.MappingRedisConverter;
53+
import org.springframework.data.redis.core.convert.MappingRedisConverter.BinaryKeyspaceIdentifier;
54+
import org.springframework.data.redis.core.convert.MappingRedisConverter.KeyspaceIdentifier;
5555
import org.springframework.data.redis.core.convert.PathIndexResolver;
5656
import org.springframework.data.redis.core.convert.RedisConverter;
5757
import org.springframework.data.redis.core.convert.RedisData;
@@ -64,7 +64,6 @@
6464
import org.springframework.data.util.CloseableIterator;
6565
import org.springframework.util.Assert;
6666
import org.springframework.util.ObjectUtils;
67-
import org.springframework.util.StringUtils;
6867

6968
/**
7069
* Redis specific {@link KeyValueAdapter} implementation. Uses binary codec to read/write data from/to Redis. Objects
@@ -228,7 +227,7 @@ public Object doInRedis(RedisConnection connection) throws DataAccessException {
228227
connection.expire(objectKey, rdo.getTimeToLive().longValue());
229228

230229
// add phantom key so values can be restored
231-
byte[] phantomKey = ByteUtils.concat(objectKey, toBytes(":phantom"));
230+
byte[] phantomKey = ByteUtils.concat(objectKey, BinaryKeyspaceIdentifier.PHANTOM_SUFFIX);
232231
connection.del(phantomKey);
233232
connection.hMSet(phantomKey, rdo.getBucket().rawMap());
234233
connection.expire(phantomKey, rdo.getTimeToLive().longValue() + 300);
@@ -484,14 +483,14 @@ public Void doInRedis(RedisConnection connection) throws DataAccessException {
484483
connection.expire(redisKey, rdo.getTimeToLive().longValue());
485484

486485
// add phantom key so values can be restored
487-
byte[] phantomKey = ByteUtils.concat(redisKey, toBytes(":phantom"));
486+
byte[] phantomKey = ByteUtils.concat(redisKey, BinaryKeyspaceIdentifier.PHANTOM_SUFFIX);
488487
connection.hMSet(phantomKey, rdo.getBucket().rawMap());
489488
connection.expire(phantomKey, rdo.getTimeToLive().longValue() + 300);
490489

491490
} else {
492491

493492
connection.persist(redisKey);
494-
connection.persist(ByteUtils.concat(redisKey, toBytes(":phantom")));
493+
connection.persist(ByteUtils.concat(redisKey, BinaryKeyspaceIdentifier.PHANTOM_SUFFIX));
495494
}
496495
}
497496

@@ -779,7 +778,7 @@ public void onMessage(Message message, byte[] pattern) {
779778
byte[] key = message.getBody();
780779

781780
final byte[] phantomKey = ByteUtils.concat(key,
782-
converter.getConversionService().convert(":phantom", byte[].class));
781+
converter.getConversionService().convert(KeyspaceIdentifier.PHANTOM_SUFFIX, byte[].class));
783782

784783
Map<byte[], byte[]> hash = ops.execute(new RedisCallback<Map<byte[], byte[]>>() {
785784

@@ -822,12 +821,7 @@ private boolean isKeyExpirationMessage(Message message) {
822821
return false;
823822
}
824823

825-
byte[][] args = ByteUtils.split(message.getBody(), ':');
826-
if (args.length != 2) {
827-
return false;
828-
}
829-
830-
return true;
824+
return BinaryKeyspaceIdentifier.isValid(message.getBody());
831825
}
832826
}
833827

0 commit comments

Comments
 (0)