package org.redisson;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.redisson.api.RExecutorService;
import org.redisson.api.RFuture;
import org.redisson.api.RMap;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import org.redisson.api.annotation.RInject;
import org.redisson.api.mapreduce.RCollator;
import org.redisson.api.mapreduce.RCollector;
import org.redisson.api.mapreduce.RMapReduce;
import org.redisson.api.mapreduce.RMapper;
import org.redisson.api.mapreduce.RReducer;
import org.redisson.mapreduce.MapReduceTimeoutException;
@RunWith(Parameterized.class)
public class RedissonMapReduceTest extends BaseTest {
public static class WordMapper implements RMapper<String, String, String, Integer> {
@Override
public void map(String key, String value, RCollector<String, Integer> collector) {
String[] words = value.split("[^a-zA-Z]");
for (String word : words) {
collector.emit(word, 1);
}
}
}
public static class WordReducer implements RReducer<String, Integer> {
@Override
public Integer reduce(String reducedKey, Iterator<Integer> iter) {
int sum = 0;
while (iter.hasNext()) {
Integer i = (Integer) iter.next();
sum += i;
}
return sum;
}
}
public static class WordCollator implements RCollator<String, Integer, Integer> {
@Override
public Integer collate(Map<String, Integer> resultMap) {
int result = 0;
for (Integer count : resultMap.values()) {
result += count;
}
return result;
}
}
@Parameterized.Parameters(name = "{index} - {0}")
public static Iterable<Object[]> mapClasses() {
return Arrays.asList(new Object[][]{
{RMap.class}, {RMapCache.class}
});
}
@Parameterized.Parameter(0)
public Class<?> mapClass;
@Before
public void beforeTest() {
redisson.getExecutorService(RExecutorService.MAPREDUCE_NAME).registerWorkers(3);
}
@Test
public void testCancel() throws InterruptedException, ExecutionException {
RMap<String, String> map = getMap();
for (int i = 0; i < 100000; i++) {
map.put("" + i, "ab cd fjks");
}
RMapReduce<String, String, String, Integer> mapReduce = map.<String, Integer>mapReduce().mapper(new WordMapper()).reducer(new WordReducer());
RFuture<Map<String, Integer>> future = mapReduce.executeAsync();
Thread.sleep(100);
future.cancel(true);
}
@Test(expected = MapReduceTimeoutException.class)
public void testTimeout() {
RMap<String, String> map = getMap();
for (int i = 0; i < 100000; i++) {
map.put("" + i, "ab cd fjks");
}
RMapReduce<String, String, String, Integer> mapReduce = map.<String, Integer>mapReduce()
.mapper(new WordMapper())
.reducer(new WordReducer())
.timeout(1, TimeUnit.SECONDS);
mapReduce.execute();
}
@Test
public void test() {
RMap<String, String> map = getMap();
map.put("1", "Alice was beginning to get very tired");
map.put("2", "of sitting by her sister on the bank and");
map.put("3", "of having nothing to do once or twice she");
map.put("4", "had peeped into the book her sister was reading");
map.put("5", "but it had no pictures or conversations in it");
map.put("6", "and what is the use of a book");
map.put("7", "thought Alice without pictures or conversation");
Map<String, Integer> result = new HashMap<>();
result.put("to", 2);
result.put("Alice", 2);
result.put("get", 1);
result.put("beginning", 1);
result.put("sitting", 1);
result.put("do", 1);
result.put("by", 1);
result.put("or", 3);
result.put("into", 1);
result.put("sister", 2);
result.put("on", 1);
result.put("a", 1);
result.put("without", 1);
result.put("and", 2);
result.put("once", 1);
result.put("twice", 1);
result.put("she", 1);
result.put("had", 2);
result.put("reading", 1);
result.put("but", 1);
result.put("it", 2);
result.put("no", 1);
result.put("in", 1);
result.put("what", 1);
result.put("use", 1);
result.put("thought", 1);
result.put("conversation", 1);
result.put("was", 2);
result.put("very", 1);
result.put("tired", 1);
result.put("of", 3);
result.put("her", 2);
result.put("the", 3);
result.put("bank", 1);
result.put("having", 1);
result.put("nothing", 1);
result.put("peeped", 1);
result.put("book", 2);
result.put("pictures", 2);
result.put("conversations", 1);
result.put("is", 1);
RMapReduce<String, String, String, Integer> mapReduce = map.<String, Integer>mapReduce().mapper(new WordMapper()).reducer(new WordReducer());
assertThat(mapReduce.execute()).isEqualTo(result);
Integer count = mapReduce.execute(new WordCollator());
assertThat(count).isEqualTo(57);
mapReduce.execute("resultMap");
RMap<Object, Object> resultMap = redisson.getMap("resultMap");
assertThat(resultMap).isEqualTo(result);
resultMap.delete();
}
private RMap<String, String> getMap() {
RMap<String, String> map = null;
if (RMapCache.class.isAssignableFrom(mapClass)) {
map = redisson.getMapCache("map");
} else {
map = redisson.getMap("map");
}
return map;
}
public static class WordMapperInject implements RMapper<String, String, String, Integer> {
@RInject
private RedissonClient redisson;
@Override
public void map(String key, String value, RCollector<String, Integer> collector) {
redisson.getAtomicLong("test").incrementAndGet();
String[] words = value.split("[^a-zA-Z]");
for (String word : words) {
collector.emit(word, 1);
}
}
}
public static class WordReducerInject implements RReducer<String, Integer> {
@RInject
private RedissonClient redisson;
@Override
public Integer reduce(String reducedKey, Iterator<Integer> iter) {
redisson.getAtomicLong("test").incrementAndGet();
int sum = 0;
while (iter.hasNext()) {
Integer i = (Integer) iter.next();
sum += i;
}
return sum;
}
}
public static class WordCollatorInject implements RCollator<String, Integer, Integer> {
@RInject
private RedissonClient redisson;
@Override
public Integer collate(Map<String, Integer> resultMap) {
redisson.getAtomicLong("test").incrementAndGet();
int result = 0;
for (Integer count : resultMap.values()) {
result += count;
}
return result;
}
}
@Test
public void testInjector() {
RMap<String, String> map = getMap();
map.put("1", "Alice was beginning to get very tired");
RMapReduce<String, String, String, Integer> mapReduce = map.<String, Integer>mapReduce().mapper(new WordMapperInject()).reducer(new WordReducerInject());
mapReduce.execute();
assertThat(redisson.getAtomicLong("test").get()).isEqualTo(8);
mapReduce.execute(new WordCollatorInject());
assertThat(redisson.getAtomicLong("test").get()).isEqualTo(16 + 1);
}
}