package oncue.tests.timedjobs; import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import oncue.common.messages.Job; import oncue.common.messages.RetryTimedJobMessage; import oncue.common.messages.WorkResponse; import oncue.tests.base.ActorSystemTest; import oncue.tests.workers.TestWorker; import oncue.timedjobs.TimedJobFactory; import org.junit.Test; import akka.actor.ActorRef; import akka.actor.Kill; import akka.camel.CamelMessage; import akka.testkit.JavaTestKit; public class TimedJobTest extends ActorSystemTest { public static final String CAMEL_WAIT_TIME = "30 seconds"; @Test public void timedJobSendsJobMessage() { new JavaTestKit(system) { { // Create an agent probe final JavaTestKit agentProbe = new JavaTestKit(system) { { new IgnoreMsg() { protected boolean ignore(Object message) { if (message instanceof WorkResponse) { return false; } return true; } }; } }; // Create a timed job probe final JavaTestKit timedJobProbe = new JavaTestKit(system) { { new IgnoreMsg() { protected boolean ignore(Object message) { return !(message instanceof CamelMessage); } }; } }; // Create a scheduler createScheduler(system, null); // Create an agent with a probe createAgent(system, new HashSet<String>(Arrays.asList(TestWorker.class.getName())), agentProbe.getRef()); // Expect a work response with no jobs WorkResponse response = agentProbe.expectMsgClass(duration("2 seconds"), WorkResponse.class); List<Job> jobs = response.getJobs(); assertEquals(0, jobs.size()); TimedJobFactory.createTimedJob(system, TestWorker.class.getName(), "test-1", "quartz://test-timer-1", null, timedJobProbe.getRef()); TimedJobFactory.createTimedJob(system, TestWorker.class.getName(), "test-2", "quartz://test-timer-2", null, timedJobProbe.getRef()); // Wait for Camel to start up timedJobProbe.expectMsgClass(duration(CAMEL_WAIT_TIME), CamelMessage.class); // Expect two workers to send work responses response = agentProbe.expectMsgClass(duration("4 seconds"), WorkResponse.class); assertEquals(TestWorker.class.getName(), response.getJobs().get(0).getWorkerType()); response = agentProbe.expectMsgClass(duration("4 seconds"), WorkResponse.class); assertEquals(TestWorker.class.getName(), response.getJobs().get(0).getWorkerType()); } }; } @Test public void timedJobSendsJobMessageWithParameters() { new JavaTestKit(system) { { // Create an agent probe final JavaTestKit agentProbe = new JavaTestKit(system) { { new IgnoreMsg() { protected boolean ignore(Object message) { if (message instanceof WorkResponse) { return false; } return true; } }; } }; // Create a timed job probe final JavaTestKit timedJobProbe = new JavaTestKit(system) { { new IgnoreMsg() { protected boolean ignore(Object message) { return !(message instanceof CamelMessage); } }; } }; // Create a scheduler createScheduler(system, null); // Create an agent with a probe createAgent(system, new HashSet<String>(Arrays.asList(TestWorker.class.getName())), agentProbe.getRef()); // Expect a work response with no jobs WorkResponse response = agentProbe.expectMsgClass(duration("2 seconds"), WorkResponse.class); List<Job> jobs = response.getJobs(); assertEquals(0, jobs.size()); Map<String, String> parameters = new HashMap<String, String>(); parameters.put("key", "value"); TimedJobFactory.createTimedJob(system, TestWorker.class.getName(), "test-1", "quartz://test-timer-1", parameters, timedJobProbe.getRef()); // Wait for Camel to start up timedJobProbe.expectMsgClass(duration(CAMEL_WAIT_TIME), CamelMessage.class); // Expect two workers to send work responses response = agentProbe.expectMsgClass(duration("2 seconds"), WorkResponse.class); Job job = response.getJobs().get(0); assertEquals(TestWorker.class.getName(), job.getWorkerType()); assertEquals(parameters, job.getParams()); } }; } @Test public void timedJobRetriesWhenSchedulerCannotBeReached() { new JavaTestKit(system) { { // Create an agent probe final JavaTestKit agentProbe = new JavaTestKit(system) { { new IgnoreMsg() { protected boolean ignore(Object message) { if (message instanceof WorkResponse) { return false; } return true; } }; } }; // Create a timed job probe final JavaTestKit timedJobProbe = new JavaTestKit(system) { { new IgnoreMsg() { protected boolean ignore(Object message) { return !(message instanceof RetryTimedJobMessage || message instanceof CamelMessage); } }; } }; // Create a scheduler createScheduler(system, null); // Create an agent with a probe createAgent(system, new HashSet<String>(Arrays.asList(TestWorker.class.getName())), agentProbe.getRef()); // Initial work response when agent starts WorkResponse response = agentProbe.expectMsgClass(duration("2 seconds"), WorkResponse.class); List<Job> jobs = response.getJobs(); assertEquals(0, jobs.size()); // Kill the scheduler ActorRef schedulerRef = system.actorFor(settings.SCHEDULER_PATH); schedulerRef.tell(Kill.getInstance(), this.getRef()); // Create timed job TimedJobFactory.createTimedJob(system, TestWorker.class.getName(), "test-1", "quartz://test-timer-1", null, timedJobProbe.getRef()); // Wait for Camel to start up timedJobProbe.expectMsgClass(duration(CAMEL_WAIT_TIME), CamelMessage.class); agentProbe.expectNoMsg(duration("2 seconds")); // Bring back the scheduler createScheduler(system, null); // Expect work response from agent as it can talk again response = agentProbe.expectMsgClass(duration("5 seconds"), WorkResponse.class); Job job = response.getJobs().get(0); assertEquals(TestWorker.class.getName(), job.getWorkerType()); assertEquals(Collections.emptyMap(), job.getParams()); } }; } @Test public void timedJobRetriesSpecifiedNumberOfTimes() { new JavaTestKit(system) { { // Create an agent probe final JavaTestKit agentProbe = new JavaTestKit(system) { { new IgnoreMsg() { protected boolean ignore(Object message) { return !(message instanceof RetryTimedJobMessage || message instanceof CamelMessage); } }; } }; Map<String, String> params = new HashMap<String, String>(); params.put("key", "value"); // Create timed job int retryCount = 3; TimedJobFactory.createTimedJob(system, TestWorker.class.getName(), "test-1", "quartz://test-timer-1", params, retryCount, agentProbe.getRef()); // Wait for Camel to start up agentProbe.expectMsgClass(duration(CAMEL_WAIT_TIME), CamelMessage.class); RetryTimedJobMessage timedJobMessage = agentProbe.expectMsgClass(duration("2 seconds"), RetryTimedJobMessage.class); validateRetryTimedJobMessageParams(params, TestWorker.class.getName(), timedJobMessage); timedJobMessage = agentProbe.expectMsgClass(duration("2 seconds"), RetryTimedJobMessage.class); validateRetryTimedJobMessageParams(params, TestWorker.class.getName(), timedJobMessage); timedJobMessage = agentProbe.expectMsgClass(duration("2 seconds"), RetryTimedJobMessage.class); validateRetryTimedJobMessageParams(params, TestWorker.class.getName(), timedJobMessage); agentProbe.expectNoMsg(); } }; } private static void validateRetryTimedJobMessageParams(Map<String, String> params, String workerType, RetryTimedJobMessage timedJobMessage) { assertEquals(workerType, timedJobMessage.getWorkerType()); assertEquals(params, timedJobMessage.getJobParameters()); } @Test public void timedJobGetsRestartedWhenKilled() { new JavaTestKit(system) { { // Create a timed job probe final JavaTestKit timedJobProbe = new JavaTestKit(system) { { new IgnoreMsg() { protected boolean ignore(Object message) { return !(message instanceof RetryTimedJobMessage || message instanceof CamelMessage); } }; } }; // Create timed job that uses the agent probe Map<String, String> params = new HashMap<String, String>(); params.put("key", "value"); String workerType = "oncue.workers.TestWorker"; String actorPath = "quartz://test-timer-1"; TimedJobFactory.createTimedJob(system, workerType, "test-1", actorPath, params, null, timedJobProbe.getRef()); // Wait for Camel to start up timedJobProbe.expectMsgClass(duration(CAMEL_WAIT_TIME), CamelMessage.class); // Observe the timed job trying to schedule the job itself RetryTimedJobMessage timedJobMessage = timedJobProbe.expectMsgClass(duration("2 seconds"), RetryTimedJobMessage.class); validateRetryTimedJobMessageParams(params, workerType, timedJobMessage); // Kill the actor ActorRef timedJob = system.actorFor(actorPath); timedJob.tell(Kill.getInstance(), this.getRef()); // Observe the timed job has restarted and is trying to schedule // the job itself timedJobMessage = timedJobProbe.expectMsgClass(duration("2 seconds"), RetryTimedJobMessage.class); validateRetryTimedJobMessageParams(params, workerType, timedJobMessage); timedJobMessage = timedJobProbe.expectMsgClass(duration("2 seconds"), RetryTimedJobMessage.class); validateRetryTimedJobMessageParams(params, workerType, timedJobMessage); expectNoMsg(duration("10 seconds")); } }; } }