Skip to content

Commit b58c18f

Browse files
mp911dechristophstrobl
authored andcommitted
DATAREDIS-462 - Support lettuce ClientResources.
Add ClientResources to LettuceConnectionFactory. Add TestClientResources for managed resources during tests and reuse ClientResources as much as possible in tests. Original Pull Request: #169
1 parent 0fa1319 commit b58c18f

26 files changed

+391
-40
lines changed

src/main/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePool.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2015 the original author or authors.
2+
* Copyright 2013-2016 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.
@@ -17,6 +17,7 @@
1717

1818
import java.util.concurrent.TimeUnit;
1919

20+
import com.lambdaworks.redis.resource.ClientResources;
2021
import org.apache.commons.pool2.BasePooledObjectFactory;
2122
import org.apache.commons.pool2.PooledObject;
2223
import org.apache.commons.pool2.impl.DefaultPooledObject;
@@ -50,6 +51,7 @@ public class DefaultLettucePool implements LettucePool, InitializingBean {
5051
private String password;
5152
private long timeout = TimeUnit.MILLISECONDS.convert(60, TimeUnit.SECONDS);
5253
private RedisSentinelConfiguration sentinelConfiguration;
54+
private ClientResources clientResources;
5355

5456
/**
5557
* Constructs a new <code>DefaultLettucePool</code> instance with default settings.
@@ -101,7 +103,14 @@ public boolean isRedisSentinelAware() {
101103

102104
@SuppressWarnings({ "rawtypes" })
103105
public void afterPropertiesSet() {
104-
this.client = new RedisClient(getRedisURI());
106+
107+
if(clientResources != null) {
108+
this.client = RedisClient.create(clientResources, getRedisURI());
109+
}
110+
else {
111+
this.client = RedisClient.create(getRedisURI());
112+
}
113+
105114
client.setDefaultTimeout(timeout, TimeUnit.MILLISECONDS);
106115
this.internalPool = new GenericObjectPool<RedisAsyncConnection>(new LettuceFactory(client, dbIndex), poolConfig);
107116
}
@@ -273,6 +282,24 @@ public void setTimeout(long timeout) {
273282
this.timeout = timeout;
274283
}
275284

285+
/**
286+
* Returns the client resources to reuse the client infrastructure.
287+
* @return client resources
288+
* @since 1.7
289+
*/
290+
public ClientResources getClientResources() {
291+
return clientResources;
292+
}
293+
294+
/**
295+
* Sets the client resources to reuse the client infrastructure.
296+
* @param clientResources
297+
* @since 1.7
298+
*/
299+
public void setClientResources(ClientResources clientResources) {
300+
this.clientResources = clientResources;
301+
}
302+
276303
@SuppressWarnings("rawtypes")
277304
private static class LettuceFactory extends BasePooledObjectFactory<RedisAsyncConnection> {
278305

src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnectionFactory.java

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.List;
2121
import java.util.concurrent.TimeUnit;
2222

23+
import com.lambdaworks.redis.resource.ClientResources;
2324
import org.apache.commons.logging.Log;
2425
import org.apache.commons.logging.LogFactory;
2526
import org.springframework.beans.factory.DisposableBean;
@@ -95,6 +96,7 @@ public class LettuceConnectionFactory implements InitializingBean, DisposableBea
9596
private RedisSentinelConfiguration sentinelConfiguration;
9697
private RedisClusterConfiguration clusterConfiguration;
9798
private ClusterCommandExecutor clusterCommandExecutor;
99+
private ClientResources clientResources;
98100

99101
/**
100102
* Constructs a new <code>LettuceConnectionFactory</code> instance with default settings.
@@ -388,6 +390,24 @@ public void setPassword(String password) {
388390
this.password = password;
389391
}
390392

393+
/**
394+
* Returns the client resources to reuse the client infrastructure.
395+
* @return client resources
396+
* @since 1.7
397+
*/
398+
public ClientResources getClientResources() {
399+
return clientResources;
400+
}
401+
402+
/**
403+
* Sets the client resources to reuse the client infrastructure.
404+
* @param clientResources
405+
* @since 1.7
406+
*/
407+
public void setClientResources(ClientResources clientResources) {
408+
this.clientResources = clientResources;
409+
}
410+
391411
/**
392412
* Returns the shutdown timeout for shutting down the RedisClient (in milliseconds).
393413
*
@@ -469,7 +489,11 @@ private AbstractRedisClient createRedisClient() {
469489

470490
if (isRedisSentinelAware()) {
471491
RedisURI redisURI = getSentinelRedisURI();
472-
return new RedisClient(redisURI);
492+
if(clientResources == null) {
493+
return RedisClient.create(redisURI);
494+
}
495+
496+
return RedisClient.create(clientResources, redisURI);
473497
}
474498

475499
if (isClusterAware()) {
@@ -486,7 +510,13 @@ private AbstractRedisClient createRedisClient() {
486510
initialUris.add(redisURI);
487511
}
488512

489-
RedisClusterClient clusterClient = new RedisClusterClient(initialUris);
513+
RedisClusterClient clusterClient;
514+
if(clientResources == null) {
515+
clusterClient = RedisClusterClient.create(initialUris);
516+
}
517+
else {
518+
clusterClient = RedisClusterClient.create(clientResources, initialUris);
519+
}
490520

491521
this.clusterCommandExecutor = new ClusterCommandExecutor(
492522
new LettuceClusterConnection.LettuceClusterTopologyProvider(clusterClient),
@@ -504,8 +534,11 @@ private AbstractRedisClient createRedisClient() {
504534
builder.withPassword(password);
505535
}
506536
builder.withTimeout(timeout, TimeUnit.MILLISECONDS);
507-
RedisClient client = new RedisClient(builder.build());
508-
return client;
537+
if(clientResources != null) {
538+
return RedisClient.create(clientResources, builder.build());
539+
}
540+
541+
return RedisClient.create(builder.build());
509542
}
510543

511544
private RedisURI getSentinelRedisURI() {

src/main/java/org/springframework/data/redis/connection/lettuce/LettuceSentinelConnection.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014 the original author or authors.
2+
* Copyright 2014-2016 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.
@@ -20,6 +20,8 @@
2020

2121
import com.lambdaworks.redis.RedisClient;
2222
import com.lambdaworks.redis.RedisSentinelAsyncConnection;
23+
import com.lambdaworks.redis.RedisURI;
24+
import com.lambdaworks.redis.resource.ClientResources;
2325
import org.springframework.data.redis.ExceptionTranslationStrategy;
2426
import org.springframework.data.redis.FallbackExceptionTranslationStrategy;
2527
import org.springframework.data.redis.connection.NamedNode;
@@ -51,12 +53,26 @@ public LettuceSentinelConnection(RedisNode sentinel) {
5153

5254
/**
5355
* Creates a {@link LettuceSentinelConnection} with a client for the supplied {@code host} and {@code port}.
54-
* @param host hostname
56+
* @param host hostname must not be {@literal null}
5557
* @param port sentinel port
5658
*/
5759
public LettuceSentinelConnection(String host, int port) {
58-
Assert.notNull(host, "Cannot created LettuceSentinelConnection using 'null' as host.");
59-
redisClient = new RedisClient(host, port);
60+
Assert.notNull(host, "Cannot create LettuceSentinelConnection using 'null' as host.");
61+
redisClient = RedisClient.create(new RedisURI.Builder().redis(host, port).build());
62+
init();
63+
}
64+
65+
/**
66+
* Creates a {@link LettuceSentinelConnection} with a client for the supplied {@code host} and {@code port} and reuse
67+
* existing {@code clientResources}.
68+
* @param clientResources must not be {@literal null}
69+
* @param host hostname must not be {@literal null}
70+
* @param port sentinel port
71+
*/
72+
public LettuceSentinelConnection(ClientResources clientResources, String host, int port) {
73+
Assert.notNull(clientResources, "Cannot create LettuceSentinelConnection using 'null' as ClientResources.");
74+
Assert.notNull(host, "Cannot create LettuceSentinelConnection using 'null' as host.");
75+
redisClient = RedisClient.create(clientResources, new RedisURI.Builder().redis(host, port).build());
6076
init();
6177
}
6278

src/test/java/org/springframework/data/redis/connection/lettuce/DefaultLettucePoolTests.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2014 the original author or authors.
2+
* Copyright 2013-2016 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.
@@ -57,6 +57,7 @@ public void tearDown() {
5757
@Test
5858
public void testGetResource() {
5959
this.pool = new DefaultLettucePool(SettingsUtils.getHost(), SettingsUtils.getPort());
60+
this.pool.setClientResources(TestClientResources.get());
6061
pool.afterPropertiesSet();
6162
RedisAsyncConnection<byte[], byte[]> client = pool.getResource();
6263
assertNotNull(client);
@@ -70,6 +71,7 @@ public void testGetResourcePoolExhausted() {
7071
poolConfig.setMaxTotal(1);
7172
poolConfig.setMaxWaitMillis(1);
7273
this.pool = new DefaultLettucePool(SettingsUtils.getHost(), SettingsUtils.getPort(), poolConfig);
74+
this.pool.setClientResources(TestClientResources.get());
7375
pool.afterPropertiesSet();
7476
RedisAsyncConnection<byte[], byte[]> client = pool.getResource();
7577
assertNotNull(client);
@@ -86,6 +88,7 @@ public void testGetResourceValidate() {
8688
PoolConfig poolConfig = new PoolConfig();
8789
poolConfig.setTestOnBorrow(true);
8890
this.pool = new DefaultLettucePool(SettingsUtils.getHost(), SettingsUtils.getPort(), poolConfig);
91+
this.pool.setClientResources(TestClientResources.get());
8992
pool.afterPropertiesSet();
9093
RedisAsyncConnection<byte[], byte[]> client = pool.getResource();
9194
assertNotNull(client);
@@ -95,6 +98,7 @@ public void testGetResourceValidate() {
9598
@Test(expected = PoolException.class)
9699
public void testGetResourceCreationUnsuccessful() throws Exception {
97100
this.pool = new DefaultLettucePool(SettingsUtils.getHost(), 3333);
101+
this.pool.setClientResources(TestClientResources.get());
98102
pool.afterPropertiesSet();
99103
pool.getResource();
100104
}
@@ -105,6 +109,7 @@ public void testReturnResource() {
105109
poolConfig.setMaxTotal(1);
106110
poolConfig.setMaxWaitMillis(1);
107111
this.pool = new DefaultLettucePool(SettingsUtils.getHost(), SettingsUtils.getPort(), poolConfig);
112+
this.pool.setClientResources(TestClientResources.get());
108113
pool.afterPropertiesSet();
109114
RedisAsyncConnection<byte[], byte[]> client = pool.getResource();
110115
assertNotNull(client);
@@ -119,6 +124,7 @@ public void testReturnBrokenResource() {
119124
poolConfig.setMaxTotal(1);
120125
poolConfig.setMaxWaitMillis(1);
121126
this.pool = new DefaultLettucePool(SettingsUtils.getHost(), SettingsUtils.getPort(), poolConfig);
127+
this.pool.setClientResources(TestClientResources.get());
122128
pool.afterPropertiesSet();
123129
RedisAsyncConnection<byte[], byte[]> client = pool.getResource();
124130
assertNotNull(client);
@@ -136,6 +142,18 @@ public void testReturnBrokenResource() {
136142

137143
@Test
138144
public void testCreateWithDbIndex() {
145+
this.pool = new DefaultLettucePool(SettingsUtils.getHost(), SettingsUtils.getPort());
146+
this.pool.setClientResources(TestClientResources.get());
147+
pool.setDatabase(1);
148+
pool.afterPropertiesSet();
149+
assertNotNull(pool.getResource());
150+
}
151+
152+
/**
153+
* @see DATAREDIS-462
154+
*/
155+
@Test
156+
public void poolWorksWithoutClientResources() {
139157
this.pool = new DefaultLettucePool(SettingsUtils.getHost(), SettingsUtils.getPort());
140158
pool.setDatabase(1);
141159
pool.afterPropertiesSet();
@@ -145,6 +163,7 @@ public void testCreateWithDbIndex() {
145163
@Test(expected = PoolException.class)
146164
public void testCreateWithDbIndexInvalid() {
147165
this.pool = new DefaultLettucePool(SettingsUtils.getHost(), SettingsUtils.getPort());
166+
this.pool.setClientResources(TestClientResources.get());
148167
pool.setDatabase(17);
149168
pool.afterPropertiesSet();
150169
pool.getResource();
@@ -153,6 +172,7 @@ public void testCreateWithDbIndexInvalid() {
153172
@Test(expected = PoolException.class)
154173
public void testCreateWithPasswordNoPassword() {
155174
this.pool = new DefaultLettucePool(SettingsUtils.getHost(), SettingsUtils.getPort());
175+
this.pool.setClientResources(TestClientResources.get());
156176
pool.setPassword("notthepassword");
157177
pool.afterPropertiesSet();
158178
pool.getResource();
@@ -162,6 +182,7 @@ public void testCreateWithPasswordNoPassword() {
162182
@Test
163183
public void testCreatePassword() {
164184
this.pool = new DefaultLettucePool(SettingsUtils.getHost(), SettingsUtils.getPort());
185+
this.pool.setClientResources(TestClientResources.get());
165186
pool.setPassword("foo");
166187
pool.afterPropertiesSet();
167188
RedisAsyncConnection<byte[], byte[]> conn = pool.getResource();
@@ -173,6 +194,7 @@ public void testCreatePassword() {
173194
@Test(expected = PoolException.class)
174195
public void testCreateInvalidPassword() {
175196
this.pool = new DefaultLettucePool(SettingsUtils.getHost(), SettingsUtils.getPort());
197+
this.pool.setClientResources(TestClientResources.get());
176198
pool.setPassword("bad");
177199
pool.afterPropertiesSet();
178200
pool.getResource();

src/test/java/org/springframework/data/redis/connection/lettuce/LettuceClusterConnectionTests.java

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ public class LettuceClusterConnectionTests implements ClusterConnectionTests {
8585
@Before
8686
public void setUp() {
8787

88-
client = new RedisClusterClient(Builder.redis(CLUSTER_HOST, MASTER_NODE_1_PORT)
89-
.withTimeout(500, TimeUnit.MILLISECONDS).build());
88+
client = RedisClusterClient.create(TestClientResources.get(),
89+
Builder.redis(CLUSTER_HOST, MASTER_NODE_1_PORT).withTimeout(100, TimeUnit.MILLISECONDS).build());
9090
nativeConnection = client.connectCluster();
9191
clusterConnection = new LettuceClusterConnection(client);
9292
}
@@ -2079,29 +2079,23 @@ public void zRangeByLexShouldReturnResultCorrectly() {
20792079

20802080
assertThat(values,
20812081
hasItems(LettuceConverters.toBytes("a"), LettuceConverters.toBytes("b"), LettuceConverters.toBytes("c")));
2082-
assertThat(
2083-
values,
2084-
not(hasItems(LettuceConverters.toBytes("d"), LettuceConverters.toBytes("e"), LettuceConverters.toBytes("f"),
2085-
LettuceConverters.toBytes("g"))));
2082+
assertThat(values, not(hasItems(LettuceConverters.toBytes("d"), LettuceConverters.toBytes("e"),
2083+
LettuceConverters.toBytes("f"), LettuceConverters.toBytes("g"))));
20862084

20872085
values = clusterConnection.zRangeByLex(KEY_1_BYTES, Range.range().lt("c"));
20882086
assertThat(values, hasItems(LettuceConverters.toBytes("a"), LettuceConverters.toBytes("b")));
20892087
assertThat(values, not(hasItem(LettuceConverters.toBytes("c"))));
20902088

20912089
values = clusterConnection.zRangeByLex(KEY_1_BYTES, Range.range().gte("aaa").lt("g"));
2092-
assertThat(
2093-
values,
2094-
hasItems(LettuceConverters.toBytes("b"), LettuceConverters.toBytes("c"), LettuceConverters.toBytes("d"),
2095-
LettuceConverters.toBytes("e"), LettuceConverters.toBytes("f")));
2090+
assertThat(values, hasItems(LettuceConverters.toBytes("b"), LettuceConverters.toBytes("c"),
2091+
LettuceConverters.toBytes("d"), LettuceConverters.toBytes("e"), LettuceConverters.toBytes("f")));
20962092
assertThat(values, not(hasItems(LettuceConverters.toBytes("a"), LettuceConverters.toBytes("g"))));
20972093

20982094
values = clusterConnection.zRangeByLex(KEY_1_BYTES, Range.range().gte("e"));
20992095
assertThat(values,
21002096
hasItems(LettuceConverters.toBytes("e"), LettuceConverters.toBytes("f"), LettuceConverters.toBytes("g")));
2101-
assertThat(
2102-
values,
2103-
not(hasItems(LettuceConverters.toBytes("a"), LettuceConverters.toBytes("b"), LettuceConverters.toBytes("c"),
2104-
LettuceConverters.toBytes("d"))));
2097+
assertThat(values, not(hasItems(LettuceConverters.toBytes("a"), LettuceConverters.toBytes("b"),
2098+
LettuceConverters.toBytes("c"), LettuceConverters.toBytes("d"))));
21052099
}
21062100

21072101
/**
@@ -2279,8 +2273,8 @@ public void getConfigShouldLoadConfigurationOfSpecificNode() {
22792273
@Test
22802274
public void clusterGetSlavesShouldReturnSlaveCorrectly() {
22812275

2282-
Set<RedisClusterNode> slaves = clusterConnection.clusterGetSlaves(new RedisClusterNode(CLUSTER_HOST,
2283-
MASTER_NODE_1_PORT));
2276+
Set<RedisClusterNode> slaves = clusterConnection
2277+
.clusterGetSlaves(new RedisClusterNode(CLUSTER_HOST, MASTER_NODE_1_PORT));
22842278

22852279
assertThat(slaves.size(), is(1));
22862280
assertThat(slaves, hasItem(new RedisClusterNode(CLUSTER_HOST, SLAVEOF_NODE_1_PORT)));

0 commit comments

Comments
 (0)