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

net.yudichev.jiotty.common.async.JobSchedulerImpl Maven / Gradle / Ivy

package net.yudichev.jiotty.common.async;

import net.yudichev.jiotty.common.inject.BaseLifecycleComponent;
import net.yudichev.jiotty.common.lang.Closeable;
import net.yudichev.jiotty.common.lang.Runnables;
import net.yudichev.jiotty.common.time.CurrentDateTimeProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;

import static com.google.common.base.Preconditions.checkNotNull;
import static net.yudichev.jiotty.common.lang.Closeable.closeIfNotNull;

final class JobSchedulerImpl extends BaseLifecycleComponent implements JobScheduler {
    private static final Logger logger = LoggerFactory.getLogger(JobSchedulerImpl.class);

    private final ExecutorFactory executorFactory;
    private final CurrentDateTimeProvider currentDateTimeProvider;
    private SchedulingExecutor schedulingExecutor;

    @Inject
    JobSchedulerImpl(ExecutorFactory executorFactory,
                     CurrentDateTimeProvider currentDateTimeProvider) {
        this.executorFactory = checkNotNull(executorFactory);
        this.currentDateTimeProvider = checkNotNull(currentDateTimeProvider);
    }

    @SuppressWarnings("ReturnOfInnerClass") // we are a singleton
    @Override
    public Closeable monthly(String jobName, int dayOfMonth, Runnable task) {
        return new MonthlyJob(jobName, dayOfMonth, task);
    }

    @Override
    protected void doStart() {
        schedulingExecutor = executorFactory.createSingleThreadedSchedulingExecutor("job-scheduler");
    }

    @Override
    protected void doStop() {
        closeIfNotNull(schedulingExecutor);
    }

    private class MonthlyJob implements Closeable {
        private final String jobName;
        private final int dayOfMonth;
        private final Runnable task;
        private Closeable scheduleHandle;

        MonthlyJob(String jobName, int dayOfMonth, Runnable task) {
            this.jobName = checkNotNull(jobName);
            this.dayOfMonth = dayOfMonth;
            this.task = Runnables.guarded(logger, String.format("executing job %s for day of month %s", jobName, dayOfMonth), task);
            scheduleNext();
        }

        @Override
        public void close() {
            scheduleHandle.close();
        }

        private void scheduleNext() {
            LocalDateTime dateTimeNow = currentDateTimeProvider.currentDateTime();
            LocalDate dateNow = dateTimeNow.toLocalDate();
            LocalDateTime nextDateTime = dateNow.plusMonths(1).withDayOfMonth(dayOfMonth).atTime(3, 0, 0);

            scheduleHandle = whenStartedAndNotLifecycling(() -> schedulingExecutor.schedule(Duration.between(dateTimeNow, nextDateTime), this::trigger));
            logger.info("Next [{}] job scheduled for {}", jobName, nextDateTime);
        }

        private void trigger() {
            scheduleNext();
            task.run();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy