Package org.jboss.soa.esb.services.jbpm.integration.msg

Source Code of org.jboss.soa.esb.services.jbpm.integration.msg.RetryExecutor

/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.soa.esb.services.jbpm.integration.msg;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.log4j.Logger;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.db.JobSession;
import org.jbpm.job.Job;
import org.jbpm.job.Timer;


/**
* Executor responsible for checking for retry invocations.  The DB service does
* this implicitly but we need to explicitly check for this during JMS.
*
* @author <a href='mailto:kevin.conner@jboss.com'>Kevin Conner</a>
*/
public class RetryExecutor implements Runnable
{
    /**
     * The lock name associated with the executor.
     */
    public static final String RETRY_EXECUTOR = "RetryExecutor" ;
    /**
     * The logger for this class.
     */
    private static final Logger LOGGER = Logger.getLogger(RetryExecutor.class) ;
   
    /**
     * terminate the executor thread.
     */
    private boolean terminateRetryExecutorThread ;
   
    /**
     * The wait lock.
     */
    private Lock waitLock = new ReentrantLock() ;
    /**
     * The wait condition.
     */
    private Condition waitCondition = waitLock.newCondition() ;
   
    /**
     * The normal idle interval.
     */
    private final int idleInterval ;
    /**
     * The maximum idle interval.
     */
    private int maxIdleInterval ;
    /**
     * The maximum number of jobs to reschedule on each poll.
     */
    private int maxRetryJobs ;
   
    /**
     * Create the retry executor thread.
     * @param idleInterval The idle interval.
     * @param maxIdleInterval The max idle interval.
     * @param maxRetryJobs The max number of retry jobs.
     */
    public RetryExecutor(final int idleInterval, final int maxIdleInterval, final int maxRetryJobs)
    {
        this.idleInterval = idleInterval ;
        this.maxIdleInterval = maxIdleInterval ;
        this.maxRetryJobs = maxRetryJobs ;
    }
   /**
     * Look for newly active suspended/retry jobs.
     */
    public void run()
    {
        int currentIdleInterval = idleInterval ;
        while(true)
        {
            final JbpmContext jbpmContext = JbpmConfiguration.getInstance().createJbpmContext() ;
            try
            {
                final JobSession jobSession = jbpmContext.getJobSession() ;
                if (jobSession != null)
                {
                    final Set<Long> monitoredJobs = new HashSet<Long>() ;
                    final long now = System.currentTimeMillis() ;
                    do
                    {
                        final Job job = jobSession.getFirstDueJob(RETRY_EXECUTOR, monitoredJobs) ;
                        if ((job == null) || (job.getDueDate().getTime() > now))
                        {
                            break ;
                        }
                        monitoredJobs.add(Long.valueOf(job.getId())) ;
                        if (RETRY_EXECUTOR.equals(job.getLockOwner()))
                        {
                            job.setLockOwner(null) ;
                            if (job instanceof Timer)
                            {
                                final Timer timer = (Timer)job ;
                                if (LOGGER.isDebugEnabled()) {
                                    LOGGER.debug("Rescheduling timer " + timer.getId());
                                }
                                jbpmContext.getServices().getSchedulerService().createTimer(timer);
                            }
                            else
                            {
                                if (LOGGER.isDebugEnabled()) {
                                    LOGGER.debug("Rescheduling job " + job.getId());
                                }
                                jbpmContext.getServices().getMessageService().send(job) ;
                            }
                        }
                    }
                    while(monitoredJobs.size() < maxRetryJobs) ;
                }
                if (currentIdleInterval > idleInterval)
                {
                    currentIdleInterval >>= 1;
                    if (currentIdleInterval < idleInterval)
                    {
                        currentIdleInterval = idleInterval ;
                    }
                }
            }
            catch (final Throwable th)
            {
                LOGGER.debug("Unexpected error rescheduling jobs, extending idle period", th);
                // after an exception, the current idle interval is doubled to prevent
                // continuous exception generation when e.g. the db is unreachable
                currentIdleInterval <<= 1;
                if (currentIdleInterval > maxIdleInterval || currentIdleInterval < 0)
                {
                    currentIdleInterval = maxIdleInterval;
                }
            }
            finally
            {
                jbpmContext.close() ;
            }
            waitLock.lock() ;
            try
            {
                if (!terminateRetryExecutorThread)
                {
                    try
                    {
                        waitCondition.await(currentIdleInterval, TimeUnit.MILLISECONDS) ;
                    }
                    catch (final InterruptedException ie) {} // ignore
                }
                if (terminateRetryExecutorThread)
                {
                    break ;
                }
            }
            finally
            {
                waitLock.unlock() ;
            }
        }
    }
   
    /**
     * Request a termination of the loop.
     */
    public void terminate()
    {
        waitLock.lock() ;
        try
        {
            terminateRetryExecutorThread = true ;
            waitCondition.signal() ;
        }
        finally
        {
            waitLock.unlock() ;
        }
    }
   
    /**
     * Process a suspended job.
     * @param job The suspended job.
     */
    public static void handleSuspendedJob(final Job job)
    {
        job.setLockOwner(RETRY_EXECUTOR) ;
        JbpmConfiguration.getInstance().getCurrentJbpmContext().getServices().getMessageService().send(job) ;
    }
   
    /**
     * Process a suspended timer.
     * @param timer The suspended timer.
     */
    public static void handleSuspendedTimer(final Timer timer)
    {
        timer.setLockOwner(RETRY_EXECUTOR) ;
        JbpmConfiguration.getInstance().getCurrentJbpmContext().getServices().getSchedulerService().createTimer(timer) ;
    }
}
TOP

Related Classes of org.jboss.soa.esb.services.jbpm.integration.msg.RetryExecutor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.