com.heisenberg.test.other.JobServiceTest.java Source code

Java tutorial

Introduction

Here is the source code for com.heisenberg.test.other.JobServiceTest.java

Source

/*
 * Copyright 2014 Heisenberg Enterprises Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.heisenberg.test.other;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

import org.joda.time.LocalDateTime;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonTypeName;
import com.heisenberg.api.activitytypes.UserTask;
import com.heisenberg.api.builder.WorkflowBuilder;
import com.heisenberg.impl.ExecutorService;
import com.heisenberg.impl.WorkflowEngineImpl;
import com.heisenberg.impl.Time;
import com.heisenberg.impl.job.AbstractJobType;
import com.heisenberg.impl.job.JobController;
import com.heisenberg.impl.job.JobExecution;
import com.heisenberg.impl.job.JobService;
import com.heisenberg.impl.job.JobServiceImpl;
import com.heisenberg.impl.memory.MemoryWorkflowEngine;

/**
 * @author Walter White
 */
public class JobServiceTest {

    public static final Logger log = LoggerFactory.getLogger(JobServiceTest.class);

    protected WorkflowEngineImpl processEngine;
    protected JobService jobService;

    public JobServiceTest() {
        initialize();
    }

    public void initialize() {
        initializeProcessEngine();
        this.jobService = processEngine.getServiceRegistry().getService(JobService.class);
        JobServiceImpl jobServiceImpl = (JobServiceImpl) jobService;
        // let's skip starting any threads
        jobServiceImpl.isRunning = true;
        // and execute the jobs in the test thread..
        jobServiceImpl.executor = new ExecutorService() {
            public void startup() {
            }

            public void shutdown() {
            }

            public int getQueueDepth() {
                return 0;
            }

            public void execute(Runnable command) {
                command.run();
            }
        };
    }

    public void initializeProcessEngine() {
        this.processEngine = new MemoryWorkflowEngine();
    }

    @JsonTypeName("tst")
    public static class TestJob extends AbstractJobType {
        static List<JobExecution> jobExecutions;
        static boolean throwException;

        @Override
        public void execute(JobController jobController) {
            jobExecutions.add((JobExecution) jobController);
            if (throwException) {
                jobController.log("oops");
                throw new RuntimeException("oops");
            } else {
                jobController.log(":ok_hand:");
            }
        }
    }

    @Before
    public void before() {
        TestJob.jobExecutions = new ArrayList<>();
        TestJob.throwException = false;
        Time.now = null;
    }

    @Test
    public void testProcessJobOK() throws Exception {
        // quickest way to get a processInstanceId
        WorkflowBuilder w = processEngine.newWorkflow();
        w.newActivity("t", new UserTask());
        String workflowId = w.deploy();
        String processInstanceId = processEngine.newStart().workflowId(workflowId).startWorkflowInstance().getId();

        jobService.newJob(new TestJob()).duedate(Time.now()).processInstanceId(processInstanceId).save();

        assertEquals(0, TestJob.jobExecutions.size());
        checkOtherJobs();
        assertEquals(0, TestJob.jobExecutions.size());
        checkProcessJobs(); // only this one should execute the job
        assertEquals(1, TestJob.jobExecutions.size());
        checkOtherJobs();
        assertEquals(1, TestJob.jobExecutions.size());
        checkProcessJobs();
        assertEquals(1, TestJob.jobExecutions.size());

        JobExecution jobExecution = TestJob.jobExecutions.get(0);
        assertNull(jobExecution.error);
    }

    @Test
    public void testRealProcessJobOK() throws Exception {
        // quickest way to get a processInstanceId
        WorkflowBuilder w = processEngine.newWorkflow();
        w.newActivity("t", new UserTask()).newTimer(new TestJob());
        String workflowId = w.deploy();
        String workflowInstanceId = processEngine.newStart().workflowId(workflowId).startWorkflowInstance().getId();

        jobService.newJob(new TestJob()).duedate(Time.now()).processInstanceId(workflowInstanceId).save();

        assertEquals(0, TestJob.jobExecutions.size());
        checkOtherJobs();
        assertEquals(0, TestJob.jobExecutions.size());
        checkProcessJobs(); // only this one should execute the job
        assertEquals(1, TestJob.jobExecutions.size());
        checkOtherJobs();
        assertEquals(1, TestJob.jobExecutions.size());
        checkProcessJobs();
        assertEquals(1, TestJob.jobExecutions.size());

        JobExecution jobExecution = TestJob.jobExecutions.get(0);
        assertNull(jobExecution.error);
    }

    @Test
    public void testOtherJobOK() throws Exception {
        jobService.newJob(new TestJob()).duedate(Time.now()).save();

        checkProcessJobs();
        assertEquals(0, TestJob.jobExecutions.size());
        checkOtherJobs(); // only this one should execute the job
        assertEquals(1, TestJob.jobExecutions.size());
        checkOtherJobs();
        assertEquals(1, TestJob.jobExecutions.size());
        checkProcessJobs();
        assertEquals(1, TestJob.jobExecutions.size());

        JobExecution jobExecution = TestJob.jobExecutions.get(0);
        assertNull(jobExecution.error);
    }

    @Test
    public void testOtherJobFailAndRecover() throws Exception {
        jobService.newJob(new TestJob()).duedate(Time.now()).save();

        TestJob.throwException = true;

        assertEquals(0, TestJob.jobExecutions.size());
        checkOtherJobs();
        assertEquals(1, TestJob.jobExecutions.size());

        assertTrue(TestJob.jobExecutions.get(0).error);
        assertNull(TestJob.jobExecutions.get(0).job.done);

        // the default retry reschedule is 3 seconds
        Time.now = new LocalDateTime().plusMinutes(10);
        TestJob.throwException = false;

        checkOtherJobs();
        assertEquals(2, TestJob.jobExecutions.size());

        assertNull(TestJob.jobExecutions.get(1).error);
        assertNotNull(TestJob.jobExecutions.get(1).job.done);
    }

    @Test
    public void testOtherJobFailTillDead() throws Exception {
        jobService.newJob(new TestJob()).duedate(Time.now()).save();

        TestJob.throwException = true;

        checkOtherJobs();
        assertEquals(1, TestJob.jobExecutions.size());
        JobExecution jobExecution = TestJob.jobExecutions.get(0);
        assertTrue(jobExecution.error);
        assertNull(jobExecution.job.done);
        assertNull(jobExecution.job.dead);

        // the first retry rescheduled in 3 seconds
        Time.now = new LocalDateTime().plusSeconds(4);

        checkOtherJobs();
        assertEquals(2, TestJob.jobExecutions.size());
        jobExecution = TestJob.jobExecutions.get(1);
        assertTrue(jobExecution.error);
        assertNull(jobExecution.job.done);
        assertNull(jobExecution.job.dead);

        // the second retry rescheduled in an hour seconds
        Time.now = new LocalDateTime().plusHours(2);

        checkOtherJobs();
        assertEquals(3, TestJob.jobExecutions.size());
        jobExecution = TestJob.jobExecutions.get(2);
        assertTrue(jobExecution.error);
        assertNull(jobExecution.job.done);
        assertNull(jobExecution.job.dead);

        // the second retry rescheduled in an hour seconds
        Time.now = new LocalDateTime().plusDays(2);

        checkOtherJobs();
        assertEquals(4, TestJob.jobExecutions.size());
        jobExecution = TestJob.jobExecutions.get(3);
        assertTrue(jobExecution.error);

        // But now the job should be dead 
        assertNotNull(jobExecution.job.done);
        assertTrue(jobExecution.job.dead);
    }

    @Test
    public void testUniqueJob() throws Exception {
        jobService.newJob(new TestJob()).key("uniqueid").save();

        jobService.newJob(new TestJob()).key("uniqueid").save();

        checkOtherJobs();
        assertEquals(1, TestJob.jobExecutions.size());
    }

    public void checkProcessJobs() {
        ((JobServiceImpl) jobService).checkProcessJobs();
    }

    public void checkOtherJobs() {
        ((JobServiceImpl) jobService).checkOtherJobs();
    }
}