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

host.anzo.core.startup.ScheduledService Maven / Gradle / Ivy

package host.anzo.core.startup;

import host.anzo.commons.threading.ThreadPool;
import host.anzo.commons.utils.ClassUtils;
import host.anzo.core.service.ForkJoinPoolService;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/***
 * @author ANZO
 * @since 8/19/2021
 */
@Slf4j
@StartupComponent(value = "AfterStart", shutdownPriority = EShutdownPriority.MAJOR)
public class ScheduledService implements IShutdownable {
    @Getter(lazy=true)
    private final static ScheduledService instance = new ScheduledService();

    private final List tasks = new ArrayList<>();
    private final Map, List> scheduledTasks = new HashMap<>();

    private ScheduledService() {
    }

    @SuppressWarnings("unused")
    @StartupRun(before = "AfterStart")
    public void scheduleTasks() {
        // Run tasks needed to run at server startup
        log.info("Running Scheduled methods after server start...");
        ForkJoinPoolService.getInstance().forEach("ScheduledService.runAfterServerStart()",
                () -> tasks.parallelStream().filter(task -> task.getMethod().getAnnotation(Scheduled.class).runAfterServerStart()).forEach(ScheduledTask::run));

        // Schedule all tasks
        log.info("Scheduling Scheduled methods tasks...");
        for (ScheduledTask task : tasks) {
            final Scheduled scheduledAnnotation = task.getMethod().getAnnotation(Scheduled.class);
            final TimeUnit timeUnit = scheduledAnnotation.timeUnit();
            final long period = scheduledAnnotation.period();
            if (TimeUnit.MILLISECONDS.convert(period, timeUnit) <= 0) {
                log.error("Delay is zero for scheduled task {}.{}", task.getServiceClass().getSimpleName(), task.getMethod().getName());
                continue;
            }
            final ScheduledFuture scheduledFuture = ThreadPool.getInstance().scheduleGeneralAtFixedRate(task.getServiceClass().getSimpleName() + "." + task.getMethod().getName(), task, period, period, timeUnit);
            task.setScheduledFuture(scheduledFuture);
            scheduledTasks.computeIfAbsent(task.getServiceClass(), k -> new ArrayList<>()).add(task);
        }
    }

    protected void addScheduledMethod(@NotNull Class serviceClass, @NotNull Method method) {
        if (method.isAnnotationPresent(Scheduled.class)) {
            tasks.add(new ScheduledTask(serviceClass, method));
        }
    }

    @Override
    public void onShutdown() {
        for (List scheduledTasks : scheduledTasks.values()) {
            for (ScheduledTask scheduledTask : scheduledTasks) {
                try {
                    scheduledTask.getScheduledFuture().cancel(true);
                }
                catch (Exception ignored) {
                }
            }
        }
    }

    private static @Getter class ScheduledTask implements Runnable {
        private final Class serviceClass;
        private final Method method;
        private @Setter ScheduledFuture scheduledFuture;

        ScheduledTask(@NotNull Class serviceClass, @NotNull Method method) {
            this.serviceClass = serviceClass;
            this.method = method;
        }

        @Override
        public void run() {
            try {
                ClassUtils.singletonInstanceMethod(serviceClass, method);
            }
            catch (Exception e) {
                log.error("Error while calling scheduled task at {}.{}", serviceClass.getSimpleName(), method.getName(), e);
            }
         }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy