package com.lambdaworks.redis.cluster.pubsub;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.lambdaworks.redis.api.sync.RedisCommands;
import com.lambdaworks.redis.cluster.AbstractClusterTest;
import com.lambdaworks.redis.cluster.api.StatefulRedisClusterConnection;
import com.lambdaworks.redis.cluster.models.partitions.RedisClusterNode;
import com.lambdaworks.redis.internal.LettuceFactories;
import com.lambdaworks.redis.pubsub.RedisPubSubListener;
import com.lambdaworks.redis.pubsub.StatefulRedisPubSubConnection;
/**
* @author Mark Paluch
*/
public class PubSubClusterTest extends AbstractClusterTest implements RedisPubSubListener<String, String> {
private BlockingQueue<String> channels;
private BlockingQueue<String> patterns;
private BlockingQueue<String> messages;
private BlockingQueue<Long> counts;
private StatefulRedisClusterConnection<String, String> connection;
private StatefulRedisPubSubConnection<String, String> pubSubConnection;
private StatefulRedisPubSubConnection<String, String> pubSubConnection2;
@Before
public void openPubSubConnection() throws Exception {
connection = clusterClient.connect();
pubSubConnection = clusterClient.connectPubSub();
pubSubConnection2 = clusterClient.connectPubSub();
channels = LettuceFactories.newBlockingQueue();
patterns = LettuceFactories.newBlockingQueue();
messages = LettuceFactories.newBlockingQueue();
counts = LettuceFactories.newBlockingQueue();
}
@After
public void closePubSubConnection() throws Exception {
connection.close();
pubSubConnection.close();
pubSubConnection2.close();
}
@Test
public void testRegularClientPubSubChannels() throws Exception {
String nodeId = pubSubConnection.sync().clusterMyId();
RedisClusterNode otherNode = getOtherThan(nodeId);
pubSubConnection.sync().subscribe(key);
List<String> channelsOnSubscribedNode = connection.getConnection(nodeId).sync().pubsubChannels();
assertThat(channelsOnSubscribedNode).hasSize(1);
List<String> channelsOnOtherNode = connection.getConnection(otherNode.getNodeId()).sync().pubsubChannels();
assertThat(channelsOnOtherNode).isEmpty();
}
@Test
public void testRegularClientPublish() throws Exception {
String nodeId = pubSubConnection.sync().clusterMyId();
RedisClusterNode otherNode = getOtherThan(nodeId);
pubSubConnection.sync().subscribe(key);
pubSubConnection.addListener(this);
connection.getConnection(nodeId).sync().publish(key, value);
assertThat(messages.take()).isEqualTo(value);
connection.getConnection(otherNode.getNodeId()).sync().publish(key, value);
assertThat(messages.take()).isEqualTo(value);
}
@Test
public void testPubSubClientPublish() throws Exception {
String nodeId = pubSubConnection.sync().clusterMyId();
pubSubConnection.sync().subscribe(key);
pubSubConnection.addListener(this);
assertThat(pubSubConnection2.sync().clusterMyId()).isEqualTo(nodeId);
pubSubConnection2.sync().publish(key, value);
assertThat(messages.take()).isEqualTo(value);
}
@Test
public void testConnectToLeastClientsNode() throws Exception {
clusterClient.reloadPartitions();
String nodeId = pubSubConnection.sync().clusterMyId();
StatefulRedisPubSubConnection<String, String> connectionAfterPartitionReload = clusterClient.connectPubSub();
String newConnectionNodeId = connectionAfterPartitionReload.sync().clusterMyId();
connectionAfterPartitionReload.close();
assertThat(nodeId).isNotEqualTo(newConnectionNodeId);
}
@Test
public void testRegularClientPubSubPublish() throws Exception {
String nodeId = pubSubConnection.sync().clusterMyId();
RedisClusterNode otherNode = getOtherThan(nodeId);
pubSubConnection.sync().subscribe(key);
pubSubConnection.addListener(this);
List<String> channelsOnSubscribedNode = connection.getConnection(nodeId).sync().pubsubChannels();
assertThat(channelsOnSubscribedNode).hasSize(1);
RedisCommands<String, String> otherNodeConnection = connection.getConnection(otherNode.getNodeId()).sync();
otherNodeConnection.publish(key, value);
assertThat(channels.take()).isEqualTo(key);
}
private RedisClusterNode getOtherThan(String nodeId) {
for (RedisClusterNode redisClusterNode : clusterClient.getPartitions()) {
if (redisClusterNode.getNodeId().equals(nodeId)) {
continue;
}
return redisClusterNode;
}
throw new IllegalStateException("No other nodes than " + nodeId + " available");
}
// RedisPubSubListener implementation
@Override
public void message(String channel, String message) {
channels.add(channel);
messages.add(message);
}
@Override
public void message(String pattern, String channel, String message) {
patterns.add(pattern);
channels.add(channel);
messages.add(message);
}
@Override
public void subscribed(String channel, long count) {
channels.add(channel);
counts.add(count);
}
@Override
public void psubscribed(String pattern, long count) {
patterns.add(pattern);
counts.add(count);
}
@Override
public void unsubscribed(String channel, long count) {
channels.add(channel);
counts.add(count);
}
@Override
public void punsubscribed(String pattern, long count) {
patterns.add(pattern);
counts.add(count);
}
}