From b74c7a4f040d7d543207fbb81e37e6669c3439ad Mon Sep 17 00:00:00 2001 From: Dmitry Kutuzov Date: Tue, 27 Jun 2023 02:54:44 +0300 Subject: [PATCH 1/2] done hw13 --- dev/docker-compose.yml | 53 +++++++++++++++ handyman-service/build.gradle | 1 + .../handyman/HandymanController.java | 11 ++-- .../handyman/HandymanService.java | 20 ++---- .../handymanservice/landscape/User.java | 4 ++ .../order/dto/SendOrderToUser.java | 10 +++ .../src/main/resources/application.properties | 14 +++- landscape-service/build.gradle | 1 + .../archie/landscapeservice/field/Field.java | 6 +- .../handyman/HandymanRepository.java | 1 - .../archie/landscapeservice/order/Order.java | 8 ++- .../landscapeservice/order/OrderResolver.java | 64 +++++++++++++------ .../landscapeservice/order/OrderService.java | 25 ++++++-- .../order/dto/CreatingOrderDto.java | 2 + .../order/dto/SendOrderToUser.java | 10 +++ .../archie/landscapeservice/user/User.java | 2 +- .../src/main/resources/application.properties | 14 +++- rancher-service/build.gradle | 1 + .../order/dto/SendOrderToUser.java | 11 ++++ .../archie/rancherservice/landscape/User.java | 4 ++ .../landscape/dto/OrderDto.java | 2 + .../rancher/GardenerController.java | 15 +++-- .../rancher/GardenerService.java | 22 +++---- .../src/main/resources/application.properties | 12 ++++ 24 files changed, 238 insertions(+), 75 deletions(-) create mode 100644 handyman-service/src/main/java/dev/archie/landscapeservice/order/dto/SendOrderToUser.java create mode 100644 landscape-service/src/main/java/dev/archie/landscapeservice/order/dto/SendOrderToUser.java create mode 100644 rancher-service/src/main/java/dev/archie/landscapeservice/order/dto/SendOrderToUser.java diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml index 7b36e47..76581f1 100644 --- a/dev/docker-compose.yml +++ b/dev/docker-compose.yml @@ -20,8 +20,11 @@ services: - PG_DB_URL=jdbc:postgresql://postgres:5432/postgres?currentSchema=public&stringtype=unspecified - PG_DB_USERNAME=postgres - PG_DB_PASSWORD=123 + - SPRING_KAFKA_BOOTSTRAP-SERVERS=kafka:9092 + - SPRING_KAFKA_CONSUMER_GROUP-ID=consumers depends_on: - mongo + - kafka landscape-service: container_name: landscape-service @@ -38,10 +41,13 @@ services: - DB_PASSWORD=123 - RANCHER_REST_URL=http://rancher-service:8082 - HANDYMAN_REST_URL=http://handyman-service:8080 + - SPRING_KAFKA_BOOTSTRAP-SERVERS=kafka:9092 + - SPRING_KAFKA_CONSUMER_GROUP-ID=consumers depends_on: - rancher-service - handyman-service - postgres + - kafka rancher-service: container_name: rancher-service @@ -58,8 +64,11 @@ services: - PG_DB_URL=jdbc:postgresql://postgres:5432/postgres?currentSchema=public&stringtype=unspecified - PG_DB_USERNAME=postgres - PG_DB_PASSWORD=123 + - SPRING_KAFKA_BOOTSTRAP-SERVERS=kafka:9092 + - SPRING_KAFKA_CONSUMER_GROUP-ID=consumers depends_on: - mongo + - kafka postgres: image: postgis/postgis:15-3.3 @@ -127,3 +136,47 @@ services: - app-tier depends_on: - prometheus + + zookeeper: + container_name: zookeeper + image: "bitnami/zookeeper:latest" + networks: + - app-tier + ports: + - "2181:2181" + environment: + ALLOW_ANONYMOUS_LOGIN: "yes" + + kafka: + container_name: kafka + image: "bitnami/kafka:3.0.0" + networks: + - app-tier + ports: + - "9093:9093" + - "9092:9092" + environment: + - KAFKA_BROKER_ID=1 + - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CLIENT:PLAINTEXT,EXTERNAL:PLAINTEXT + - KAFKA_CFG_LISTENERS=CLIENT://:9092,EXTERNAL://:9093 + - KAFKA_CFG_ADVERTISED_LISTENERS=CLIENT://kafka:9092,EXTERNAL://localhost:9093 + - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=CLIENT + - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181 + - KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true + - ALLOW_PLAINTEXT_LISTENER=yes + depends_on: + - zookeeper + + kafka-ui: + container_name: kafka-ui + image: "provectuslabs/kafka-ui" + networks: + - app-tier + ports: + - "8090:8080" + environment: + - KAFKA_CLUSTERS_0_NAME=kafka + - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9092 + restart: unless-stopped + depends_on: + - kafka \ No newline at end of file diff --git a/handyman-service/build.gradle b/handyman-service/build.gradle index 93afae0..0b31504 100644 --- a/handyman-service/build.gradle +++ b/handyman-service/build.gradle @@ -64,6 +64,7 @@ ext { } dependencies { + implementation 'org.springframework.kafka:spring-kafka' implementation 'org.n52.jackson:jackson-datatype-jts:1.2.10' implementation 'org.locationtech.jts:jts-io:1.18.2' implementation 'org.locationtech.jts:jts-core:1.18.2' diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanController.java b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanController.java index e6c36ff..f2dd567 100644 --- a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanController.java +++ b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanController.java @@ -1,8 +1,9 @@ package dev.archie.handymanservice.handyman; import dev.archie.handymanservice.handyman.dto.CreatingHandymanDto; -import dev.archie.handymanservice.landscape.Order; +import dev.archie.landscapeservice.order.dto.SendOrderToUser; import lombok.RequiredArgsConstructor; +import org.springframework.kafka.annotation.KafkaListener; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -12,8 +13,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.UUID; - @RestController @RequiredArgsConstructor @RequestMapping("/handymen") @@ -57,8 +56,8 @@ public void delete(@PathVariable String id) { handymanService.delete(id); } - @PostMapping("/order/{innerId}") - public boolean orderAJob(@PathVariable UUID innerId, @RequestBody Order order) { - return handymanService.orderAJob(innerId, order); + @KafkaListener(topics = "handyman.notify.order") + public void orderAJob(SendOrderToUser orderToUser) { + handymanService.orderAJob(orderToUser.handyman().getId(), orderToUser.order()); } } diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanService.java b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanService.java index bf1a4b8..bc21a34 100644 --- a/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanService.java +++ b/handyman-service/src/main/java/dev/archie/handymanservice/handyman/HandymanService.java @@ -9,12 +9,12 @@ import dev.archie.handymanservice.landscape.HandymanClient; import dev.archie.handymanservice.landscape.LandscapeService; import dev.archie.handymanservice.landscape.Order; -import dev.archie.handymanservice.landscape.OrderClient; import dev.archie.handymanservice.landscape.WorkStatus; -import dev.archie.handymanservice.landscape.dto.CreatingOrderDto; import dev.archie.handymanservice.landscape.dto.HandymanDto; +import dev.archie.landscapeservice.order.dto.SendOrderToUser; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Service; import java.util.List; @@ -36,7 +36,7 @@ public class HandymanService { private final AccountService accountService; private final HandymanClient handymanClient; - private final OrderClient orderClient; + private final KafkaTemplate kafkaTemplate; /** * @param creatingHandymanDto handyman dto create. Email should not exist @@ -125,8 +125,9 @@ private Handyman mapUserToHandyman(HandymanDto createdUser, CreatingHandymanDto .build(); } - public boolean orderAJob(UUID innerId, Order order) { + public void orderAJob(UUID innerId, Order order) { if (!handymanRepository.existsByInnerId(innerId)) { + kafkaTemplate.send("landscape.order.cancel", order); throw new NoSuchUserException(innerId.toString()); } boolean acceptedTheJob = order.getSkills().stream() @@ -136,8 +137,8 @@ public boolean orderAJob(UUID innerId, Order order) { log.info(innerId + " принял работу"); } else { log.info(innerId + " отказался от работы"); + kafkaTemplate.send("landscape.order.cancel", order); } - return acceptedTheJob; } public void getTheJobDone(Order order, UUID innerId) { @@ -148,14 +149,7 @@ public void getTheJobDone(Order order, UUID innerId) { throw new RuntimeException("Execution was interrupted" + e); } order.setStatus(WorkStatus.DONE); - CreatingOrderDto updatingDto = CreatingOrderDto.builder() - .status(order.getStatus()) - .fieldId(order.getField().getId()) - .userId(innerId) - .workType(order.getWorkType()) - .skills(order.getSkills().stream().map(Skill::getName).toList()) - .build(); - orderClient.update(order.getId(), updatingDto); + kafkaTemplate.send("landscape.order.complete", new SendOrderToUser(null, order)); log.info(innerId + " выполнил работу"); } diff --git a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/User.java b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/User.java index 3bf2d01..14aa62c 100644 --- a/handyman-service/src/main/java/dev/archie/handymanservice/landscape/User.java +++ b/handyman-service/src/main/java/dev/archie/handymanservice/landscape/User.java @@ -1,12 +1,16 @@ package dev.archie.handymanservice.landscape; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import java.time.LocalDateTime; import java.util.UUID; @Data +@AllArgsConstructor +@NoArgsConstructor @Builder public class User { diff --git a/handyman-service/src/main/java/dev/archie/landscapeservice/order/dto/SendOrderToUser.java b/handyman-service/src/main/java/dev/archie/landscapeservice/order/dto/SendOrderToUser.java new file mode 100644 index 0000000..0289f58 --- /dev/null +++ b/handyman-service/src/main/java/dev/archie/landscapeservice/order/dto/SendOrderToUser.java @@ -0,0 +1,10 @@ +package dev.archie.landscapeservice.order.dto; + +import dev.archie.handymanservice.landscape.Order; +import dev.archie.handymanservice.landscape.User; + +public record SendOrderToUser( + User handyman, + Order order +) { +} diff --git a/handyman-service/src/main/resources/application.properties b/handyman-service/src/main/resources/application.properties index 4d754bb..b2ccfae 100644 --- a/handyman-service/src/main/resources/application.properties +++ b/handyman-service/src/main/resources/application.properties @@ -14,4 +14,16 @@ spring.datasource.url=${PG_DB_URL} spring.datasource.username=${PG_DB_USERNAME} spring.datasource.password=${PG_DB_PASSWORD} -application.landscape.rest.url=${LANDSCAPE_REST_URL} \ No newline at end of file +application.landscape.rest.url=${LANDSCAPE_REST_URL} + +spring.kafka.bootstrap-servers=${SPRING_KAFKA_BOOTSTRAP-SERVERS} + +spring.kafka.consumer.group-id=${SPRING_KAFKA_CONSUMER_GROUP-ID} +spring.kafka.consumer.auto-offset-reset=earliest +spring.kafka.consumer.enable-auto-commit=true +spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer +spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer +spring.kafka.consumer.properties.spring.json.trusted.packages=* + +spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer +spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer diff --git a/landscape-service/build.gradle b/landscape-service/build.gradle index 2e1580c..dc43f48 100644 --- a/landscape-service/build.gradle +++ b/landscape-service/build.gradle @@ -53,6 +53,7 @@ jar { } dependencies { + implementation 'org.springframework.kafka:spring-kafka' implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' implementation 'org.hibernate:hibernate-spatial' diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/field/Field.java b/landscape-service/src/main/java/dev/archie/landscapeservice/field/Field.java index 073bf9b..9344df5 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/field/Field.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/field/Field.java @@ -1,5 +1,6 @@ package dev.archie.landscapeservice.field; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; @@ -44,11 +45,10 @@ public class Field { @Column(name = "longitude", nullable = false) private Double longitude; - @JsonSerialize(using = GeometrySerializer.class) - @JsonDeserialize(contentUsing = GeometryDeserializer.class) + @JsonIgnore private Geometry area; - @JsonIgnoreProperties("fields") + @JsonIgnoreProperties({"fields", "orders"}) @ManyToOne @JoinColumn(name = "gardener_id") private Gardener gardener; diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanRepository.java b/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanRepository.java index 83caceb..28c9451 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanRepository.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/handyman/HandymanRepository.java @@ -11,7 +11,6 @@ public interface HandymanRepository extends JpaRepository { select h from Handyman h join User u on u.id = h.id - where u.orders.size = 0 order by ST_Distance(ST_Point(?1, ?2), ST_Point(u.latitude, u.longitude)) """) List findNearestNotBusyHandyman(Double latitude, Double longitude); diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/Order.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/Order.java index ccaa7c8..399a4f8 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/Order.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/Order.java @@ -10,11 +10,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.hibernate.annotations.Fetch; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; +import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @@ -55,15 +57,15 @@ public class Order { @JoinColumn(name = "field_id") private Field field; - @JsonIgnoreProperties("orders") @ManyToOne @JoinColumn(name = "user_id") private User user; - @OneToMany + @JsonIgnoreProperties("handyman") + @OneToMany(fetch = FetchType.EAGER) @JoinColumn(name = "order_id") - private Set skills = new LinkedHashSet<>(); + private Set skills; @Column(name = "grade", nullable = false) private int grade; diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java index c1559b2..de40238 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java @@ -4,43 +4,38 @@ import dev.archie.landscapeservice.field.Field; import dev.archie.landscapeservice.gardener.GardenerClient; import dev.archie.landscapeservice.handyman.Handyman; -import dev.archie.landscapeservice.handyman.HandymanClient; import dev.archie.landscapeservice.handyman.HandymanRepository; +import dev.archie.landscapeservice.order.dto.CreatingOrderDto; +import dev.archie.landscapeservice.order.dto.SendOrderToUser; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import java.util.Set; @Service @RequiredArgsConstructor @Slf4j public class OrderResolver { - private final OrderRepository orderRepository; + private final HandymanRepository handymanRepository; - private final HandymanClient handymanClient; - private final GardenerClient gardenerClient; + private final KafkaTemplate kafkaTemplate; + private final OrderService orderService; + @KafkaListener(topics = "landscape.resolve.order") @Transactional - @Scheduled(initialDelay = 5000, fixedDelay = 2000) - public void sceduledResolver() { - resolve(); + public void sceduledResolver(Order order) { + resolve(order); } @Transactional - public void resolve() { - Optional firstCreatedOrder = orderRepository.findFirstCreatedOrder(); - if (firstCreatedOrder.isEmpty()) { - return; - } - Order order = firstCreatedOrder.get(); - + public void resolve(Order order) { List threeNearestSuitableHandymen = findThreeNearestSuitableHandymen(order); if (threeNearestSuitableHandymen.size() == 3) { log.info("notifying handymen"); @@ -51,7 +46,8 @@ public void resolve() { } } - private List findThreeNearestSuitableHandymen(Order order) { + @Transactional + public List findThreeNearestSuitableHandymen(Order order) { Field field = order.getField(); Set requiredSkills = order.getSkills(); List foundHandymen = new ArrayList<>(); @@ -64,14 +60,42 @@ private List findThreeNearestSuitableHandymen(Order order) { return foundHandymen.stream().limit(3).toList(); } + @KafkaListener(topics = "landscape.order.complete") + public void getTheJobDone(SendOrderToUser orderToUser) { + Order order = orderToUser.order(); + order.setStatus(WorkStatus.DONE); + CreatingOrderDto updating = CreatingOrderDto.builder() + .fieldId(order.getField().getId()) + .workType(order.getWorkType()) + .status(order.getStatus()) + .skills(order.getSkills().stream().map(Skill::getName).toList()) + .build(); + orderService.update(updating, order.getId()); + } + + @KafkaListener(topics = "landscape.order.rated") + public void saveRatedOrder(SendOrderToUser orderToUser) { + Order order = orderToUser.order(); + order.setStatus(WorkStatus.APPROVED); + CreatingOrderDto updating = CreatingOrderDto.builder() + .fieldId(order.getField().getId()) + .workType(order.getWorkType()) + .status(order.getStatus()) + .skills(order.getSkills().stream().map(Skill::getName).toList()) + .grade(order.getGrade()) + .userId(order.getUser().getId()) + .build(); + orderService.update(updating, order.getId()); + } + private void notifyFoundHandymen(List threeNearestSuitableHandymen, Order order) { - if (threeNearestSuitableHandymen.stream().allMatch(handyman -> handymanClient.orderAJob(handyman.getId(), order))) { - order.setStatus(WorkStatus.APPROVED); + for (Handyman handyman : threeNearestSuitableHandymen) { + kafkaTemplate.send("handyman.notify.order", new SendOrderToUser(handyman, order)); } } private void notifyRancher(Order order) { - gardenerClient.notifyAboutMissingWorkers(order); + kafkaTemplate.send("rancher.notify.missing-workers", new SendOrderToUser(order.getField().getGardener(), order)); } } diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java index 9435e6e..d248d5d 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java @@ -6,6 +6,7 @@ import dev.archie.landscapeservice.field.FieldService; import dev.archie.landscapeservice.gardener.GardenerClient; import dev.archie.landscapeservice.order.dto.CreatingOrderDto; +import dev.archie.landscapeservice.order.dto.SendOrderToUser; import dev.archie.landscapeservice.order.exception.DirectionIsNotSpecifiedException; import dev.archie.landscapeservice.order.exception.NoSuchOrderException; import dev.archie.landscapeservice.user.User; @@ -14,7 +15,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.Set; @@ -32,13 +35,24 @@ public class OrderService { private final FieldService fieldService; private final OrderRepository orderRepository; private final SkillRepository skillRepository; - private final GardenerClient gardenerClient; + private final KafkaTemplate kafkaTemplate; + private final KafkaTemplate kafkaTemplateOrder; + @Transactional public Order create(CreatingOrderDto orderDto) { User user = userService.getById(orderDto.getUserId()); Field field = fieldService.getById(orderDto.getFieldId()); Order order = mapCreatingOrderDtoToOrder(orderDto, user, field); - return orderRepository.save(order); + order.setSkills(orderDto.getSkills() + .stream() + .map(skillName -> Skill.builder() + .name(skillName) + .build()) + .map(skillRepository::save) + .collect(Collectors.toSet())); + order = orderRepository.save(order); + kafkaTemplateOrder.send("landscape.resolve.order", order); + return order; } public Order getById(Long id) { @@ -58,6 +72,7 @@ public Page getAllSorted(int pageNumber, int size, UUID userId, String di }; } + @Transactional public Order update(CreatingOrderDto creatingOrderDto, Long id) { Order order = getById(id); WorkStatus status = creatingOrderDto.getStatus(); @@ -71,12 +86,12 @@ public Order update(CreatingOrderDto creatingOrderDto, Long id) { .collect(Collectors.toSet()); order.setSkills(skills); order.setGrade(creatingOrderDto.getGrade()); - Order save = orderRepository.save(order); + order = orderRepository.save(order); log.info(order.toString()); if (order.getStatus().equals(WorkStatus.DONE)) { - gardenerClient.notifyAboutOrderUpdate(save); + kafkaTemplate.send("rancher.notify.order-updated", new SendOrderToUser(order.getField().getGardener(), order)); } - return save; + return order; } public void delete(Long id) { diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/dto/CreatingOrderDto.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/dto/CreatingOrderDto.java index 61f0161..2d20367 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/dto/CreatingOrderDto.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/dto/CreatingOrderDto.java @@ -2,12 +2,14 @@ import dev.archie.landscapeservice.order.WorkStatus; import dev.archie.landscapeservice.order.WorkType; +import lombok.Builder; import lombok.Data; import java.util.List; import java.util.UUID; @Data +@Builder public class CreatingOrderDto { private WorkType workType; diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/dto/SendOrderToUser.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/dto/SendOrderToUser.java new file mode 100644 index 0000000..86bb9b2 --- /dev/null +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/dto/SendOrderToUser.java @@ -0,0 +1,10 @@ +package dev.archie.landscapeservice.order.dto; + +import dev.archie.landscapeservice.order.Order; +import dev.archie.landscapeservice.user.User; + +public record SendOrderToUser( + User handyman, + Order order +) { +} diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/user/User.java b/landscape-service/src/main/java/dev/archie/landscapeservice/user/User.java index 52161aa..4cbfc40 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/user/User.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/user/User.java @@ -76,7 +76,7 @@ public class User { @JsonIgnoreProperties({"user", "field"}) @OneToMany(mappedBy = "user") - private List orders = new ArrayList<>(); + private List orders; @Override public boolean equals(Object o) { diff --git a/landscape-service/src/main/resources/application.properties b/landscape-service/src/main/resources/application.properties index f665a3a..819fb65 100644 --- a/landscape-service/src/main/resources/application.properties +++ b/landscape-service/src/main/resources/application.properties @@ -19,4 +19,16 @@ spring.jpa.hibernate.ddl-auto=update spring.liquibase.enabled=true application.rancher.rest.url=${RANCHER_REST_URL:http://localhost:8082} -application.handyman.rest.url=${HANDYMAN_REST_URL:http://localhost:8080} \ No newline at end of file +application.handyman.rest.url=${HANDYMAN_REST_URL:http://localhost:8080} + +spring.kafka.bootstrap-servers=${SPRING_KAFKA_BOOTSTRAP-SERVERS} + +spring.kafka.consumer.group-id=${SPRING_KAFKA_CONSUMER_GROUP-ID} +spring.kafka.consumer.auto-offset-reset=earliest +spring.kafka.consumer.enable-auto-commit=true +spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer +spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer +spring.kafka.consumer.properties.spring.json.trusted.packages=* + +spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer +spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer diff --git a/rancher-service/build.gradle b/rancher-service/build.gradle index 1e8585f..65cde2b 100644 --- a/rancher-service/build.gradle +++ b/rancher-service/build.gradle @@ -66,6 +66,7 @@ jar { } dependencies { + implementation 'org.springframework.kafka:spring-kafka' implementation 'org.hibernate:hibernate-spatial' implementation 'org.n52.jackson:jackson-datatype-jts:1.2.10' implementation 'org.locationtech.jts:jts-io:1.18.2' diff --git a/rancher-service/src/main/java/dev/archie/landscapeservice/order/dto/SendOrderToUser.java b/rancher-service/src/main/java/dev/archie/landscapeservice/order/dto/SendOrderToUser.java new file mode 100644 index 0000000..6a05575 --- /dev/null +++ b/rancher-service/src/main/java/dev/archie/landscapeservice/order/dto/SendOrderToUser.java @@ -0,0 +1,11 @@ +package dev.archie.landscapeservice.order.dto; + + +import dev.archie.rancherservice.landscape.User; +import dev.archie.rancherservice.landscape.dto.OrderDto; + +public record SendOrderToUser( + User handyman, + OrderDto order +) { +} diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/landscape/User.java b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/User.java index 9437cce..d70ba03 100644 --- a/rancher-service/src/main/java/dev/archie/rancherservice/landscape/User.java +++ b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/User.java @@ -1,12 +1,16 @@ package dev.archie.rancherservice.landscape; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import java.time.LocalDateTime; import java.util.UUID; @Data +@NoArgsConstructor +@AllArgsConstructor @Builder public class User { diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/OrderDto.java b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/OrderDto.java index 78f7d4e..e6e701e 100644 --- a/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/OrderDto.java +++ b/rancher-service/src/main/java/dev/archie/rancherservice/landscape/dto/OrderDto.java @@ -22,4 +22,6 @@ public class OrderDto { private User user; private List skills; + + private int grade; } diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerController.java b/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerController.java index 4763c03..8b89348 100644 --- a/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerController.java +++ b/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerController.java @@ -1,8 +1,9 @@ package dev.archie.rancherservice.rancher; -import dev.archie.rancherservice.landscape.dto.OrderDto; +import dev.archie.landscapeservice.order.dto.SendOrderToUser; import dev.archie.rancherservice.rancher.dto.CreatingGardenerDto; import lombok.RequiredArgsConstructor; +import org.springframework.kafka.annotation.KafkaListener; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -55,13 +56,13 @@ public void delete(@PathVariable String id) { gardenerService.delete(id); } - @PostMapping("/notify/missingWorkers") - public void notifyAboutMissingWorkers(@RequestBody OrderDto orderDto) { - gardenerService.notifyAboutMissingWorkers(orderDto); + @KafkaListener(topics = "rancher.notify.missing-workers") + public void notifyAboutMissingWorkers(SendOrderToUser sendOrderToUser) { + gardenerService.notifyAboutMissingWorkers(sendOrderToUser.order()); } - @PostMapping("/notify/orderUpdate") - public void notifyAboutOrderUpdate(@RequestBody OrderDto orderDto) { - gardenerService.notifyAboutOrderUpdate(orderDto); + @KafkaListener(topics = "rancher.notify.order-updated") + public void notifyAboutOrderUpdate(SendOrderToUser sendOrderToUser) { + gardenerService.notifyAboutOrderUpdate(sendOrderToUser.order()); } } diff --git a/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerService.java b/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerService.java index 25453c3..9ead4a6 100644 --- a/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerService.java +++ b/rancher-service/src/main/java/dev/archie/rancherservice/rancher/GardenerService.java @@ -1,10 +1,10 @@ package dev.archie.rancherservice.rancher; +import dev.archie.landscapeservice.order.dto.SendOrderToUser; import dev.archie.rancherservice.landscape.GardenerClient; import dev.archie.rancherservice.landscape.dto.CreatingOrderDto; import dev.archie.rancherservice.landscape.dto.GardenerDto; import dev.archie.rancherservice.landscape.dto.OrderDto; -import dev.archie.rancherservice.landscape.dto.SkillDto; import dev.archie.rancherservice.landscape.dto.WorkStatus; import dev.archie.rancherservice.landscape.dto.WorkType; import dev.archie.rancherservice.order.OrderService; @@ -12,6 +12,7 @@ import dev.archie.rancherservice.rancher.exception.NoSuchUserException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Service; import java.util.List; @@ -26,6 +27,7 @@ public class GardenerService { private final GardenerRepository gardenerRepository; private final GardenerClient gardenerClient; private final OrderService orderService; + private final KafkaTemplate kafkaTemplate; /** * @param creatingGardenerDto rancher to create @@ -48,7 +50,7 @@ public Gardener getById(String id) { } /** - * @param id of existing rancher + * @param id of existing rancher * @param creatingGardenerDto new fields. New email should not exist * @return updated profile */ @@ -64,7 +66,7 @@ public Gardener update(String id, CreatingGardenerDto creatingGardenerDto) { * @param id of existing user */ public void delete(String id) { - Gardener gardener= getById(id); + Gardener gardener = getById(id); gardenerClient.delete(gardener.getInnerId()); gardenerRepository.delete(gardener); } @@ -99,17 +101,9 @@ public void notifyAboutOrderUpdate(OrderDto orderDto) { } public void evaluateTheOrder(OrderDto orderDto) { - log.info("По данному запросу копателей не нашлось. Измените объем работ."); - // по-хорошему тут нужно держать соединение с клиентом, но представим, что мы его уведомили + log.info("Оцениваем работу"); Random random = new Random(); - CreatingOrderDto updatingOrderDto = CreatingOrderDto.builder() - .status(orderDto.getStatus()) - .userId(orderDto.getUser().getId()) - .fieldId(orderDto.getField().getId()) - .skills(orderDto.getSkills().stream().map(SkillDto::getName).toList()) - .workType(orderDto.getWorkType()) - .grade(random.nextInt(10)) - .build(); - orderService.update(updatingOrderDto, orderDto.getId()); + orderDto.setGrade(random.nextInt(10)); + kafkaTemplate.send("landscape.order.rated", new SendOrderToUser(null, orderDto)); } } diff --git a/rancher-service/src/main/resources/application.properties b/rancher-service/src/main/resources/application.properties index c16354f..fcf0078 100644 --- a/rancher-service/src/main/resources/application.properties +++ b/rancher-service/src/main/resources/application.properties @@ -15,3 +15,15 @@ spring.datasource.username=${PG_DB_USERNAME} spring.datasource.password=${PG_DB_PASSWORD} application.landscape.rest.url=${LANDSCAPE_REST_URL} + +spring.kafka.bootstrap-servers=${SPRING_KAFKA_BOOTSTRAP-SERVERS} + +spring.kafka.consumer.group-id=${SPRING_KAFKA_CONSUMER_GROUP-ID} +spring.kafka.consumer.auto-offset-reset=earliest +spring.kafka.consumer.enable-auto-commit=true +spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer +spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer +spring.kafka.consumer.properties.spring.json.trusted.packages=* + +spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer +spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer From 75adea94382405391a55243639ef2364bfa5bd46 Mon Sep 17 00:00:00 2001 From: Dmitry Kutuzov Date: Tue, 27 Jun 2023 02:55:27 +0300 Subject: [PATCH 2/2] remove unused --- .../main/java/dev/archie/landscapeservice/field/Field.java | 4 ---- .../main/java/dev/archie/landscapeservice/order/Order.java | 2 -- .../java/dev/archie/landscapeservice/order/OrderResolver.java | 2 -- .../java/dev/archie/landscapeservice/order/OrderService.java | 1 - .../src/main/java/dev/archie/landscapeservice/user/User.java | 1 - 5 files changed, 10 deletions(-) diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/field/Field.java b/landscape-service/src/main/java/dev/archie/landscapeservice/field/Field.java index 9344df5..d386cd9 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/field/Field.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/field/Field.java @@ -2,8 +2,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import dev.archie.landscapeservice.gardener.Gardener; import lombok.AllArgsConstructor; import lombok.Builder; @@ -11,8 +9,6 @@ import lombok.NoArgsConstructor; import lombok.Setter; import org.locationtech.jts.geom.Geometry; -import org.n52.jackson.datatype.jts.GeometryDeserializer; -import org.n52.jackson.datatype.jts.GeometrySerializer; import javax.persistence.Column; import javax.persistence.Entity; diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/Order.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/Order.java index 399a4f8..cf1756b 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/Order.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/Order.java @@ -10,7 +10,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.hibernate.annotations.Fetch; import javax.persistence.Column; import javax.persistence.Entity; @@ -26,7 +25,6 @@ import javax.persistence.OneToOne; import javax.persistence.Table; import java.time.LocalDateTime; -import java.util.LinkedHashSet; import java.util.Set; @Builder diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java index de40238..9a8415c 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderResolver.java @@ -2,7 +2,6 @@ import dev.archie.landscapeservice.account.skill.Skill; import dev.archie.landscapeservice.field.Field; -import dev.archie.landscapeservice.gardener.GardenerClient; import dev.archie.landscapeservice.handyman.Handyman; import dev.archie.landscapeservice.handyman.HandymanRepository; import dev.archie.landscapeservice.order.dto.CreatingOrderDto; @@ -22,7 +21,6 @@ @RequiredArgsConstructor @Slf4j public class OrderResolver { - private final OrderRepository orderRepository; private final HandymanRepository handymanRepository; private final KafkaTemplate kafkaTemplate; diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java index d248d5d..b275c93 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/order/OrderService.java @@ -4,7 +4,6 @@ import dev.archie.landscapeservice.account.skill.SkillRepository; import dev.archie.landscapeservice.field.Field; import dev.archie.landscapeservice.field.FieldService; -import dev.archie.landscapeservice.gardener.GardenerClient; import dev.archie.landscapeservice.order.dto.CreatingOrderDto; import dev.archie.landscapeservice.order.dto.SendOrderToUser; import dev.archie.landscapeservice.order.exception.DirectionIsNotSpecifiedException; diff --git a/landscape-service/src/main/java/dev/archie/landscapeservice/user/User.java b/landscape-service/src/main/java/dev/archie/landscapeservice/user/User.java index 4cbfc40..820a133 100644 --- a/landscape-service/src/main/java/dev/archie/landscapeservice/user/User.java +++ b/landscape-service/src/main/java/dev/archie/landscapeservice/user/User.java @@ -22,7 +22,6 @@ import javax.persistence.OneToMany; import javax.persistence.Table; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.UUID;