From 8cd58228dd7617377a69e46352cf4e2c305d9693 Mon Sep 17 00:00:00 2001 From: ScarletRedMan Date: Sun, 26 Nov 2023 21:00:45 +0700 Subject: [PATCH] Implemented node backend connection --- .../loadbalancer/web/component/NodeList.java | 7 +- .../loadbalancer/web/model/Node.java | 4 +- .../loadbalancer/web/page/BucketsPage.java | 4 +- .../web/page/NodeDetailsPage.java | 27 ++++++-- .../loadbalancer/web/page/NodesPage.java | 31 +++++++-- .../web/repository/NodeRepository.java | 17 +++++ .../repository/impl/NodeRepositoryImpl.java | 67 +++++++++++++++++++ .../impl/response/NodeDetailsResponse.java | 5 ++ .../impl/response/NodeListResponse.java | 7 ++ .../impl/response/NodeRegisterResponse.java | 3 + 10 files changed, 158 insertions(+), 14 deletions(-) create mode 100644 LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/NodeRepository.java create mode 100644 LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/NodeRepositoryImpl.java create mode 100644 LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/NodeDetailsResponse.java create mode 100644 LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/NodeListResponse.java create mode 100644 LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/NodeRegisterResponse.java diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/component/NodeList.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/component/NodeList.java index 999fda0..f4b56b4 100644 --- a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/component/NodeList.java +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/component/NodeList.java @@ -13,15 +13,18 @@ import com.vaadin.flow.component.notification.NotificationVariant; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.textfield.TextField; +import lombok.Setter; import ru.dragonestia.loadbalancer.web.model.Node; import java.util.List; +import java.util.function.Consumer; public class NodeList extends VerticalLayout { private final Grid nodesGrid; private final TextField searchField; private List cachedNodes; + @Setter private Consumer removeMethod; public NodeList(List nodes) { super(); @@ -125,6 +128,8 @@ public class NodeList extends VerticalLayout { } private void removeNode(Node node) { - // TODO: send remove request and getting nodes list + if (removeMethod != null) { + removeMethod.accept(node.identifier()); + } } } diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/model/Node.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/model/Node.java index 9de58a9..bae7df9 100644 --- a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/model/Node.java +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/model/Node.java @@ -3,7 +3,9 @@ package ru.dragonestia.loadbalancer.web.model; import lombok.NonNull; import ru.dragonestia.loadbalancer.web.model.type.LoadBalancingMethod; -public record Node(@NonNull String identifier, @NonNull LoadBalancingMethod method) { +import java.io.Serializable; + +public record Node(@NonNull String identifier, @NonNull LoadBalancingMethod method) implements Serializable { @Override public int hashCode() { diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/BucketsPage.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/BucketsPage.java index 9d55159..f34b26c 100644 --- a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/BucketsPage.java +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/BucketsPage.java @@ -7,6 +7,7 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.BeforeEnterEvent; import com.vaadin.flow.router.BeforeEnterObserver; import com.vaadin.flow.router.Route; +import ru.dragonestia.loadbalancer.web.component.AddUsers; import ru.dragonestia.loadbalancer.web.component.NavPath; import ru.dragonestia.loadbalancer.web.model.Bucket; import ru.dragonestia.loadbalancer.web.model.Node; @@ -17,6 +18,7 @@ import ru.dragonestia.loadbalancer.web.model.type.SlotLimit; public class BucketsPage extends VerticalLayout implements BeforeEnterObserver { private Bucket bucket; + private AddUsers addUsers; @Override public void beforeEnter(BeforeEnterEvent event) { @@ -40,7 +42,7 @@ public class BucketsPage extends VerticalLayout implements BeforeEnterObserver { add(new H2("Bucket details")); printBucketDetails(); add(new Hr()); - add(new H2("Add users")); + add(addUsers = new AddUsers(bucket)); add(new Hr()); add(new H2("Users")); } diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/NodeDetailsPage.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/NodeDetailsPage.java index 74f0271..2478da3 100644 --- a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/NodeDetailsPage.java +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/NodeDetailsPage.java @@ -3,12 +3,16 @@ package ru.dragonestia.loadbalancer.web.page; import com.vaadin.flow.component.Html; import com.vaadin.flow.component.html.H2; import com.vaadin.flow.component.html.Hr; +import com.vaadin.flow.component.html.Paragraph; +import com.vaadin.flow.component.notification.Notification; +import com.vaadin.flow.component.notification.NotificationVariant; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.BeforeEnterEvent; import com.vaadin.flow.router.BeforeEnterObserver; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import lombok.Getter; +import org.springframework.beans.factory.annotation.Autowired; import ru.dragonestia.loadbalancer.web.component.BucketList; import ru.dragonestia.loadbalancer.web.component.NavPath; import ru.dragonestia.loadbalancer.web.component.RegisterBucket; @@ -16,6 +20,7 @@ import ru.dragonestia.loadbalancer.web.model.Bucket; import ru.dragonestia.loadbalancer.web.model.Node; import ru.dragonestia.loadbalancer.web.model.type.LoadBalancingMethod; import ru.dragonestia.loadbalancer.web.model.type.SlotLimit; +import ru.dragonestia.loadbalancer.web.repository.NodeRepository; import java.util.List; @@ -24,10 +29,15 @@ import java.util.List; @Route("/nodes/:nodeId") public class NodeDetailsPage extends VerticalLayout implements BeforeEnterObserver { + private final NodeRepository nodeRepository; private Node node; private RegisterBucket registerBucket; private BucketList bucketList; + public NodeDetailsPage(@Autowired NodeRepository nodeRepository) { + this.nodeRepository = nodeRepository; + } + @Override public void beforeEnter(BeforeEnterEvent event) { var nodeIdOpt = event.getRouteParameters().get("nodeId"); @@ -35,7 +45,19 @@ public class NodeDetailsPage extends VerticalLayout implements BeforeEnterObserv getUI().ifPresent(ui -> ui.navigate("/nodes")); return; } - node = new Node(nodeIdOpt.get(), LoadBalancingMethod.ROUND_ROBIN); // TODO: getting node + var nodeId = nodeIdOpt.get(); + add(new NavPath(new NavPath.Point("Nodes", "/nodes"), new NavPath.Point(nodeId, "/nodes/" + nodeId))); + + var nodeOpt = nodeRepository.findNode(nodeId); + if (nodeOpt.isEmpty()) { + add(new H2("Error 404")); + add(new Paragraph("Node not found")); + Notification.show("Node '" + nodeId + "' does not exist", 3000, Notification.Position.TOP_END) + .addThemeVariants(NotificationVariant.LUMO_ERROR); + return; + } + + node = nodeOpt.get(); // TODO: getting node // TODO: getting buckets initComponents(node, List.of( @@ -47,9 +69,6 @@ public class NodeDetailsPage extends VerticalLayout implements BeforeEnterObserv } private void initComponents(Node node, List buckets) { - add(new NavPath(new NavPath.Point("Nodes", "/nodes"), - new NavPath.Point(node.identifier(), "/nodes/" + node.identifier()))); - printNodeDetails(node); add(new Hr()); add(registerBucket = new RegisterBucket(node, (bucket) -> { diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/NodesPage.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/NodesPage.java index 7012cd8..fd3a64e 100644 --- a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/NodesPage.java +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/NodesPage.java @@ -5,38 +5,55 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import lombok.Getter; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.client.RestTemplate; import ru.dragonestia.loadbalancer.web.component.NavPath; import ru.dragonestia.loadbalancer.web.component.NodeList; import ru.dragonestia.loadbalancer.web.component.RegisterNode; +import ru.dragonestia.loadbalancer.web.repository.NodeRepository; -import java.util.List; - +@Log4j2 @Getter @PageTitle("Nodes") @Route("/nodes") public class NodesPage extends VerticalLayout { + private final NodeRepository nodeRepository; private final RegisterNode registerNode; private final NodeList nodeList; - public NodesPage() { + public NodesPage(@Autowired NodeRepository nodeRepository) { super(); + this.nodeRepository = nodeRepository; add(new NavPath(new NavPath.Point("Nodes", "/nodes"))); add(registerNode = createRegisterNodeElement()); add(new Hr()); add(nodeList = createNodeListElement()); + nodeList.setRemoveMethod(nodeIdentifier -> { + nodeRepository.removeNode(nodeIdentifier); + nodeList.update(nodeRepository.getNodes()); + }); } protected RegisterNode createRegisterNodeElement() { return new RegisterNode(node -> { - nodeList.update(List.of(node)); // remove it later - return new RegisterNode.Response(false, "Some error"); // TODO + try { + nodeRepository.registerNode(node); + return new RegisterNode.Response(false, ""); + } catch (Error ex) { + return new RegisterNode.Response(true, ex.getMessage()); + } catch (RuntimeException ex) { + log.throwing(ex); + return new RegisterNode.Response(true, ex.getMessage()); + } finally { + nodeList.update(nodeRepository.getNodes()); + } }); } protected NodeList createNodeListElement() { - // TODO: getting nodes list - return new NodeList(List.of()); + return new NodeList(nodeRepository.getNodes()); } } diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/NodeRepository.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/NodeRepository.java new file mode 100644 index 0000000..6b45f7c --- /dev/null +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/NodeRepository.java @@ -0,0 +1,17 @@ +package ru.dragonestia.loadbalancer.web.repository; + +import ru.dragonestia.loadbalancer.web.model.Node; + +import java.util.List; +import java.util.Optional; + +public interface NodeRepository { + + void registerNode(Node node); + + List getNodes(); + + Optional findNode(String identifier); + + void removeNode(String identifier); +} diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/NodeRepositoryImpl.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/NodeRepositoryImpl.java new file mode 100644 index 0000000..d733a89 --- /dev/null +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/NodeRepositoryImpl.java @@ -0,0 +1,67 @@ +package ru.dragonestia.loadbalancer.web.repository.impl; + +import com.vaadin.flow.spring.annotation.SpringComponent; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; +import ru.dragonestia.loadbalancer.web.model.Node; +import ru.dragonestia.loadbalancer.web.repository.NodeRepository; +import ru.dragonestia.loadbalancer.web.repository.impl.response.NodeDetailsResponse; +import ru.dragonestia.loadbalancer.web.repository.impl.response.NodeListResponse; +import ru.dragonestia.loadbalancer.web.repository.impl.response.NodeRegisterResponse; + +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Supplier; + +@Log4j2 +@RequiredArgsConstructor +@SpringComponent +public class NodeRepositoryImpl implements NodeRepository { + + private final RestUtil rest; + + @Override + public void registerNode(Node node) { + NodeRegisterResponse response; + try { + response = rest.post(URI.create("nodes"), + NodeRegisterResponse.class, + params -> { + params.put("identifier", node.identifier()); + params.put("method", node.method().name()); + }); + } catch (Exception ex) { + throw new RuntimeException("Internal error", ex); + } + + if (!response.success()) { + throw new Error(response.message()); + } + } + + @Override + public List getNodes() { + return rest.get(URI.create("nodes"), NodeListResponse.class).nodes(); + } + + @Override + public Optional findNode(String identifier) { + try { + var response = rest.get(URI.create("nodes/" + identifier), NodeDetailsResponse.class); + return Optional.of(response.node()); + } catch (Exception ex) { + return Optional.empty(); + } + } + + @Override + public void removeNode(String identifier) { + rest.delete(URI.create("nodes/" + identifier), params -> {}); + } +} diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/NodeDetailsResponse.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/NodeDetailsResponse.java new file mode 100644 index 0000000..6311274 --- /dev/null +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/NodeDetailsResponse.java @@ -0,0 +1,5 @@ +package ru.dragonestia.loadbalancer.web.repository.impl.response; + +import ru.dragonestia.loadbalancer.web.model.Node; + +public record NodeDetailsResponse(Node node) {} diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/NodeListResponse.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/NodeListResponse.java new file mode 100644 index 0000000..adcff14 --- /dev/null +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/NodeListResponse.java @@ -0,0 +1,7 @@ +package ru.dragonestia.loadbalancer.web.repository.impl.response; + +import ru.dragonestia.loadbalancer.web.model.Node; + +import java.util.List; + +public record NodeListResponse(List nodes) {} diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/NodeRegisterResponse.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/NodeRegisterResponse.java new file mode 100644 index 0000000..ae6bfe4 --- /dev/null +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/NodeRegisterResponse.java @@ -0,0 +1,3 @@ +package ru.dragonestia.loadbalancer.web.repository.impl.response; + +public record NodeRegisterResponse(boolean success, String message) {}