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 710f281..0ea283e 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 @@ -1,44 +1,84 @@ package ru.dragonestia.loadbalancer.web.page; import com.vaadin.flow.component.Html; +import com.vaadin.flow.component.Unit; 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.component.textfield.TextArea; import com.vaadin.flow.router.BeforeEnterEvent; import com.vaadin.flow.router.BeforeEnterObserver; import com.vaadin.flow.router.Route; +import org.springframework.beans.factory.annotation.Autowired; 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; -import ru.dragonestia.loadbalancer.web.model.type.LoadBalancingMethod; -import ru.dragonestia.loadbalancer.web.model.type.SlotLimit; +import ru.dragonestia.loadbalancer.web.repository.BucketRepository; +import ru.dragonestia.loadbalancer.web.repository.NodeRepository; @Route("/nodes/:nodeId/buckets/:bucketId") public class BucketsPage extends VerticalLayout implements BeforeEnterObserver { + private final NodeRepository nodeRepository; + private final BucketRepository bucketRepository; + private Node node; private Bucket bucket; private AddUsers addUsers; + @Autowired + public BucketsPage(NodeRepository nodeRepository, BucketRepository bucketRepository) { + this.nodeRepository = nodeRepository; + this.bucketRepository = bucketRepository; + } + @Override public void beforeEnter(BeforeEnterEvent event) { var nodeIdOpt = event.getRouteParameters().get("nodeId"); - var bucketIdOpt = event.getRouteParameters().get("bucketId"); - - if (nodeIdOpt.isEmpty() || bucketIdOpt.isEmpty()) { + if (nodeIdOpt.isEmpty()) { getUI().ifPresent(ui -> ui.navigate("/nodes")); return; } - // TODO: getting bucket - bucket = Bucket.create(bucketIdOpt.get(), new Node(nodeIdOpt.get(), LoadBalancingMethod.ROUND_ROBIN), SlotLimit.unlimited(), ""); + + var bucketIdOpt = event.getRouteParameters().get("bucketId"); + if (bucketIdOpt.isEmpty()) { + getUI().ifPresent(ui -> ui.navigate("/buckets/" + nodeIdOpt.get())); + return; + } + + var nodeId = nodeIdOpt.get(); + var bucketId = bucketIdOpt.get(); + add(new NavPath(new NavPath.Point("Nodes", "/nodes"), + new NavPath.Point(nodeId, "/nodes/" + nodeId), + new NavPath.Point(bucketId, "/nodes/" + nodeId + "/buckets/" + bucketId))); + + 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(); + + var bucketOpt = bucketRepository.find(node, bucketId); + if (bucketOpt.isEmpty()) { + add(new H2("Error 404")); + add(new Paragraph("Bucket not found!")); + Notification.show("Bucket '" + nodeId + "' does not exist", 3000, Notification.Position.TOP_END) + .addThemeVariants(NotificationVariant.LUMO_ERROR); + return; + } + bucket = bucketOpt.get(); init(); } private void init() { - add(new NavPath(new NavPath.Point("Nodes", "/nodes"), - new NavPath.Point(bucket.getNodeIdentifier(), "/nodes/" + bucket.getNodeIdentifier()), - new NavPath.Point(bucket.getIdentifier(), "/nodes/" + bucket.getNodeIdentifier() + "/buckets/" + bucket.getIdentifier()))); add(new H2("Bucket details")); printBucketDetails(); add(new Hr()); @@ -51,5 +91,12 @@ public class BucketsPage extends VerticalLayout implements BeforeEnterObserver { add(new Html("Node identifier: " + bucket.getNodeIdentifier() + "")); add(new Html("Bucket identifier: " + bucket.getIdentifier() + "")); add(new Html("Slots: " + (bucket.getSlots().isUnlimited()? "Unlimited" : bucket.getSlots().slots()) + "")); + add(new Html("Locked: " + (bucket.isLocked()? "Yes" : "No") + "")); + + var payload = new TextArea("Payload(" + bucket.getPayload().length() + ")"); + payload.setValue(bucket.getPayload()); + payload.setReadOnly(true); + payload.setMinWidth(50, Unit.REM); + add(payload); } } diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/BucketRepository.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/BucketRepository.java index 806887e..2465102 100644 --- a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/BucketRepository.java +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/BucketRepository.java @@ -4,6 +4,7 @@ import ru.dragonestia.loadbalancer.web.model.Bucket; import ru.dragonestia.loadbalancer.web.model.Node; import java.util.List; +import java.util.Optional; public interface BucketRepository { @@ -12,4 +13,6 @@ public interface BucketRepository { void register(Bucket bucket); void remove(Bucket bucket); + + Optional find(Node node, String identifier); } diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/BucketRepositoryImpl.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/BucketRepositoryImpl.java index d5f2970..d42cdf1 100644 --- a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/BucketRepositoryImpl.java +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/BucketRepositoryImpl.java @@ -7,12 +7,14 @@ import org.springframework.web.client.HttpClientErrorException; import ru.dragonestia.loadbalancer.web.model.Bucket; import ru.dragonestia.loadbalancer.web.model.Node; import ru.dragonestia.loadbalancer.web.repository.BucketRepository; +import ru.dragonestia.loadbalancer.web.repository.impl.response.BucketInfoResponse; import ru.dragonestia.loadbalancer.web.repository.impl.response.BucketListResponse; import ru.dragonestia.loadbalancer.web.repository.impl.response.BucketRegisterResponse; import java.net.URI; import java.util.List; import java.util.Objects; +import java.util.Optional; @Log4j2 @RequiredArgsConstructor @@ -67,4 +69,14 @@ public class BucketRepositoryImpl implements BucketRepository { public void remove(Bucket bucket) { rest.delete(URI.create("/nodes/" + bucket.getNodeIdentifier() + "/buckets/" + bucket.getIdentifier()), params -> {}); } + + @Override + public Optional find(Node node, String identifier) { + try { + var response = rest.get(URI.create("/nodes/" + node.identifier() + "/buckets/" + identifier), BucketInfoResponse.class, map -> {}); + return Optional.of(response.bucket()); + } catch (Exception ex) { + return Optional.empty(); + } + } } diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/BucketInfoResponse.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/BucketInfoResponse.java new file mode 100644 index 0000000..628f191 --- /dev/null +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/repository/impl/response/BucketInfoResponse.java @@ -0,0 +1,5 @@ +package ru.dragonestia.loadbalancer.web.repository.impl.response; + +import ru.dragonestia.loadbalancer.web.model.Bucket; + +public record BucketInfoResponse(Bucket bucket) {} diff --git a/src/main/java/ru/dragonestia/loadbalancer/controller/BucketController.java b/src/main/java/ru/dragonestia/loadbalancer/controller/BucketController.java index 4984620..539b84c 100644 --- a/src/main/java/ru/dragonestia/loadbalancer/controller/BucketController.java +++ b/src/main/java/ru/dragonestia/loadbalancer/controller/BucketController.java @@ -4,6 +4,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import ru.dragonestia.loadbalancer.controller.response.BucketInfoResponse; import ru.dragonestia.loadbalancer.controller.response.BucketListResponse; import ru.dragonestia.loadbalancer.controller.response.BucketRegisterResponse; import ru.dragonestia.loadbalancer.controller.response.NodeRegisterResponse; @@ -13,6 +14,8 @@ import ru.dragonestia.loadbalancer.service.BucketService; import ru.dragonestia.loadbalancer.service.NodeService; import ru.dragonestia.loadbalancer.util.NamingValidator; +import java.util.Objects; + @Log4j2 @RestController @RequestMapping("/nodes/{nodeIdentifier}/buckets") @@ -69,4 +72,21 @@ public class BucketController { return ResponseEntity.ok().build(); } + + @GetMapping("/{identifier}") + ResponseEntity info(@PathVariable("nodeIdentifier") String nodeId, + @PathVariable("identifier") String bucketId) { + if (!NamingValidator.validateNodeIdentifier(nodeId) || !NamingValidator.validateBucketIdentifier(bucketId)) { + return ResponseEntity.ok().build(); + } + + var nodeOpt = nodeService.findNode(nodeId); + if (nodeOpt.isEmpty()) { + return ResponseEntity.notFound().build(); + } + + var bucketOpt = bucketService.findBucket(Objects.requireNonNull(nodeOpt.get()), bucketId); + return bucketOpt.map(bucket -> ResponseEntity.ok(new BucketInfoResponse(bucket))) + .orElseGet(() -> ResponseEntity.notFound().build()); + } } diff --git a/src/main/java/ru/dragonestia/loadbalancer/controller/response/BucketInfoResponse.java b/src/main/java/ru/dragonestia/loadbalancer/controller/response/BucketInfoResponse.java new file mode 100644 index 0000000..05e343c --- /dev/null +++ b/src/main/java/ru/dragonestia/loadbalancer/controller/response/BucketInfoResponse.java @@ -0,0 +1,5 @@ +package ru.dragonestia.loadbalancer.controller.response; + +import ru.dragonestia.loadbalancer.model.Bucket; + +public record BucketInfoResponse(Bucket bucket) {}