From 5de00244a46000f1113afee776055c6de3b19959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B0=D1=89=D0=B8=D0=BB=D0=BA=D0=BE=20=D0=90=D0=BB?= =?UTF-8?q?=D0=B5=D0=BA=D1=81=D0=B5=D0=B9?= Date: Sun, 19 Oct 2025 21:28:13 +0300 Subject: [PATCH] add task 8 --- README.md | 2 +- src/main/java/task/TaskApplication.java | 4 ++ src/main/java/task/config/AsyncConfig.java | 22 +++++++++ src/main/java/task/config/RabbitConfig.java | 15 +++++- .../task/listener/TaskOverdueListener.java | 33 +++++++++++++ .../task/scheduler/TaskSchedulerService.java | 47 +++++++++++++++++++ .../resources/application-postgres.properties | 8 ++++ 7 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 src/main/java/task/config/AsyncConfig.java create mode 100644 src/main/java/task/listener/TaskOverdueListener.java create mode 100644 src/main/java/task/scheduler/TaskSchedulerService.java diff --git a/README.md b/README.md index 0872d00..5010485 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # REST API using Spring Boot - ## task 7 + ## task 8 diff --git a/src/main/java/task/TaskApplication.java b/src/main/java/task/TaskApplication.java index 2fab75b..a503ce9 100644 --- a/src/main/java/task/TaskApplication.java +++ b/src/main/java/task/TaskApplication.java @@ -4,10 +4,14 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableCaching @EnableRabbit +@EnableAsync +@EnableScheduling public class TaskApplication { public static void main(String[] args) { diff --git a/src/main/java/task/config/AsyncConfig.java b/src/main/java/task/config/AsyncConfig.java new file mode 100644 index 0000000..8b72467 --- /dev/null +++ b/src/main/java/task/config/AsyncConfig.java @@ -0,0 +1,22 @@ +package task.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; + +@Configuration +public class AsyncConfig implements AsyncConfigurer { + + @Override + public Executor getAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(3); + executor.setMaxPoolSize(10); + executor.setQueueCapacity(50); + executor.setThreadNamePrefix("AsyncTask-"); + executor.initialize(); + return executor; + } +} diff --git a/src/main/java/task/config/RabbitConfig.java b/src/main/java/task/config/RabbitConfig.java index 7bbd315..7eb5a36 100644 --- a/src/main/java/task/config/RabbitConfig.java +++ b/src/main/java/task/config/RabbitConfig.java @@ -14,11 +14,19 @@ public class RabbitConfig { public static final String TASK_EXCHANGE = "task_exchange"; public static final String TASK_ROUTING_KEY = "task.created"; + // Новая очередь для просроченных задач + public static final String OVERDUE_TASK_QUEUE = "task_overdue_queue"; + public static final String OVERDUE_TASK_ROUTING_KEY = "task.overdue"; + @Bean public Queue taskQueue() { return QueueBuilder.durable(TASK_QUEUE).build(); } - + // для просроченных задач + @Bean + public Queue overdueTaskQueue() { + return QueueBuilder.durable(OVERDUE_TASK_QUEUE).build(); + } @Bean public TopicExchange taskExchange() { return new TopicExchange(TASK_EXCHANGE); @@ -28,6 +36,11 @@ public TopicExchange taskExchange() { public Binding taskBinding(Queue taskQueue, TopicExchange taskExchange) { return BindingBuilder.bind(taskQueue).to(taskExchange).with(TASK_ROUTING_KEY); } + // для просроченных задач + @Bean + public Binding overdueTaskBinding(Queue overdueTaskQueue, TopicExchange taskExchange) { + return BindingBuilder.bind(overdueTaskQueue).to(taskExchange).with(OVERDUE_TASK_ROUTING_KEY); + } @Bean public Jackson2JsonMessageConverter messageConverter() { diff --git a/src/main/java/task/listener/TaskOverdueListener.java b/src/main/java/task/listener/TaskOverdueListener.java new file mode 100644 index 0000000..958849d --- /dev/null +++ b/src/main/java/task/listener/TaskOverdueListener.java @@ -0,0 +1,33 @@ +package task.listener; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; +import task.config.RabbitConfig; +import task.model.Notification; +import task.model.Task; +import task.service.NotificationService; + +@Component +@RequiredArgsConstructor +@Slf4j +public class TaskOverdueListener { + + private final NotificationService notificationService; + + @RabbitListener(queues = RabbitConfig.OVERDUE_TASK_QUEUE) + public void handleOverdueTask(Task task) { + log.warn("Получено событие просроченной задачи из RabbitMQ: #{}", task.getTaskId()); + + Notification notification = Notification.builder() + .text(" Задача просрочена: " + task.getTaskText()) + .taskId(task.getTaskId()) + .userId(task.getUserId()) + .build(); + + notificationService.createNotification(notification); + + log.info("Уведомление о просроченной задаче #{} создано", task.getTaskId()); + } +} diff --git a/src/main/java/task/scheduler/TaskSchedulerService.java b/src/main/java/task/scheduler/TaskSchedulerService.java new file mode 100644 index 0000000..a1c292a --- /dev/null +++ b/src/main/java/task/scheduler/TaskSchedulerService.java @@ -0,0 +1,47 @@ +package task.scheduler; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import task.config.RabbitConfig; +import task.model.Task; +import task.repository.TaskRepository; + +import java.time.LocalDateTime; +import java.util.List; + +@Service +@RequiredArgsConstructor +@Slf4j +public class TaskSchedulerService { + + private final TaskRepository taskRepository; + private final RabbitTemplate rabbitTemplate; + + @Scheduled(cron = "${task.check-rate}") // task.check-rate - время проверки просроченных задач задается в application-postgres.properties + @Async + public void checkOverdueTasks() { + log.info("Запуск проверки просроченных задач..."); + + List tasks = taskRepository.findByIsDeleteFalse(); + LocalDateTime now = LocalDateTime.now(); + + tasks.stream() + .filter(task -> !task.getIsComplete() + && task.getActionDate() != null + && task.getActionDate().isBefore(now)) + .forEach(task -> { + log.warn(" Обнаружена просроченная задача #{}: {}", task.getTaskId(), task.getTaskText()); + rabbitTemplate.convertAndSend( + RabbitConfig.TASK_EXCHANGE, + RabbitConfig.OVERDUE_TASK_ROUTING_KEY, + task + ); + }); + + log.info("Проверка просроченных задач завершена"); + } +} diff --git a/src/main/resources/application-postgres.properties b/src/main/resources/application-postgres.properties index 12491d1..c5f5675 100644 --- a/src/main/resources/application-postgres.properties +++ b/src/main/resources/application-postgres.properties @@ -28,3 +28,11 @@ spring.rabbitmq.username=guest spring.rabbitmq.password=guest +# ??????????? ????? +# ????????? ????????? ???????? ????? +# ?????? 4 ???? "0 0 */4 * * *" (00:00, 04:00, 08:00, 12:00, 16:00, 20:00) +# ?????? 2 ???? "0 0 */2 * * *" +# ?????? 5 ????? "0 */5 * * * *" +task.check-rate=0 */5 * * * * + +