From 355983b7644237f38368cbb385bbeae4603591d8 Mon Sep 17 00:00:00 2001 From: ScarletRedMan Date: Mon, 4 Dec 2023 10:14:35 +0700 Subject: [PATCH] Added update locked state for buckets --- .../loadbalancer/web/model/Bucket.java | 6 ++ ...ucketsPage.java => BucketDetailsPage.java} | 56 +++++++++++++++++-- .../web/repository/BucketRepository.java | 2 + .../repository/impl/BucketRepositoryImpl.java | 12 ++++ .../controller/BucketController.java | 25 ++++++++- 5 files changed, 94 insertions(+), 7 deletions(-) rename LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/{BucketsPage.java => BucketDetailsPage.java} (61%) diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/model/Bucket.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/model/Bucket.java index fb451c4..d8335fc 100644 --- a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/model/Bucket.java +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/model/Bucket.java @@ -7,6 +7,8 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import ru.dragonestia.loadbalancer.web.model.type.SlotLimit; +import java.net.URI; + @Getter public class Bucket { @@ -57,4 +59,8 @@ public class Bucket { } return false; } + + public URI createApiURI() { + return URI.create("/nodes/" + nodeIdentifier + "/buckets/" + identifier); + } } diff --git a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/BucketsPage.java b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/BucketDetailsPage.java similarity index 61% rename from LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/BucketsPage.java rename to LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/BucketDetailsPage.java index 0ea283e..4c7fc8d 100644 --- a/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/BucketsPage.java +++ b/LoadBalancerWeb/src/main/java/ru/dragonestia/loadbalancer/web/page/BucketDetailsPage.java @@ -2,9 +2,13 @@ package ru.dragonestia.loadbalancer.web.page; import com.vaadin.flow.component.Html; import com.vaadin.flow.component.Unit; +import com.vaadin.flow.component.button.Button; +import com.vaadin.flow.component.html.Div; 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.icon.Icon; +import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.component.notification.NotificationVariant; import com.vaadin.flow.component.orderedlayout.VerticalLayout; @@ -21,16 +25,18 @@ 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 { +public class BucketDetailsPage extends VerticalLayout implements BeforeEnterObserver { private final NodeRepository nodeRepository; private final BucketRepository bucketRepository; private Node node; private Bucket bucket; private AddUsers addUsers; + private Button lockBucketButton; + private VerticalLayout bucketInfo; @Autowired - public BucketsPage(NodeRepository nodeRepository, BucketRepository bucketRepository) { + public BucketDetailsPage(NodeRepository nodeRepository, BucketRepository bucketRepository) { this.nodeRepository = nodeRepository; this.bucketRepository = bucketRepository; } @@ -87,11 +93,21 @@ public class BucketsPage extends VerticalLayout implements BeforeEnterObserver { add(new H2("Users")); } + private void updateBucketInfo() { + bucketInfo.removeAll(); + bucketInfo.add(new Html("Node identifier: " + bucket.getNodeIdentifier() + "")); + bucketInfo.add(new Html("Bucket identifier: " + bucket.getIdentifier() + "")); + bucketInfo.add(new Html("Slots: " + (bucket.getSlots().isUnlimited()? "Unlimited" : bucket.getSlots().slots()) + "")); + bucketInfo.add(new Html("Locked: " + (bucket.isLocked()? "Yes" : "No") + "")); + } + private void printBucketDetails() { - 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") + "")); + add(bucketInfo = new VerticalLayout()); + bucketInfo.setPadding(false); + + updateBucketInfo(); + add(lockBucketButton = new Button("", event -> changeBucketLockedState())); + setLockBucketButtonState(); var payload = new TextArea("Payload(" + bucket.getPayload().length() + ")"); payload.setValue(bucket.getPayload()); @@ -99,4 +115,32 @@ public class BucketsPage extends VerticalLayout implements BeforeEnterObserver { payload.setMinWidth(50, Unit.REM); add(payload); } + + private void setLockBucketButtonState() { + if (bucket.isLocked()) { + lockBucketButton.setText("Unlock"); + lockBucketButton.setPrefixComponent(new Icon(VaadinIcon.UNLOCK)); + } else { + lockBucketButton.setText("Lock"); + lockBucketButton.setPrefixComponent(new Icon(VaadinIcon.LOCK)); + } + } + + private void changeBucketLockedState() { + var newValue = !bucket.isLocked(); + try { + bucketRepository.lock(bucket, newValue); + } catch (Error error) { + Notification.show(error.getMessage(), 3000, Notification.Position.TOP_END) + .addThemeVariants(NotificationVariant.LUMO_ERROR); + return; + } + + bucket.setLocked(newValue); + setLockBucketButtonState(); + updateBucketInfo(); + + Notification.show("Success", 3000, Notification.Position.TOP_END) + .addThemeVariants(NotificationVariant.LUMO_SUCCESS); + } } 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 2465102..b75430d 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 @@ -15,4 +15,6 @@ public interface BucketRepository { void remove(Bucket bucket); Optional find(Node node, String identifier); + + void lock(Bucket bucket, boolean value); } 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 d42cdf1..e9894c0 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 @@ -79,4 +79,16 @@ public class BucketRepositoryImpl implements BucketRepository { return Optional.empty(); } } + + @Override + public void lock(Bucket bucket, boolean value) { + try { + rest.post(URI.create(bucket.createApiURI() + "/lock"), Boolean.class, params -> { + params.put("state", Boolean.toString(value)); + }); + } catch (Exception ex) { + log.throwing(ex); + throw new Error("Error when changing bucket locked state"); + } + } } diff --git a/src/main/java/ru/dragonestia/loadbalancer/controller/BucketController.java b/src/main/java/ru/dragonestia/loadbalancer/controller/BucketController.java index 539b84c..8fb405c 100644 --- a/src/main/java/ru/dragonestia/loadbalancer/controller/BucketController.java +++ b/src/main/java/ru/dragonestia/loadbalancer/controller/BucketController.java @@ -7,7 +7,6 @@ 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; import ru.dragonestia.loadbalancer.model.Bucket; import ru.dragonestia.loadbalancer.model.type.SlotLimit; import ru.dragonestia.loadbalancer.service.BucketService; @@ -89,4 +88,28 @@ public class BucketController { return bucketOpt.map(bucket -> ResponseEntity.ok(new BucketInfoResponse(bucket))) .orElseGet(() -> ResponseEntity.notFound().build()); } + + @PostMapping("/{identifier}/lock") + ResponseEntity lockBucket(@PathVariable("nodeIdentifier") String nodeId, + @PathVariable("identifier") String bucketId, + @RequestParam(name = "state") boolean value) { + + if (!NamingValidator.validateNodeIdentifier(nodeId) || !NamingValidator.validateBucketIdentifier(bucketId)) { + return ResponseEntity.notFound().build(); + } + + var nodeOpt = nodeService.findNode(nodeId); + if (nodeOpt.isEmpty()) { + return ResponseEntity.notFound().build(); + } + + var bucketOpt = bucketService.findBucket(Objects.requireNonNull(nodeOpt.get()), bucketId); + if (bucketOpt.isEmpty()) { + return ResponseEntity.notFound().build(); + } + + var bucket = bucketOpt.get(); + bucket.setLocked(value); + return ResponseEntity.ok(true); + } }