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

com.shinitech.djammadev.jobs.JobLoaderImpl Maven / Gradle / Ivy

package com.shinitech.djammadev.jobs;

import akka.actor.Cancellable;
import com.avaje.ebean.Ebean;
import com.shinitech.djammadev.jobs.tasks.SendMail;
import com.shinitech.djammadev.mail.MailSender;
import com.shinitech.djammadev.mail.STMail;
import com.shinitech.djammadev.models.jobs.EmailItem;
import com.shinitech.djammadev.models.jobs.JobItem;
import com.shinitech.djammadev.time.DayDate;
import com.typesafe.config.Config;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;

import javax.inject.Inject;
import java.lang.reflect.InvocationTargetException;
import java.util.*;

/**
 * Created by sissoko on 01/11/2017.
 */
public class JobLoaderImpl implements JobLoader {
    private static final Logger LOGGER = Logger.getLogger(JobLoaderImpl.class);
    private final JobScheduler scheduler;
    private final Config config;
    private final STMail mailSender;
    private final Map jobs = new HashMap<>();

    private final Queue queue = new LinkedList<>();

    @Inject
    public JobLoaderImpl(final JobScheduler scheduler, final Config config, final STMail mailSender) {
        this.scheduler = scheduler;
        this.config = config;
        this.mailSender = mailSender;
    }

    @Override
    public Map load() {
        if (this.config.hasPath("jobs")) {
            List jobClasses = this.config.getStringList("jobs");
            if (jobClasses != null) {
                jobClasses.forEach(className -> {
                    try {
                        Class clazz = this.config.getClass().getClassLoader().loadClass(className);
                        if (!Job.class.isAssignableFrom(clazz)) {
                            throw new IllegalStateException("Invalid class class. The class must be a subclass of Job.");
                        }
                        Schedules annotation = clazz.getAnnotation(Schedules.class);
                        Job job;
                        job = (Job) clazz.getConstructor().newInstance();
                        job.with(this);
                        job.with(this.config);
                        job.with(this.mailSender);
                        for (Schedules.Schedule schedule : annotation.schedules()) {
                            LOGGER.info(String.format("Loading job %s", schedule.name()));
                            DayDate originOfTime = DayDate.parse(schedule.originOfTime());
                            boolean periodic = schedule.periodic();
                            Cancellable cancellable;
                            if (periodic) {
                                Duration duration = Duration.create(schedule.interval());
                                FiniteDuration interval = FiniteDuration.create(duration.length(), duration.unit());
                                cancellable = this.scheduler.schedule(schedule.runRightNow(), originOfTime, interval, job);
                            } else {
                                cancellable = this.scheduler.scheduleOne(originOfTime, job);
                            }
                            jobs.put(schedule.name(), new CancellableJob(cancellable, job));
                        }

                    } catch (Exception e) {
                        LOGGER.error(e.getMessage(), e);
                    }
                });
            }
        }
        loadDatabaseJob();
        //loadCrons();
        return jobs;
    }

    private void loadCrons() {
        if (this.config.hasPath("crons")) {
            this.config.getConfigList("crons").forEach(c -> {
                String name = c.getString("name");
                String expression = c.getString("expression");
                String taskClass = c.getString("task");
                try {
                    Class clazz = this.config.getClass().getClassLoader().loadClass(taskClass);
                    if (!Runnable.class.isAssignableFrom(clazz)) {
                        throw new IllegalStateException("Invalid class class. The class must be a subclass of Job.");
                    }
                    Runnable task = (Runnable) clazz.getConstructor().newInstance();
                    Job job = new CronJob(name, expression, task);
                    this.jobs.put(name, new CancellableJob(this.scheduler.scheduleOne(new DayDate(), job), job));
                } catch (ClassNotFoundException
                        | IllegalAccessException
                        | InstantiationException
                        | NoSuchMethodException
                        | InvocationTargetException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            });
        }
    }

    private void loadDatabaseJob() {
        JobItem.find.where()
                .findList()
                .forEach(this::post);
        EmailItem.find.where()
                .findList()
                .forEach(this::post);
    }

    @Override
    public Cancellable post(JobItem jobItem) {
        return post(jobItem, true);
    }

    @Override
    public Cancellable execute(JobItem jobItem) {
        return post(jobItem, false);
    }

    /**
     * @param jobItem
     * @param update
     * @return
     */
    private Cancellable post(JobItem jobItem, boolean update) {
        cancel(jobItem.getName());
        if (jobItem.getActive() == Boolean.FALSE) {
            jobItem.setScheduled(false);
            if (update) {
                jobItem.update();
            }
            return null;
        }
        Cancellable schedule;
        CancellableJob cancellableJob = null;
        try {
            Class clazz = this.config.getClass().getClassLoader().loadClass(jobItem.getJobClassName());
            if (!Job.class.isAssignableFrom(clazz)) {
                throw new IllegalStateException("Invalid class class. The class must be a subclass of Job.");
            }
            Job job = (Job) clazz.getConstructor().newInstance();
            job.with(jobItem);
            job.with(this.config);
            job.with(this.mailSender);
            LOGGER.info(String.format("Loading job %s", jobItem.getName()));
            if (!StringUtils.isEmpty(jobItem.getCronExpression())) {
                Job cronJob = new CronJob(jobItem.getName(), jobItem.getCronExpression(), job);
                schedule = this.scheduler.scheduleOne(DayDate.today(), cronJob);
                cancellableJob = new CancellableJob(schedule, cronJob);
            } else {
                DayDate originOfTime = DayDate.from(jobItem.getOriginOfTime());
                if (jobItem.getPeriodic() == Boolean.TRUE) {
                    Duration duration = Duration.create(jobItem.getInterval());
                    FiniteDuration interval = FiniteDuration.create(duration.length(), duration.unit());
                    schedule = this.scheduler.schedule(jobItem.getRunRightNow(), originOfTime, interval, job);
                } else {
                    schedule = this.scheduler.scheduleOne(originOfTime, job);
                }
                cancellableJob = new CancellableJob(schedule, job);
            }
            jobs.put(jobItem.getName(), cancellableJob);
            jobItem.setScheduled(true);
            if (update) {
                jobItem.update();
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
        return cancellableJob;
    }

    @Override
    public Cancellable post(EmailItem jobItem) {
        cancel(jobItem.getName());
        if (jobItem.getActive() == Boolean.FALSE) {
            jobItem.setScheduled(false);
            jobItem.update();
            return null;
        }
        Job job = new SendMail(jobItem, this.mailSender, this.config);
        Job cronJob = new CronJob(jobItem.getName(), jobItem.getCronExpression(), job);
        Cancellable cancellable = new CancellableJob(this.scheduler.scheduleOne(DayDate.today(), cronJob), cronJob);
        jobs.put(jobItem.getName(), cancellable);
        jobItem.setScheduled(true);
        jobItem.update();
        return cancellable;
    }

    public void cancel(String name) {
        Cancellable job = jobs.get(name);
        if (job != null) {
            job.cancel();
            jobs.remove(name);
        }
    }

    public void post(Job job) {
        this.scheduler.execute(job);
    }

    @Override
    public Cancellable schedule(Job job, long millis, String name) {
        cancel(name);
        Cancellable schedule = this.scheduler.schedule(job, millis);
        jobs.put(name, schedule);
        return schedule;
    }

    public Set getJobs() {
        return jobs.keySet();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy