Skip to content

Commit d1e4110

Browse files
author
R-J Lim
committed
Iteration on key-prefixing POC
- Demonstrated automatic key-prefixing for all subclasses of UnifiedJedis: JedisCluster, JedisPooled, and JedisSentineled - Key-prefixing is possible as long as the underlying CommandObjects can be customized. - CommandObjects cannot use commandArguments in its constructor since in the specific case of key-prefixing, commandArguments depends on the child constructor running first. So we lose caching of argument-less CommandObjects. - Based on this POC, the minimum changes required to jedis would be: - public constructors that allow UnifiedJedis and its subclasses to take a custom CommandObjects. - Consistent use of supplied CommandObjects throughout code (e.g. in Pipeline, Transaction, etc). - Removal of caching of argument-less CommandObjects in the constructor of CommandObjects. - Applications can then supply CommandObjects with custom behavior as necessary. Sample classes CommandObjectsWithPrefixedKeys that implement the behavior of prefixed keys, etc are provided but these can be supplied by the application as long as required constructors are available.
1 parent a0efc76 commit d1e4110

15 files changed

+233
-126
lines changed

src/main/java/redis/clients/jedis/ClusterCommandObjectsWithPrefixedKeys.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
import redis.clients.jedis.commands.ProtocolCommand;
44

55
public class ClusterCommandObjectsWithPrefixedKeys extends ClusterCommandObjects {
6-
// For the purposes of this demonstration, the prefix is assigned statically.
7-
// Additional changes are required to prevent the parent class CommandObjects
8-
// from calling commandArguments in its constructor, which would be a prerequisite
9-
// to making this field into an instance field.
10-
public static String PREFIX_STRING;
6+
private final String prefixString;
7+
8+
public ClusterCommandObjectsWithPrefixedKeys(String prefixString) {
9+
this.prefixString = prefixString;
10+
}
1111

1212
@Override
1313
protected ClusterCommandArguments commandArguments(ProtocolCommand command) {
14-
return new ClusterCommandArgumentsWithPrefixedKeys(command, PREFIX_STRING);
14+
return new ClusterCommandArgumentsWithPrefixedKeys(command, prefixString);
1515
}
1616
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package redis.clients.jedis;
2+
3+
import redis.clients.jedis.args.Rawable;
4+
import redis.clients.jedis.args.RawableFactory;
5+
import redis.clients.jedis.commands.ProtocolCommand;
6+
import redis.clients.jedis.util.SafeEncoder;
7+
8+
public class CommandArgumentsWithPrefixedKeys extends CommandArguments {
9+
private final byte[] prefix;
10+
private final String prefixString;
11+
12+
public CommandArgumentsWithPrefixedKeys(ProtocolCommand command, String prefixString) {
13+
super(command);
14+
this.prefixString = prefixString;
15+
prefix = SafeEncoder.encode(prefixString);
16+
}
17+
18+
public CommandArguments key(Object key) {
19+
return super.key(namespacedKey(key));
20+
}
21+
22+
private Object namespacedKey(Object key) {
23+
if (key instanceof Rawable) {
24+
byte[] raw = ((Rawable) key).getRaw();
25+
return RawableFactory.from(namespacedKeyBytes(raw));
26+
}
27+
28+
if (key instanceof byte[]) {
29+
return namespacedKeyBytes((byte[]) key);
30+
}
31+
32+
if (key instanceof String) {
33+
String raw = (String) key;
34+
return prefixString + raw;
35+
}
36+
37+
throw new IllegalArgumentException("\"" + key.toString() + "\" is not a valid argument.");
38+
}
39+
40+
private byte[] namespacedKeyBytes(byte[] key) {
41+
byte[] namespaced = new byte[prefix.length + key.length];
42+
System.arraycopy(prefix, 0, namespaced, 0, prefix.length);
43+
System.arraycopy(key, 0, namespaced, prefix.length, key.length);
44+
return namespaced;
45+
}
46+
}

src/main/java/redis/clients/jedis/CommandObjects.java

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,16 @@ protected CommandArguments commandArguments(ProtocolCommand command) {
6363
return new CommandArguments(command);
6464
}
6565

66-
private final CommandObject<String> PING_COMMAND_OBJECT = new CommandObject<>(commandArguments(PING), BuilderFactory.STRING);
67-
6866
public final CommandObject<String> ping() {
69-
return PING_COMMAND_OBJECT;
67+
return new CommandObject<>(commandArguments(PING), BuilderFactory.STRING);
7068
}
7169

72-
private final CommandObject<String> FLUSHALL_COMMAND_OBJECT = new CommandObject<>(commandArguments(FLUSHALL), BuilderFactory.STRING);
73-
7470
public final CommandObject<String> flushAll() {
75-
return FLUSHALL_COMMAND_OBJECT;
71+
return new CommandObject<>(commandArguments(FLUSHALL), BuilderFactory.STRING);
7672
}
7773

78-
private final CommandObject<String> FLUSHDB_COMMAND_OBJECT = new CommandObject<>(commandArguments(FLUSHDB), BuilderFactory.STRING);
79-
8074
public final CommandObject<String> flushDB() {
81-
return FLUSHDB_COMMAND_OBJECT;
75+
return new CommandObject<>(commandArguments(FLUSHDB), BuilderFactory.STRING);
8276
}
8377

8478
public final CommandObject<String> configSet(String parameter, String value) {
@@ -2818,10 +2812,8 @@ public final CommandObject<String> scriptLoad(String script, String sampleKey) {
28182812
return new CommandObject<>(commandArguments(SCRIPT).add(LOAD).add(script).processKey(sampleKey), BuilderFactory.STRING);
28192813
}
28202814

2821-
private final CommandObject<String> SCRIPT_FLUSH_COMMAND_OBJECT = new CommandObject<>(commandArguments(SCRIPT).add(FLUSH), BuilderFactory.STRING);
2822-
28232815
public final CommandObject<String> scriptFlush() {
2824-
return SCRIPT_FLUSH_COMMAND_OBJECT;
2816+
return new CommandObject<>(commandArguments(SCRIPT).add(FLUSH), BuilderFactory.STRING);
28252817
}
28262818

28272819
public final CommandObject<String> scriptFlush(String sampleKey) {
@@ -2832,10 +2824,8 @@ public final CommandObject<String> scriptFlush(String sampleKey, FlushMode flush
28322824
return new CommandObject<>(commandArguments(SCRIPT).add(FLUSH).add(flushMode).processKey(sampleKey), BuilderFactory.STRING);
28332825
}
28342826

2835-
private final CommandObject<String> SCRIPT_KILL_COMMAND_OBJECT = new CommandObject<>(commandArguments(SCRIPT).add(KILL), BuilderFactory.STRING);
2836-
28372827
public final CommandObject<String> scriptKill() {
2838-
return SCRIPT_KILL_COMMAND_OBJECT;
2828+
return new CommandObject<>(commandArguments(SCRIPT).add(KILL), BuilderFactory.STRING);
28392829
}
28402830

28412831
public final CommandObject<String> scriptKill(String sampleKey) {
@@ -2863,11 +2853,8 @@ public final CommandObject<String> scriptKill(byte[] sampleKey) {
28632853
return new CommandObject<>(commandArguments(SCRIPT).add(KILL).processKey(sampleKey), BuilderFactory.STRING);
28642854
}
28652855

2866-
private final CommandObject<String> SLOWLOG_RESET_COMMAND_OBJECT
2867-
= new CommandObject<>(commandArguments(SLOWLOG).add(Keyword.RESET), BuilderFactory.STRING);
2868-
28692856
public final CommandObject<String> slowlogReset() {
2870-
return SLOWLOG_RESET_COMMAND_OBJECT;
2857+
return new CommandObject<>(commandArguments(SLOWLOG).add(Keyword.RESET), BuilderFactory.STRING);
28712858
}
28722859

28732860
public final CommandObject<Object> fcall(String name, List<String> keys, List<String> args) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package redis.clients.jedis;
2+
3+
import redis.clients.jedis.commands.ProtocolCommand;
4+
5+
public class CommandObjectsWithPrefixedKeys extends CommandObjects {
6+
private final String prefixString;
7+
8+
public CommandObjectsWithPrefixedKeys(String prefixString) {
9+
this.prefixString = prefixString;
10+
}
11+
12+
@Override
13+
protected CommandArguments commandArguments(ProtocolCommand command) {
14+
return new CommandArgumentsWithPrefixedKeys(command, prefixString);
15+
}
16+
}

src/main/java/redis/clients/jedis/JedisCluster.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
99

10+
import redis.clients.jedis.executors.ClusterCommandExecutor;
1011
import redis.clients.jedis.providers.ClusterConnectionProvider;
1112
import redis.clients.jedis.util.JedisClusterCRC16;
1213

@@ -222,6 +223,10 @@ private JedisCluster(ClusterConnectionProvider provider, int maxAttempts, Durati
222223
super(provider, maxAttempts, maxTotalRetriesDuration, protocol);
223224
}
224225

226+
public JedisCluster(ClusterCommandExecutor executor, ClusterConnectionProvider provider, ClusterCommandObjects commandObjects, RedisProtocol protocol) {
227+
super(executor, provider, commandObjects, protocol);
228+
}
229+
225230
public Map<String, ConnectionPool> getClusterNodes() {
226231
return ((ClusterConnectionProvider) provider).getNodes();
227232
}

src/main/java/redis/clients/jedis/JedisClusterWithPrefixedKeys.java

Lines changed: 0 additions & 61 deletions
This file was deleted.

src/main/java/redis/clients/jedis/JedisPooled.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.apache.commons.pool2.PooledObjectFactory;
99
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
1010

11+
import redis.clients.jedis.executors.CommandExecutor;
1112
import redis.clients.jedis.providers.PooledConnectionProvider;
1213
import redis.clients.jedis.util.JedisURIHelper;
1314
import redis.clients.jedis.util.Pool;
@@ -394,6 +395,11 @@ public JedisPooled(PooledConnectionProvider provider) {
394395
super(provider);
395396
}
396397

398+
public JedisPooled(CommandExecutor executor, PooledConnectionProvider provider, CommandObjects commandObjects,
399+
RedisProtocol redisProtocol) {
400+
super(executor, provider, commandObjects, redisProtocol);
401+
}
402+
397403
public final Pool<Connection> getPool() {
398404
return ((PooledConnectionProvider) provider).getPool();
399405
}

src/main/java/redis/clients/jedis/JedisSentineled.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.Set;
44
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
5+
import redis.clients.jedis.executors.CommandExecutor;
56
import redis.clients.jedis.providers.SentineledConnectionProvider;
67

78
public class JedisSentineled extends UnifiedJedis {
@@ -23,6 +24,10 @@ public JedisSentineled(SentineledConnectionProvider sentineledConnectionProvider
2324
super(sentineledConnectionProvider);
2425
}
2526

27+
public JedisSentineled(CommandExecutor executor, SentineledConnectionProvider sentineledConnectionProvider, CommandObjects commandObjects, RedisProtocol redisProtocol) {
28+
super(executor, sentineledConnectionProvider, commandObjects, redisProtocol);
29+
}
30+
2631
public HostAndPort getCurrentMaster() {
2732
return ((SentineledConnectionProvider) provider).getCurrentMaster();
2833
}

src/main/java/redis/clients/jedis/Pipeline.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ public Pipeline(Connection connection) {
2828
}
2929

3030
public Pipeline(Connection connection, boolean closeConnection) {
31-
super(new CommandObjects());
31+
this(connection, new CommandObjects(), closeConnection);
32+
}
33+
34+
public Pipeline(Connection connection, CommandObjects commandObjects, boolean closeConnection) {
35+
super(commandObjects);
3236
this.connection = connection;
3337
this.closeConnection = closeConnection;
3438
RedisProtocol proto = this.connection.getRedisProtocol();

src/main/java/redis/clients/jedis/UnifiedJedis.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4859,7 +4859,7 @@ public PipelineBase pipelined() {
48594859
} else if (provider instanceof MultiClusterPooledConnectionProvider) {
48604860
return new MultiClusterPipeline((MultiClusterPooledConnectionProvider) provider, commandObjects);
48614861
} else {
4862-
return new Pipeline(provider.getConnection(), true);
4862+
return new Pipeline(provider.getConnection(), commandObjects, true);
48634863
}
48644864
}
48654865

0 commit comments

Comments
 (0)