Newer
Older
screenshot-app / src / main / java / com / screenshot / scheduler / ScreenshotScheduler.java
@malexple malexple on 15 Dec 4 KB Add app
package com.screenshot.scheduler;

import com.cronutils.model.Cron;
import com.cronutils.model.CronType;
import com.cronutils.model.definition.CronDefinitionBuilder;
import com.cronutils.model.time.ExecutionTime;
import com.cronutils.parser.CronParser;
import com.screenshot.config.AppConfig;
import com.screenshot.service.ScreenshotService;

import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.Optional;
import java.util.concurrent.*;

public class ScreenshotScheduler {
    private final ScheduledExecutorService scheduler;
    private final ScreenshotService screenshotService;
    private final AppConfig config;
    private ScheduledFuture<?> currentTask;
    private volatile boolean running = false;

    public ScreenshotScheduler(ScreenshotService screenshotService, AppConfig config) {
        this.scheduler = Executors.newScheduledThreadPool(1);
        this.screenshotService = screenshotService;
        this.config = config;
    }

    /**
     * Запустить планировщик
     */
    public void start() {
        if (running) {
            System.out.println("Планировщик уже запущен");
            return;
        }

        running = true;

        if (config.useCron()) {
            startWithCron();
        } else {
            startWithInterval();
        }

        System.out.println("Планировщик запущен");
    }

    /**
     * Запуск с использованием интервала
     */
    private void startWithInterval() {
        int intervalMinutes = config.getIntervalMinutes();

        currentTask = scheduler.scheduleAtFixedRate(
                this::takeScreenshot,
                0, // Начать сразу
                intervalMinutes,
                TimeUnit.MINUTES
        );

        System.out.println("Скриншоты каждые " + intervalMinutes + " мин.");
    }

    /**
     * Запуск с использованием cron-выражения
     */
    private void startWithCron() {
        String cronExpression = config.getCronExpression();

        CronParser parser = new CronParser(
                CronDefinitionBuilder.instanceDefinitionFor(CronType.SPRING)
        );

        try {
            Cron cron = parser.parse(cronExpression);
            ExecutionTime executionTime = ExecutionTime.forCron(cron);

            scheduleCronTask(executionTime);
            System.out.println("Cron расписание: " + cronExpression);

        } catch (IllegalArgumentException e) {
            System.err.println("Неверное cron-выражение: " + cronExpression);
            System.out.println("Используем интервал по умолчанию");
            startWithInterval();
        }
    }

    /**
     * Рекурсивное планирование задач по cron
     */
    private void scheduleCronTask(ExecutionTime executionTime) {
        if (!running) return;

        ZonedDateTime now = ZonedDateTime.now();
        Optional<Duration> nextExecution = executionTime.timeToNextExecution(now);

        if (nextExecution.isPresent()) {
            long delayMillis = nextExecution.get().toMillis();

            currentTask = scheduler.schedule(() -> {
                takeScreenshot();
                // Планируем следующее выполнение
                scheduleCronTask(executionTime);
            }, delayMillis, TimeUnit.MILLISECONDS);
        }
    }

    /**
     * Сделать скриншот
     */
    private void takeScreenshot() {
        String savePath = config.getSavePath();
        String targetWindow = config.getTargetWindow();

        screenshotService.captureAndSave(savePath, targetWindow);
    }

    /**
     * Остановить планировщик
     */
    public void stop() {
        running = false;

        if (currentTask != null) {
            currentTask.cancel(false);
        }

        System.out.println("Планировщик остановлен");
    }

    /**
     * Перезапустить с новыми настройками
     */
    public void restart() {
        stop();
        screenshotService.resetImageComparison();
        start();
    }

    /**
     * Завершить работу
     */
    public void shutdown() {
        stop();
        scheduler.shutdown();
        try {
            if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduler.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    public boolean isRunning() {
        return running;
    }
}