package org.swisspush.redisques;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Vertx;
import io.vertx.core.eventbus.MessageConsumer;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.unit.Async;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.junit.Timeout;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.swisspush.redisques.util.RedisquesConfiguration;
import redis.clients.jedis.Jedis;
import static org.swisspush.redisques.util.RedisquesAPI.*;
/**
* Created by florian.kammermann on 31.05.2016.
*/
public class RedisQuesProcessorRedeployTest extends AbstractTestCase {
@Rule
public Timeout rule = Timeout.seconds(20);
private static final String CUSTOM_REDIS_KEY_PREFIX = "mycustomredisprefix:";
@Override
protected String getRedisPrefix() {
return CUSTOM_REDIS_KEY_PREFIX;
}
@BeforeClass
public static void deployRedisques(TestContext context) {
deployRedisques(context, 2);
}
protected static void deployRedisques(TestContext context, int refreshPeriod) {
vertx = Vertx.vertx();
JsonObject config = RedisquesConfiguration.with()
.redisPrefix(CUSTOM_REDIS_KEY_PREFIX)
.processorAddress("processor-address")
.redisEncoding("ISO-8859-1")
.refreshPeriod(refreshPeriod)
.build()
.asJsonObject();
RedisQues redisQues = new RedisQues();
vertx.deployVerticle(redisQues, new DeploymentOptions().setConfig(config), context.asyncAssertSuccess(event -> {
deploymentId = event;
log.info("vert.x Deploy - " + redisQues.getClass().getSimpleName() + " was successful.");
jedis = new Jedis("localhost", 6379, 5000);
}));
}
/**
* This test checks if existing queues are processed after a restart of the redisque verticle.
* The important point is, that we wait long enough, that the consumer key expires.
* So there will be no consumer registered in redis and because of the clean state of redisques,
* there is no consumer registered in the redisques verticle too.
* We have to rely onto the check function of RediesQues.
*/
@Test
public void notActiveQueueActivatedThroughCheckAfterRedeploy(TestContext context) throws Exception {
Async async = context.async();
flushAll();
final MessageConsumer<JsonObject> queueProcessor = vertx.eventBus().consumer("processor-address");
// we don't reply here, this leads redisques in the consuming state
queueProcessor.handler(message -> {
// assert the values we sent too
context.assertEquals("check-queue", message.body().getString("queue"));
context.assertEquals("hello", message.body().getString("payload"));
// tell redisques, that the processing was not successfull
message.reply(new JsonObject().put(STATUS, ERROR));
// assert that there is a consumer assigned
String consumer = jedis.get(getConsumersRedisKeyPrefix() + "check-queue");
context.assertNotNull(consumer);
// assert that value is still in the queue
String queueValueInRedis = jedis.lindex(getQueuesRedisKeyPrefix() + "check-queue", 0);
context.assertEquals("hello", queueValueInRedis);
// undeploy redisques to simulate a server restart
vertx.undeploy(deploymentId, res -> {
if (! res.succeeded()) {
throw new IllegalStateException("couldn't redeploy redisques", res.cause());
}
// we have to wait long enough, that the redisques consumer key expires
sleep(3000);
deployRedisques(context, 1);
sleep(3000);
// reregister the processor
final MessageConsumer<JsonObject> queueProcessorAfterRedeploy = vertx.eventBus().consumer("processor-address");
queueProcessorAfterRedeploy.handler(messageAfterRedeploy -> {
message.reply(new JsonObject().put(STATUS, OK));
// end the test
async.complete();
});
// assert that the consumer is null
String consumerAfterRedeploy = jedis.get(getConsumersRedisKeyPrefix() + "check-queue");
context.assertNull(consumerAfterRedeploy);
// execute check operation, which registers a new consumer to the existing queue and process the queue
final JsonObject operation = buildCheckOperation();
eventBusSend(operation, reply -> {
context.assertEquals(OK, reply.result().body().getString(STATUS));
});
});
});
final JsonObject operation = buildEnqueueOperation("check-queue", "hello");
eventBusSend(operation, reply -> {
context.assertEquals(OK, reply.result().body().getString(STATUS));
});
}
private void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new IllegalStateException("can not handle interrups on sleeps");
}
}
}