#3 - Added samples for Spring Data Redis.
We added basic samples showing KEYS and SCAN command as well as configuration options for Redis Sentinel. Original pull request: #9.
This commit is contained in:
committed by
Oliver Gierke
parent
7cfd45920f
commit
91565e3e21
@@ -25,6 +25,11 @@ We have separate folders for the samples of individual modules:
|
||||
* `starbucks` - A sample REST web-service built with Spring Data REST and MongoDB.
|
||||
* `multi-store` - A sample REST web-service based on both Spring Data JPA and Spring Data MongoDB.
|
||||
|
||||
## Spring Data Redis
|
||||
|
||||
* `example` - Example for basic Sprign Data Redis setup.
|
||||
* `cluster-sentinel` - Example for Redis cluster and Sentinel support.
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
* `multi-store` - Example project to use both Spring Data MongoDB and Spring Data JPA in one project.
|
||||
1
pom.xml
1
pom.xml
@@ -20,6 +20,7 @@
|
||||
<module>jpa</module>
|
||||
<module>mongodb</module>
|
||||
<module>rest</module>
|
||||
<module>redis</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
||||
28
redis/cluster-sentinel/README.md
Normal file
28
redis/cluster-sentinel/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Spring Data Redis - Sentinel and Cluster Examples
|
||||
|
||||
This project contains samples of Sentinel and CLuster specific features of Spring Data Redis.
|
||||
|
||||
## Support for Sentinel
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
public class RedisSentinelApplicationConfig {
|
||||
|
||||
static final RedisSentinelConfiguration SENTINEL_CONFIG = new RedisSentinelConfiguration().master("mymaster") //
|
||||
.sentinel("localhost", 26379) //
|
||||
.sentinel("localhost", 26380) //
|
||||
.sentinel("localhost", 26381);
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory connectionFactory() {
|
||||
return new JedisConnectionFactory(sentinelConfig());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisSentinelConfiguration sentinelConfig() {
|
||||
return SENTINEL_CONFIG;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
29
redis/cluster-sentinel/pom.xml
Normal file
29
redis/cluster-sentinel/pom.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-data-redis-cluster-sentinel-example</artifactId>
|
||||
<name>Spring Data Redis - Cluster/Sentinel Example</name>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.examples</groupId>
|
||||
<artifactId>spring-data-redis-examples</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-data-redis-example-utils</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2014 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 example.springdata.redis.sentinel;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.util.StopWatch;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisSentinelApplicationConfig {
|
||||
|
||||
static final RedisSentinelConfiguration SENTINEL_CONFIG = new RedisSentinelConfiguration().master("mymaster") //
|
||||
.sentinel("localhost", 26379) //
|
||||
.sentinel("localhost", 26380) //
|
||||
.sentinel("localhost", 26381);
|
||||
|
||||
@Autowired RedisConnectionFactory factory;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
ApplicationContext context = SpringApplication.run(RedisSentinelApplicationConfig.class, args);
|
||||
|
||||
RedisConnectionFactory factory = context.getBean(RedisConnectionFactory.class);
|
||||
|
||||
StringRedisTemplate template = new StringRedisTemplate();
|
||||
template.setConnectionFactory(factory);
|
||||
template.afterPropertiesSet();
|
||||
|
||||
template.opsForValue().set("loop-forever", "0");
|
||||
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
|
||||
while (true) {
|
||||
|
||||
try {
|
||||
String value = "IT:= " + template.opsForValue().increment("loop-forever", 1);
|
||||
printBackFromErrorStateInfoIfStopWatchIsRunning(stopWatch);
|
||||
System.out.println(value);
|
||||
} catch (RuntimeException e) {
|
||||
System.err.println(e.getCause().getMessage());
|
||||
startStopWatchIfNotRunning(stopWatch);
|
||||
}
|
||||
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisConnectionFactory connectionFactory() {
|
||||
return new JedisConnectionFactory(sentinelConfig());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisSentinelConfiguration sentinelConfig() {
|
||||
return SENTINEL_CONFIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear database before shut down.
|
||||
*/
|
||||
@PreDestroy
|
||||
public void flushTestDb() {
|
||||
factory.getConnection().flushDb();
|
||||
}
|
||||
|
||||
private static void startStopWatchIfNotRunning(StopWatch stopWatch) {
|
||||
|
||||
if (!stopWatch.isRunning()) {
|
||||
stopWatch.start();
|
||||
}
|
||||
}
|
||||
|
||||
private static void printBackFromErrorStateInfoIfStopWatchIsRunning(StopWatch stopWatch) {
|
||||
|
||||
if (stopWatch.isRunning()) {
|
||||
stopWatch.stop();
|
||||
System.err.println("INFO: Recovered after: " + stopWatch.getLastTaskInfo().getTimeSeconds());
|
||||
}
|
||||
}
|
||||
}
|
||||
14
redis/cluster-sentinel/src/test/resources/logback.xml
Normal file
14
redis/cluster-sentinel/src/test/resources/logback.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
4
redis/example/README.md
Normal file
4
redis/example/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Spring Data Redis - Examples
|
||||
|
||||
This project contains samples of specific features of Spring Data Redis.
|
||||
|
||||
31
redis/example/pom.xml
Normal file
31
redis/example/pom.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-data-redis-example</artifactId>
|
||||
<name>Spring Data Redis - Example</name>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.examples</groupId>
|
||||
<artifactId>spring-data-redis-examples</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-data-redis-example-utils</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2014 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 example.springdata.redis;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
public class RedisTestConfiguration {
|
||||
|
||||
@Autowired RedisConnectionFactory factory;
|
||||
|
||||
/**
|
||||
* Clear database before shut down.
|
||||
*/
|
||||
@PreDestroy
|
||||
public void flushTestDb() {
|
||||
factory.getConnection().flushDb();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2014 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 example.springdata.redis.commands;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import example.springdata.redis.RedisTestConfiguration;
|
||||
import example.springdata.redis.test.util.RequiresRedisServer;
|
||||
|
||||
/**
|
||||
* Show usage of operations on redis keys using low level API provided by {@link RedisConnection}.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = { RedisTestConfiguration.class })
|
||||
public class KeyOperationsTests {
|
||||
|
||||
// we only want to run this tests when redis is up an running
|
||||
public static @ClassRule RequiresRedisServer requiresServer = RequiresRedisServer.onLocalhost();
|
||||
|
||||
private static final String PREFIX = KeyOperationsTests.class.getSimpleName();
|
||||
private static final String KEY_PATTERN = PREFIX + "*";
|
||||
|
||||
@Autowired RedisConnectionFactory connectionFactory;
|
||||
|
||||
private RedisConnection connection;
|
||||
private RedisSerializer<String> serializer = new StringRedisSerializer();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.connection = connectionFactory.getConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses {@code KEYS} command for loading all matching keys. <br />
|
||||
* Note that {@code KEYS} is a blocking command that potentially might affect other operations execution time. <br />
|
||||
* All keys will be loaded within <strong>one single</strong> operation.
|
||||
*/
|
||||
@Test
|
||||
public void iterateOverKeysMatchingPrefixUsingKeysCommand() {
|
||||
|
||||
generateRandomKeys(1000);
|
||||
|
||||
Set<byte[]> keys = this.connection.keys(serializer.serialize(KEY_PATTERN));
|
||||
printKeys(keys.iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses {@code SCAN} command for loading all matching keys. <br />
|
||||
* {@code SCAN} uses a cursor on server side returning only a subset of the available data with the possibility to
|
||||
* ripple load further elements using the cursors position. <br />
|
||||
* All keys will be loaded using <strong>multiple</strong> operations.
|
||||
*/
|
||||
@Test
|
||||
public void iterateOverKeysMatchingPrefixUsingScanCommand() {
|
||||
|
||||
generateRandomKeys(1000);
|
||||
|
||||
Cursor<byte[]> cursor = this.connection.scan(ScanOptions.scanOptions().match(KEY_PATTERN).build());
|
||||
printKeys(cursor);
|
||||
}
|
||||
|
||||
private void printKeys(Iterator<byte[]> keys) {
|
||||
|
||||
int i = 0;
|
||||
while (keys.hasNext()) {
|
||||
System.out.println(new String(keys.next()));
|
||||
i++;
|
||||
}
|
||||
System.out.println(String.format("Total No. found: %s", i));
|
||||
}
|
||||
|
||||
private void generateRandomKeys(int nrKeys) {
|
||||
|
||||
for (int i = 0; i < nrKeys; i++) {
|
||||
this.connection.set((PREFIX + "-" + i).getBytes(), UUID.randomUUID().toString().getBytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
14
redis/example/src/test/resources/logback.xml
Normal file
14
redis/example/src/test/resources/logback.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d %5p %40.40c:%4L - %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="warn">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
38
redis/pom.xml
Normal file
38
redis/pom.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-data-redis-examples</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.examples</groupId>
|
||||
<artifactId>spring-data-examples</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>Spring Data Redis - Examples</name>
|
||||
<description>Sample projects for Spring Data Redis</description>
|
||||
|
||||
<modules>
|
||||
<module>util</module>
|
||||
<module>cluster-sentinel</module>
|
||||
<module>example</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>2.5.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
26
redis/util/pom.xml
Normal file
26
redis/util/pom.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-data-redis-example-utils</artifactId>
|
||||
<name>Spring Data Redis - Example utilities</name>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.data.examples</groupId>
|
||||
<artifactId>spring-data-redis-examples</artifactId>
|
||||
<version>1.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-redis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright 2014 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 example.springdata.redis.test.util;
|
||||
|
||||
import org.junit.internal.AssumptionViolatedException;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runners.model.Statement;
|
||||
import org.springframework.data.redis.connection.RedisNode;
|
||||
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
|
||||
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class RequiresRedisSentinel implements TestRule {
|
||||
|
||||
public enum SentinelsAvailable {
|
||||
ALL_ACTIVE, ONE_ACTIVE, NONE_ACTIVE
|
||||
}
|
||||
|
||||
private static final RedisSentinelConfiguration DEFAULT_SENTINEL_CONFIG = new RedisSentinelConfiguration()
|
||||
.master("mymaster").sentinel("127.0.0.1", 26379).sentinel("127.0.0.1", 26380).sentinel("127.0.0.1", 26381);
|
||||
|
||||
private RedisSentinelConfiguration sentinelConfig;
|
||||
private SentinelsAvailable requiredSentinels;
|
||||
|
||||
protected RequiresRedisSentinel(RedisSentinelConfiguration config) {
|
||||
this.sentinelConfig = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new {@link RedisSentinelRule} for given {@link RedisSentinelConfiguration}.
|
||||
*
|
||||
* @param config
|
||||
* @return
|
||||
*/
|
||||
public static RequiresRedisSentinel forConfig(RedisSentinelConfiguration config) {
|
||||
return new RequiresRedisSentinel(config != null ? config : DEFAULT_SENTINEL_CONFIG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new {@link RedisSentinelRule} using default configuration.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static RequiresRedisSentinel withDefaultConfig() {
|
||||
return new RequiresRedisSentinel(DEFAULT_SENTINEL_CONFIG);
|
||||
}
|
||||
|
||||
public RequiresRedisSentinel sentinelsDisabled() {
|
||||
|
||||
this.requiredSentinels = SentinelsAvailable.NONE_ACTIVE;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies all {@literal Sentinel} nodes are available.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public RequiresRedisSentinel allActive() {
|
||||
|
||||
this.requiredSentinels = SentinelsAvailable.ALL_ACTIVE;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies at least one {@literal Sentinel} node is available.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public RequiresRedisSentinel oneActive() {
|
||||
|
||||
this.requiredSentinels = SentinelsAvailable.ONE_ACTIVE;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will only check {@link RedisSentinelConfiguration} configuration in case {@link RequiresRedisSentinel} is detected
|
||||
* on test method.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public RequiresRedisSentinel dynamicModeSelection() {
|
||||
this.requiredSentinels = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.junit.rules.TestRule#apply(org.junit.runners.model.Statement, org.junit.runner.Description)
|
||||
*/
|
||||
@Override
|
||||
public Statement apply(final Statement base, final Description description) {
|
||||
|
||||
return new Statement() {
|
||||
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
|
||||
if (description.isTest()) {
|
||||
if (RequiresRedisSentinel.this.requiredSentinels != null) {
|
||||
verify(RequiresRedisSentinel.this.requiredSentinels);
|
||||
}
|
||||
|
||||
} else {
|
||||
verify(RequiresRedisSentinel.this.requiredSentinels);
|
||||
}
|
||||
|
||||
base.evaluate();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void verify(SentinelsAvailable verificationMode) {
|
||||
|
||||
int failed = 0;
|
||||
for (RedisNode node : sentinelConfig.getSentinels()) {
|
||||
if (!isAvailable(node)) {
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed > 0) {
|
||||
if (SentinelsAvailable.ALL_ACTIVE.equals(verificationMode)) {
|
||||
throw new AssumptionViolatedException(String.format(
|
||||
"Expected all Redis Sentinels to respone but %s of %s did not responde", failed, sentinelConfig
|
||||
.getSentinels().size()));
|
||||
}
|
||||
|
||||
if (SentinelsAvailable.ONE_ACTIVE.equals(verificationMode) && sentinelConfig.getSentinels().size() - 1 < failed) {
|
||||
throw new AssumptionViolatedException(
|
||||
"Expected at least one sentinel to respond but it seems all are offline - Game Over!");
|
||||
}
|
||||
}
|
||||
|
||||
if (SentinelsAvailable.NONE_ACTIVE.equals(verificationMode) && failed != sentinelConfig.getSentinels().size()) {
|
||||
throw new AssumptionViolatedException(String.format(
|
||||
"Expected to have no sentinels online but found that %s are still alive.", (sentinelConfig.getSentinels()
|
||||
.size() - failed)));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAvailable(RedisNode node) {
|
||||
|
||||
Jedis jedis = null;
|
||||
|
||||
try {
|
||||
jedis = new Jedis(node.getHost(), node.getPort());
|
||||
jedis.connect();
|
||||
jedis.ping();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
} finally {
|
||||
|
||||
if (jedis != null) {
|
||||
try {
|
||||
jedis.disconnect();
|
||||
jedis.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2014 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 example.springdata.redis.test.util;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.junit.internal.AssumptionViolatedException;
|
||||
import org.junit.rules.ExternalResource;
|
||||
|
||||
/**
|
||||
* Implementation of junit rule {@link ExternalResource} to verify Redis (or at least something on the defined host and
|
||||
* port) is up and running.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class RequiresRedisServer extends ExternalResource {
|
||||
|
||||
private int timeout = 30;
|
||||
|
||||
private final String host;
|
||||
private final int port;
|
||||
|
||||
private RequiresRedisServer(String host, int port) {
|
||||
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public static RequiresRedisServer onLocalhost() {
|
||||
return new RequiresRedisServer("localhost", 6379);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.junit.rules.ExternalResource#before()
|
||||
*/
|
||||
@Override
|
||||
protected void before() throws Throwable {
|
||||
|
||||
try (Socket socket = new Socket()) {
|
||||
socket.setTcpNoDelay(true);
|
||||
socket.setSoLinger(true, 0);
|
||||
socket.connect(new InetSocketAddress(host, port), timeout);
|
||||
} catch (Exception e) {
|
||||
throw new AssumptionViolatedException(String.format("Seems as redis is not running at %s:%s.", host, port), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user