Будильники на Spring

145
12 декабря 2021, 14:00

У меня есть объекты рассылки, в которых есть параметр времени. В это время они должны быть отправлены на e-mail пользователям.

В данный момент реализовано так: есть Scheduler, который просыпается каждые 15 минут, смотрит, есть ли неотправленные письма, которые он проспал и отправляет. т.е. допустим есть рассылка со временем отправки в 8:00. Также допустим, что Scheduler просыпается в 8:07, смотрит в базу. В базе лежит неотправленное письмо. Он берёт это письмо и отправляет.

Я так понимаю, нужно создать какой-то "будильник", который будет срабатывать в определенное время и отправлять письма. И ставить Scheduler на проверку раз в секунду довольно дорого.

Как мне средствами Spring создать отправку письма в какое-то конкретное время?

За примеры кода или ссылки на туториалы буду особо благодарен

Answer 1

Есть в spring аннотация @Scheduled, ее можно использовать с параметрами, как у планировщика cron:

@Scheduled(cron = "0 15 10 15 * ?")
public void scheduleTaskUsingCronExpression() {
    long now = System.currentTimeMillis() / 1000;
    System.out.println(
      "schedule tasks using cron jobs - " + now);
}

Т.е. запускать этот метод в 10:15 AM 15th числа каждый месяц.

Answer 2

Если ты хочешь моментальную отправку сообщений, то в простейшем случае тебе стоит посмотреть в сторону объекта BlockingQueue, который можно шарить между компонентом, который генерирует сообщения и которых их отправляет. Псевдокод будет примерно таким:

class MyMessage{
//.... поля и т.д.
}
class MessageGenerator{
  private final BlockingQueue<MyMessage> queue; 
  //.... поля и т.д.
  public void send(MyMessage message) {
      queue.put(message);
  }
}
class MessageSender implements Runnable{
  private final BlockingQueue<MyMessage> queue; 
 //.... поля и т.д.
  public void run(){
      while(true) {
         MyMessage message = queue.take(); //это ожидание в реальном времени
         //дальше собственно отправка
      }
  }
}

Однако, раз у тебя присутствует БД, то скорее всего тебе нужна какая-то отказоустойчивость, чтобы ещё не отправленные письма не пропали при аварии/перезапуске сервера. В таком случае стоит посмотреть в сторону очередей типа ActiveMq/RabbitMq/Kafka и т.д. Но даже твоё решение с БД является вполне рабочим. Просто сократи поллинг с 15 минут до 1 минуты, или даже до 30 секунд. Такая погрешность в отправке писем считается вполне нормальной и практикуется почти везде.

READ ALSO
Maven не видит класс из другого модуля

Maven не видит класс из другого модуля

При сборке проекта Maven выдает следующие ошибки:

246
Patch сущности в REST Spring MVC

Patch сущности в REST Spring MVC

изучаю принципы REST, остановился на обновлении сущностиНе могу понять, как в сущность передать поля, которые передаю в запросе и затем обновить...

183
Дженерики, метод of

Дженерики, метод of

Почему две данных реализации работают? В чем их принципиальное отличие?

288