Package org.candlepin.pinsetter.core

Source Code of org.candlepin.pinsetter.core.PinsetterJobListener

/**
* Copyright (c) 2009 - 2012 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package org.candlepin.pinsetter.core;

import org.candlepin.auth.Principal;
import org.candlepin.model.JobCurator;
import org.candlepin.pinsetter.core.model.JobStatus;
import org.candlepin.pinsetter.core.model.JobStatus.JobState;
import org.candlepin.pinsetter.tasks.UniqueByOwnerJob;

import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import com.google.inject.persist.UnitOfWork;

import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.JobListener;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* This component receives events around job status and performs actions to
* allow for the job in question to run outside of a request scope, as well as
* record the status of the job for later retrieval.
*/
public class PinsetterJobListener implements JobListener {
    private static Logger log = LoggerFactory.getLogger(PinsetterJobListener.class);

    public static final String LISTENER_NAME = "Pinsetter Job Listener";
    public static final String PRINCIPAL_KEY = "principal_key";

    private JobCurator curator;

    // this is a separate unitOfWork and units of work from the actual pinsetter
    // job because we want to tie this closer to the quartz execution, rather than
    // job execution.
    private UnitOfWork unitOfWork;

    @Inject
    public PinsetterJobListener(JobCurator curator, UnitOfWork unitOfWork) {
        this.curator = curator;
        this.unitOfWork = unitOfWork;
    }

    @Override
    public String getName() {
        return LISTENER_NAME;
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        Principal principal = (Principal) context.getMergedJobDataMap().get(PRINCIPAL_KEY);
        ResteasyProviderFactory.pushContext(Principal.class, principal);

        try {
            unitOfWork.begin();
            updateJob(context);
        }
        catch (Exception e) {
            log.error("jobToBeExecuted encountered a problem. Usually means " +
                "there was a problem storing the job status. Job will run.", e);
        }
        finally {
            unitOfWork.end();
        }
    }

    @Override
    public void jobExecutionVetoed(JobExecutionContext context) {
        // Do nothing sentence
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context,
        JobExecutionException exception) {
        deleteDetail(context);
        try {
            unitOfWork.begin();
            updateJob(context, exception);
        }
        catch (Exception e) {
            if (UniqueByOwnerJob.class.isAssignableFrom(
                    context.getJobDetail().getJobClass())) {
                log.error("jobWasExecuted encountered a problem on a blocking job." +
                    " This can block other jobs.  Marking finished, if possible", e);
                try {
                    //This time only update the state so it doesn't block other jobs
                    curator.cancelNoReturn(context.getJobDetail().getKey().getName());
                }
                catch (Exception ex) {
                    log.error("Failed again to cancel status: " +
                        context.getJobDetail().getKey().getName(), ex);
                }
            }
            else {
                log.error("jobWasExecuted encountered a problem. Usually means " +
                    "there was a problem storing the job status. Job finished ok.", e);
            }
        }
        finally {
            unitOfWork.end();
            ResteasyProviderFactory.popContextData(Principal.class);
        }
    }

    private void updateJob(JobExecutionContext ctx) {
        updateJob(ctx, null);
    }

    @Transactional
    private void updateJob(JobExecutionContext ctx, JobExecutionException exc) {
        JobStatus status = curator.find(ctx.getJobDetail().getKey().getName());
        if (status != null) {
            if (exc != null) {
                log.error("Job [" + status.getId() + "] failed." , exc);
                status.setState(JobState.FAILED);
                status.setResult(exc.getMessage());
            }
            else {
                status.update(ctx);
            }
            curator.merge(status);
        }
        else {
            log.debug("No jobinfo found for job: " + ctx);
        }
    }

    private void deleteDetail(JobExecutionContext cx) {
        JobKey key = cx.getJobDetail().getKey();
        if (key.getGroup().equals(PinsetterKernel.SINGLE_JOB_GROUP)) {
            try {
                cx.getScheduler().deleteJob(key);
            }
            catch (SchedulerException e1) {
                // Should fail if the job isn't durable
            }
        }
    }
}
TOP

Related Classes of org.candlepin.pinsetter.core.PinsetterJobListener

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.