Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Задачи по расписанию

Некоторую работу приложение должно делать само, без запроса: раз в минуту собирать статистику, ночью чистить старые черновики, каждый час отправлять сводку. Для этого в Micronaut есть аннотация @Scheduled. Метод с ней фреймворк запускает в отдельном пуле потоков по расписанию. Ничего подключать не нужно — планировщик входит в ядро.

Первая задача

Создайте класс вручную или командой mn create-job com.example.StatsJob:

// src/main/java/com/example/StatsJob.java
package com.example;
 
import io.micronaut.scheduling.annotation.Scheduled;
import jakarta.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
@Singleton
public class StatsJob {
 
    private static final Logger LOG = LoggerFactory.getLogger(StatsJob.class);
 
    private final ArticleRepository articleRepository;
 
    public StatsJob(ArticleRepository articleRepository) {
        this.articleRepository = articleRepository;
    }
 
    @Scheduled(fixedDelay = "${blog.stats-interval:1m}", initialDelay = "5s")
    void logStats() {
        LOG.info("Статей в блоге: {}", articleRepository.count());
    }
}

Задача — обычный бин: она получает репозиторий через конструктор. initialDelay = "5s" — первый запуск через 5 секунд после старта, дальше пауза из настройки blog.stats-interval, а если её нет — одна минута. Длительности пишутся как 10s, 1m, 2h.

Проверка

Для наглядности сократите интервал в application.properties:

# src/main/resources/application.properties
blog.stats-interval=10s

Запустите приложение, создайте статью и посмотрите в журнал:

12:10:52.113 [scheduled-executor-thread-1] INFO  com.example.StatsJob - Статей в блоге: 1
12:11:02.114 [scheduled-executor-thread-2] INFO  com.example.StatsJob - Статей в блоге: 1

Записи появляются каждые 10 секунд. Имя потока scheduled-executor-thread показывает, что задача выполняется не в потоке HTTP-запросов.

Виды расписаний

ПараметрКак работает
fixedDelay = "1m"Пауза 1 минута после окончания предыдущего запуска
fixedRate = "1m"Запуск каждую минуту от начала предыдущего
cron = "0 0 3 * * *"По cron-выражению: каждый день в 03:00
initialDelay = "5s"Задержка перед первым запуском

Cron-выражение в Micronaut состоит из шести полей: секунды, минуты, часы, день месяца, месяц, день недели. Ночная задача выглядит так:

// src/main/java/com/example/StatsJob.java
@Scheduled(cron = "0 0 3 * * *")
void nightly() {
    LOG.info("Ночная уборка");
}

Если задача может длиться дольше интервала, выбирайте fixedDelay: запуски не наложатся друг на друга.

Частая ошибка

Метод с @Scheduled выполняется, только если его класс — бин. Если забыть @Singleton, приложение запустится без ошибок и предупреждений, но задача не будет работать ни разу — в журнале просто не появятся её записи. Когда задача «молчит», первым делом проверьте аннотацию области видимости на классе.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.