All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openehealth.ipf.commons.flow.purge.FlowPurgeJob Maven / Gradle / Ivy

There is a newer version: 3.3-20170504
Show newest version
/*
 * Copyright 2009 the original author or authors.
 * 
 * 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 org.openehealth.ipf.commons.flow.purge;

import static org.openehealth.ipf.commons.flow.config.ApplicationConfig.DO_NOT_PURGE_ERROR_FLOWS_DEFAULT;
import static org.openehealth.ipf.commons.flow.config.ApplicationConfig.FLOW_PURGE_SCHEDULE_DEFAULT;
import static org.openehealth.ipf.commons.flow.config.ApplicationConfig.PURGE_FLOWS_OLDER_THAN_DEFAULT;
import static org.openehealth.ipf.commons.flow.repository.FlowPurgeCriteria.PurgeMode.ALL;
import static org.openehealth.ipf.commons.flow.repository.FlowPurgeCriteria.PurgeMode.CLEAN;

import java.util.Date;

import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.openehealth.ipf.commons.core.datetime.Duration;
import org.openehealth.ipf.commons.flow.FlowManager;
import org.openehealth.ipf.commons.flow.config.ApplicationConfig;
import org.openehealth.ipf.commons.flow.jmx.FlowPurgerMBean;
import org.openehealth.ipf.commons.flow.repository.FlowPurgeCriteria;
import org.openehealth.ipf.commons.flow.repository.FlowPurgeCriteria.PurgeMode;

import static org.quartz.TriggerBuilder.*;
import static org.quartz.JobBuilder.*;
import static org.quartz.CronScheduleBuilder.*;

/**
 * A flow purge job implementation used by both, Quartz scheduler and
 * {@link FlowPurgerMBean}. The interface to the Quartz scheduler is
 * {@link Job} whereas the {@link FlowPurgerMBean} uses this class directly for
 * managing jobs and and tracking their status.
 * 
 * @author Martin Krasser
 */
public class FlowPurgeJob implements Job {
    
    private static final String FLOW_MANAGER_KEY = "flowManager";
    private static final String APP_CONFIG_KEY = "appConfig";
    private static final Logger LOG = LoggerFactory.getLogger(FlowPurgeJob.class);
    
    private final FlowManager flowManager;
    private final Scheduler scheduler;
    private final String application;

    private String flowPurgeSchedule;
    private String purgeFlowsOlderThan;
    private boolean doNotPurgeErrorFlows;
    
    /**
     * Constructor used by Quartz.
     */
    public FlowPurgeJob() {
        this(null, null, null);
    }

    /**
     * Constructor used by {@link FlowPurgerMBean}.
     * 
     * @param flowManager
     *            flow manager.
     * @param scheduler
     *            Quartz scheduler.
     * @param application
     *            application name.
     */
    public FlowPurgeJob(FlowManager flowManager, Scheduler scheduler, String application) {
        this.flowManager = flowManager;
        this.scheduler = scheduler;
        this.application = application;
        flowPurgeSchedule = FLOW_PURGE_SCHEDULE_DEFAULT;
        purgeFlowsOlderThan = PURGE_FLOWS_OLDER_THAN_DEFAULT;
        doNotPurgeErrorFlows = DO_NOT_PURGE_ERROR_FLOWS_DEFAULT;
    }
    
    public String getFlowPurgeSchedule() {
        return flowPurgeSchedule;
    }

    /**
     * @see ApplicationConfig#setFlowPurgeSchedule(String)
     */
    public void setFlowPurgeSchedule(String flowPurgeSchedule) {
        this.flowPurgeSchedule = flowPurgeSchedule;
    }

    public String getPurgeFlowsOlderThan() {
        return purgeFlowsOlderThan;
    }

    /**
     * @see ApplicationConfig#setPurgeFlowsOlderThan(String)
     */
    public void setPurgeFlowsOlderThan(String purgeFlowsOlderThan) {
        this.purgeFlowsOlderThan = purgeFlowsOlderThan;
    }

    public boolean isDoNotPurgeErrorFlows() {
        return doNotPurgeErrorFlows;
    }

    /**
     * @see ApplicationConfig#setDoNotPurgeErrorFlows(boolean) 
     */
    public void setDoNotPurgeErrorFlows(boolean doNotPurgeErrorFlows) {
        this.doNotPurgeErrorFlows = doNotPurgeErrorFlows;
    }

    /**
     * @see org.quartz.Job#execute(org.quartz.JobExecutionContext)
     */
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        FlowManager manager = (FlowManager)context.getJobDetail().getJobDataMap().get(FLOW_MANAGER_KEY);
        ApplicationConfig config = (ApplicationConfig)context.getJobDetail().getJobDataMap().get(APP_CONFIG_KEY);
        synchronized (manager) {
            execute(manager, config);
        }
    }

    /**
     * Runs repeated {@link FlowManager#purgeFlows(FlowPurgeCriteria)}
     * operations based on criteria given in config until all flows
     * matching the criteria have been purged from the database. .
     * 
     * @param manager
     *            flow manager
     * @param config
     *            application-specific purge configuration
     */
    private void execute(FlowManager manager, ApplicationConfig config) {
        PurgeMode mode = config.isDoNotPurgeErrorFlows() ? CLEAN : ALL;
        Date olderThan = Duration.parse(config.getPurgeFlowsOlderThan()).since();
        FlowPurgeCriteria criteria = new FlowPurgeCriteria(mode, olderThan, config.getApplication(), 100);
    
        int purgeCountTotal = 0;
        int purgeCount;
        LOG.info("Start purging flows for application {}", config.getApplication());
        do {
            purgeCount = manager.purgeFlows(criteria);
            purgeCountTotal += purgeCount;
            LOG.info("Purged {} flows (application={})", purgeCountTotal, config.getApplication());
        } while (purgeCount >= criteria.getMaxPurgeCount()); 
        LOG.info("Finished purging flows for application {}", config.getApplication());
    }

    /**
     * Schedules this job for an single, immediate execution in a separate
     * thread.
     * 
     * @param config
     *            application-specific purge configuration
     */
    public void execute(ApplicationConfig config) {
        String name = "once";

        schedule(config, newTrigger().withIdentity(name, null).build(), name);
        LOG.info("Execute purge job once for application {}", application);
    }
    
    /**
     * Schedules this job for a repeated execution based on a cron expression.
     * 
     * @param config
     *            application-specific purge configuration
     * @see ApplicationConfig#setFlowPurgeSchedule(String)
     */
    public void schedule(ApplicationConfig config) {
        CronTrigger cronTrigger = newTrigger().withIdentity(application, null)
                                              .withSchedule(cronSchedule(flowPurgeSchedule))
                                              .build();
        schedule(config, cronTrigger, application);
        setFlowPurgeScheduled(true);
        LOG.info("Scheduled purge job for application {}", application);
    }
    
    private void schedule(ApplicationConfig config, Trigger trigger, String jobName) {
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put(FlowPurgeJob.FLOW_MANAGER_KEY, flowManager);
        jobDataMap.put(FlowPurgeJob.APP_CONFIG_KEY, config);

        JobDetail jobDetail = newJob()
                                  .withIdentity(jobName, null)
                                  .ofType(FlowPurgeJob.class)
                                  .usingJobData(jobDataMap)
                                  .build();
        
        try {
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            throw new FlowPurgeJobException("Cannot schedule job: " + e.getMessage());
        }
    }
    
    /**
     * Unschedules this job from repeated execution.
     */
    public void unschedule() {
        try {
            scheduler.deleteJob(JobKey.jobKey(application, null));
            setFlowPurgeScheduled(false);
            LOG.info("Unscheduled purge job for application {}", application);
        } catch (SchedulerException e) {
            throw new FlowPurgeJobException("Cannot unschedule job: " + e.getMessage());
        }
    }

    /**
     * Returns true is this job is currently scheduled for repeated
     * execution. This method does not return
     *  if the job currently as a result of a {@link #execute(ApplicationConfig)} invocation.
     * 
     * @return true if the job is scheduled for repeated execution,
     *         false otherwise.
     */
    public boolean isScheduled() {
        try {
            return scheduler.getJobDetail(JobKey.jobKey(application, null)) != null;
        } catch (SchedulerException e) {
            throw new FlowPurgeJobException("Cannot get job details: " + e.getMessage());
        }
    }
    
    private void setFlowPurgeScheduled(boolean purgeScheduled) {
        ApplicationConfig applicationConfig = flowManager.getApplicationConfig(application);
        applicationConfig.setFlowPurgeScheduled(purgeScheduled);
        flowManager.mergeApplicationConfig(applicationConfig);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy