Implemented getting bucket users
This commit is contained in:
parent
070068aecc
commit
b8dc6a24df
@ -0,0 +1,44 @@
|
||||
package ru.dragonestia.loadbalancer.web.component;
|
||||
|
||||
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.loadbalancer.web.model.Bucket;
|
||||
import ru.dragonestia.loadbalancer.web.model.User;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class UserList extends VerticalLayout {
|
||||
|
||||
private final Bucket bucket;
|
||||
private final Grid<User> usersGrid;
|
||||
private final Span totalUsers = new Span();
|
||||
private final Span occupancy = new Span();
|
||||
private List<User> cachedUsers = new ArrayList<>();
|
||||
|
||||
public UserList(Bucket bucket, List<User> users) {
|
||||
this.bucket = bucket;
|
||||
|
||||
add(usersGrid = createUsersGrid());
|
||||
|
||||
update(users);
|
||||
}
|
||||
|
||||
private Grid<User> createUsersGrid() {
|
||||
var grid = new Grid<User>();
|
||||
grid.addColumn(User::identifier).setHeader("User Identifier").setFooter(totalUsers);
|
||||
grid.addColumn(user -> 0).setTextAlign(ColumnTextAlign.CENTER).setHeader("Linked with buckets") // TODO
|
||||
.setFooter(occupancy);
|
||||
grid.addComponentColumn(user -> new Span("buttons")).setHeader("Manage"); // TODO
|
||||
return grid;
|
||||
}
|
||||
|
||||
public void update(List<User> users) {
|
||||
cachedUsers = users;
|
||||
usersGrid.setItems(users);
|
||||
totalUsers.setText("Total users: " + users.size());
|
||||
occupancy.setText("Occupancy: %s".formatted(bucket.getUsingPercentage(users.size())));
|
||||
}
|
||||
}
|
||||
@ -63,4 +63,10 @@ public class Bucket {
|
||||
public URI createApiURI() {
|
||||
return URI.create("/nodes/" + nodeIdentifier + "/buckets/" + identifier);
|
||||
}
|
||||
|
||||
public String getUsingPercentage(int used) {
|
||||
if (getSlots().isUnlimited()) return "0%";
|
||||
double percent = used / (double) getSlots().slots() * 100;
|
||||
return ((int) percent) + "%";
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,26 +18,31 @@ import com.vaadin.flow.router.Route;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import ru.dragonestia.loadbalancer.web.component.AddUsers;
|
||||
import ru.dragonestia.loadbalancer.web.component.NavPath;
|
||||
import ru.dragonestia.loadbalancer.web.component.UserList;
|
||||
import ru.dragonestia.loadbalancer.web.model.Bucket;
|
||||
import ru.dragonestia.loadbalancer.web.model.Node;
|
||||
import ru.dragonestia.loadbalancer.web.repository.BucketRepository;
|
||||
import ru.dragonestia.loadbalancer.web.repository.NodeRepository;
|
||||
import ru.dragonestia.loadbalancer.web.repository.UserRepository;
|
||||
|
||||
@Route("/nodes/:nodeId/buckets/:bucketId")
|
||||
public class BucketDetailsPage extends VerticalLayout implements BeforeEnterObserver {
|
||||
|
||||
private final NodeRepository nodeRepository;
|
||||
private final BucketRepository bucketRepository;
|
||||
private final UserRepository userRepository;
|
||||
private Node node;
|
||||
private Bucket bucket;
|
||||
private AddUsers addUsers;
|
||||
private UserList userList;
|
||||
private Button lockBucketButton;
|
||||
private VerticalLayout bucketInfo;
|
||||
|
||||
@Autowired
|
||||
public BucketDetailsPage(NodeRepository nodeRepository, BucketRepository bucketRepository) {
|
||||
public BucketDetailsPage(NodeRepository nodeRepository, BucketRepository bucketRepository, UserRepository userRepository) {
|
||||
this.nodeRepository = nodeRepository;
|
||||
this.bucketRepository = bucketRepository;
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -90,6 +95,7 @@ public class BucketDetailsPage extends VerticalLayout implements BeforeEnterObse
|
||||
add(addUsers = new AddUsers(bucket));
|
||||
add(new Hr());
|
||||
add(new H2("Users"));
|
||||
add(userList = new UserList(bucket, userRepository.all(bucket)));
|
||||
}
|
||||
|
||||
private void updateBucketInfo() {
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
package ru.dragonestia.loadbalancer.web.repository;
|
||||
|
||||
import ru.dragonestia.loadbalancer.web.model.Bucket;
|
||||
import ru.dragonestia.loadbalancer.web.model.User;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public interface UserRepository {
|
||||
|
||||
void linkWithBucket(Bucket bucket, Collection<User> users);
|
||||
|
||||
void unlinkFromBucket(Bucket bucket, Collection<User> users);
|
||||
|
||||
List<User> all(Bucket bucket);
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
package ru.dragonestia.loadbalancer.web.repository.impl;
|
||||
|
||||
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import ru.dragonestia.loadbalancer.web.model.Bucket;
|
||||
import ru.dragonestia.loadbalancer.web.model.User;
|
||||
import ru.dragonestia.loadbalancer.web.repository.UserRepository;
|
||||
import ru.dragonestia.loadbalancer.web.repository.impl.response.BucketUserListResponse;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Log4j2
|
||||
@RequiredArgsConstructor
|
||||
@SpringComponent
|
||||
public class UserRepositoryImpl implements UserRepository {
|
||||
|
||||
private final RestUtil rest;
|
||||
|
||||
@Override
|
||||
public void linkWithBucket(Bucket bucket, Collection<User> users) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlinkFromBucket(Bucket bucket, Collection<User> users) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<User> all(Bucket bucket) {
|
||||
try {
|
||||
var response = rest.get(URI.create("/nodes/%s/buckets/%s/users".formatted(bucket.getNodeIdentifier(), bucket.getIdentifier())),
|
||||
BucketUserListResponse.class,
|
||||
params -> {});
|
||||
|
||||
return response.users();
|
||||
} catch (Exception ex) {
|
||||
log.throwing(ex);
|
||||
throw new Error("Internal error");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package ru.dragonestia.loadbalancer.web.repository.impl.response;
|
||||
|
||||
import ru.dragonestia.loadbalancer.web.model.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record BucketUserListResponse(int slots, int usedSlots, List<User> users) {}
|
||||
@ -10,11 +10,16 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import ru.dragonestia.loadbalancer.interceptor.DebugInterceptor;
|
||||
import ru.dragonestia.loadbalancer.model.Bucket;
|
||||
import ru.dragonestia.loadbalancer.model.Node;
|
||||
import ru.dragonestia.loadbalancer.model.User;
|
||||
import ru.dragonestia.loadbalancer.model.type.LoadBalancingMethod;
|
||||
import ru.dragonestia.loadbalancer.model.type.SlotLimit;
|
||||
import ru.dragonestia.loadbalancer.repository.BucketRepository;
|
||||
import ru.dragonestia.loadbalancer.repository.NodeRepository;
|
||||
import ru.dragonestia.loadbalancer.repository.UserRepository;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
@Profile("test")
|
||||
@ -24,6 +29,9 @@ public class TestConfig implements WebMvcConfigurer {
|
||||
|
||||
private final NodeRepository nodeRepository;
|
||||
private final BucketRepository bucketRepository;
|
||||
private final UserRepository userRepository;
|
||||
|
||||
private final Random rand = new Random(0);
|
||||
|
||||
@Override
|
||||
public void addInterceptors(@NonNull InterceptorRegistry registry) {
|
||||
@ -41,13 +49,26 @@ public class TestConfig implements WebMvcConfigurer {
|
||||
nodeRepository.createNode(node);
|
||||
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
bucketRepository.createBucket(Bucket.create("test-" + i, node, SlotLimit.of(5 * i), "Some payload"));
|
||||
var slots = 5 * i;
|
||||
var bucket = Bucket.create("test-" + i, node, SlotLimit.of(slots), "Some payload");
|
||||
bucketRepository.createBucket(bucket);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
var bucket = Bucket.create(UUID.randomUUID().toString(), node, SlotLimit.unlimited(), "Some payload");
|
||||
var bucket = Bucket.create(randomUUID().toString(), node, SlotLimit.unlimited(), "Some payload");
|
||||
bucket.setLocked((i & 1) == 0);
|
||||
bucketRepository.createBucket(bucket);
|
||||
}
|
||||
}
|
||||
|
||||
private UUID randomUUID() {
|
||||
byte[] randomBytes = new byte[16];
|
||||
rand.nextBytes(randomBytes);
|
||||
return UUID.nameUUIDFromBytes(randomBytes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,114 @@
|
||||
package ru.dragonestia.loadbalancer.controller;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.function.EntityResponse;
|
||||
import ru.dragonestia.loadbalancer.controller.response.BucketUserListResponse;
|
||||
import ru.dragonestia.loadbalancer.controller.response.LinkUsersWithBucketResponse;
|
||||
import ru.dragonestia.loadbalancer.model.Bucket;
|
||||
import ru.dragonestia.loadbalancer.model.Node;
|
||||
import ru.dragonestia.loadbalancer.model.User;
|
||||
import ru.dragonestia.loadbalancer.service.BucketService;
|
||||
import ru.dragonestia.loadbalancer.service.NodeService;
|
||||
import ru.dragonestia.loadbalancer.service.UserService;
|
||||
import ru.dragonestia.loadbalancer.util.NamingValidator;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
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<BucketUserListResponse> 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<LinkUsersWithBucketResponse> 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<User>();
|
||||
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());
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
package ru.dragonestia.loadbalancer.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.dragonestia.loadbalancer.model.Bucket;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/users")
|
||||
public class UserController {
|
||||
|
||||
@GetMapping
|
||||
Collection<Bucket> linkedBucketsForUser(@RequestParam(name = "user") String userIdentifier) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
String linkUserWithBucket(@RequestParam(name = "user") String userIdentifier,
|
||||
@RequestParam(name = "bucket") String bucketIdentifier,
|
||||
@RequestParam(name = "force") boolean force) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
String unlinkUsersForBucket(@RequestParam(name = "users") String userIdentifiers,
|
||||
@RequestParam(name = "bucket") String bucketIdentifier) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package ru.dragonestia.loadbalancer.controller.response;
|
||||
|
||||
import ru.dragonestia.loadbalancer.model.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record BucketUserListResponse(int slots, int usedSlots, List<User> users) {}
|
||||
@ -0,0 +1,3 @@
|
||||
package ru.dragonestia.loadbalancer.controller.response;
|
||||
|
||||
public record LinkUsersWithBucketResponse(boolean success, String message) {}
|
||||
@ -26,8 +26,6 @@ public interface BucketRepository {
|
||||
|
||||
Optional<Bucket> pickFreeBucket(Node node, Collection<User> users);
|
||||
|
||||
void freeBucket(Bucket bucket, Collection<User> users);
|
||||
|
||||
void onCreateNode(Node node);
|
||||
|
||||
void onRemoveNode(Node node);
|
||||
|
||||
@ -9,11 +9,13 @@ import java.util.Map;
|
||||
|
||||
public interface UserRepository {
|
||||
|
||||
Map<User, Boolean> linkWithBucket(Bucket bucket, Collection<User> users);
|
||||
Map<User, Boolean> linkWithBucket(Bucket bucket, Collection<User> users, boolean force);
|
||||
|
||||
int unlinkWithBucket(Bucket bucket, Collection<User> users);
|
||||
|
||||
List<Bucket> findAllLinkedUserBuckets(User user);
|
||||
|
||||
void onRemoveBucket(Bucket bucket);
|
||||
|
||||
List<User> usersOf(Bucket bucket);
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ public class BucketRepositoryImpl implements BucketRepository {
|
||||
|
||||
if (container.isPresent()) {
|
||||
var cont = container.get();
|
||||
var addedUsers = userRepository.linkWithBucket(cont.bucket(), users);
|
||||
var addedUsers = userRepository.linkWithBucket(cont.bucket(), users, false);
|
||||
cont.used().getAndAdd((int) addedUsers.values().stream().filter(Boolean.TRUE::equals).count());
|
||||
}
|
||||
|
||||
@ -106,30 +106,6 @@ public class BucketRepositoryImpl implements BucketRepository {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeBucket(Bucket bucket, Collection<User> users) {
|
||||
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");
|
||||
}
|
||||
|
||||
var buckets = node2bucketsMap.get(node.get());
|
||||
if (!buckets.containsKey(bucket.getIdentifier())) {
|
||||
throw new IllegalArgumentException("Bucket '" + nodeId + "' does not exist");
|
||||
}
|
||||
|
||||
var delta = userRepository.unlinkWithBucket(bucket, users);
|
||||
if (buckets.get(bucket.getIdentifier()).used().getAndAdd(-delta) < 0) {
|
||||
throw new RuntimeException("Bucket has less than 0 users");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateNode(Node node) {
|
||||
synchronized (node2bucketsMap) {
|
||||
|
||||
@ -13,17 +13,37 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
public class UserRepositoryImpl implements UserRepository {
|
||||
|
||||
private final Map<User, Set<Bucket>> usersMap = new ConcurrentHashMap<>();
|
||||
private final Map<NodeBucketPath, Set<User>> bucketUsers = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public Map<User, Boolean> linkWithBucket(Bucket bucket, Collection<User> users) {
|
||||
public Map<User, Boolean> linkWithBucket(Bucket bucket, Collection<User> users, boolean force) {
|
||||
var result = new HashMap<User, Boolean>();
|
||||
|
||||
synchronized (usersMap) {
|
||||
var path = new NodeBucketPath(bucket.getNodeIdentifier(), bucket.getIdentifier());
|
||||
var usersSet = bucketUsers.getOrDefault(path, new HashSet<>());
|
||||
|
||||
if (force || bucket.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.add(bucket));
|
||||
result.put(user, !set.contains(bucket));
|
||||
}
|
||||
|
||||
if (bucket.getSlots().getSlots() < usersSet.size() + users.size()) {
|
||||
throw new Error("Bucket are full");
|
||||
}
|
||||
}
|
||||
|
||||
for (var user: users) {
|
||||
var set = usersMap.getOrDefault(user, new HashSet<>());
|
||||
set.add(bucket);
|
||||
usersMap.put(user, set);
|
||||
}
|
||||
|
||||
usersSet.addAll(users);
|
||||
bucketUsers.put(path, usersSet);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -43,6 +63,15 @@ public class UserRepositoryImpl implements UserRepository {
|
||||
usersMap.remove(user);
|
||||
}
|
||||
});
|
||||
|
||||
var path = new NodeBucketPath(bucket.getNodeIdentifier(), bucket.getIdentifier());
|
||||
var set = bucketUsers.getOrDefault(path, new HashSet<>());
|
||||
set.removeAll(users);
|
||||
if (set.isEmpty()) {
|
||||
bucketUsers.remove(path);
|
||||
} else {
|
||||
bucketUsers.put(path, set);
|
||||
}
|
||||
}
|
||||
return counter.get();
|
||||
}
|
||||
@ -65,4 +94,31 @@ public class UserRepositoryImpl implements UserRepository {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<User> usersOf(Bucket bucket) {
|
||||
synchronized (usersMap) {
|
||||
return bucketUsers.getOrDefault(new NodeBucketPath(bucket.getNodeIdentifier(), bucket.getIdentifier()), new HashSet<>())
|
||||
.stream()
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
private record NodeBucketPath(String node, String bucket) {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(node, bucket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) return false;
|
||||
if (o == this) return true;
|
||||
if (o instanceof NodeBucketPath other) {
|
||||
return other.node().equals(node()) && other.bucket().equals(bucket());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,6 +24,4 @@ public interface BucketService {
|
||||
int countAvailableBuckets(Node node, int requiredSlots);
|
||||
|
||||
Bucket pickAvailableBucket(Node node, List<User> users);
|
||||
|
||||
void freeBucket(Bucket bucket, List<User> users);
|
||||
}
|
||||
|
||||
@ -3,9 +3,16 @@ package ru.dragonestia.loadbalancer.service;
|
||||
import ru.dragonestia.loadbalancer.model.Bucket;
|
||||
import ru.dragonestia.loadbalancer.model.User;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public interface UserService {
|
||||
|
||||
List<Bucket> getUserBuckets(User user);
|
||||
|
||||
void linkUsersWithBucket(Bucket bucket, Collection<User> users, boolean force);
|
||||
|
||||
void unlinkUsersFromBucket(Bucket bucket, Collection<User> users);
|
||||
|
||||
List<User> getBucketUsers(Bucket bucket);
|
||||
}
|
||||
|
||||
@ -51,9 +51,4 @@ public class BucketServiceImpl implements BucketService {
|
||||
public Bucket pickAvailableBucket(Node node, List<User> users) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeBucket(Bucket bucket, List<User> users) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
package ru.dragonestia.loadbalancer.service.impl;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.dragonestia.loadbalancer.model.Bucket;
|
||||
import ru.dragonestia.loadbalancer.model.User;
|
||||
import ru.dragonestia.loadbalancer.repository.UserRepository;
|
||||
import ru.dragonestia.loadbalancer.service.UserService;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
@Override
|
||||
public List<Bucket> getUserBuckets(User user) {
|
||||
return userRepository.findAllLinkedUserBuckets(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void linkUsersWithBucket(Bucket bucket, Collection<User> users, boolean force) {
|
||||
userRepository.linkWithBucket(bucket, users, force);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlinkUsersFromBucket(Bucket bucket, Collection<User> users) {
|
||||
userRepository.unlinkWithBucket(bucket, users);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<User> getBucketUsers(Bucket bucket) {
|
||||
return userRepository.usersOf(bucket);
|
||||
}
|
||||
}
|
||||
@ -12,4 +12,8 @@ public class NamingValidator {
|
||||
public boolean validateBucketIdentifier(String input) {
|
||||
return input.matches("^[a-z\\d-]+$");
|
||||
}
|
||||
|
||||
public boolean validateUserIdentifier(String input) {
|
||||
return input.matches("^[aA-zZ\\d-.\\s:/@%?!~$)(+=_|;*]+$");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user