package net.joelinn.quartz;
import net.jodah.concurrentunit.Waiter;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.NameMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import java.util.Properties;
import static junit.framework.TestCase.fail;
import static net.joelinn.quartz.TestUtils.createCronTrigger;
import static net.joelinn.quartz.TestUtils.createJob;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
/**
* @author Joe Linn
* 12/10/2016
*/
public class MultiSchedulerIntegrationTest extends BaseIntegrationTest {
private static final Logger log = LoggerFactory.getLogger(MultiSchedulerIntegrationTest.class);
private static final String KEY_ID = "id";
private Scheduler scheduler2;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
Properties props = schedulerConfig(HOST, port);
props.setProperty(StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME, "second");
scheduler2 = new StdSchedulerFactory(props).getScheduler();
}
@After
@Override
public void tearDown() throws Exception {
scheduler2.shutdown();
super.tearDown();
}
@Override
protected Properties schedulerConfig(String host, int port) {
Properties config = super.schedulerConfig(host, port);
config.setProperty("org.quartz.threadPool.threadCount", "2");
config.setProperty("org.quartz.scheduler.instanceId", "AUTO");
config.setProperty("org.quartz.scheduler.instanceIdGenerator.class", "org.quartz.simpl.SimpleInstanceIdGenerator");
return config;
}
@Test
public void testMultipleSchedulers() throws Exception {
scheduler.setJobFactory(new RedisJobFactory());
scheduler2.setJobFactory(new RedisJobFactory());
assertThat(scheduler.getSchedulerInstanceId(), notNullValue());
assertThat(scheduler2.getSchedulerInstanceId(), notNullValue());
assertThat(scheduler.getSchedulerInstanceId(), not(equalTo(scheduler2.getSchedulerInstanceId())));
JobDetail job = createJob(SchedulerIDCheckingJob.class, "testJob", "group");
final String triggerName = "trigger";
CronTrigger trigger = createCronTrigger(triggerName, "group", "* * * * * ?");
Waiter waiter = new Waiter();
scheduler.getListenerManager().addTriggerListener(new CompleteListener(waiter), NameMatcher.triggerNameEquals(triggerName));
scheduler.scheduleJob(job, trigger);
waiter.await(1500);
try (Jedis jedis = jedisPool.getResource()) {
assertThat(jedis.get(KEY_ID), equalTo(scheduler.getSchedulerInstanceId()));
}
scheduler.shutdown();
scheduler2.getListenerManager().addTriggerListener(new CompleteListener(waiter), NameMatcher.triggerNameEquals(triggerName));
scheduler2.start();
waiter.await(1500);
try (Jedis jedis = jedisPool.getResource()) {
assertThat(jedis.get(KEY_ID), equalTo(scheduler2.getSchedulerInstanceId()));
}
}
@DisallowConcurrentExecution
public static class SchedulerIDCheckingJob extends DataJob {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
final String schedulerID = context.getScheduler().getSchedulerInstanceId();
try (Jedis jedis = jedisPool.getResource()) {
if (jedis.setnx(KEY_ID, schedulerID) == 0) {
// we already have an ID stored
final String storedID = jedis.get(KEY_ID);
if (storedID.equals(schedulerID)) {
fail("The same schedule executed the job twice.");
} else {
jedis.set(KEY_ID, schedulerID);
}
}
}
} catch (SchedulerException e) {
log.error("Unable to obtain scheduler instance ID.", e);
fail("Failed to obtain scheduler instance ID.");
}
}
}
}