From 3de835cc6f944575001e62a1258a40f7cf26134b Mon Sep 17 00:00:00 2001 From: ScarletRedMan Date: Wed, 27 Dec 2023 22:06:09 +0700 Subject: [PATCH] Renamed Bucket to Room --- README.md | 3 +- .../picker/LoadBalancerApplication.java | 2 - .../dragonestia/picker/config/TestConfig.java | 28 ++-- .../picker/controller/BucketController.java | 117 ---------------- .../picker/controller/NodeController.java | 28 ++-- .../picker/controller/RoomController.java | 117 ++++++++++++++++ .../controller/UserBucketController.java | 111 --------------- .../picker/controller/UserRoomController.java | 111 +++++++++++++++ .../response/BucketInfoResponse.java | 5 - .../response/BucketListResponse.java | 8 -- .../response/BucketRegisterResponse.java | 3 - .../response/LinkUsersWithBucketResponse.java | 3 - .../response/LinkUsersWithRoomResponse.java | 3 + .../controller/response/RoomInfoResponse.java | 5 + .../controller/response/RoomListResponse.java | 8 ++ .../response/RoomRegisterResponse.java | 3 + ...esponse.java => RoomUserListResponse.java} | 2 +- .../ru/dragonestia/picker/model/Node.java | 8 +- .../picker/model/{Bucket.java => Room.java} | 16 +-- .../ru/dragonestia/picker/model/User.java | 6 +- ...dBalancingMethod.java => PickingMode.java} | 2 +- .../picker/repository/BucketRepository.java | 32 ----- .../picker/repository/NodeRepository.java | 6 +- .../picker/repository/RoomRepository.java | 32 +++++ .../picker/repository/UserRepository.java | 12 +- .../repository/impl/BucketRepositoryImpl.java | 131 ------------------ .../repository/impl/NodeRepositoryImpl.java | 22 +-- .../repository/impl/RoomRepositoryImpl.java | 131 ++++++++++++++++++ .../repository/impl/UserRepositoryImpl.java | 52 +++---- .../picker/service/BucketService.java | 27 ---- .../picker/service/NodeService.java | 8 +- .../picker/service/RoomService.java | 27 ++++ .../picker/service/UserService.java | 10 +- .../service/impl/BucketServiceImpl.java | 54 -------- .../picker/service/impl/NodeServiceImpl.java | 18 +-- .../picker/service/impl/RoomServiceImpl.java | 54 ++++++++ .../picker/service/impl/UserServiceImpl.java | 18 +-- .../picker/util/NamingValidator.java | 6 +- .../picker/service/BucketServiceTest.java | 39 ------ .../picker/service/RoomServiceTest.java | 39 ++++++ .../picker/cp/component/AddUsers.java | 12 +- .../picker/cp/component/NodeList.java | 16 +-- .../picker/cp/component/RegisterNode.java | 22 +-- ...{RegisterBucket.java => RegisterRoom.java} | 28 ++-- .../{BucketList.java => RoomList.java} | 64 ++++----- .../picker/cp/component/UserList.java | 14 +- .../ru/dragonestia/picker/cp/model/Node.java | 8 +- .../cp/model/{Bucket.java => Room.java} | 33 ++--- .../ru/dragonestia/picker/cp/model/User.java | 6 +- .../dto/{BucketDTO.java => RoomDTO.java} | 6 +- ...dBalancingMethod.java => PickingMode.java} | 2 +- .../picker/cp/page/NodeDetailsPage.java | 46 +++--- .../dragonestia/picker/cp/page/NodesPage.java | 10 +- ...tDetailsPage.java => RoomDetailsPage.java} | 99 ++++++------- .../cp/repository/BucketRepository.java | 23 --- .../picker/cp/repository/NodeRepository.java | 8 +- .../picker/cp/repository/RoomRepository.java | 23 +++ .../picker/cp/repository/UserRepository.java | 8 +- .../repository/impl/BucketRepositoryImpl.java | 100 ------------- .../repository/impl/NodeRepositoryImpl.java | 16 +-- .../repository/impl/RoomRepositoryImpl.java | 100 +++++++++++++ .../repository/impl/UserRepositoryImpl.java | 14 +- .../impl/response/BucketInfoResponse.java | 5 - .../impl/response/BucketListResponse.java | 7 - .../impl/response/BucketRegisterResponse.java | 3 - .../impl/response/RoomInfoResponse.java | 5 + .../impl/response/RoomListResponse.java | 7 + .../impl/response/RoomRegisterResponse.java | 3 + ...esponse.java => RoomUserListResponse.java} | 2 +- 69 files changed, 999 insertions(+), 998 deletions(-) delete mode 100644 app/src/main/java/ru/dragonestia/picker/controller/BucketController.java create mode 100644 app/src/main/java/ru/dragonestia/picker/controller/RoomController.java delete mode 100644 app/src/main/java/ru/dragonestia/picker/controller/UserBucketController.java create mode 100644 app/src/main/java/ru/dragonestia/picker/controller/UserRoomController.java delete mode 100644 app/src/main/java/ru/dragonestia/picker/controller/response/BucketInfoResponse.java delete mode 100644 app/src/main/java/ru/dragonestia/picker/controller/response/BucketListResponse.java delete mode 100644 app/src/main/java/ru/dragonestia/picker/controller/response/BucketRegisterResponse.java delete mode 100644 app/src/main/java/ru/dragonestia/picker/controller/response/LinkUsersWithBucketResponse.java create mode 100644 app/src/main/java/ru/dragonestia/picker/controller/response/LinkUsersWithRoomResponse.java create mode 100644 app/src/main/java/ru/dragonestia/picker/controller/response/RoomInfoResponse.java create mode 100644 app/src/main/java/ru/dragonestia/picker/controller/response/RoomListResponse.java create mode 100644 app/src/main/java/ru/dragonestia/picker/controller/response/RoomRegisterResponse.java rename app/src/main/java/ru/dragonestia/picker/controller/response/{BucketUserListResponse.java => RoomUserListResponse.java} (58%) rename app/src/main/java/ru/dragonestia/picker/model/{Bucket.java => Room.java} (68%) rename app/src/main/java/ru/dragonestia/picker/model/type/{LoadBalancingMethod.java => PickingMode.java} (75%) delete mode 100644 app/src/main/java/ru/dragonestia/picker/repository/BucketRepository.java create mode 100644 app/src/main/java/ru/dragonestia/picker/repository/RoomRepository.java delete mode 100644 app/src/main/java/ru/dragonestia/picker/repository/impl/BucketRepositoryImpl.java create mode 100644 app/src/main/java/ru/dragonestia/picker/repository/impl/RoomRepositoryImpl.java delete mode 100644 app/src/main/java/ru/dragonestia/picker/service/BucketService.java create mode 100644 app/src/main/java/ru/dragonestia/picker/service/RoomService.java delete mode 100644 app/src/main/java/ru/dragonestia/picker/service/impl/BucketServiceImpl.java create mode 100644 app/src/main/java/ru/dragonestia/picker/service/impl/RoomServiceImpl.java delete mode 100644 app/src/test/java/ru/dragonestia/picker/service/BucketServiceTest.java create mode 100644 app/src/test/java/ru/dragonestia/picker/service/RoomServiceTest.java rename control-panel/src/main/java/ru/dragonestia/picker/cp/component/{RegisterBucket.java => RegisterRoom.java} (81%) rename control-panel/src/main/java/ru/dragonestia/picker/cp/component/{BucketList.java => RoomList.java} (70%) rename control-panel/src/main/java/ru/dragonestia/picker/cp/model/{Bucket.java => Room.java} (58%) rename control-panel/src/main/java/ru/dragonestia/picker/cp/model/dto/{BucketDTO.java => RoomDTO.java} (51%) rename control-panel/src/main/java/ru/dragonestia/picker/cp/model/type/{LoadBalancingMethod.java => PickingMode.java} (89%) rename control-panel/src/main/java/ru/dragonestia/picker/cp/page/{BucketDetailsPage.java => RoomDetailsPage.java} (52%) delete mode 100644 control-panel/src/main/java/ru/dragonestia/picker/cp/repository/BucketRepository.java create mode 100644 control-panel/src/main/java/ru/dragonestia/picker/cp/repository/RoomRepository.java delete mode 100644 control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/BucketRepositoryImpl.java create mode 100644 control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/RoomRepositoryImpl.java delete mode 100644 control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketInfoResponse.java delete mode 100644 control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketListResponse.java delete mode 100644 control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketRegisterResponse.java create mode 100644 control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomInfoResponse.java create mode 100644 control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomListResponse.java create mode 100644 control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomRegisterResponse.java rename control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/{BucketUserListResponse.java => RoomUserListResponse.java} (60%) diff --git a/README.md b/README.md index 62a9255..7c2be2c 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,9 @@ For use api methods from main application you need add http headers with usernam and password (`Room_Picker-Password`). Example: + ```http request -GET http://localhost:8080/nodes/hub/buckets/test-3/users +GET http://localhost:8080/nodes/hub/rooms/test-3/users RoomPicker-User: admin RoomPicker-Password: admin ``` \ No newline at end of file diff --git a/app/src/main/java/ru/dragonestia/picker/LoadBalancerApplication.java b/app/src/main/java/ru/dragonestia/picker/LoadBalancerApplication.java index b4ec39d..67eb0ee 100644 --- a/app/src/main/java/ru/dragonestia/picker/LoadBalancerApplication.java +++ b/app/src/main/java/ru/dragonestia/picker/LoadBalancerApplication.java @@ -6,8 +6,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class LoadBalancerApplication { - public record Test(String text) {} - public static void main(String[] args) { SpringApplication.run(LoadBalancerApplication.class, args); } diff --git a/app/src/main/java/ru/dragonestia/picker/config/TestConfig.java b/app/src/main/java/ru/dragonestia/picker/config/TestConfig.java index cdafbf0..1daf508 100644 --- a/app/src/main/java/ru/dragonestia/picker/config/TestConfig.java +++ b/app/src/main/java/ru/dragonestia/picker/config/TestConfig.java @@ -8,12 +8,12 @@ import org.springframework.lang.NonNull; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import ru.dragonestia.picker.interceptor.DebugInterceptor; -import ru.dragonestia.picker.model.Bucket; +import ru.dragonestia.picker.model.Room; import ru.dragonestia.picker.model.Node; import ru.dragonestia.picker.model.User; -import ru.dragonestia.picker.model.type.LoadBalancingMethod; +import ru.dragonestia.picker.model.type.PickingMode; import ru.dragonestia.picker.model.type.SlotLimit; -import ru.dragonestia.picker.repository.BucketRepository; +import ru.dragonestia.picker.repository.RoomRepository; import ru.dragonestia.picker.repository.NodeRepository; import ru.dragonestia.picker.repository.UserRepository; @@ -27,7 +27,7 @@ import java.util.UUID; public class TestConfig implements WebMvcConfigurer { private final NodeRepository nodeRepository; - private final BucketRepository bucketRepository; + private final RoomRepository roomRepository; private final UserRepository userRepository; private final Random rand = new Random(0); @@ -39,29 +39,29 @@ public class TestConfig implements WebMvcConfigurer { @Bean void createNodes() { - createNodeWithContent(new Node("game-servers", LoadBalancingMethod.ROUND_ROBIN)); - createNodeWithContent(new Node("game-lobbies", LoadBalancingMethod.LEAST_PICKED)); - createNodeWithContent(new Node("hub", LoadBalancingMethod.SEQUENTIAL_FILLING)); + createNodeWithContent(new Node("game-servers", PickingMode.ROUND_ROBIN)); + createNodeWithContent(new Node("game-lobbies", PickingMode.LEAST_PICKED)); + createNodeWithContent(new Node("hub", PickingMode.SEQUENTIAL_FILLING)); } private void createNodeWithContent(Node node) { - nodeRepository.createNode(node); + nodeRepository.create(node); for (int i = 1; i <= 5; i++) { var slots = 5 * i; - var bucket = Bucket.create("test-" + i, node, SlotLimit.of(slots), "Some payload"); - bucketRepository.createBucket(bucket); + var room = Room.create("test-" + i, node, SlotLimit.of(slots), "Some payload"); + roomRepository.create(room); for (int j = 0, n = rand.nextInt(slots + 1); j < n; j++) { var user = new User("test-user-" + rand.nextInt(20)); - userRepository.linkWithBucket(bucket, List.of(user), false); + userRepository.linkWithRoom(room, List.of(user), false); } } for (int i = 0; i < 5; i++) { - var bucket = Bucket.create(randomUUID().toString(), node, SlotLimit.unlimited(), "Some payload"); - bucket.setLocked((i & 1) == 0); - bucketRepository.createBucket(bucket); + var room = Room.create(randomUUID().toString(), node, SlotLimit.unlimited(), "Some payload"); + room.setLocked((i & 1) == 0); + roomRepository.create(room); } } diff --git a/app/src/main/java/ru/dragonestia/picker/controller/BucketController.java b/app/src/main/java/ru/dragonestia/picker/controller/BucketController.java deleted file mode 100644 index 6756fe2..0000000 --- a/app/src/main/java/ru/dragonestia/picker/controller/BucketController.java +++ /dev/null @@ -1,117 +0,0 @@ -package ru.dragonestia.picker.controller; - -import lombok.RequiredArgsConstructor; -import lombok.extern.log4j.Log4j2; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import ru.dragonestia.picker.controller.response.BucketInfoResponse; -import ru.dragonestia.picker.controller.response.BucketListResponse; -import ru.dragonestia.picker.controller.response.BucketRegisterResponse; -import ru.dragonestia.picker.model.Bucket; -import ru.dragonestia.picker.model.type.SlotLimit; -import ru.dragonestia.picker.service.BucketService; -import ru.dragonestia.picker.service.NodeService; -import ru.dragonestia.picker.util.NamingValidator; - -import java.util.Objects; - -@Log4j2 -@RestController -@RequestMapping("/nodes/{nodeIdentifier}/buckets") -@RequiredArgsConstructor -public class BucketController { - - private final NodeService nodeService; - private final BucketService bucketService; - - @GetMapping - ResponseEntity allBuckets(@PathVariable(name = "nodeIdentifier") String nodeId) { - var nodeOpt = nodeService.findNode(nodeId); - return nodeOpt.map(node -> ResponseEntity.ok(new BucketListResponse(nodeId, - bucketService.allBuckets(node).stream() - .map(bucket -> new BucketListResponse.BucketDTO(bucket.getIdentifier(), bucket.getSlots().getSlots(), bucket.isLocked())) - .toList() - ))).orElseGet(() -> ResponseEntity.notFound().build()); - } - - @PostMapping - ResponseEntity registerBucket(@PathVariable(name = "nodeIdentifier") String nodeId, - @RequestParam(name = "identifier") String bucketId, - @RequestParam(name = "slots") int slots, - @RequestParam(name = "payload") String payload, - @RequestParam(name = "locked", defaultValue = "false") boolean locked) { - - var nodeOpt = nodeService.findNode(nodeId); - - if (nodeOpt.isEmpty()) { - return ResponseEntity.status(404) - .body(new BucketRegisterResponse(false, "Node does not exist")); - } - - var bucket = Bucket.create(bucketId, nodeOpt.get(), SlotLimit.of(slots), payload); - bucket.setLocked(locked); - try { - bucketService.createBucket(bucket); - return ResponseEntity.ok(new BucketRegisterResponse(true, "")); - } catch (Error error) { - return ResponseEntity.status(400).body(new BucketRegisterResponse(false, error.getMessage())); - } catch (Exception ex) { - return ResponseEntity.status(500).body(new BucketRegisterResponse(false, ex.getMessage())); - } - } - - @DeleteMapping("/{identifier}") - ResponseEntity removeBucket(@PathVariable("nodeIdentifier") String nodeId, - @PathVariable("identifier") String bucketId) { - if (!NamingValidator.validateNodeIdentifier(nodeId) || !NamingValidator.validateBucketIdentifier(bucketId)) { - return ResponseEntity.ok().build(); - } - - var nodeOpt = nodeService.findNode(nodeId); - nodeOpt.flatMap(node -> bucketService.findBucket(node, bucketId)) - .ifPresent(bucketService::removeBucket); - - 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()); - } - - @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); - } -} diff --git a/app/src/main/java/ru/dragonestia/picker/controller/NodeController.java b/app/src/main/java/ru/dragonestia/picker/controller/NodeController.java index 48a3915..9c45ade 100644 --- a/app/src/main/java/ru/dragonestia/picker/controller/NodeController.java +++ b/app/src/main/java/ru/dragonestia/picker/controller/NodeController.java @@ -8,7 +8,7 @@ import ru.dragonestia.picker.controller.response.NodeDetailsResponse; import ru.dragonestia.picker.controller.response.NodeListResponse; import ru.dragonestia.picker.controller.response.NodeRegisterResponse; import ru.dragonestia.picker.model.Node; -import ru.dragonestia.picker.model.type.LoadBalancingMethod; +import ru.dragonestia.picker.model.type.PickingMode; import ru.dragonestia.picker.service.NodeService; import ru.dragonestia.picker.util.NamingValidator; @@ -21,15 +21,15 @@ public class NodeController { @GetMapping NodeListResponse allNodes() { - return new NodeListResponse(nodeService.allNodes()); + return new NodeListResponse(nodeService.all()); } @PostMapping - NodeRegisterResponse registerNode(@RequestParam(name = "identifier") String identifier, - @RequestParam(name = "method") LoadBalancingMethod method) { + NodeRegisterResponse registerNode(@RequestParam(name = "nodeId") String nodeId, + @RequestParam(name = "method") PickingMode method) { try { - nodeService.createNode(new Node(identifier, method)); + nodeService.create(new Node(nodeId, method)); } catch (IllegalArgumentException ex) { return new NodeRegisterResponse(false, ex.getMessage()); } catch (Error error) { @@ -39,25 +39,25 @@ public class NodeController { return new NodeRegisterResponse(true, ""); } - @GetMapping("/{identifier}") - ResponseEntity nodeDetails(@PathVariable("identifier") String identifier) { - if (!NamingValidator.validateNodeIdentifier(identifier)) { + @GetMapping("/{nodeId}") + ResponseEntity nodeDetails(@PathVariable("nodeId") String nodeId) { + if (!NamingValidator.validateNodeId(nodeId)) { return new ResponseEntity<>(HttpStatusCode.valueOf(404)); } - var nodeOpt = nodeService.findNode(identifier); + var nodeOpt = nodeService.find(nodeId); return nodeOpt.map(node -> ResponseEntity.ok(new NodeDetailsResponse(node))) .orElseGet(() -> new ResponseEntity<>(HttpStatusCode.valueOf(404))); } - @DeleteMapping("/{identifier}") - ResponseEntity removeNode(@PathVariable("identifier") String identifier) { - if (!NamingValidator.validateNodeIdentifier(identifier)) { + @DeleteMapping("/{nodeId}") + ResponseEntity removeNode(@PathVariable("nodeId") String nodeId) { + if (!NamingValidator.validateNodeId(nodeId)) { return ResponseEntity.ok().build(); } - var nodeOpt = nodeService.findNode(identifier); - nodeOpt.ifPresent(nodeService::removeNode); + var nodeOpt = nodeService.find(nodeId); + nodeOpt.ifPresent(nodeService::remove); return ResponseEntity.ok().build(); } diff --git a/app/src/main/java/ru/dragonestia/picker/controller/RoomController.java b/app/src/main/java/ru/dragonestia/picker/controller/RoomController.java new file mode 100644 index 0000000..d915989 --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/controller/RoomController.java @@ -0,0 +1,117 @@ +package ru.dragonestia.picker.controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ru.dragonestia.picker.controller.response.RoomInfoResponse; +import ru.dragonestia.picker.controller.response.RoomListResponse; +import ru.dragonestia.picker.controller.response.RoomRegisterResponse; +import ru.dragonestia.picker.model.Room; +import ru.dragonestia.picker.model.type.SlotLimit; +import ru.dragonestia.picker.service.RoomService; +import ru.dragonestia.picker.service.NodeService; +import ru.dragonestia.picker.util.NamingValidator; + +import java.util.Objects; + +@Log4j2 +@RestController +@RequestMapping("/nodes/{nodeId}/rooms") +@RequiredArgsConstructor +public class RoomController { + + private final NodeService nodeService; + private final RoomService roomService; + + @GetMapping + ResponseEntity all(@PathVariable(name = "nodeId") String nodeId) { + var nodeOpt = nodeService.find(nodeId); + return nodeOpt.map(node -> ResponseEntity.ok(new RoomListResponse(nodeId, + roomService.all(node).stream() + .map(room -> new RoomListResponse.RoomDTO(room.getId(), room.getSlots().getSlots(), room.isLocked())) + .toList() + ))).orElseGet(() -> ResponseEntity.notFound().build()); + } + + @PostMapping + ResponseEntity register(@PathVariable(name = "nodeId") String nodeId, + @RequestParam(name = "roomId") String roomId, + @RequestParam(name = "slots") int slots, + @RequestParam(name = "payload") String payload, + @RequestParam(name = "locked", defaultValue = "false") boolean locked) { + + var nodeOpt = nodeService.find(nodeId); + + if (nodeOpt.isEmpty()) { + return ResponseEntity.status(404) + .body(new RoomRegisterResponse(false, "Node does not exist")); + } + + var room = Room.create(roomId, nodeOpt.get(), SlotLimit.of(slots), payload); + room.setLocked(locked); + try { + roomService.create(room); + return ResponseEntity.ok(new RoomRegisterResponse(true, "")); + } catch (Error error) { + return ResponseEntity.status(400).body(new RoomRegisterResponse(false, error.getMessage())); + } catch (Exception ex) { + return ResponseEntity.status(500).body(new RoomRegisterResponse(false, ex.getMessage())); + } + } + + @DeleteMapping("/{roomId}") + ResponseEntity remove(@PathVariable("nodeId") String nodeId, + @PathVariable("roomId") String roomId) { + if (!NamingValidator.validateNodeId(nodeId) || !NamingValidator.validateRoomId(roomId)) { + return ResponseEntity.ok().build(); + } + + var nodeOpt = nodeService.find(nodeId); + nodeOpt.flatMap(node -> roomService.find(node, roomId)) + .ifPresent(roomService::remove); + + return ResponseEntity.ok().build(); + } + + @GetMapping("/{roomId}") + ResponseEntity info(@PathVariable("nodeId") String nodeId, + @PathVariable("roomId") String roomId) { + if (!NamingValidator.validateNodeId(nodeId) || !NamingValidator.validateRoomId(roomId)) { + return ResponseEntity.ok().build(); + } + + var nodeOpt = nodeService.find(nodeId); + if (nodeOpt.isEmpty()) { + return ResponseEntity.notFound().build(); + } + + var roomOpt = roomService.find(Objects.requireNonNull(nodeOpt.get()), roomId); + return roomOpt.map(room -> ResponseEntity.ok(new RoomInfoResponse(room))) + .orElseGet(() -> ResponseEntity.notFound().build()); + } + + @PostMapping("/{roomId}/lock") + ResponseEntity lockBucket(@PathVariable("nodeId") String nodeId, + @PathVariable("roomId") String roomId, + @RequestParam(name = "newState") boolean value) { + + if (!NamingValidator.validateNodeId(nodeId) || !NamingValidator.validateRoomId(roomId)) { + return ResponseEntity.notFound().build(); + } + + var nodeOpt = nodeService.find(nodeId); + if (nodeOpt.isEmpty()) { + return ResponseEntity.notFound().build(); + } + + var roomOpt = roomService.find(Objects.requireNonNull(nodeOpt.get()), roomId); + if (roomOpt.isEmpty()) { + return ResponseEntity.notFound().build(); + } + + var room = roomOpt.get(); + room.setLocked(value); + return ResponseEntity.ok(true); + } +} diff --git a/app/src/main/java/ru/dragonestia/picker/controller/UserBucketController.java b/app/src/main/java/ru/dragonestia/picker/controller/UserBucketController.java deleted file mode 100644 index 3e2b564..0000000 --- a/app/src/main/java/ru/dragonestia/picker/controller/UserBucketController.java +++ /dev/null @@ -1,111 +0,0 @@ -package ru.dragonestia.picker.controller; - -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import ru.dragonestia.picker.controller.response.BucketUserListResponse; -import ru.dragonestia.picker.controller.response.LinkUsersWithBucketResponse; -import ru.dragonestia.picker.model.Bucket; -import ru.dragonestia.picker.model.Node; -import ru.dragonestia.picker.model.User; -import ru.dragonestia.picker.service.BucketService; -import ru.dragonestia.picker.service.NodeService; -import ru.dragonestia.picker.service.UserService; -import ru.dragonestia.picker.util.NamingValidator; - -import java.util.LinkedList; -import java.util.Objects; - -@RequiredArgsConstructor -@RestController -@RequestMapping("/nodes/{nodeIdentifier}/buckets/{bucketIdentifier}/users") -public class UserBucketController { - - private final NodeService nodeService; - private final BucketService bucketService; - private final UserService userService; - - @GetMapping - ResponseEntity usersInsideBucket(@PathVariable(name = "nodeIdentifier") String nodeId, - @PathVariable(name = "bucketIdentifier") String bucketId) { - - Bucket bucket; - try { - var temp = getNodeAndBucket(nodeId, bucketId); - bucket = temp.bucket(); - } catch (Error error) { - return ResponseEntity.notFound().build(); - } - - var users = userService.getBucketUsers(bucket); - return ResponseEntity.ok(new BucketUserListResponse(bucket.getSlots().getSlots(), users.size(), users)); - } - - @PostMapping - ResponseEntity linkUserWithBucket(@PathVariable(name = "nodeIdentifier") String nodeId, - @PathVariable(name = "bucketIdentifier") String bucketId, - @RequestParam(name = "users") String userIds, - @RequestParam(name = "force") boolean force) { - - Bucket bucket; - try { - var temp = getNodeAndBucket(nodeId, bucketId); - bucket = temp.bucket(); - } catch (Error error) { - return ResponseEntity.status(404).body(new LinkUsersWithBucketResponse(false, error.getMessage())); - } - - var list = new LinkedList(); - for (var username: userIds.split(",")) { - if (!NamingValidator.validateUserIdentifier(username)) continue; - - list.add(new User(username)); - } - - try { - userService.linkUsersWithBucket(bucket, list, force); - } catch (Error error) { - return ResponseEntity.status(400).body(new LinkUsersWithBucketResponse(false, error.getMessage())); - } - - return ResponseEntity.ok(new LinkUsersWithBucketResponse(true, "Success")); - } - - @DeleteMapping - ResponseEntity unlinkUsersForBucket(@PathVariable(name = "nodeIdentifier") String nodeId, - @PathVariable(name = "bucketIdentifier") String bucketId, - @RequestParam(name = "users") String userIdentifiers) { - - Node node; - Bucket bucket; - try { - var temp = getNodeAndBucket(nodeId, bucketId); - node = temp.node(); - bucket = temp.bucket(); - } catch (Error error) { - return ResponseEntity.notFound().build(); - } - - return null; - } - - private record NodeAndBucket(Node node, Bucket bucket) {} - - private NodeAndBucket getNodeAndBucket(String nodeId, String bucketId) { - if (!NamingValidator.validateNodeIdentifier(nodeId) || !NamingValidator.validateBucketIdentifier(bucketId)) { - throw new Error(); - } - - var nodeOpt = nodeService.findNode(nodeId); - if (nodeOpt.isEmpty()) { - throw new Error(); - } - - var bucketOpt = bucketService.findBucket(Objects.requireNonNull(nodeOpt.get()), bucketId); - if (bucketOpt.isEmpty()) { - throw new Error(); - } - - return new NodeAndBucket(nodeOpt.get(), bucketOpt.get()); - } -} diff --git a/app/src/main/java/ru/dragonestia/picker/controller/UserRoomController.java b/app/src/main/java/ru/dragonestia/picker/controller/UserRoomController.java new file mode 100644 index 0000000..579a09d --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/controller/UserRoomController.java @@ -0,0 +1,111 @@ +package ru.dragonestia.picker.controller; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ru.dragonestia.picker.controller.response.RoomUserListResponse; +import ru.dragonestia.picker.controller.response.LinkUsersWithRoomResponse; +import ru.dragonestia.picker.model.Room; +import ru.dragonestia.picker.model.Node; +import ru.dragonestia.picker.model.User; +import ru.dragonestia.picker.service.RoomService; +import ru.dragonestia.picker.service.NodeService; +import ru.dragonestia.picker.service.UserService; +import ru.dragonestia.picker.util.NamingValidator; + +import java.util.LinkedList; +import java.util.Objects; + +@RequiredArgsConstructor +@RestController +@RequestMapping("/nodes/{nodeId}/rooms/{roomId}/users") +public class UserRoomController { + + private final NodeService nodeService; + private final RoomService roomService; + private final UserService userService; + + @GetMapping + ResponseEntity usersInsideRoom(@PathVariable(name = "nodeId") String nodeId, + @PathVariable(name = "roomId") String bucketId) { + + Room room; + try { + var temp = getNodeAndRoom(nodeId, bucketId); + room = temp.room(); + } catch (Error error) { + return ResponseEntity.notFound().build(); + } + + var users = userService.getRoomUsers(room); + return ResponseEntity.ok(new RoomUserListResponse(room.getSlots().getSlots(), users.size(), users)); + } + + @PostMapping + ResponseEntity linkUserWithRoom(@PathVariable(name = "nodeId") String nodeId, + @PathVariable(name = "roomId") String roomId, + @RequestParam(name = "userIds") String userIds, + @RequestParam(name = "force") boolean force) { + + Room room; + try { + var temp = getNodeAndRoom(nodeId, roomId); + room = temp.room(); + } catch (Error error) { + return ResponseEntity.status(404).body(new LinkUsersWithRoomResponse(false, error.getMessage())); + } + + var list = new LinkedList(); + for (var username: userIds.split(",")) { + if (!NamingValidator.validateUserId(username)) continue; + + list.add(new User(username)); + } + + try { + userService.linkUsersWithRoom(room, list, force); + } catch (Error error) { + return ResponseEntity.status(400).body(new LinkUsersWithRoomResponse(false, error.getMessage())); + } + + return ResponseEntity.ok(new LinkUsersWithRoomResponse(true, "Success")); + } + + @DeleteMapping + ResponseEntity unlinkUsersForBucket(@PathVariable(name = "nodeId") String nodeId, + @PathVariable(name = "roomId") String roomId, + @RequestParam(name = "userIds") String userIds) { + + Node node; + Room room; + try { + var temp = getNodeAndRoom(nodeId, roomId); + node = temp.node(); + room = temp.room(); + } catch (Error error) { + return ResponseEntity.notFound().build(); + } + + return null; + } + + private record NodeAndRoom(Node node, Room room) {} + + private NodeAndRoom getNodeAndRoom(String nodeId, String roomId) { + if (!NamingValidator.validateNodeId(nodeId) || !NamingValidator.validateRoomId(roomId)) { + throw new Error(); + } + + var nodeOpt = nodeService.find(nodeId); + if (nodeOpt.isEmpty()) { + throw new Error(); + } + + var roomOpt = roomService.find(Objects.requireNonNull(nodeOpt.get()), roomId); + if (roomOpt.isEmpty()) { + throw new Error(); + } + + return new NodeAndRoom(nodeOpt.get(), roomOpt.get()); + } +} diff --git a/app/src/main/java/ru/dragonestia/picker/controller/response/BucketInfoResponse.java b/app/src/main/java/ru/dragonestia/picker/controller/response/BucketInfoResponse.java deleted file mode 100644 index dbadee9..0000000 --- a/app/src/main/java/ru/dragonestia/picker/controller/response/BucketInfoResponse.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.dragonestia.picker.controller.response; - -import ru.dragonestia.picker.model.Bucket; - -public record BucketInfoResponse(Bucket bucket) {} diff --git a/app/src/main/java/ru/dragonestia/picker/controller/response/BucketListResponse.java b/app/src/main/java/ru/dragonestia/picker/controller/response/BucketListResponse.java deleted file mode 100644 index 6fbfe17..0000000 --- a/app/src/main/java/ru/dragonestia/picker/controller/response/BucketListResponse.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.dragonestia.picker.controller.response; - -import java.util.List; - -public record BucketListResponse(String node, List buckets) { - - public record BucketDTO(String identifier, int slots, boolean locked) {} -} diff --git a/app/src/main/java/ru/dragonestia/picker/controller/response/BucketRegisterResponse.java b/app/src/main/java/ru/dragonestia/picker/controller/response/BucketRegisterResponse.java deleted file mode 100644 index 7929707..0000000 --- a/app/src/main/java/ru/dragonestia/picker/controller/response/BucketRegisterResponse.java +++ /dev/null @@ -1,3 +0,0 @@ -package ru.dragonestia.picker.controller.response; - -public record BucketRegisterResponse(boolean success, String message) {} diff --git a/app/src/main/java/ru/dragonestia/picker/controller/response/LinkUsersWithBucketResponse.java b/app/src/main/java/ru/dragonestia/picker/controller/response/LinkUsersWithBucketResponse.java deleted file mode 100644 index a434733..0000000 --- a/app/src/main/java/ru/dragonestia/picker/controller/response/LinkUsersWithBucketResponse.java +++ /dev/null @@ -1,3 +0,0 @@ -package ru.dragonestia.picker.controller.response; - -public record LinkUsersWithBucketResponse(boolean success, String message) {} diff --git a/app/src/main/java/ru/dragonestia/picker/controller/response/LinkUsersWithRoomResponse.java b/app/src/main/java/ru/dragonestia/picker/controller/response/LinkUsersWithRoomResponse.java new file mode 100644 index 0000000..aa7093b --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/controller/response/LinkUsersWithRoomResponse.java @@ -0,0 +1,3 @@ +package ru.dragonestia.picker.controller.response; + +public record LinkUsersWithRoomResponse(boolean success, String message) {} diff --git a/app/src/main/java/ru/dragonestia/picker/controller/response/RoomInfoResponse.java b/app/src/main/java/ru/dragonestia/picker/controller/response/RoomInfoResponse.java new file mode 100644 index 0000000..d432406 --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/controller/response/RoomInfoResponse.java @@ -0,0 +1,5 @@ +package ru.dragonestia.picker.controller.response; + +import ru.dragonestia.picker.model.Room; + +public record RoomInfoResponse(Room room) {} diff --git a/app/src/main/java/ru/dragonestia/picker/controller/response/RoomListResponse.java b/app/src/main/java/ru/dragonestia/picker/controller/response/RoomListResponse.java new file mode 100644 index 0000000..9e66507 --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/controller/response/RoomListResponse.java @@ -0,0 +1,8 @@ +package ru.dragonestia.picker.controller.response; + +import java.util.List; + +public record RoomListResponse(String node, List rooms) { + + public record RoomDTO(String id, int slots, boolean locked) {} +} diff --git a/app/src/main/java/ru/dragonestia/picker/controller/response/RoomRegisterResponse.java b/app/src/main/java/ru/dragonestia/picker/controller/response/RoomRegisterResponse.java new file mode 100644 index 0000000..21893c6 --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/controller/response/RoomRegisterResponse.java @@ -0,0 +1,3 @@ +package ru.dragonestia.picker.controller.response; + +public record RoomRegisterResponse(boolean success, String message) {} diff --git a/app/src/main/java/ru/dragonestia/picker/controller/response/BucketUserListResponse.java b/app/src/main/java/ru/dragonestia/picker/controller/response/RoomUserListResponse.java similarity index 58% rename from app/src/main/java/ru/dragonestia/picker/controller/response/BucketUserListResponse.java rename to app/src/main/java/ru/dragonestia/picker/controller/response/RoomUserListResponse.java index 663d200..9d9ea0c 100644 --- a/app/src/main/java/ru/dragonestia/picker/controller/response/BucketUserListResponse.java +++ b/app/src/main/java/ru/dragonestia/picker/controller/response/RoomUserListResponse.java @@ -4,4 +4,4 @@ import ru.dragonestia.picker.model.User; import java.util.List; -public record BucketUserListResponse(int slots, int usedSlots, List users) {} +public record RoomUserListResponse(int slots, int usedSlots, List users) {} diff --git a/app/src/main/java/ru/dragonestia/picker/model/Node.java b/app/src/main/java/ru/dragonestia/picker/model/Node.java index ff945d4..ee9b88e 100644 --- a/app/src/main/java/ru/dragonestia/picker/model/Node.java +++ b/app/src/main/java/ru/dragonestia/picker/model/Node.java @@ -1,13 +1,13 @@ package ru.dragonestia.picker.model; import lombok.NonNull; -import ru.dragonestia.picker.model.type.LoadBalancingMethod; +import ru.dragonestia.picker.model.type.PickingMode; -public record Node(@NonNull String identifier, @NonNull LoadBalancingMethod method) { +public record Node(@NonNull String id, @NonNull PickingMode mode) { @Override public int hashCode() { - return identifier.hashCode(); + return id.hashCode(); } @Override @@ -15,7 +15,7 @@ public record Node(@NonNull String identifier, @NonNull LoadBalancingMethod meth if (object == this) return true; if (object == null) return false; if (object instanceof Node other) { - return identifier.equals(other.identifier); + return id.equals(other.id); } return false; } diff --git a/app/src/main/java/ru/dragonestia/picker/model/Bucket.java b/app/src/main/java/ru/dragonestia/picker/model/Room.java similarity index 68% rename from app/src/main/java/ru/dragonestia/picker/model/Bucket.java rename to app/src/main/java/ru/dragonestia/picker/model/Room.java index abc04a1..ae18b08 100644 --- a/app/src/main/java/ru/dragonestia/picker/model/Bucket.java +++ b/app/src/main/java/ru/dragonestia/picker/model/Room.java @@ -7,16 +7,16 @@ import ru.dragonestia.picker.model.type.SlotLimit; @Getter @RequiredArgsConstructor(access = AccessLevel.PRIVATE) -public class Bucket { +public class Room { - private final String identifier; - private final String nodeIdentifier; + private final String id; + private final String nodeId; private final SlotLimit slots; private final String payload; private boolean locked = false; - public static Bucket create(String identifier, Node node, SlotLimit limit, String payload) { - return new Bucket(identifier, node.identifier(), limit, payload); + public static Room create(String roomId, Node node, SlotLimit limit, String payload) { + return new Room(roomId, node.id(), limit, payload); } public void setLocked(boolean value) { @@ -31,15 +31,15 @@ public class Bucket { @Override public int hashCode() { - return identifier.hashCode(); + return id.hashCode(); } @Override public boolean equals(Object object) { if (object == this) return true; if (object == null) return false; - if (object instanceof Bucket other) { - return identifier.equals(other.identifier); + if (object instanceof Room other) { + return id.equals(other.id); } return false; } diff --git a/app/src/main/java/ru/dragonestia/picker/model/User.java b/app/src/main/java/ru/dragonestia/picker/model/User.java index 72deadd..79bbdca 100644 --- a/app/src/main/java/ru/dragonestia/picker/model/User.java +++ b/app/src/main/java/ru/dragonestia/picker/model/User.java @@ -2,11 +2,11 @@ package ru.dragonestia.picker.model; import lombok.NonNull; -public record User(@NonNull String identifier) { +public record User(@NonNull String id) { @Override public int hashCode() { - return identifier.hashCode(); + return id.hashCode(); } @Override @@ -14,7 +14,7 @@ public record User(@NonNull String identifier) { if (object == this) return true; if (object == null) return false; if (object instanceof User other) { - return identifier.equals(other.identifier); + return id.equals(other.id); } return false; } diff --git a/app/src/main/java/ru/dragonestia/picker/model/type/LoadBalancingMethod.java b/app/src/main/java/ru/dragonestia/picker/model/type/PickingMode.java similarity index 75% rename from app/src/main/java/ru/dragonestia/picker/model/type/LoadBalancingMethod.java rename to app/src/main/java/ru/dragonestia/picker/model/type/PickingMode.java index 7053704..9038526 100644 --- a/app/src/main/java/ru/dragonestia/picker/model/type/LoadBalancingMethod.java +++ b/app/src/main/java/ru/dragonestia/picker/model/type/PickingMode.java @@ -1,6 +1,6 @@ package ru.dragonestia.picker.model.type; -public enum LoadBalancingMethod { +public enum PickingMode { SEQUENTIAL_FILLING, ROUND_ROBIN, LEAST_PICKED, diff --git a/app/src/main/java/ru/dragonestia/picker/repository/BucketRepository.java b/app/src/main/java/ru/dragonestia/picker/repository/BucketRepository.java deleted file mode 100644 index 70e2987..0000000 --- a/app/src/main/java/ru/dragonestia/picker/repository/BucketRepository.java +++ /dev/null @@ -1,32 +0,0 @@ -package ru.dragonestia.picker.repository; - -import ru.dragonestia.picker.model.Bucket; -import ru.dragonestia.picker.model.Node; -import ru.dragonestia.picker.model.User; - -import java.util.Collection; -import java.util.List; -import java.util.Optional; - -public interface BucketRepository { - - void createBucket(Bucket bucket); - - void removeBucket(Bucket bucket); - - Optional findBucket(Node node, String identifier); - - List all(Node node); - - default int countAvailableBuckets(Node node) { - return countAvailableBuckets(node, 0); - } - - int countAvailableBuckets(Node node, int requiredSlots); - - Optional pickFreeBucket(Node node, Collection users); - - void onCreateNode(Node node); - - void onRemoveNode(Node node); -} diff --git a/app/src/main/java/ru/dragonestia/picker/repository/NodeRepository.java b/app/src/main/java/ru/dragonestia/picker/repository/NodeRepository.java index 4a17467..e22d7ff 100644 --- a/app/src/main/java/ru/dragonestia/picker/repository/NodeRepository.java +++ b/app/src/main/java/ru/dragonestia/picker/repository/NodeRepository.java @@ -7,11 +7,11 @@ import java.util.Optional; public interface NodeRepository { - void createNode(Node node); + void create(Node node); - void deleteNode(Node node); + void delete(Node node); - Optional findNode(String nodeId); + Optional find(String nodeId); List all(); } diff --git a/app/src/main/java/ru/dragonestia/picker/repository/RoomRepository.java b/app/src/main/java/ru/dragonestia/picker/repository/RoomRepository.java new file mode 100644 index 0000000..163d849 --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/repository/RoomRepository.java @@ -0,0 +1,32 @@ +package ru.dragonestia.picker.repository; + +import ru.dragonestia.picker.model.Room; +import ru.dragonestia.picker.model.Node; +import ru.dragonestia.picker.model.User; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +public interface RoomRepository { + + void create(Room room); + + void remove(Room room); + + Optional find(Node node, String identifier); + + List all(Node node); + + default int countAvailable(Node node) { + return countAvailable(node, 0); + } + + int countAvailable(Node node, int requiredSlots); + + Optional pickFree(Node node, Collection users); + + void onCreateNode(Node node); + + void onRemoveNode(Node node); +} diff --git a/app/src/main/java/ru/dragonestia/picker/repository/UserRepository.java b/app/src/main/java/ru/dragonestia/picker/repository/UserRepository.java index a02c6ea..79fdd71 100644 --- a/app/src/main/java/ru/dragonestia/picker/repository/UserRepository.java +++ b/app/src/main/java/ru/dragonestia/picker/repository/UserRepository.java @@ -1,6 +1,6 @@ package ru.dragonestia.picker.repository; -import ru.dragonestia.picker.model.Bucket; +import ru.dragonestia.picker.model.Room; import ru.dragonestia.picker.model.User; import java.util.Collection; @@ -9,13 +9,13 @@ import java.util.Map; public interface UserRepository { - Map linkWithBucket(Bucket bucket, Collection users, boolean force); + Map linkWithRoom(Room room, Collection users, boolean force); - int unlinkWithBucket(Bucket bucket, Collection users); + int unlinkWithRoom(Room room, Collection users); - List findAllLinkedUserBuckets(User user); + List findAllLinkedUserRooms(User user); - void onRemoveBucket(Bucket bucket); + void onRemoveRoom(Room room); - List usersOf(Bucket bucket); + List usersOf(Room room); } diff --git a/app/src/main/java/ru/dragonestia/picker/repository/impl/BucketRepositoryImpl.java b/app/src/main/java/ru/dragonestia/picker/repository/impl/BucketRepositoryImpl.java deleted file mode 100644 index c23d854..0000000 --- a/app/src/main/java/ru/dragonestia/picker/repository/impl/BucketRepositoryImpl.java +++ /dev/null @@ -1,131 +0,0 @@ -package ru.dragonestia.picker.repository.impl; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Repository; -import ru.dragonestia.picker.model.Bucket; -import ru.dragonestia.picker.model.Node; -import ru.dragonestia.picker.model.User; -import ru.dragonestia.picker.repository.BucketRepository; -import ru.dragonestia.picker.repository.UserRepository; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -@Repository -@RequiredArgsConstructor -public class BucketRepositoryImpl implements BucketRepository { - - private final UserRepository userRepository; - private final Map node2bucketsMap = new ConcurrentHashMap<>(); - - @Override - public void createBucket(Bucket bucket) { - var nodeId = bucket.getNodeIdentifier(); - - synchronized (node2bucketsMap) { - var node = node2bucketsMap.keySet().stream() - .filter(n -> bucket.getNodeIdentifier().equals(n.identifier())) - .findFirst(); - - if (node.isEmpty()) { - throw new IllegalArgumentException("Node '" + nodeId + "' does not exist"); - } - - var buckets = node2bucketsMap.get(node.get()); - if (buckets.containsKey(bucket.getIdentifier())) { - throw new IllegalArgumentException("Bucket already exists"); - } - buckets.put(bucket.getIdentifier(), new BucketContainer(bucket, new AtomicInteger(0))); - } - } - - @Override - public void removeBucket(Bucket bucket) { - var nodeId = bucket.getNodeIdentifier(); - var node = node2bucketsMap.keySet().stream() - .filter(n -> bucket.getNodeIdentifier().equals(n.identifier())) - .findFirst(); - - synchronized (node2bucketsMap) { - if (node.isEmpty()) { - throw new IllegalArgumentException("Node '" + nodeId + "' does not exist"); - } - - node2bucketsMap.get(node.get()).remove(bucket.getIdentifier()); - } - - userRepository.onRemoveBucket(bucket); - } - - @Override - public Optional findBucket(Node node, String identifier) { - synchronized (node2bucketsMap) { - if (!node2bucketsMap.containsKey(node)) { - throw new IllegalArgumentException("Node '" + node.identifier() + "' does not exist"); - } - - var result = node2bucketsMap.get(node).getOrDefault(identifier, null); - return result == null? Optional.empty() : Optional.of(result.bucket()); - } - } - - @Override - public List all(Node node) { - synchronized (node2bucketsMap) { - return node2bucketsMap.get(node).values().stream().map(BucketContainer::bucket).toList(); - } - } - - @Override - public int countAvailableBuckets(Node node, int requiredSlots) { - return (int) node2bucketsMap.get(node).values().stream() - .filter(bucket -> bucket.isAvailable(requiredSlots)) - .count(); - } - - @Override - public Optional pickFreeBucket(Node node, Collection users) { - synchronized (node2bucketsMap) { - if (!node2bucketsMap.containsKey(node)) { - throw new IllegalArgumentException("Node '" + node.identifier() + "' does not exist"); - } - - var requiredSlots = users.size(); - var container = node2bucketsMap.get(node).values().stream() // TODO: pick bucket with used node balancing method - .filter(b -> b.isAvailable(requiredSlots)) - .findFirst(); - - if (container.isPresent()) { - var cont = container.get(); - var addedUsers = userRepository.linkWithBucket(cont.bucket(), users, false); - cont.used().getAndAdd((int) addedUsers.values().stream().filter(Boolean.TRUE::equals).count()); - } - - return container.map(BucketContainer::bucket); - } - } - - @Override - public void onCreateNode(Node node) { - synchronized (node2bucketsMap) { - node2bucketsMap.put(node, new Buckets()); - } - } - - @Override - public void onRemoveNode(Node node) { - synchronized (node2bucketsMap) { - node2bucketsMap.remove(node); - } - } - - private record BucketContainer(Bucket bucket, AtomicInteger used) { - - public boolean isAvailable(int requiredSlots) { - return bucket.isAvailable(used.get(), requiredSlots); - } - } - - private static class Buckets extends LinkedHashMap {} -} diff --git a/app/src/main/java/ru/dragonestia/picker/repository/impl/NodeRepositoryImpl.java b/app/src/main/java/ru/dragonestia/picker/repository/impl/NodeRepositoryImpl.java index b45a0ac..6929357 100644 --- a/app/src/main/java/ru/dragonestia/picker/repository/impl/NodeRepositoryImpl.java +++ b/app/src/main/java/ru/dragonestia/picker/repository/impl/NodeRepositoryImpl.java @@ -3,7 +3,7 @@ package ru.dragonestia.picker.repository.impl; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; import ru.dragonestia.picker.model.Node; -import ru.dragonestia.picker.repository.BucketRepository; +import ru.dragonestia.picker.repository.RoomRepository; import ru.dragonestia.picker.repository.NodeRepository; import java.util.List; @@ -15,33 +15,33 @@ import java.util.concurrent.ConcurrentHashMap; @RequiredArgsConstructor public class NodeRepositoryImpl implements NodeRepository { - private final BucketRepository bucketRepository; + private final RoomRepository roomRepository; private final Map nodeMap = new ConcurrentHashMap<>(); @Override - public void createNode(Node node) { + public void create(Node node) { synchronized (nodeMap) { - if (nodeMap.containsKey(node.identifier())) { - throw new IllegalArgumentException("Node with id '" + node.identifier() + "' already exists"); + if (nodeMap.containsKey(node.id())) { + throw new IllegalArgumentException("Node with id '" + node.id() + "' already exists"); } - nodeMap.put(node.identifier(), node); + nodeMap.put(node.id(), node); } - bucketRepository.onCreateNode(node); + roomRepository.onCreateNode(node); } @Override - public void deleteNode(Node node) { + public void delete(Node node) { synchronized (nodeMap) { - nodeMap.remove(node.identifier()); + nodeMap.remove(node.id()); } - bucketRepository.onRemoveNode(node); + roomRepository.onRemoveNode(node); } @Override - public Optional findNode(String nodeId) { + public Optional find(String nodeId) { synchronized (nodeMap) { return nodeMap.containsKey(nodeId)? Optional.of(nodeMap.get(nodeId)) : Optional.empty(); } diff --git a/app/src/main/java/ru/dragonestia/picker/repository/impl/RoomRepositoryImpl.java b/app/src/main/java/ru/dragonestia/picker/repository/impl/RoomRepositoryImpl.java new file mode 100644 index 0000000..e7db423 --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/repository/impl/RoomRepositoryImpl.java @@ -0,0 +1,131 @@ +package ru.dragonestia.picker.repository.impl; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import ru.dragonestia.picker.model.Room; +import ru.dragonestia.picker.model.Node; +import ru.dragonestia.picker.model.User; +import ru.dragonestia.picker.repository.RoomRepository; +import ru.dragonestia.picker.repository.UserRepository; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +@Repository +@RequiredArgsConstructor +public class RoomRepositoryImpl implements RoomRepository { + + private final UserRepository userRepository; + private final Map node2roomsMap = new ConcurrentHashMap<>(); + + @Override + public void create(Room room) { + var nodeId = room.getNodeId(); + + synchronized (node2roomsMap) { + var node = node2roomsMap.keySet().stream() + .filter(n -> room.getNodeId().equals(n.id())) + .findFirst(); + + if (node.isEmpty()) { + throw new IllegalArgumentException("Node '" + nodeId + "' does not exist"); + } + + var rooms = node2roomsMap.get(node.get()); + if (rooms.containsKey(room.getId())) { + throw new IllegalArgumentException("Room already exists"); + } + rooms.put(room.getId(), new RoomContainer(room, new AtomicInteger(0))); + } + } + + @Override + public void remove(Room room) { + var nodeId = room.getNodeId(); + var node = node2roomsMap.keySet().stream() + .filter(n -> room.getNodeId().equals(n.id())) + .findFirst(); + + synchronized (node2roomsMap) { + if (node.isEmpty()) { + throw new IllegalArgumentException("Node '" + nodeId + "' does not exist"); + } + + node2roomsMap.get(node.get()).remove(room.getId()); + } + + userRepository.onRemoveRoom(room); + } + + @Override + public Optional find(Node node, String identifier) { + synchronized (node2roomsMap) { + if (!node2roomsMap.containsKey(node)) { + throw new IllegalArgumentException("Node '" + node.id() + "' does not exist"); + } + + var result = node2roomsMap.get(node).getOrDefault(identifier, null); + return result == null? Optional.empty() : Optional.of(result.room()); + } + } + + @Override + public List all(Node node) { + synchronized (node2roomsMap) { + return node2roomsMap.get(node).values().stream().map(RoomContainer::room).toList(); + } + } + + @Override + public int countAvailable(Node node, int requiredSlots) { + return (int) node2roomsMap.get(node).values().stream() + .filter(bucket -> bucket.isAvailable(requiredSlots)) + .count(); + } + + @Override + public Optional pickFree(Node node, Collection users) { + synchronized (node2roomsMap) { + if (!node2roomsMap.containsKey(node)) { + throw new IllegalArgumentException("Node '" + node.id() + "' does not exist"); + } + + var requiredSlots = users.size(); + var container = node2roomsMap.get(node).values().stream() // TODO: pick room with used node balancing mode + .filter(r -> r.isAvailable(requiredSlots)) + .findFirst(); + + if (container.isPresent()) { + var cont = container.get(); + var addedUsers = userRepository.linkWithRoom(cont.room(), users, false); + cont.used().getAndAdd((int) addedUsers.values().stream().filter(Boolean.TRUE::equals).count()); + } + + return container.map(RoomContainer::room); + } + } + + @Override + public void onCreateNode(Node node) { + synchronized (node2roomsMap) { + node2roomsMap.put(node, new Rooms()); + } + } + + @Override + public void onRemoveNode(Node node) { + synchronized (node2roomsMap) { + node2roomsMap.remove(node); + } + } + + private record RoomContainer(Room room, AtomicInteger used) { + + public boolean isAvailable(int requiredSlots) { + return room.isAvailable(used.get(), requiredSlots); + } + } + + private static class Rooms extends LinkedHashMap {} +} diff --git a/app/src/main/java/ru/dragonestia/picker/repository/impl/UserRepositoryImpl.java b/app/src/main/java/ru/dragonestia/picker/repository/impl/UserRepositoryImpl.java index 655134c..837ae15 100644 --- a/app/src/main/java/ru/dragonestia/picker/repository/impl/UserRepositoryImpl.java +++ b/app/src/main/java/ru/dragonestia/picker/repository/impl/UserRepositoryImpl.java @@ -1,7 +1,7 @@ package ru.dragonestia.picker.repository.impl; import org.springframework.stereotype.Repository; -import ru.dragonestia.picker.model.Bucket; +import ru.dragonestia.picker.model.Room; import ru.dragonestia.picker.model.User; import ru.dragonestia.picker.repository.UserRepository; @@ -12,51 +12,51 @@ import java.util.concurrent.atomic.AtomicInteger; @Repository public class UserRepositoryImpl implements UserRepository { - private final Map> usersMap = new ConcurrentHashMap<>(); - private final Map> bucketUsers = new ConcurrentHashMap<>(); + private final Map> usersMap = new ConcurrentHashMap<>(); + private final Map> roomUsers = new ConcurrentHashMap<>(); @Override - public Map linkWithBucket(Bucket bucket, Collection users, boolean force) { + public Map linkWithRoom(Room room, Collection users, boolean force) { var result = new HashMap(); synchronized (usersMap) { - var path = new NodeBucketPath(bucket.getNodeIdentifier(), bucket.getIdentifier()); - var usersSet = bucketUsers.getOrDefault(path, new HashSet<>()); + var path = new NodeRoomPath(room.getNodeId(), room.getId()); + var usersSet = roomUsers.getOrDefault(path, new HashSet<>()); - if (force || bucket.getSlots().isUnlimited()) { + if (force || room.getSlots().isUnlimited()) { users.forEach(user -> result.put(user, true)); } else { for (var user : users) { var set = usersMap.getOrDefault(user, new HashSet<>()); - result.put(user, !set.contains(bucket)); + result.put(user, !set.contains(room)); } - if (bucket.getSlots().getSlots() < usersSet.size() + users.size()) { - throw new Error("Bucket are full"); + if (room.getSlots().getSlots() < usersSet.size() + users.size()) { + throw new Error("Room are full"); } } for (var user: users) { var set = usersMap.getOrDefault(user, new HashSet<>()); - set.add(bucket); + set.add(room); usersMap.put(user, set); } usersSet.addAll(users); - bucketUsers.put(path, usersSet); + roomUsers.put(path, usersSet); } return result; } @Override - public int unlinkWithBucket(Bucket bucket, Collection users) { + public int unlinkWithRoom(Room room, Collection users) { var counter = new AtomicInteger(); synchronized (usersMap) { usersMap.forEach((user, set) -> { - if (!set.contains(bucket)) return; + if (!set.contains(room)) return; - set.remove(bucket); + set.remove(room); counter.incrementAndGet(); if (set.isEmpty()) { @@ -64,30 +64,30 @@ public class UserRepositoryImpl implements UserRepository { } }); - var path = new NodeBucketPath(bucket.getNodeIdentifier(), bucket.getIdentifier()); - var set = bucketUsers.getOrDefault(path, new HashSet<>()); + var path = new NodeRoomPath(room.getNodeId(), room.getId()); + var set = roomUsers.getOrDefault(path, new HashSet<>()); set.removeAll(users); if (set.isEmpty()) { - bucketUsers.remove(path); + roomUsers.remove(path); } else { - bucketUsers.put(path, set); + roomUsers.put(path, set); } } return counter.get(); } @Override - public List findAllLinkedUserBuckets(User user) { + public List findAllLinkedUserRooms(User user) { synchronized (usersMap) { return usersMap.getOrDefault(user, new HashSet<>()).stream().toList(); } } @Override - public void onRemoveBucket(Bucket bucket) { + public void onRemoveRoom(Room room) { synchronized (usersMap) { usersMap.forEach((user, set) -> { - set.remove(bucket); + set.remove(room); if (set.isEmpty()) { usersMap.remove(user); } @@ -96,15 +96,15 @@ public class UserRepositoryImpl implements UserRepository { } @Override - public List usersOf(Bucket bucket) { + public List usersOf(Room room) { synchronized (usersMap) { - return bucketUsers.getOrDefault(new NodeBucketPath(bucket.getNodeIdentifier(), bucket.getIdentifier()), new HashSet<>()) + return roomUsers.getOrDefault(new NodeRoomPath(room.getNodeId(), room.getId()), new HashSet<>()) .stream() .toList(); } } - private record NodeBucketPath(String node, String bucket) { + private record NodeRoomPath(String node, String bucket) { @Override public int hashCode() { @@ -115,7 +115,7 @@ public class UserRepositoryImpl implements UserRepository { public boolean equals(Object o) { if (o == null) return false; if (o == this) return true; - if (o instanceof NodeBucketPath other) { + if (o instanceof NodeRoomPath other) { return other.node().equals(node()) && other.bucket().equals(bucket()); } return false; diff --git a/app/src/main/java/ru/dragonestia/picker/service/BucketService.java b/app/src/main/java/ru/dragonestia/picker/service/BucketService.java deleted file mode 100644 index da0cfb6..0000000 --- a/app/src/main/java/ru/dragonestia/picker/service/BucketService.java +++ /dev/null @@ -1,27 +0,0 @@ -package ru.dragonestia.picker.service; - -import ru.dragonestia.picker.model.Bucket; -import ru.dragonestia.picker.model.Node; -import ru.dragonestia.picker.model.User; - -import java.util.List; -import java.util.Optional; - -public interface BucketService { - - void createBucket(Bucket bucket); - - void removeBucket(Bucket bucket); - - Optional findBucket(Node node, String identifier); - - List allBuckets(Node node); - - default int countAvailableBuckets(Node node) { - return countAvailableBuckets(node, 1); - } - - int countAvailableBuckets(Node node, int requiredSlots); - - Bucket pickAvailableBucket(Node node, List users); -} diff --git a/app/src/main/java/ru/dragonestia/picker/service/NodeService.java b/app/src/main/java/ru/dragonestia/picker/service/NodeService.java index 33f125b..8333122 100644 --- a/app/src/main/java/ru/dragonestia/picker/service/NodeService.java +++ b/app/src/main/java/ru/dragonestia/picker/service/NodeService.java @@ -7,11 +7,11 @@ import java.util.Optional; public interface NodeService { - void createNode(Node node); + void create(Node node); - void removeNode(Node node); + void remove(Node node); - List allNodes(); + List all(); - Optional findNode(String identifier); + Optional find(String nodeId); } diff --git a/app/src/main/java/ru/dragonestia/picker/service/RoomService.java b/app/src/main/java/ru/dragonestia/picker/service/RoomService.java new file mode 100644 index 0000000..27d965f --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/service/RoomService.java @@ -0,0 +1,27 @@ +package ru.dragonestia.picker.service; + +import ru.dragonestia.picker.model.Room; +import ru.dragonestia.picker.model.Node; +import ru.dragonestia.picker.model.User; + +import java.util.List; +import java.util.Optional; + +public interface RoomService { + + void create(Room room); + + void remove(Room room); + + Optional find(Node node, String roomId); + + List all(Node node); + + default int countAvailable(Node node) { + return countAvailable(node, 1); + } + + int countAvailable(Node node, int requiredSlots); + + Room pickAvailable(Node node, List users); +} diff --git a/app/src/main/java/ru/dragonestia/picker/service/UserService.java b/app/src/main/java/ru/dragonestia/picker/service/UserService.java index 50425e9..3e6a8f3 100644 --- a/app/src/main/java/ru/dragonestia/picker/service/UserService.java +++ b/app/src/main/java/ru/dragonestia/picker/service/UserService.java @@ -1,6 +1,6 @@ package ru.dragonestia.picker.service; -import ru.dragonestia.picker.model.Bucket; +import ru.dragonestia.picker.model.Room; import ru.dragonestia.picker.model.User; import java.util.Collection; @@ -8,11 +8,11 @@ import java.util.List; public interface UserService { - List getUserBuckets(User user); + List getUserRooms(User user); - void linkUsersWithBucket(Bucket bucket, Collection users, boolean force); + void linkUsersWithRoom(Room room, Collection users, boolean force); - void unlinkUsersFromBucket(Bucket bucket, Collection users); + void unlinkUsersFromRoom(Room room, Collection users); - List getBucketUsers(Bucket bucket); + List getRoomUsers(Room room); } diff --git a/app/src/main/java/ru/dragonestia/picker/service/impl/BucketServiceImpl.java b/app/src/main/java/ru/dragonestia/picker/service/impl/BucketServiceImpl.java deleted file mode 100644 index 0a795ce..0000000 --- a/app/src/main/java/ru/dragonestia/picker/service/impl/BucketServiceImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -package ru.dragonestia.picker.service.impl; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import ru.dragonestia.picker.model.Bucket; -import ru.dragonestia.picker.model.Node; -import ru.dragonestia.picker.model.User; -import ru.dragonestia.picker.repository.BucketRepository; -import ru.dragonestia.picker.service.BucketService; -import ru.dragonestia.picker.util.NamingValidator; - -import java.util.List; -import java.util.Optional; - -@Service -@RequiredArgsConstructor -public class BucketServiceImpl implements BucketService { - - private final BucketRepository bucketRepository; - - @Override - public void createBucket(Bucket bucket) { - if (!NamingValidator.validateBucketIdentifier(bucket.getIdentifier())) { - throw new Error("Invalid bucket identifier format"); - } - - bucketRepository.createBucket(bucket); - } - - @Override - public void removeBucket(Bucket bucket) { - bucketRepository.removeBucket(bucket); - } - - @Override - public Optional findBucket(Node node, String identifier) { - return bucketRepository.findBucket(node, identifier); - } - - @Override - public List allBuckets(Node node) { - return bucketRepository.all(node); - } - - @Override - public int countAvailableBuckets(Node node, int requiredSlots) { - throw new RuntimeException("Not implemented"); - } - - @Override - public Bucket pickAvailableBucket(Node node, List users) { - throw new RuntimeException("Not implemented"); - } -} diff --git a/app/src/main/java/ru/dragonestia/picker/service/impl/NodeServiceImpl.java b/app/src/main/java/ru/dragonestia/picker/service/impl/NodeServiceImpl.java index 94fe864..304518d 100644 --- a/app/src/main/java/ru/dragonestia/picker/service/impl/NodeServiceImpl.java +++ b/app/src/main/java/ru/dragonestia/picker/service/impl/NodeServiceImpl.java @@ -17,26 +17,26 @@ public class NodeServiceImpl implements NodeService { private final NodeRepository nodeRepository; @Override - public void createNode(Node node) { - if (!NamingValidator.validateNodeIdentifier(node.identifier())) { - throw new Error("Invalid node identifier format"); + public void create(Node node) { + if (!NamingValidator.validateNodeId(node.id())) { + throw new Error("Invalid node id format"); } - nodeRepository.createNode(node); + nodeRepository.create(node); } @Override - public void removeNode(Node node) { - nodeRepository.deleteNode(node); + public void remove(Node node) { + nodeRepository.delete(node); } @Override - public List allNodes() { + public List all() { return nodeRepository.all(); } @Override - public Optional findNode(String identifier) { - return nodeRepository.findNode(identifier); + public Optional find(String nodeId) { + return nodeRepository.find(nodeId); } } diff --git a/app/src/main/java/ru/dragonestia/picker/service/impl/RoomServiceImpl.java b/app/src/main/java/ru/dragonestia/picker/service/impl/RoomServiceImpl.java new file mode 100644 index 0000000..e5fb7ea --- /dev/null +++ b/app/src/main/java/ru/dragonestia/picker/service/impl/RoomServiceImpl.java @@ -0,0 +1,54 @@ +package ru.dragonestia.picker.service.impl; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import ru.dragonestia.picker.model.Room; +import ru.dragonestia.picker.model.Node; +import ru.dragonestia.picker.model.User; +import ru.dragonestia.picker.repository.RoomRepository; +import ru.dragonestia.picker.service.RoomService; +import ru.dragonestia.picker.util.NamingValidator; + +import java.util.List; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class RoomServiceImpl implements RoomService { + + private final RoomRepository roomRepository; + + @Override + public void create(Room room) { + if (!NamingValidator.validateRoomId(room.getId())) { + throw new Error("Invalid room id format"); + } + + roomRepository.create(room); + } + + @Override + public void remove(Room room) { + roomRepository.remove(room); + } + + @Override + public Optional find(Node node, String roomId) { + return roomRepository.find(node, roomId); + } + + @Override + public List all(Node node) { + return roomRepository.all(node); + } + + @Override + public int countAvailable(Node node, int requiredSlots) { + throw new RuntimeException("Not implemented"); + } + + @Override + public Room pickAvailable(Node node, List users) { + throw new RuntimeException("Not implemented"); + } +} diff --git a/app/src/main/java/ru/dragonestia/picker/service/impl/UserServiceImpl.java b/app/src/main/java/ru/dragonestia/picker/service/impl/UserServiceImpl.java index 21e16d0..13057fc 100644 --- a/app/src/main/java/ru/dragonestia/picker/service/impl/UserServiceImpl.java +++ b/app/src/main/java/ru/dragonestia/picker/service/impl/UserServiceImpl.java @@ -2,7 +2,7 @@ package ru.dragonestia.picker.service.impl; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import ru.dragonestia.picker.model.Bucket; +import ru.dragonestia.picker.model.Room; import ru.dragonestia.picker.model.User; import ru.dragonestia.picker.repository.UserRepository; import ru.dragonestia.picker.service.UserService; @@ -17,22 +17,22 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; @Override - public List getUserBuckets(User user) { - return userRepository.findAllLinkedUserBuckets(user); + public List getUserRooms(User user) { + return userRepository.findAllLinkedUserRooms(user); } @Override - public void linkUsersWithBucket(Bucket bucket, Collection users, boolean force) { - userRepository.linkWithBucket(bucket, users, force); + public void linkUsersWithRoom(Room room, Collection users, boolean force) { + userRepository.linkWithRoom(room, users, force); } @Override - public void unlinkUsersFromBucket(Bucket bucket, Collection users) { - userRepository.unlinkWithBucket(bucket, users); + public void unlinkUsersFromRoom(Room room, Collection users) { + userRepository.unlinkWithRoom(room, users); } @Override - public List getBucketUsers(Bucket bucket) { - return userRepository.usersOf(bucket); + public List getRoomUsers(Room room) { + return userRepository.usersOf(room); } } diff --git a/app/src/main/java/ru/dragonestia/picker/util/NamingValidator.java b/app/src/main/java/ru/dragonestia/picker/util/NamingValidator.java index 4b83a2f..1182f30 100644 --- a/app/src/main/java/ru/dragonestia/picker/util/NamingValidator.java +++ b/app/src/main/java/ru/dragonestia/picker/util/NamingValidator.java @@ -5,15 +5,15 @@ import lombok.experimental.UtilityClass; @UtilityClass public class NamingValidator { - public boolean validateNodeIdentifier(String input) { + public boolean validateNodeId(String input) { return input.matches("^[a-z\\d-]+$"); } - public boolean validateBucketIdentifier(String input) { + public boolean validateRoomId(String input) { return input.matches("^[a-z\\d-]+$"); } - public boolean validateUserIdentifier(String input) { + public boolean validateUserId(String input) { return input.matches("^[aA-zZ\\d-.\\s:/@%?!~$)(+=_|;*]+$"); } } diff --git a/app/src/test/java/ru/dragonestia/picker/service/BucketServiceTest.java b/app/src/test/java/ru/dragonestia/picker/service/BucketServiceTest.java deleted file mode 100644 index ab63647..0000000 --- a/app/src/test/java/ru/dragonestia/picker/service/BucketServiceTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package ru.dragonestia.picker.service; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import ru.dragonestia.picker.model.Bucket; -import ru.dragonestia.picker.model.Node; -import ru.dragonestia.picker.model.type.LoadBalancingMethod; -import ru.dragonestia.picker.model.type.SlotLimit; - -import java.util.HashMap; - -public class BucketServiceTest { - - private BucketService bucketService; - private HashMap bucketMap; - - @BeforeEach - void setup() { - bucketMap = new HashMap<>(); - bucketService = Mockito.mock(BucketService.class); - Mockito.doAnswer(invocation -> { - var bucket = invocation.getArgument(0, Bucket.class); - - return null; - }).when(bucketService).createBucket(Mockito.any(Bucket.class)); - } - - Node createNode() { - return new Node("test-node", LoadBalancingMethod.ROUND_ROBIN); - } - - @Test - void test() { - var node = createNode(); - - bucketService.createBucket(Bucket.create("test-bucket", node, SlotLimit.unlimited(), "")); - } -} diff --git a/app/src/test/java/ru/dragonestia/picker/service/RoomServiceTest.java b/app/src/test/java/ru/dragonestia/picker/service/RoomServiceTest.java new file mode 100644 index 0000000..3a7daff --- /dev/null +++ b/app/src/test/java/ru/dragonestia/picker/service/RoomServiceTest.java @@ -0,0 +1,39 @@ +package ru.dragonestia.picker.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import ru.dragonestia.picker.model.Room; +import ru.dragonestia.picker.model.Node; +import ru.dragonestia.picker.model.type.PickingMode; +import ru.dragonestia.picker.model.type.SlotLimit; + +import java.util.HashMap; + +public class RoomServiceTest { + + private RoomService roomService; + private HashMap roomMap; + + @BeforeEach + void setup() { + roomMap = new HashMap<>(); + roomService = Mockito.mock(RoomService.class); + Mockito.doAnswer(invocation -> { + var room = invocation.getArgument(0, Room.class); + + return null; + }).when(roomService).create(Mockito.any(Room.class)); + } + + Node createNode() { + return new Node("test-node", PickingMode.ROUND_ROBIN); + } + + @Test + void test() { + var node = createNode(); + + roomService.create(Room.create("test-room", node, SlotLimit.unlimited(), "")); + } +} diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/component/AddUsers.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/component/AddUsers.java index 2a19dc9..f20f325 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/component/AddUsers.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/component/AddUsers.java @@ -12,21 +12,21 @@ import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.textfield.TextField; import lombok.Getter; -import ru.dragonestia.picker.cp.model.Bucket; +import ru.dragonestia.picker.cp.model.Room; import ru.dragonestia.picker.cp.model.User; import java.util.List; public class AddUsers extends Details { - private final Bucket bucket; + private final Room room; private final Checkbox ignoreSlots; private final VerticalLayout usersLayout; - public AddUsers(Bucket bucket) { + public AddUsers(Room room) { super(new H2("Add users")); - this.bucket = bucket; + this.room = room; usersLayout = new VerticalLayout(); add(addUserToTransacionButton()); @@ -84,8 +84,8 @@ public class AddUsers extends Details { } private TextField createUserIdentifierField(boolean canBeDeleted) { - var field = new TextField("User identifier"); - field.setPlaceholder("example-user-identifier"); + var field = new TextField("User id"); + field.setPlaceholder("example-user-id"); field.setHelperText("It can be UUID, username, numeric ids, etc"); field.setMinWidth(20, Unit.REM); diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/component/NodeList.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/component/NodeList.java index 6ef198a..0919c91 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/component/NodeList.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/component/NodeList.java @@ -51,14 +51,14 @@ public class NodeList extends VerticalLayout { var temp = input.trim(); nodesGrid.setItems(cachedNodes.stream() - .filter(node -> node.identifier().startsWith(temp)) + .filter(node -> node.id().startsWith(temp)) .toList()); } private Grid createGrid() { var grid = new Grid<>(Node.class, false); - grid.addColumn(Node::identifier).setHeader("Identifier"); - grid.addColumn(node -> node.method().getName()).setHeader("Mode"); + grid.addColumn(Node::id).setHeader("Identifier"); + grid.addColumn(node -> node.mode().getName()).setHeader("Mode"); grid.addComponentColumn(this::createManageButtons).setHeader("Manage"); return grid; } @@ -84,12 +84,12 @@ public class NodeList extends VerticalLayout { } private void clickDetailsButton(Node node) { - getUI().ifPresent(ui -> ui.navigate("/nodes/" + node.identifier())); + getUI().ifPresent(ui -> ui.navigate("/nodes/" + node.id())); } private void clickRemoveButton(Node node) { var dialog = new Dialog("Confirm node deletion"); - dialog.add(new Paragraph("Confirm that you want to delete node. Enter '" + node.identifier() + "' to field below and confirm.")); + dialog.add(new Paragraph("Confirm that you want to delete node. Enter '" + node.id() + "' to field below and confirm.")); var inputField = new TextField(); dialog.add(inputField); @@ -98,14 +98,14 @@ public class NodeList extends VerticalLayout { var button = new Button("Confirm"); button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR); button.addClickListener(event -> { - if (!node.identifier().equals(inputField.getValue())) { + if (!node.id().equals(inputField.getValue())) { Notification.show("Invalid input", 3000, Notification.Position.TOP_END) .addThemeVariants(NotificationVariant.LUMO_ERROR); return; } removeNode(node); - Notification.show("Node '" + node.identifier() + "' was successfully removed!", 3000, Notification.Position.TOP_END) + Notification.show("Node '" + node.id() + "' was successfully removed!", 3000, Notification.Position.TOP_END) .addThemeVariants(NotificationVariant.LUMO_SUCCESS); dialog.close(); }); @@ -129,7 +129,7 @@ public class NodeList extends VerticalLayout { private void removeNode(Node node) { if (removeMethod != null) { - removeMethod.accept(node.identifier()); + removeMethod.accept(node.id()); } } } diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/component/RegisterNode.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/component/RegisterNode.java index 3cf7be4..f12d9c2 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/component/RegisterNode.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/component/RegisterNode.java @@ -17,7 +17,7 @@ import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.data.renderer.ComponentRenderer; import org.springframework.lang.Nullable; import ru.dragonestia.picker.cp.model.Node; -import ru.dragonestia.picker.cp.model.type.LoadBalancingMethod; +import ru.dragonestia.picker.cp.model.type.PickingMode; import java.util.function.Function; @@ -25,7 +25,7 @@ public class RegisterNode extends Details { private final Function onSubmit; private final TextField identifierField; - private final RadioButtonGroup modeRadio; + private final RadioButtonGroup modeRadio; public RegisterNode(Function onSubmit) { super(new H2("Register node")); @@ -58,15 +58,15 @@ public class RegisterNode extends Details { return button; } - private RadioButtonGroup createModeRadio() { - var radio = new RadioButtonGroup("Mode"); + private RadioButtonGroup createModeRadio() { + var radio = new RadioButtonGroup("Mode"); radio.addThemeVariants(RadioGroupVariant.LUMO_VERTICAL); - radio.setRenderer(new ComponentRenderer(mode -> new Span(mode.getName()))); - radio.setItems(LoadBalancingMethod.SEQUENTIAL_FILLING, - LoadBalancingMethod.ROUND_ROBIN, - LoadBalancingMethod.LEAST_PICKED); + radio.setRenderer(new ComponentRenderer(mode -> new Span(mode.getName()))); + radio.setItems(PickingMode.SEQUENTIAL_FILLING, + PickingMode.ROUND_ROBIN, + PickingMode.LEAST_PICKED); - radio.setValue(LoadBalancingMethod.SEQUENTIAL_FILLING); + radio.setValue(PickingMode.SEQUENTIAL_FILLING); return radio; } @@ -76,7 +76,7 @@ public class RegisterNode extends Details { private @Nullable String validateForm(String identifier) { if (identifier.isEmpty()) { - return "Node identifier cannot be empty"; + return "Node id cannot be empty"; } return null; @@ -88,7 +88,7 @@ public class RegisterNode extends Details { String error = null; if (identifierField.isInvalid() || (error = validateForm(nodeIdentifier)) != null) { if (identifierField.isInvalid()) { - error = "Invalid node identifier format"; + error = "Invalid node id format"; } Notification.show(error, 3000, Notification.Position.TOP_END) diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/component/RegisterBucket.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/component/RegisterRoom.java similarity index 81% rename from control-panel/src/main/java/ru/dragonestia/picker/cp/component/RegisterBucket.java rename to control-panel/src/main/java/ru/dragonestia/picker/cp/component/RegisterRoom.java index 0d5bfee..7cae85c 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/component/RegisterBucket.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/component/RegisterRoom.java @@ -13,28 +13,28 @@ import com.vaadin.flow.component.textfield.Autocomplete; import com.vaadin.flow.component.textfield.TextArea; import com.vaadin.flow.component.textfield.TextField; import org.springframework.lang.Nullable; -import ru.dragonestia.picker.cp.model.Bucket; +import ru.dragonestia.picker.cp.model.Room; import ru.dragonestia.picker.cp.model.Node; import ru.dragonestia.picker.cp.model.type.SlotLimit; import java.util.function.Function; -public class RegisterBucket extends Details { +public class RegisterRoom extends Details { private final Node node; - private final Function onSubmit; + private final Function onSubmit; private final TextField identifierField; private final TextArea payloadField; private final Checkbox lockedField; - public RegisterBucket(Node node, Function onSubmit) { - super(new H2("Register bucket")); + public RegisterRoom(Node node, Function onSubmit) { + super(new H2("Register room")); this.node = node; this.onSubmit = onSubmit; var layout = new VerticalLayout(); layout.add(createNodeIdentifierField()); - layout.add(identifierField = createBucketIdentifierField()); + layout.add(identifierField = createRoomIdentifierField()); layout.add(payloadField = createPayloadField()); layout.add(lockedField = createLockedField()); layout.add(createSubmitButton()); @@ -45,15 +45,15 @@ public class RegisterBucket extends Details { private TextField createNodeIdentifierField() { var field = new TextField("Node identifier"); field.setMinWidth(20, Unit.REM); - field.setValue(node.identifier()); + field.setValue(node.id()); field.setReadOnly(true); return field; } - private TextField createBucketIdentifierField() { + private TextField createRoomIdentifierField() { var field = new TextField("Identifier"); field.setMinWidth(20, Unit.REM); - field.setPlaceholder("example-bucket-id"); + field.setPlaceholder("example-room-id"); field.setHelperText("The field can contain only lowercase letters, numbers and a dash character"); field.setRequired(true); field.setPattern("^[a-z\\d-]+$"); @@ -103,7 +103,7 @@ public class RegisterBucket extends Details { String error = null; if (identifierField.isInvalid() || (error = validateForm(nodeIdentifier)) != null) { if (identifierField.isInvalid()) { - error = "Invalid bucket identifier format"; + error = "Invalid room id format"; } Notification.show(error, 3000, Notification.Position.TOP_END) @@ -111,9 +111,9 @@ public class RegisterBucket extends Details { return; } - var bucket = Bucket.create(nodeIdentifier, node, SlotLimit.unlimited(), payloadField.getValue()); - bucket.setLocked(lockedField.getValue()); - var response = onSubmit.apply(bucket); + var room = Room.create(nodeIdentifier, node, SlotLimit.unlimited(), payloadField.getValue()); + room.setLocked(lockedField.getValue()); + var response = onSubmit.apply(room); clear(); if (response.error()) { Notification.show(response.reason(), 3000, Notification.Position.TOP_END) @@ -121,7 +121,7 @@ public class RegisterBucket extends Details { return; } - Notification.show("Bucket was successfully registered", 3000, Notification.Position.TOP_END) + Notification.show("Room was successfully registered", 3000, Notification.Position.TOP_END) .addThemeVariants(NotificationVariant.LUMO_SUCCESS); } diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/component/BucketList.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/component/RoomList.java similarity index 70% rename from control-panel/src/main/java/ru/dragonestia/picker/cp/component/BucketList.java rename to control-panel/src/main/java/ru/dragonestia/picker/cp/component/RoomList.java index 599eba0..5d67551 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/component/BucketList.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/component/RoomList.java @@ -16,32 +16,32 @@ 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.picker.cp.model.dto.BucketDTO; +import ru.dragonestia.picker.cp.model.dto.RoomDTO; import java.util.List; import java.util.function.Consumer; -public class BucketList extends VerticalLayout { +public class RoomList extends VerticalLayout { private final String nodeIdentifier; - private final Grid bucketsGrid; + private final Grid roomsGrid; private final TextField searchField; - private List cachedBuckets; - @Setter private Consumer removeMethod; + private List cachedRooms; + @Setter private Consumer removeMethod; - public BucketList(String nodeIdentifier, List buckets) { + public RoomList(String nodeIdentifier, List buckets) { this.nodeIdentifier = nodeIdentifier; - cachedBuckets = buckets; + cachedRooms = buckets; - add(new H2("Buckets")); + add(new H2("Rooms")); add(searchField = createSearchField()); - add(bucketsGrid = createGrid()); + add(roomsGrid = createGrid()); update(buckets); } private TextField createSearchField() { - var field = new TextField("Search bucket"); + var field = new TextField("Search room"); field.setPrefixComponent(new Icon(VaadinIcon.SEARCH)); field.setClearButtonVisible(true); field.setHelperText("Press Enter to search"); @@ -52,27 +52,27 @@ public class BucketList extends VerticalLayout { private void applySearch(String input) { var temp = input.trim(); - bucketsGrid.setItems(cachedBuckets.stream() - .filter(bucket -> bucket.identifier().startsWith(temp)) + roomsGrid.setItems(cachedRooms.stream() + .filter(room -> room.id().startsWith(temp)) .toList()); } - private Grid createGrid() { - var grid = new Grid<>(BucketDTO.class, false); - grid.addColumn(BucketDTO::identifier).setHeader("Identifier"); - grid.addComponentColumn(bucket -> { + private Grid createGrid() { + var grid = new Grid<>(RoomDTO.class, false); + grid.addColumn(RoomDTO::id).setHeader("Identifier"); + grid.addComponentColumn(room -> { var result = new Span(); - if (bucket.slots() == -1) { + if (room.slots() == -1) { result.setText("Unlimited"); result.getElement().getThemeList().add("badge contrast"); } else { - result.setText(Integer.toString(bucket.slots())); + result.setText(Integer.toString(room.slots())); } return result; }).setHeader("Slots").setTextAlign(ColumnTextAlign.CENTER); - grid.addComponentColumn(bucket -> { + grid.addComponentColumn(room -> { var result = new Span(); - if (bucket.locked()) { + if (room.locked()) { result.setText("Yes"); result.getElement().getThemeList().add("badge error"); } else { @@ -84,19 +84,19 @@ public class BucketList extends VerticalLayout { return grid; } - private HorizontalLayout createManageButtons(BucketDTO bucket) { + private HorizontalLayout createManageButtons(RoomDTO room) { var layout = new HorizontalLayout(); { var button = new Button("Details"); - button.addClickListener(event -> clickDetailsButton(bucket)); + button.addClickListener(event -> clickDetailsButton(room)); button.addThemeVariants(ButtonVariant.LUMO_PRIMARY); layout.add(button); } { var button = new Button("Remove"); - button.addClickListener(event -> clickRemoveButton(bucket)); + button.addClickListener(event -> clickRemoveButton(room)); button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR); layout.add(button); } @@ -104,16 +104,16 @@ public class BucketList extends VerticalLayout { return layout; } - private void clickDetailsButton(BucketDTO bucket) { + private void clickDetailsButton(RoomDTO bucket) { getUI().ifPresent(ui -> { ui.navigate("/nodes/" + nodeIdentifier + - "/buckets/" + bucket.identifier()); + "/rooms/" + bucket.id()); }); } - private void clickRemoveButton(BucketDTO bucket) { + private void clickRemoveButton(RoomDTO bucket) { var dialog = new Dialog("Confirm bucket deletion"); - dialog.add(new Paragraph("Confirm that you want to delete bucket. Enter '" + bucket.identifier() + "' to field below and confirm.")); + dialog.add(new Paragraph("Confirm that you want to delete bucket. Enter '" + bucket.id() + "' to field below and confirm.")); var inputField = new TextField(); dialog.add(inputField); @@ -122,14 +122,14 @@ public class BucketList extends VerticalLayout { var button = new Button("Confirm"); button.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR); button.addClickListener(event -> { - if (!bucket.identifier().equals(inputField.getValue())) { + if (!bucket.id().equals(inputField.getValue())) { Notification.show("Invalid input", 3000, Notification.Position.TOP_END) .addThemeVariants(NotificationVariant.LUMO_ERROR); return; } removeBucket(bucket); - Notification.show("Bucket '" + bucket.identifier() + "' was successfully removed!", 3000, Notification.Position.TOP_END) + Notification.show("Bucket '" + bucket.id() + "' was successfully removed!", 3000, Notification.Position.TOP_END) .addThemeVariants(NotificationVariant.LUMO_SUCCESS); dialog.close(); }); @@ -146,12 +146,12 @@ public class BucketList extends VerticalLayout { dialog.open(); } - public void update(List buckets) { - cachedBuckets = buckets; + public void update(List buckets) { + cachedRooms = buckets; applySearch(searchField.getValue()); } - private void removeBucket(BucketDTO bucket) { + private void removeBucket(RoomDTO bucket) { if (removeMethod != null) { removeMethod.accept(bucket); } diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/component/UserList.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/component/UserList.java index 0f3d9f3..adc5b55 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/component/UserList.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/component/UserList.java @@ -4,7 +4,7 @@ import com.vaadin.flow.component.grid.ColumnTextAlign; import com.vaadin.flow.component.grid.Grid; import com.vaadin.flow.component.html.Span; import com.vaadin.flow.component.orderedlayout.VerticalLayout; -import ru.dragonestia.picker.cp.model.Bucket; +import ru.dragonestia.picker.cp.model.Room; import ru.dragonestia.picker.cp.model.User; import java.util.ArrayList; @@ -12,14 +12,14 @@ import java.util.List; public class UserList extends VerticalLayout { - private final Bucket bucket; + private final Room room; private final Grid usersGrid; private final Span totalUsers = new Span(); private final Span occupancy = new Span(); private List cachedUsers = new ArrayList<>(); - public UserList(Bucket bucket, List users) { - this.bucket = bucket; + public UserList(Room room, List users) { + this.room = room; add(usersGrid = createUsersGrid()); @@ -28,8 +28,8 @@ public class UserList extends VerticalLayout { private Grid createUsersGrid() { var grid = new Grid(); - grid.addColumn(User::identifier).setHeader("User Identifier").setFooter(totalUsers); - grid.addColumn(user -> 0).setTextAlign(ColumnTextAlign.CENTER).setHeader("Linked with buckets") // TODO + grid.addColumn(User::id).setHeader("User Identifier").setFooter(totalUsers); + grid.addColumn(user -> 0).setTextAlign(ColumnTextAlign.CENTER).setHeader("Linked with rooms") // TODO .setFooter(occupancy); grid.addComponentColumn(user -> new Span("buttons")).setHeader("Manage"); // TODO return grid; @@ -39,6 +39,6 @@ public class UserList extends VerticalLayout { cachedUsers = users; usersGrid.setItems(users); totalUsers.setText("Total users: " + users.size()); - occupancy.setText("Occupancy: %s".formatted(bucket.getUsingPercentage(users.size()))); + occupancy.setText("Occupancy: %s".formatted(room.getUsingPercentage(users.size()))); } } diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/model/Node.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/model/Node.java index f6dc48d..046167a 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/model/Node.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/model/Node.java @@ -1,15 +1,15 @@ package ru.dragonestia.picker.cp.model; import lombok.NonNull; -import ru.dragonestia.picker.cp.model.type.LoadBalancingMethod; +import ru.dragonestia.picker.cp.model.type.PickingMode; import java.io.Serializable; -public record Node(@NonNull String identifier, @NonNull LoadBalancingMethod method) implements Serializable { +public record Node(@NonNull String id, @NonNull PickingMode mode) implements Serializable { @Override public int hashCode() { - return identifier.hashCode(); + return id.hashCode(); } @Override @@ -17,7 +17,7 @@ public record Node(@NonNull String identifier, @NonNull LoadBalancingMethod meth if (object == this) return true; if (object == null) return false; if (object instanceof Node other) { - return identifier.equals(other.identifier); + return id.equals(other.id); } return false; } diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/model/Bucket.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/model/Room.java similarity index 58% rename from control-panel/src/main/java/ru/dragonestia/picker/cp/model/Bucket.java rename to control-panel/src/main/java/ru/dragonestia/picker/cp/model/Room.java index 87cf600..35d3a97 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/model/Bucket.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/model/Room.java @@ -8,29 +8,30 @@ import ru.dragonestia.picker.cp.model.type.SlotLimit; import java.net.URI; @Getter -public class Bucket { +public class Room { - private final String identifier; - private final String nodeIdentifier; + private final String id; + private final String nodeId; private final SlotLimit slots; private final String payload; private boolean locked = false; @JsonCreator - private Bucket(@JsonProperty("identifier") String identifier, - @JsonProperty("nodeIdentifier") String nodeIdentifier, - @JsonProperty("slots") SlotLimit slots, - @JsonProperty("payload") String payload, - @JsonProperty("locked") boolean locked) { - this.identifier = identifier; - this.nodeIdentifier = nodeIdentifier; + private Room(@JsonProperty("id") String id, + @JsonProperty("nodeIdentifier") String nodeId, + @JsonProperty("slots") SlotLimit slots, + @JsonProperty("payload") String payload, + @JsonProperty("locked") boolean locked) { + + this.id = id; + this.nodeId = nodeId; this.slots = slots; this.payload = payload; this.locked = locked; } - public static Bucket create(String identifier, Node node, SlotLimit limit, String payload) { - return new Bucket(identifier, node.identifier(), limit, payload, false); + public static Room create(String roomId, Node node, SlotLimit limit, String payload) { + return new Room(roomId, node.id(), limit, payload, false); } public void setLocked(boolean value) { @@ -45,21 +46,21 @@ public class Bucket { @Override public int hashCode() { - return identifier.hashCode(); + return id.hashCode(); } @Override public boolean equals(Object object) { if (object == this) return true; if (object == null) return false; - if (object instanceof Bucket other) { - return identifier.equals(other.identifier); + if (object instanceof Room other) { + return id.equals(other.id); } return false; } public URI createApiURI() { - return URI.create("/nodes/" + nodeIdentifier + "/buckets/" + identifier); + return URI.create("/nodes/" + nodeId + "/rooms/" + id); } public String getUsingPercentage(int used) { diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/model/User.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/model/User.java index 4f47d18..a91553a 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/model/User.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/model/User.java @@ -2,11 +2,11 @@ package ru.dragonestia.picker.cp.model; import lombok.NonNull; -public record User(@NonNull String identifier) { +public record User(@NonNull String id) { @Override public int hashCode() { - return identifier.hashCode(); + return id.hashCode(); } @Override @@ -14,7 +14,7 @@ public record User(@NonNull String identifier) { if (object == this) return true; if (object == null) return false; if (object instanceof User other) { - return identifier.equals(other.identifier); + return id.equals(other.id); } return false; } diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/model/dto/BucketDTO.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/model/dto/RoomDTO.java similarity index 51% rename from control-panel/src/main/java/ru/dragonestia/picker/cp/model/dto/BucketDTO.java rename to control-panel/src/main/java/ru/dragonestia/picker/cp/model/dto/RoomDTO.java index 1131576..4e13f95 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/model/dto/BucketDTO.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/model/dto/RoomDTO.java @@ -4,13 +4,13 @@ import ru.dragonestia.picker.cp.model.Node; import java.net.URI; -public record BucketDTO(String identifier, int slots, boolean locked) { +public record RoomDTO(String id, int slots, boolean locked) { public URI uriAPI(Node node) { - return uriAPI(node.identifier()); + return uriAPI(node.id()); } public URI uriAPI(String nodeId) { - return URI.create("/nodes/" + nodeId + "/buckets/" + identifier); + return URI.create("/nodes/" + nodeId + "/rooms/" + id); } } diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/model/type/LoadBalancingMethod.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/model/type/PickingMode.java similarity index 89% rename from control-panel/src/main/java/ru/dragonestia/picker/cp/model/type/LoadBalancingMethod.java rename to control-panel/src/main/java/ru/dragonestia/picker/cp/model/type/PickingMode.java index 51de23a..f48ec09 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/model/type/LoadBalancingMethod.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/model/type/PickingMode.java @@ -5,7 +5,7 @@ import lombok.RequiredArgsConstructor; @Getter @RequiredArgsConstructor -public enum LoadBalancingMethod { +public enum PickingMode { SEQUENTIAL_FILLING("Sequential filling"), ROUND_ROBIN("Round Robin"), LEAST_PICKED("Least Picked"); diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/page/NodeDetailsPage.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/page/NodeDetailsPage.java index 92521eb..9cd43b8 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/page/NodeDetailsPage.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/page/NodeDetailsPage.java @@ -13,12 +13,12 @@ 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.picker.cp.component.BucketList; +import ru.dragonestia.picker.cp.component.RoomList; import ru.dragonestia.picker.cp.component.NavPath; -import ru.dragonestia.picker.cp.component.RegisterBucket; +import ru.dragonestia.picker.cp.component.RegisterRoom; import ru.dragonestia.picker.cp.model.Node; -import ru.dragonestia.picker.cp.model.dto.BucketDTO; -import ru.dragonestia.picker.cp.repository.BucketRepository; +import ru.dragonestia.picker.cp.model.dto.RoomDTO; +import ru.dragonestia.picker.cp.repository.RoomRepository; import ru.dragonestia.picker.cp.repository.NodeRepository; import java.util.List; @@ -29,16 +29,16 @@ import java.util.List; public class NodeDetailsPage extends VerticalLayout implements BeforeEnterObserver { private final NodeRepository nodeRepository; - private final BucketRepository bucketRepository; + private final RoomRepository roomRepository; private Node node; - private RegisterBucket registerBucket; - private BucketList bucketList; + private RegisterRoom registerRoom; + private RoomList roomList; public NodeDetailsPage(@Autowired NodeRepository nodeRepository, - @Autowired BucketRepository bucketRepository) { + @Autowired RoomRepository roomRepository) { this.nodeRepository = nodeRepository; - this.bucketRepository = bucketRepository; + this.roomRepository = roomRepository; } @Override @@ -51,7 +51,7 @@ public class NodeDetailsPage extends VerticalLayout implements BeforeEnterObserv var nodeId = nodeIdOpt.get(); add(new NavPath(new NavPath.Point("Nodes", "/nodes"), new NavPath.Point(nodeId, "/nodes/" + nodeId))); - var nodeOpt = nodeRepository.findNode(nodeId); + var nodeOpt = nodeRepository.find(nodeId); if (nodeOpt.isEmpty()) { add(new H2("Error 404")); add(new Paragraph("Node not found")); @@ -61,27 +61,27 @@ public class NodeDetailsPage extends VerticalLayout implements BeforeEnterObserv } node = nodeOpt.get(); - initComponents(node, bucketRepository.all(node)); + initComponents(node, roomRepository.all(node)); } - private void initComponents(Node node, List buckets) { + private void initComponents(Node node, List rooms) { printNodeDetails(node); add(new Hr()); - add(registerBucket = new RegisterBucket(node, (bucket) -> { + add(registerRoom = new RegisterRoom(node, (bucket) -> { try { - bucketRepository.register(bucket); - return new RegisterBucket.Response(false, null); + roomRepository.register(bucket); + return new RegisterRoom.Response(false, null); } catch (Error error) { - return new RegisterBucket.Response(true, error.getMessage()); + return new RegisterRoom.Response(true, error.getMessage()); } finally { - bucketList.update(bucketRepository.all(node)); + roomList.update(roomRepository.all(node)); } })); add(new Hr()); - add(bucketList = new BucketList(node.identifier(), buckets)); - bucketList.setRemoveMethod(bucket -> { - bucketRepository.remove(node, bucket); - bucketList.update(bucketRepository.all(node)); + add(roomList = new RoomList(node.id(), rooms)); + roomList.setRemoveMethod(bucket -> { + roomRepository.remove(node, bucket); + roomList.update(roomRepository.all(node)); }); } @@ -89,8 +89,8 @@ public class NodeDetailsPage extends VerticalLayout implements BeforeEnterObserv add(new H2("Node details")); var layout = new VerticalLayout(); - layout.add(new Html("Identifier: " + node.identifier() + "")); - layout.add(new Html("Mode: " + node.method().getName() + "")); + layout.add(new Html("Identifier: " + node.id() + "")); + layout.add(new Html("Mode: " + node.mode().getName() + "")); add(layout); } diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/page/NodesPage.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/page/NodesPage.java index 4f6c9a3..d3a746b 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/page/NodesPage.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/page/NodesPage.java @@ -31,15 +31,15 @@ public class NodesPage extends VerticalLayout { add(new Hr()); add(nodeList = createNodeListElement()); nodeList.setRemoveMethod(nodeIdentifier -> { - nodeRepository.removeNode(nodeIdentifier); - nodeList.update(nodeRepository.getNodes()); + nodeRepository.remove(nodeIdentifier); + nodeList.update(nodeRepository.all()); }); } protected RegisterNode createRegisterNodeElement() { return new RegisterNode(node -> { try { - nodeRepository.registerNode(node); + nodeRepository.register(node); return new RegisterNode.Response(false, ""); } catch (Error ex) { return new RegisterNode.Response(true, ex.getMessage()); @@ -47,12 +47,12 @@ public class NodesPage extends VerticalLayout { log.throwing(ex); return new RegisterNode.Response(true, ex.getMessage()); } finally { - nodeList.update(nodeRepository.getNodes()); + nodeList.update(nodeRepository.all()); } }); } protected NodeList createNodeListElement() { - return new NodeList(nodeRepository.getNodes()); + return new NodeList(nodeRepository.all()); } } diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/page/BucketDetailsPage.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/page/RoomDetailsPage.java similarity index 52% rename from control-panel/src/main/java/ru/dragonestia/picker/cp/page/BucketDetailsPage.java rename to control-panel/src/main/java/ru/dragonestia/picker/cp/page/RoomDetailsPage.java index 79abfb0..871dedc 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/page/BucketDetailsPage.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/page/RoomDetailsPage.java @@ -1,6 +1,7 @@ package ru.dragonestia.picker.cp.page; import com.vaadin.flow.component.Html; +import com.vaadin.flow.component.Text; import com.vaadin.flow.component.Unit; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.html.H2; @@ -19,29 +20,29 @@ import org.springframework.beans.factory.annotation.Autowired; import ru.dragonestia.picker.cp.component.AddUsers; import ru.dragonestia.picker.cp.component.NavPath; import ru.dragonestia.picker.cp.component.UserList; -import ru.dragonestia.picker.cp.model.Bucket; +import ru.dragonestia.picker.cp.model.Room; import ru.dragonestia.picker.cp.model.Node; -import ru.dragonestia.picker.cp.repository.BucketRepository; +import ru.dragonestia.picker.cp.repository.RoomRepository; import ru.dragonestia.picker.cp.repository.NodeRepository; import ru.dragonestia.picker.cp.repository.UserRepository; -@Route("/nodes/:nodeId/buckets/:bucketId") -public class BucketDetailsPage extends VerticalLayout implements BeforeEnterObserver { +@Route("/nodes/:nodeId/rooms/:roomId") +public class RoomDetailsPage extends VerticalLayout implements BeforeEnterObserver { private final NodeRepository nodeRepository; - private final BucketRepository bucketRepository; + private final RoomRepository roomRepository; private final UserRepository userRepository; private Node node; - private Bucket bucket; + private Room room; private AddUsers addUsers; private UserList userList; - private Button lockBucketButton; - private VerticalLayout bucketInfo; + private Button lockRoomButton; + private VerticalLayout roomInfo; @Autowired - public BucketDetailsPage(NodeRepository nodeRepository, BucketRepository bucketRepository, UserRepository userRepository) { + public RoomDetailsPage(NodeRepository nodeRepository, RoomRepository roomRepository, UserRepository userRepository) { this.nodeRepository = nodeRepository; - this.bucketRepository = bucketRepository; + this.roomRepository = roomRepository; this.userRepository = userRepository; } @@ -53,19 +54,19 @@ public class BucketDetailsPage extends VerticalLayout implements BeforeEnterObse return; } - var bucketIdOpt = event.getRouteParameters().get("bucketId"); - if (bucketIdOpt.isEmpty()) { - getUI().ifPresent(ui -> ui.navigate("/buckets/" + nodeIdOpt.get())); + var roomIdOpt = event.getRouteParameters().get("roomId"); + if (roomIdOpt.isEmpty()) { + getUI().ifPresent(ui -> ui.navigate("/rooms/" + nodeIdOpt.get())); return; } var nodeId = nodeIdOpt.get(); - var bucketId = bucketIdOpt.get(); + var roomId = roomIdOpt.get(); add(new NavPath(new NavPath.Point("Nodes", "/nodes"), new NavPath.Point(nodeId, "/nodes/" + nodeId), - new NavPath.Point(bucketId, "/nodes/" + nodeId + "/buckets/" + bucketId))); + new NavPath.Point(roomId, "/nodes/" + nodeId + "/rooms/" + roomId))); - var nodeOpt = nodeRepository.findNode(nodeId); + var nodeOpt = nodeRepository.find(nodeId); if (nodeOpt.isEmpty()) { add(new H2("Error 404")); add(new Paragraph("Node not found!")); @@ -75,75 +76,75 @@ public class BucketDetailsPage extends VerticalLayout implements BeforeEnterObse } node = nodeOpt.get(); - var bucketOpt = bucketRepository.find(node, bucketId); + var bucketOpt = roomRepository.find(node, roomId); 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) + add(new Paragraph("Room not found!")); + Notification.show("Room '" + nodeId + "' does not exist", 3000, Notification.Position.TOP_END) .addThemeVariants(NotificationVariant.LUMO_ERROR); return; } - bucket = bucketOpt.get(); + room = bucketOpt.get(); init(); } private void init() { - add(new H2("Bucket details")); - printBucketDetails(); + add(new H2("Room details")); + printRoomDetails(); add(new Hr()); - add(addUsers = new AddUsers(bucket)); + add(addUsers = new AddUsers(room)); add(new Hr()); add(new H2("Users")); - add(userList = new UserList(bucket, userRepository.all(bucket))); + add(userList = new UserList(room, userRepository.all(room))); } - 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 updateRoomInfo() { + roomInfo.removeAll(); + roomInfo.add(new Html("Node identifier: " + room.getNodeId() + "")); + roomInfo.add(new Html("Room identifier: " + room.getId() + "")); + roomInfo.add(new Html("Slots: " + (room.getSlots().isUnlimited()? "Unlimited" : room.getSlots().slots()) + "")); + roomInfo.add(new Html("Locked: " + (room.isLocked()? "Yes" : "No") + "")); } - private void printBucketDetails() { - add(bucketInfo = new VerticalLayout()); - bucketInfo.setPadding(false); + private void printRoomDetails() { + add(roomInfo = new VerticalLayout()); + roomInfo.setPadding(false); - updateBucketInfo(); - add(lockBucketButton = new Button("", event -> changeBucketLockedState())); - setLockBucketButtonState(); + updateRoomInfo(); + add(lockRoomButton = new Button("", event -> changeBucketLockedState())); + setLockRoomButtonState(); - var payload = new TextArea("Payload(" + bucket.getPayload().length() + ")"); - payload.setValue(bucket.getPayload()); + var payload = new TextArea("Payload(" + room.getPayload().length() + ")"); + payload.setValue(room.getPayload()); payload.setReadOnly(true); payload.setMinWidth(50, Unit.REM); add(payload); } - private void setLockBucketButtonState() { - if (bucket.isLocked()) { - lockBucketButton.setText("Unlock"); - lockBucketButton.setPrefixComponent(new Icon(VaadinIcon.UNLOCK)); + private void setLockRoomButtonState() { + if (room.isLocked()) { + lockRoomButton.setText("Unlock"); + lockRoomButton.setPrefixComponent(new Icon(VaadinIcon.UNLOCK)); } else { - lockBucketButton.setText("Lock"); - lockBucketButton.setPrefixComponent(new Icon(VaadinIcon.LOCK)); + lockRoomButton.setText("Lock"); + lockRoomButton.setPrefixComponent(new Icon(VaadinIcon.LOCK)); } } private void changeBucketLockedState() { - var newValue = !bucket.isLocked(); + var newValue = !room.isLocked(); try { - bucketRepository.lock(bucket, newValue); + roomRepository.lock(room, newValue); } catch (Error error) { Notification.show(error.getMessage(), 3000, Notification.Position.TOP_END) .addThemeVariants(NotificationVariant.LUMO_ERROR); return; } - bucket.setLocked(newValue); - setLockBucketButtonState(); - updateBucketInfo(); + room.setLocked(newValue); + setLockRoomButtonState(); + updateRoomInfo(); Notification.show("Success", 3000, Notification.Position.TOP_END) .addThemeVariants(NotificationVariant.LUMO_SUCCESS); diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/BucketRepository.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/BucketRepository.java deleted file mode 100644 index a66216c..0000000 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/BucketRepository.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.dragonestia.picker.cp.repository; - -import ru.dragonestia.picker.cp.model.Bucket; -import ru.dragonestia.picker.cp.model.Node; -import ru.dragonestia.picker.cp.model.dto.BucketDTO; - -import java.util.List; -import java.util.Optional; - -public interface BucketRepository { - - List all(Node node); - - void register(Bucket bucket); - - void remove(Bucket bucket); - - void remove(Node node, BucketDTO bucket); - - Optional find(Node node, String identifier); - - void lock(Bucket bucket, boolean value); -} diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/NodeRepository.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/NodeRepository.java index 3d21b22..8a4fdda 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/NodeRepository.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/NodeRepository.java @@ -7,11 +7,11 @@ import java.util.Optional; public interface NodeRepository { - void registerNode(Node node); + void register(Node node); - List getNodes(); + List all(); - Optional findNode(String identifier); + Optional find(String nodeId); - void removeNode(String identifier); + void remove(String nodeId); } diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/RoomRepository.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/RoomRepository.java new file mode 100644 index 0000000..0cfa563 --- /dev/null +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/RoomRepository.java @@ -0,0 +1,23 @@ +package ru.dragonestia.picker.cp.repository; + +import ru.dragonestia.picker.cp.model.Room; +import ru.dragonestia.picker.cp.model.Node; +import ru.dragonestia.picker.cp.model.dto.RoomDTO; + +import java.util.List; +import java.util.Optional; + +public interface RoomRepository { + + List all(Node node); + + void register(Room room); + + void remove(Room room); + + void remove(Node node, RoomDTO bucket); + + Optional find(Node node, String roomId); + + void lock(Room room, boolean value); +} diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/UserRepository.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/UserRepository.java index 5a4a31a..e326c22 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/UserRepository.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/UserRepository.java @@ -1,6 +1,6 @@ package ru.dragonestia.picker.cp.repository; -import ru.dragonestia.picker.cp.model.Bucket; +import ru.dragonestia.picker.cp.model.Room; import ru.dragonestia.picker.cp.model.User; import java.util.Collection; @@ -8,9 +8,9 @@ import java.util.List; public interface UserRepository { - void linkWithBucket(Bucket bucket, Collection users); + void linkWithRoom(Room room, Collection users); - void unlinkFromBucket(Bucket bucket, Collection users); + void unlinkFromRoom(Room room, Collection users); - List all(Bucket bucket); + List all(Room room); } diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/BucketRepositoryImpl.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/BucketRepositoryImpl.java deleted file mode 100644 index 131fa24..0000000 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/BucketRepositoryImpl.java +++ /dev/null @@ -1,100 +0,0 @@ -package ru.dragonestia.picker.cp.repository.impl; - -import com.vaadin.flow.spring.annotation.SpringComponent; -import lombok.RequiredArgsConstructor; -import lombok.extern.log4j.Log4j2; -import org.springframework.web.client.HttpClientErrorException; -import ru.dragonestia.picker.cp.model.Bucket; -import ru.dragonestia.picker.cp.model.Node; -import ru.dragonestia.picker.cp.model.dto.BucketDTO; -import ru.dragonestia.picker.cp.repository.BucketRepository; -import ru.dragonestia.picker.cp.repository.impl.response.BucketInfoResponse; -import ru.dragonestia.picker.cp.repository.impl.response.BucketListResponse; -import ru.dragonestia.picker.cp.repository.impl.response.BucketRegisterResponse; - -import java.net.URI; -import java.util.List; -import java.util.Objects; -import java.util.Optional; - -@Log4j2 -@RequiredArgsConstructor -@SpringComponent -public class BucketRepositoryImpl implements BucketRepository { - - private final RestUtil rest; - - @Override - public List all(Node node) { - var entity = rest.getEntity(URI.create("/nodes/" + node.identifier() + "/buckets"), - BucketListResponse.class); - - if (entity.getStatusCode().value() == 404) { - throw new Error("Node with identifier '" + node.identifier() + "' does not exists'"); - } - - if (!entity.hasBody()) { - throw new Error("Bucket list did not present"); - } - - return Objects.requireNonNull(entity.getBody()).buckets(); - } - - @Override - public void register(Bucket bucket) { - try { - var response = rest.post(URI.create("/nodes/" + bucket.getNodeIdentifier() + "/buckets"), - BucketRegisterResponse.class, - params -> { - params.put("identifier", bucket.getIdentifier()); - params.put("slots", Integer.toString(bucket.getSlots().slots())); - params.put("payload", bucket.getPayload()); - params.put("locked", Boolean.toString(bucket.isLocked())); - }); - - if (response.success()) return; - throw new Error(response.message()); - } catch (HttpClientErrorException ex) { - var response = ex.getResponseBodyAs(BucketRegisterResponse.class); - - if (response != null) { - throw new Error(response.message()); - } - - log.throwing(ex); - throw new Error("Internal error. Check logs"); - } - } - - @Override - public void remove(Bucket bucket) { - rest.delete(URI.create("/nodes/" + bucket.getNodeIdentifier() + "/buckets/" + bucket.getIdentifier()), params -> {}); - } - - @Override - public void remove(Node node, BucketDTO bucket) { - rest.delete(URI.create("/nodes/" + node.identifier() + "/buckets/" + bucket.identifier()), 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(); - } - } - - @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/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/NodeRepositoryImpl.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/NodeRepositoryImpl.java index f7e4863..d26300d 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/NodeRepositoryImpl.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/NodeRepositoryImpl.java @@ -21,14 +21,14 @@ public class NodeRepositoryImpl implements NodeRepository { private final RestUtil rest; @Override - public void registerNode(Node node) { + public void register(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()); + params.put("nodeId", node.id()); + params.put("method", node.mode().name()); }); } catch (Exception ex) { throw new RuntimeException("Internal error", ex); @@ -40,14 +40,14 @@ public class NodeRepositoryImpl implements NodeRepository { } @Override - public List getNodes() { + public List all() { return rest.get(URI.create("nodes"), NodeListResponse.class).nodes(); } @Override - public Optional findNode(String identifier) { + public Optional find(String nodeId) { try { - var response = rest.get(URI.create("nodes/" + identifier), NodeDetailsResponse.class); + var response = rest.get(URI.create("nodes/" + nodeId), NodeDetailsResponse.class); return Optional.of(response.node()); } catch (Exception ex) { return Optional.empty(); @@ -55,7 +55,7 @@ public class NodeRepositoryImpl implements NodeRepository { } @Override - public void removeNode(String identifier) { - rest.delete(URI.create("nodes/" + identifier), params -> {}); + public void remove(String nodeId) { + rest.delete(URI.create("nodes/" + nodeId), params -> {}); } } diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/RoomRepositoryImpl.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/RoomRepositoryImpl.java new file mode 100644 index 0000000..8ca8528 --- /dev/null +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/RoomRepositoryImpl.java @@ -0,0 +1,100 @@ +package ru.dragonestia.picker.cp.repository.impl; + +import com.vaadin.flow.spring.annotation.SpringComponent; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.springframework.web.client.HttpClientErrorException; +import ru.dragonestia.picker.cp.model.Room; +import ru.dragonestia.picker.cp.model.Node; +import ru.dragonestia.picker.cp.model.dto.RoomDTO; +import ru.dragonestia.picker.cp.repository.RoomRepository; +import ru.dragonestia.picker.cp.repository.impl.response.RoomInfoResponse; +import ru.dragonestia.picker.cp.repository.impl.response.RoomListResponse; +import ru.dragonestia.picker.cp.repository.impl.response.RoomRegisterResponse; + +import java.net.URI; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +@Log4j2 +@RequiredArgsConstructor +@SpringComponent +public class RoomRepositoryImpl implements RoomRepository { + + private final RestUtil rest; + + @Override + public List all(Node node) { + var entity = rest.getEntity(URI.create("/nodes/" + node.id() + "/rooms"), + RoomListResponse.class); + + if (entity.getStatusCode().value() == 404) { + throw new Error("Node with identifier '" + node.id() + "' does not exists'"); + } + + if (!entity.hasBody()) { + throw new Error("Room list did not present"); + } + + return Objects.requireNonNull(entity.getBody()).rooms(); + } + + @Override + public void register(Room room) { + try { + var response = rest.post(URI.create("/nodes/" + room.getNodeId() + "/rooms"), + RoomRegisterResponse.class, + params -> { + params.put("roomId", room.getId()); + params.put("slots", Integer.toString(room.getSlots().slots())); + params.put("payload", room.getPayload()); + params.put("locked", Boolean.toString(room.isLocked())); + }); + + if (response.success()) return; + throw new Error(response.message()); + } catch (HttpClientErrorException ex) { + var response = ex.getResponseBodyAs(RoomRegisterResponse.class); + + if (response != null) { + throw new Error(response.message()); + } + + log.throwing(ex); + throw new Error("Internal error. Check logs"); + } + } + + @Override + public void remove(Room room) { + rest.delete(URI.create("/nodes/" + room.getNodeId() + "/rooms/" + room.getId()), params -> {}); + } + + @Override + public void remove(Node node, RoomDTO room) { + rest.delete(URI.create("/nodes/" + node.id() + "/rooms/" + room.id()), params -> {}); + } + + @Override + public Optional find(Node node, String roomId) { + try { + var response = rest.get(URI.create("/nodes/" + node.id() + "/rooms/" + roomId), RoomInfoResponse.class, map -> {}); + return Optional.of(response.room()); + } catch (Exception ex) { + return Optional.empty(); + } + } + + @Override + public void lock(Room room, boolean value) { + try { + rest.post(URI.create(room.createApiURI() + "/lock"), Boolean.class, params -> { + params.put("newState", Boolean.toString(value)); + }); + } catch (Exception ex) { + log.throwing(ex); + throw new Error("Error when changing room locked state"); + } + } +} diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/UserRepositoryImpl.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/UserRepositoryImpl.java index bb1fd6e..1ced238 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/UserRepositoryImpl.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/UserRepositoryImpl.java @@ -3,10 +3,10 @@ package ru.dragonestia.picker.cp.repository.impl; import com.vaadin.flow.spring.annotation.SpringComponent; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; -import ru.dragonestia.picker.cp.model.Bucket; +import ru.dragonestia.picker.cp.model.Room; import ru.dragonestia.picker.cp.model.User; import ru.dragonestia.picker.cp.repository.UserRepository; -import ru.dragonestia.picker.cp.repository.impl.response.BucketUserListResponse; +import ru.dragonestia.picker.cp.repository.impl.response.RoomUserListResponse; import java.net.URI; import java.util.Collection; @@ -20,20 +20,20 @@ public class UserRepositoryImpl implements UserRepository { private final RestUtil rest; @Override - public void linkWithBucket(Bucket bucket, Collection users) { + public void linkWithRoom(Room room, Collection users) { // TODO } @Override - public void unlinkFromBucket(Bucket bucket, Collection users) { + public void unlinkFromRoom(Room room, Collection users) { // TODO } @Override - public List all(Bucket bucket) { + public List all(Room room) { try { - var response = rest.get(URI.create("/nodes/%s/buckets/%s/users".formatted(bucket.getNodeIdentifier(), bucket.getIdentifier())), - BucketUserListResponse.class, + var response = rest.get(URI.create("/nodes/%s/rooms/%s/users".formatted(room.getNodeId(), room.getId())), + RoomUserListResponse.class, params -> {}); return response.users(); diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketInfoResponse.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketInfoResponse.java deleted file mode 100644 index dcefcaf..0000000 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketInfoResponse.java +++ /dev/null @@ -1,5 +0,0 @@ -package ru.dragonestia.picker.cp.repository.impl.response; - -import ru.dragonestia.picker.cp.model.Bucket; - -public record BucketInfoResponse(Bucket bucket) {} diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketListResponse.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketListResponse.java deleted file mode 100644 index e9b1875..0000000 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketListResponse.java +++ /dev/null @@ -1,7 +0,0 @@ -package ru.dragonestia.picker.cp.repository.impl.response; - -import ru.dragonestia.picker.cp.model.dto.BucketDTO; - -import java.util.List; - -public record BucketListResponse(String node, List buckets) {} diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketRegisterResponse.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketRegisterResponse.java deleted file mode 100644 index 0cb548c..0000000 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketRegisterResponse.java +++ /dev/null @@ -1,3 +0,0 @@ -package ru.dragonestia.picker.cp.repository.impl.response; - -public record BucketRegisterResponse(boolean success, String message) {} diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomInfoResponse.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomInfoResponse.java new file mode 100644 index 0000000..9f3dfcd --- /dev/null +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomInfoResponse.java @@ -0,0 +1,5 @@ +package ru.dragonestia.picker.cp.repository.impl.response; + +import ru.dragonestia.picker.cp.model.Room; + +public record RoomInfoResponse(Room room) {} diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomListResponse.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomListResponse.java new file mode 100644 index 0000000..5dbe758 --- /dev/null +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomListResponse.java @@ -0,0 +1,7 @@ +package ru.dragonestia.picker.cp.repository.impl.response; + +import ru.dragonestia.picker.cp.model.dto.RoomDTO; + +import java.util.List; + +public record RoomListResponse(String node, List rooms) {} diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomRegisterResponse.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomRegisterResponse.java new file mode 100644 index 0000000..86adffe --- /dev/null +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomRegisterResponse.java @@ -0,0 +1,3 @@ +package ru.dragonestia.picker.cp.repository.impl.response; + +public record RoomRegisterResponse(boolean success, String message) {} diff --git a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketUserListResponse.java b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomUserListResponse.java similarity index 60% rename from control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketUserListResponse.java rename to control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomUserListResponse.java index 1abc033..abc3c22 100644 --- a/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/BucketUserListResponse.java +++ b/control-panel/src/main/java/ru/dragonestia/picker/cp/repository/impl/response/RoomUserListResponse.java @@ -4,4 +4,4 @@ import ru.dragonestia.picker.cp.model.User; import java.util.List; -public record BucketUserListResponse(int slots, int usedSlots, List users) {} +public record RoomUserListResponse(int slots, int usedSlots, List users) {}