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

com.github.ltsopensource.spring.quartz.QuartzLTSProxyAgent Maven / Gradle / Ivy

The newest version!
package com.github.ltsopensource.spring.quartz;

import com.github.ltsopensource.core.commons.utils.CollectionUtils;
import com.github.ltsopensource.core.commons.utils.QuietUtils;
import com.github.ltsopensource.core.domain.Job;
import com.github.ltsopensource.core.factory.NamedThreadFactory;
import com.github.ltsopensource.core.json.JSON;
import com.github.ltsopensource.core.logger.Logger;
import com.github.ltsopensource.core.logger.LoggerFactory;
import com.github.ltsopensource.jobclient.JobClient;
import com.github.ltsopensource.jobclient.JobClientBuilder;
import com.github.ltsopensource.core.properties.JobClientProperties;
import com.github.ltsopensource.jobclient.domain.Response;
import com.github.ltsopensource.tasktracker.TaskTracker;
import com.github.ltsopensource.tasktracker.TaskTrackerBuilder;
import com.github.ltsopensource.tasktracker.runner.JobRunner;
import com.github.ltsopensource.tasktracker.runner.RunnerFactory;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.quartz.impl.triggers.SimpleTriggerImpl;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author Robert HG ([email protected]) on 3/16/16.
 */
class QuartzLTSProxyAgent {

    private static final Logger LOGGER = LoggerFactory.getLogger(QuartzLTSProxyAgent.class);
    private QuartzLTSConfig quartzLTSConfig;
    private List quartzJobContexts = new CopyOnWriteArrayList();
    private AtomicBoolean ready = new AtomicBoolean(false);

    public QuartzLTSProxyAgent(QuartzLTSConfig quartzLTSConfig) {
        this.quartzLTSConfig = quartzLTSConfig;
    }

    // 开始代理
    public void startProxy(List cronJobs) {
        if (CollectionUtils.isEmpty(cronJobs)) {
            return;
        }
        quartzJobContexts.addAll(cronJobs);

        if (!ready.compareAndSet(false, true)) {
            return;
        }
        new NamedThreadFactory(QuartzLTSProxyAgent.class.getSimpleName() + "_LazyStart").newThread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 3S之后启动 JobClient和TaskTracker, 为了防止有多个SchedulerFactoryBean, 从而这个方法被调用多次
                    QuietUtils.sleep(3000);
                    startProxy0();
                } catch (Throwable t) {
                    LOGGER.error("Error on start " + QuartzLTSProxyAgent.class.getSimpleName(), t);
                }
            }
        }).start();
    }

    private void startProxy0() {
        // 1. 先启动 TaskTracker
        startTaskTracker();

        // 2. 启动JobClient并提交任务
        JobClient jobClient = startJobClient();

        // 3. 提交任务
        submitJobs(jobClient);
    }

    private void startTaskTracker() {

        TaskTracker taskTracker = TaskTrackerBuilder.buildByProperties(quartzLTSConfig.getTaskTrackerProperties());
        taskTracker.setWorkThreads(quartzJobContexts.size());
        taskTracker.setJobRunnerClass(QuartzJobRunnerDispatcher.class);

        final QuartzJobRunnerDispatcher jobRunnerDispatcher = new QuartzJobRunnerDispatcher(quartzJobContexts);
        taskTracker.setRunnerFactory(new RunnerFactory() {
            @Override
            public JobRunner newRunner() {
                return jobRunnerDispatcher;
            }
        });

        taskTracker.start();
    }

    private JobClient startJobClient() {
        JobClientProperties jobClientProperties = quartzLTSConfig.getJobClientProperties();
        jobClientProperties.setUseRetryClient(false);
        JobClient jobClient = JobClientBuilder.buildByProperties(jobClientProperties);
        jobClient.start();
        return jobClient;
    }

    private void submitJobs(JobClient jobClient) {

        List jobs = new ArrayList(quartzJobContexts.size());
        for (QuartzJobContext quartzJobContext : quartzJobContexts) {

            if (QuartzJobType.CRON == quartzJobContext.getType()) {
                jobs.add(buildCronJob(quartzJobContext));
            } else if (QuartzJobType.SIMPLE_REPEAT == quartzJobContext.getType()) {
                jobs.add(buildSimpleJob(quartzJobContext));
            }
        }
        LOGGER.info("=============LTS=========== Submit start");
        submitJobs0(jobClient, jobs);
        LOGGER.info("=============LTS=========== Submit end");
    }

    private Job buildCronJob(QuartzJobContext quartzJobContext) {

        CronTriggerImpl cronTrigger = (CronTriggerImpl) quartzJobContext.getTrigger();
        String cronExpression = cronTrigger.getCronExpression();
        String description = cronTrigger.getDescription();
        int priority = cronTrigger.getPriority();
        String name = quartzJobContext.getName();

        Job job = new Job();
        job.setTaskId(name);
        job.setPriority(priority);
        job.setCronExpression(cronExpression);
        job.setSubmitNodeGroup(quartzLTSConfig.getJobClientProperties().getNodeGroup());
        job.setTaskTrackerNodeGroup(quartzLTSConfig.getTaskTrackerProperties().getNodeGroup());
        job.setParam("description", description);
        setJobProp(job);

        return job;
    }

    private Job buildSimpleJob(QuartzJobContext quartzJobContext) {

        SimpleTriggerImpl simpleTrigger = (SimpleTriggerImpl) quartzJobContext.getTrigger();

        String description = simpleTrigger.getDescription();
        int priority = simpleTrigger.getPriority();
        String name = quartzJobContext.getName();
        int repeatCount = simpleTrigger.getRepeatCount();
        long repeatInterval = simpleTrigger.getRepeatInterval();

        Job job = new Job();
        job.setTaskId(name);

        job.setTriggerDate(simpleTrigger.getNextFireTime());
        job.setRepeatCount(repeatCount);

        if (repeatCount != 0) {
            job.setRepeatInterval(repeatInterval);
        }
        job.setPriority(priority);
        job.setSubmitNodeGroup(quartzLTSConfig.getJobClientProperties().getNodeGroup());
        job.setTaskTrackerNodeGroup(quartzLTSConfig.getTaskTrackerProperties().getNodeGroup());
        job.setParam("description", description);
        setJobProp(job);

        return job;
    }

    private void setJobProp(Job job) {
        QuartzLTSConfig.JobProperties jobProperties = quartzLTSConfig.getJobProperties();
        if (jobProperties == null) {
            return;
        }
        if (jobProperties.getMaxRetryTimes() != null) {
            job.setMaxRetryTimes(jobProperties.getMaxRetryTimes());
        }
        if (jobProperties.getNeedFeedback() != null) {
            job.setNeedFeedback(jobProperties.getNeedFeedback());
        }
        if (jobProperties.getRelyOnPrevCycle() != null) {
            job.setRelyOnPrevCycle(jobProperties.getRelyOnPrevCycle());
        }
        if (jobProperties.getReplaceOnExist() != null) {
            job.setReplaceOnExist(jobProperties.getReplaceOnExist());
        }
    }

    private void submitJobs0(JobClient jobClient, List jobs) {
        List failedJobs = null;
        try {
            Response response = jobClient.submitJob(jobs);
            if (!response.isSuccess()) {
                LOGGER.warn("Submit Quartz Jobs to LTS failed: {}", JSON.toJSONString(response));
                failedJobs = response.getFailedJobs();
            }
        } catch (Throwable e) {
            LOGGER.warn("Submit Quartz Jobs to LTS error", e);
            failedJobs = jobs;
        }

        if (CollectionUtils.isNotEmpty(failedJobs)) {
            // 没提交成功要重试 3S 之后重试
            LOGGER.info("=============LTS=========== Sleep 3 Seconds and retry");
            QuietUtils.sleep(3000);
            submitJobs0(jobClient, failedJobs);
            return;
        }

        // 如果成功了, 关闭jobClient
        jobClient.stop();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy