!renamed Node to Instance

This commit is contained in:
Andrey Terentev 2024-05-10 11:37:11 +07:00 committed by Andrey Terentev
parent de54a8590e
commit cdb4f69a0f
58 changed files with 482 additions and 482 deletions

View File

@ -32,8 +32,8 @@ class Example {
"qwerty123"
);
// Creating node
var nodeId = NodeIdentifier.of("test-node");
// Creating instance
var nodeId = NodeIdentifier.of("test-instance");
var nodeDefinition = new NodeDefinition(nodeId)
.setPickingMethod(PickingMethod.LEAST_PICKED);
client.getNodeRepository().saveNode(nodeDefinition);

View File

@ -15,7 +15,7 @@ public class ExceptionFactory {
private static Map<String, Constructor> init() {
var factory = new HashMap<String, Constructor>();
factory.put(InvalidNodeIdentifierException.ERROR_ID, InvalidNodeIdentifierException::new);
factory.put(InvalidInstanceIdentifierException.ERROR_ID, InvalidInstanceIdentifierException::new);
factory.put(InvalidRoomIdentifierException.ERROR_ID, InvalidRoomIdentifierException::new);
factory.put(InvalidUsernamesException.ERROR_ID, InvalidUsernamesException::new);
factory.put(NodeAlreadyExistException.ERROR_ID, NodeAlreadyExistException::new);

View File

@ -4,17 +4,17 @@ import ru.dragonestia.picker.api.repository.response.ErrorResponse;
import java.util.Map;
public final class InvalidNodeIdentifierException extends ApiException {
public final class InvalidInstanceIdentifierException extends ApiException {
public static final String ERROR_ID = "err.node.invalid_identifier";
private final String nodeId;
public InvalidNodeIdentifierException(String nodeId) {
public InvalidInstanceIdentifierException(String nodeId) {
this.nodeId = nodeId;
}
public InvalidNodeIdentifierException(ErrorResponse errorResponse) {
public InvalidInstanceIdentifierException(ErrorResponse errorResponse) {
this(errorResponse.details().get("identifier"));
}

View File

@ -19,15 +19,15 @@ public interface IRoom {
return RoomIdentifier.of(getIdentifier());
}
@NotNull String getNodeIdentifier();
@NotNull String getInstanceIdentifier();
@Transient
default @NotNull NodeIdentifier getNodeIdentifierObject() {
return NodeIdentifier.of(getNodeIdentifier());
return NodeIdentifier.of(getInstanceIdentifier());
}
default @NotNull RoomPath getPath() {
return new RoomPath(NodeIdentifier.of(getNodeIdentifier()), RoomIdentifier.of(getIdentifier()));
return new RoomPath(NodeIdentifier.of(getInstanceIdentifier()), RoomIdentifier.of(getIdentifier()));
}
int getMaxSlots();

View File

@ -19,7 +19,7 @@ public class ResponseRoom implements IRoom {
private String id;
@Schema(description = "Node identifier", example = "test-node")
private String nodeId;
private String instanceId;
@Schema(description = "Slots for users. -1 - unlimited slots", example = "25")
private int slots;
@ -36,9 +36,9 @@ public class ResponseRoom implements IRoom {
@Internal
public ResponseRoom() {}
public ResponseRoom(@NotNull String id, @NotNull String nodeId, int slots, boolean locked, @NotNull String payload) {
public ResponseRoom(@NotNull String id, @NotNull String instanceId, int slots, boolean locked, @NotNull String payload) {
this.id = id;
this.nodeId = nodeId;
this.instanceId = instanceId;
this.slots = slots;
this.locked = locked;
this.payload = payload;
@ -51,8 +51,8 @@ public class ResponseRoom implements IRoom {
}
@Override
public @NotNull String getNodeIdentifier() {
return nodeId;
public @NotNull String getInstanceIdentifier() {
return instanceId;
}
@Transient
@ -117,7 +117,7 @@ public class ResponseRoom implements IRoom {
@Override
public int hashCode() {
return Objects.hash(id, nodeId);
return Objects.hash(id, instanceId);
}
@Override
@ -125,13 +125,13 @@ public class ResponseRoom implements IRoom {
if (object == this) return true;
if (object == null) return false;
if (object instanceof ResponseRoom other) {
return id.equals(other.id) && nodeId.equals(other.nodeId);
return id.equals(other.id) && instanceId.equals(other.instanceId);
}
return false;
}
@Override
public String toString() {
return "[ResponseRoom id='%s' nodeId='%s' slots=%s payload.len=%s]".formatted(id, nodeId, slots, payload.length());
return "[ResponseRoom id='%s' nodeId='%s' slots=%s payload.len=%s]".formatted(id, instanceId, slots, payload.length());
}
}

View File

@ -28,7 +28,7 @@ public class RoomDefinition implements IRoom {
}
@Override
public @NotNull String getNodeIdentifier() {
public @NotNull String getInstanceIdentifier() {
return nodeId;
}

View File

@ -18,7 +18,7 @@ public class ShortResponseRoom implements IRoom {
private String id;
@Schema(description = "Node identifier", example = "test-node")
private String nodeId;
private String instanceId;
@Schema(description = "Slots for users. -1 - unlimited slots", example = "25")
private int slots;
@ -32,9 +32,9 @@ public class ShortResponseRoom implements IRoom {
@Internal
public ShortResponseRoom() {}
public ShortResponseRoom(String id, String nodeId, int slots, boolean locked) {
public ShortResponseRoom(String id, String instanceId, int slots, boolean locked) {
this.id = id;
this.nodeId = nodeId;
this.instanceId = instanceId;
this.slots = slots;
this.locked = locked;
this.details = new HashMap<>();
@ -46,8 +46,8 @@ public class ShortResponseRoom implements IRoom {
}
@Override
public @NotNull String getNodeIdentifier() {
return nodeId;
public @NotNull String getInstanceIdentifier() {
return instanceId;
}
@Transient
@ -93,7 +93,7 @@ public class ShortResponseRoom implements IRoom {
@Override
public int hashCode() {
return Objects.hash(id, nodeId);
return Objects.hash(id, instanceId);
}
@Override
@ -101,13 +101,13 @@ public class ShortResponseRoom implements IRoom {
if (object == this) return true;
if (object == null) return false;
if (object instanceof ShortResponseRoom other) {
return id.equals(other.id) && nodeId.equals(other.nodeId);
return id.equals(other.id) && instanceId.equals(other.instanceId);
}
return false;
}
@Override
public String toString() {
return "[ShortResponseRoom id='%s' nodeId='%s' slots=%s]".formatted(id, nodeId, slots);
return "[ShortResponseRoom id='%s' nodeId='%s' slots=%s]".formatted(id, instanceId, slots);
}
}

View File

@ -33,7 +33,7 @@ public class RoomRepositoryImpl implements RoomRepository {
@Override
public void saveRoom(@NotNull RoomDefinition definition) {
rest.query("/nodes/" + definition.getNodeIdentifier() + "/rooms", HttpMethod.POST, params -> {
rest.query("/nodes/" + definition.getInstanceIdentifier() + "/rooms", HttpMethod.POST, params -> {
params.put("roomId", definition.getIdentifier());
params.put("slots", Integer.toString(definition.getMaxSlots()));
params.put("payload", definition.getPayload());
@ -54,7 +54,7 @@ public class RoomRepositoryImpl implements RoomRepository {
@Override
public void removeRoom(@NotNull IRoom room) {
rest.query(
"/nodes/%s/rooms/%s".formatted(room.getNodeIdentifier(), room.getIdentifier()),
"/nodes/%s/rooms/%s".formatted(room.getInstanceIdentifier(), room.getIdentifier()),
HttpMethod.DELETE,
params -> {}
);

View File

@ -75,7 +75,7 @@ public class RoomDetailsPage extends VerticalLayout implements BeforeEnterObserv
private void updateRoomInfo() {
roomInfo.removeAll();
roomInfo.add(new Html("<span>Node identifier: <b>" + room.getNodeIdentifier() + "</b></span>"));
roomInfo.add(new Html("<span>Node identifier: <b>" + room.getInstanceIdentifier() + "</b></span>"));
roomInfo.add(new Html("<span>Room identifier: <b>" + room.getIdentifier() + "</b></span>"));
roomInfo.add(new Html("<span>Slots: <b>" + (room.hasUnlimitedSlots()? "Unlimited" : room.getMaxSlots()) + "</b></span>"));
roomInfo.add(new Html("<span>Locked: <b>" + (room.isLocked()? "Yes" : "No") + "</b></span>"));

View File

@ -64,7 +64,7 @@ public class UserDetailsPage extends VerticalLayout implements BeforeEnterObserv
grid.addColumn(ShortResponseRoom::getIdentifier).setHeader("Room identifier").setSortable(true);
grid.addColumn(ShortResponseRoom::getNodeIdentifier).setHeader("Node identifier").setSortable(true);
grid.addColumn(ShortResponseRoom::getInstanceIdentifier).setHeader("Node identifier").setSortable(true);
grid.addColumn(room -> room.getDetail(RoomDetails.COUNT_USERS)).setHeader("Users")
.setComparator((room1, room2) -> {
@ -78,7 +78,7 @@ public class UserDetailsPage extends VerticalLayout implements BeforeEnterObserv
var button = new Button("Details");
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
button.addClickListener(event -> {
getUI().ifPresent(ui -> ui.navigate("/nodes/%s/rooms/%s".formatted(room.getNodeIdentifier(), room.getIdentifier())));
getUI().ifPresent(ui -> ui.navigate("/nodes/%s/rooms/%s".formatted(room.getInstanceIdentifier(), room.getIdentifier())));
});
return button;
}).setTextAlign(ColumnTextAlign.END).setFrozenToEnd(true).setHeader(createRefreshButton());

View File

@ -4,13 +4,13 @@ import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.ErrorParameter;
import com.vaadin.flow.router.HasErrorParameter;
import jakarta.servlet.http.HttpServletResponse;
import ru.dragonestia.picker.api.exception.InvalidNodeIdentifierException;
import ru.dragonestia.picker.api.exception.InvalidInstanceIdentifierException;
import ru.dragonestia.picker.cp.component.NavPath;
public class InvalidNodeIdentifierPlug extends ErrorPlug implements HasErrorParameter<InvalidNodeIdentifierException> {
public class InvalidNodeIdentifierPlug extends ErrorPlug implements HasErrorParameter<InvalidInstanceIdentifierException> {
@Override
public int setErrorParameter(BeforeEnterEvent beforeEnterEvent, ErrorParameter<InvalidNodeIdentifierException> errorParameter) {
public int setErrorParameter(BeforeEnterEvent beforeEnterEvent, ErrorParameter<InvalidInstanceIdentifierException> errorParameter) {
var ex = errorParameter.getException();
var nodeId = ex.getNodeId();

View File

@ -11,7 +11,7 @@ import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.room.Room;
import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.repository.UserRepository;
@ -55,9 +55,9 @@ public class UserMetricsAspect {
totalUsers.set(userRepository.countAllUsers());
}
@After(value = "execution(void ru.dragonestia.picker.repository.NodeRepository.create(ru.dragonestia.picker.model.node.Node)) && args(node)", argNames = "node")
void onCreateNode(Node node) {
var nodeId = node.getIdentifier();
@After(value = "execution(void ru.dragonestia.picker.repository.InstanceRepository.create(ru.dragonestia.picker.model.instance.Instance)) && args(instance)", argNames = "instance")
void onCreateNode(Instance instance) {
var nodeId = instance.getIdentifier();
var gauge = Gauge.builder("roompicker_node_users_total", () -> data.get(nodeId).users())
.tag("nodeId", nodeId)
.register(meterRegistry);
@ -71,16 +71,16 @@ public class UserMetricsAspect {
.tag("nodeId", nodeId)
.register(meterRegistry);
var roomsGauge = Gauge.builder("roompicker_rooms", () -> roomRepository.all(node).size())
var roomsGauge = Gauge.builder("roompicker_rooms", () -> roomRepository.all(instance).size())
.tag("nodeId", nodeId)
.register(meterRegistry);
data.put(nodeId, new NodeData(gauge, new AtomicInteger(0), counter, new AtomicInteger(0), lockedGauge, roomsGauge));
}
@After(value = "execution(* ru.dragonestia.picker.repository.NodeRepository.delete(ru.dragonestia.picker.model.node.Node)) && args(node)", argNames = "node")
void onDeleteNode(Node node) {
var data = this.data.remove(node.getIdentifier());
@After(value = "execution(* ru.dragonestia.picker.repository.InstanceRepository.delete(ru.dragonestia.picker.model.instance.Instance)) && args(instance)", argNames = "instance")
void onDeleteNode(Instance instance) {
var data = this.data.remove(instance.getIdentifier());
meterRegistry.remove(data.usersGauge());
meterRegistry.remove(data.picksPerMinute());
@ -88,9 +88,9 @@ public class UserMetricsAspect {
meterRegistry.remove(data.roomsGauge());
}
@AfterReturning(value = "execution(* ru.dragonestia.picker.repository.RoomRepository.pick(ru.dragonestia.picker.model.node.Node, *)) && args(node, ..)", argNames = "node")
void onPickRoom(Node node) {
data.get(node.getIdentifier()).picksPerMinute().increment();
@AfterReturning(value = "execution(* ru.dragonestia.picker.repository.RoomRepository.pick(ru.dragonestia.picker.model.instance.Instance, *)) && args(instance, ..)", argNames = "instance")
void onPickRoom(Instance instance) {
data.get(instance.getIdentifier()).picksPerMinute().increment();
}
@Scheduled(fixedDelay = 3_000)
@ -100,7 +100,7 @@ public class UserMetricsAspect {
});
containerRepository.all().forEach(nodeContainer -> {
var locked = data.get(nodeContainer.getNode().getIdentifier()).locked();
var locked = data.get(nodeContainer.getInstance().getIdentifier()).locked();
locked.set(0);
nodeContainer.allRooms().forEach(roomContainer -> {

View File

@ -16,11 +16,11 @@ import ru.dragonestia.picker.api.repository.type.NodeIdentifier;
import ru.dragonestia.picker.api.repository.type.RoomIdentifier;
import ru.dragonestia.picker.api.repository.type.UserIdentifier;
import ru.dragonestia.picker.interceptor.DebugInterceptor;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.user.User;
import ru.dragonestia.picker.model.factory.RoomFactory;
import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.repository.NodeRepository;
import ru.dragonestia.picker.repository.InstanceRepository;
import ru.dragonestia.picker.repository.UserRepository;
import java.util.List;
@ -32,7 +32,7 @@ import java.util.UUID;
@RequiredArgsConstructor
public class TestConfig implements WebMvcConfigurer {
private final NodeRepository nodeRepository;
private final InstanceRepository instanceRepository;
private final RoomRepository roomRepository;
private final UserRepository userRepository;
private final RoomFactory roomFactory;
@ -45,20 +45,20 @@ public class TestConfig implements WebMvcConfigurer {
}
@Bean
void createNodes() {
createNodeWithContent(new Node(NodeIdentifier.of("game-servers"), PickingMethod.ROUND_ROBIN, false));
createNodeWithContent(new Node(NodeIdentifier.of("game-lobbies"), PickingMethod.LEAST_PICKED, false));
createNodeWithContent(new Node(NodeIdentifier.of("hub"), PickingMethod.SEQUENTIAL_FILLING, false));
void createInstances() {
createInstanceWithContent(new Instance(NodeIdentifier.of("game-servers"), PickingMethod.ROUND_ROBIN, false));
createInstanceWithContent(new Instance(NodeIdentifier.of("game-lobbies"), PickingMethod.LEAST_PICKED, false));
createInstanceWithContent(new Instance(NodeIdentifier.of("hub"), PickingMethod.SEQUENTIAL_FILLING, false));
}
@SneakyThrows
private void createNodeWithContent(Node node) {
nodeRepository.create(node);
private void createInstanceWithContent(Instance instance) {
instanceRepository.create(instance);
var json = new ObjectMapper().writer().withDefaultPrettyPrinter();
for (int i = 1; i <= 5; i++) {
var slots = 5 * i;
var room = roomFactory.create(RoomIdentifier.of("test-" + i), node, slots, json.writeValueAsString(generatePayload()), false);
var room = roomFactory.create(RoomIdentifier.of("test-" + i), instance, slots, json.writeValueAsString(generatePayload()), false);
roomRepository.create(room);
for (int j = 0, n = rand.nextInt(slots + 1); j < n; j++) {
@ -68,7 +68,7 @@ public class TestConfig implements WebMvcConfigurer {
}
for (int i = 0; i < 5; i++) {
var room = roomFactory.create(RoomIdentifier.of(randomUUID().toString()), node, IRoom.UNLIMITED_SLOTS, json.writeValueAsString(generatePayload()), false);
var room = roomFactory.create(RoomIdentifier.of(randomUUID().toString()), instance, IRoom.UNLIMITED_SLOTS, json.writeValueAsString(generatePayload()), false);
room.setLocked((i & 1) == 0);
roomRepository.create(room);
}

View File

@ -26,8 +26,8 @@ public class ExceptionHandlerController {
return create(400, ex);
}
@ExceptionHandler(InvalidNodeIdentifierException.class)
ResponseEntity<?> invalidNodeIdentifier(InvalidNodeIdentifierException ex) {
@ExceptionHandler(InvalidInstanceIdentifierException.class)
ResponseEntity<?> invalidNodeIdentifier(InvalidInstanceIdentifierException ex) {
return create(400, ex);
}

View File

@ -11,7 +11,7 @@ import ru.dragonestia.picker.api.repository.response.NodeDetailsResponse;
import ru.dragonestia.picker.api.repository.response.NodeListResponse;
import ru.dragonestia.picker.api.repository.response.PickedRoomResponse;
@Tag(name = "Nodes", description = "Node management")
@Tag(name = "Nodes", description = "Instance management")
@RestController
@RequestMapping("/nodes")
@RequiredArgsConstructor
@ -26,7 +26,7 @@ public class NodeController {
@Operation(summary = "Register new node")
@PostMapping
ResponseEntity<?> registerNode(
@Parameter(description = "Node identifier") @RequestParam(name = "nodeId") String nodeId,
@Parameter(description = "Instance identifier") @RequestParam(name = "nodeId") String nodeId,
@Parameter(description = "Picking method method") @RequestParam(name = "method") PickingMethod method,
@Parameter(description = "Save node") @RequestParam(name = "persist", required = false, defaultValue = "false") boolean persist
) {
@ -36,7 +36,7 @@ public class NodeController {
@Operation(summary = "Get node details")
@GetMapping("/{nodeId}")
ResponseEntity<NodeDetailsResponse> nodeDetails(
@Parameter(description = "Node identifier") @PathVariable("nodeId") String nodeId
@Parameter(description = "Instance identifier") @PathVariable("nodeId") String nodeId
) {
throw new UnsupportedOperationException("Not implemented");
}
@ -44,7 +44,7 @@ public class NodeController {
@Operation(summary = "Unregister node")
@DeleteMapping("/{nodeId}")
ResponseEntity<?> removeNode(
@Parameter(description = "Node identifier") @PathVariable("nodeId") String nodeId
@Parameter(description = "Instance identifier") @PathVariable("nodeId") String nodeId
) {
throw new UnsupportedOperationException("Not implemented");
}
@ -52,7 +52,7 @@ public class NodeController {
@Operation(summary = "Pick node for users")
@PostMapping("/{nodeId}/pick")
ResponseEntity<PickedRoomResponse> pickRoom(
@Parameter(description = "Node identifier") @PathVariable("nodeId") String nodeId,
@Parameter(description = "Instance identifier") @PathVariable("nodeId") String nodeId,
@RequestBody String userIds
) {
throw new UnsupportedOperationException("Not implemented");

View File

@ -19,7 +19,7 @@ public class RoomController {
@Operation(summary = "Get all rooms from node")
@GetMapping
ResponseEntity<RoomListResponse> all(
@Parameter(description = "Node identifier") @PathVariable(name = "nodeId") String nodeId
@Parameter(description = "Instance identifier") @PathVariable(name = "nodeId") String nodeId
) {
throw new UnsupportedOperationException("Not implemented");
}
@ -27,7 +27,7 @@ public class RoomController {
@Operation(summary = "Register new room")
@PostMapping
ResponseEntity<?> register(
@Parameter(description = "Node identifier") @PathVariable(name = "nodeId") String nodeId,
@Parameter(description = "Instance identifier") @PathVariable(name = "nodeId") String nodeId,
@Parameter(description = "Room identifier") @RequestParam(name = "roomId") String roomId,
@Parameter(description = "Maximum users count in room") @RequestParam(name = "slots") int slots,
@Parameter(description = "Payload. Some data") @RequestParam(name = "payload") String payload,
@ -40,7 +40,7 @@ public class RoomController {
@Operation(summary = "Unregister room")
@DeleteMapping("/{roomId}")
ResponseEntity<?> remove(
@Parameter(description = "Node identifier") @PathVariable("nodeId") String nodeId,
@Parameter(description = "Instance identifier") @PathVariable("nodeId") String nodeId,
@Parameter(description = "Room identifier") @PathVariable("roomId") String roomId
) {
throw new UnsupportedOperationException("Not implemented");
@ -49,7 +49,7 @@ public class RoomController {
@Operation(summary = "Get room details")
@GetMapping("/{roomId}")
ResponseEntity<RoomInfoResponse> info(
@Parameter(description = "Node identifier") @PathVariable("nodeId") String nodeId,
@Parameter(description = "Instance identifier") @PathVariable("nodeId") String nodeId,
@Parameter(description = "Room identifier") @PathVariable("roomId") String roomId
) {
throw new UnsupportedOperationException("Not implemented");
@ -59,7 +59,7 @@ public class RoomController {
@ApiResponse(description = "New lock state")
@PutMapping("/{roomId}/lock")
ResponseEntity<Boolean> lockRoom(
@Parameter(description = "Node identifier") @PathVariable("nodeId") String nodeId,
@Parameter(description = "Instance identifier") @PathVariable("nodeId") String nodeId,
@Parameter(description = "Room identifier") @PathVariable("roomId") String roomId,
@Parameter(description = "New state for Lock property") @RequestParam(name = "newState") boolean value
) {

View File

@ -18,7 +18,7 @@ public class UserRoomController {
@Operation(summary = "Get users inside room")
@GetMapping
ResponseEntity<RoomUserListResponse> usersInsideRoom(
@Parameter(description = "Node identifier") @PathVariable(name = "nodeId") String nodeId,
@Parameter(description = "Instance identifier") @PathVariable(name = "nodeId") String nodeId,
@Parameter(description = "Room identifier") @PathVariable(name = "roomId") String roomId,
@Parameter(description = "Required addition user data", example = "COUNT_ROOMS") @RequestParam(name = "requiredDetails", required = false, defaultValue = "") String detailsSeq
) {
@ -28,7 +28,7 @@ public class UserRoomController {
@Operation(summary = "Link users with room")
@PostMapping
ResponseEntity<LinkUsersWithRoomResponse> linkUserWithRoom(
@Parameter(description = "Node identifier") @PathVariable(name = "nodeId") String nodeId,
@Parameter(description = "Instance identifier") @PathVariable(name = "nodeId") String nodeId,
@Parameter(description = "Room identifier") @PathVariable(name = "roomId") String roomId,
@Parameter(description = "User identifiers", example = "user1,user2,user3") @RequestParam(name = "userIds") String userIds,
@Parameter(description = "Ignore slot limitation") @RequestParam(name = "force") boolean force
@ -39,7 +39,7 @@ public class UserRoomController {
@Operation(summary = "Unlink users from room")
@DeleteMapping
ResponseEntity<?> unlinkUsersForBucket(
@Parameter(description = "Node identifier") @PathVariable(name = "nodeId") String nodeId,
@Parameter(description = "Instance identifier") @PathVariable(name = "nodeId") String nodeId,
@Parameter(description = "Room identifier") @PathVariable(name = "roomId") String roomId,
@Parameter(description = "User identifiers", example = "user1,user2,user3") @RequestParam(name = "userIds") String userIds
) {

View File

@ -5,12 +5,12 @@ import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
import ru.dragonestia.picker.api.repository.type.UserIdentifier;
import ru.dragonestia.picker.controller.graphql.entity.EntityNode;
import ru.dragonestia.picker.controller.graphql.entity.EntityInstance;
import ru.dragonestia.picker.controller.graphql.entity.EntityRoom;
import ru.dragonestia.picker.controller.graphql.entity.EntityUser;
import ru.dragonestia.picker.controller.graphql.entity.type.DataProvider;
import ru.dragonestia.picker.model.user.User;
import ru.dragonestia.picker.service.NodeService;
import ru.dragonestia.picker.service.InstanceService;
import ru.dragonestia.picker.service.RoomService;
import ru.dragonestia.picker.service.UserService;
@ -19,35 +19,35 @@ import java.util.List;
@Controller
public class GraphqlController {
private final NodeService nodeService;
private final InstanceService instanceService;
private final RoomService roomService;
private final UserService userService;
private final DataProvider dataProvider;
public GraphqlController(NodeService nodeService, RoomService roomService, UserService userService) {
this.nodeService = nodeService;
public GraphqlController(InstanceService instanceService, RoomService roomService, UserService userService) {
this.instanceService = instanceService;
this.roomService = roomService;
this.userService = userService;
dataProvider = new DataProvider(nodeService, roomService, userService);
dataProvider = new DataProvider(instanceService, roomService, userService);
}
@QueryMapping
List<EntityNode> allNodes() {
return nodeService.all().stream()
.map(node -> new EntityNode(node, dataProvider))
List<EntityInstance> allInstances() {
return instanceService.all().stream()
.map(node -> new EntityInstance(node, dataProvider))
.toList();
}
@QueryMapping
EntityNode nodeById(@Argument String id) {
return nodeService.find(id)
.map(node -> new EntityNode(node, dataProvider))
EntityInstance instanceById(@Argument String id) {
return instanceService.find(id)
.map(node -> new EntityInstance(node, dataProvider))
.orElse(null);
}
@QueryMapping
List<EntityRoom> allRooms(@NotNull String nodeId) {
var node = nodeService.find(nodeId).orElse(null);
var node = instanceService.find(nodeId).orElse(null);
if (node == null) return null;
return roomService.all(node).stream()
@ -57,7 +57,7 @@ public class GraphqlController {
@QueryMapping
EntityRoom roomById(@Argument String nodeId, @NotNull String roomId) {
var node = nodeService.find(nodeId).orElse(null);
var node = instanceService.find(nodeId).orElse(null);
if (node == null) return null;
return roomService.find(node, roomId)

View File

@ -2,23 +2,23 @@ package ru.dragonestia.picker.controller.graphql.entity;
import lombok.RequiredArgsConstructor;
import ru.dragonestia.picker.controller.graphql.entity.type.DataProvider;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import java.util.List;
@RequiredArgsConstructor
public class EntityNode {
public class EntityInstance {
private final Node node;
private final Instance instance;
private final DataProvider dataProvider;
private List<EntityRoom> cachedRooms = null;
public String getId() {
return node.getIdentifier();
return instance.getIdentifier();
}
public String getMethod() {
return node.getPickingMethod().name();
return instance.getPickingMethod().name();
}
public List<EntityRoom> getRooms() {
@ -26,7 +26,7 @@ public class EntityNode {
return cachedRooms;
}
cachedRooms = dataProvider.roomService().all(node).stream()
cachedRooms = dataProvider.roomService().all(instance).stream()
.map(room -> new EntityRoom(room, dataProvider))
.toList();
@ -38,6 +38,6 @@ public class EntityNode {
}
public boolean isPersist() {
return node.isPersist();
return instance.isPersist();
}
}

View File

@ -17,13 +17,13 @@ public class EntityRoom {
return room.getIdentifier();
}
public String getNodeId() {
return room.getNodeIdentifier();
public String getInstanceId() {
return room.getInstanceIdentifier();
}
public EntityNode getNode() {
return dataProvider.nodeService().find(room.getNodeIdentifier())
.map(node -> new EntityNode(node, dataProvider))
public EntityInstance getInstance() {
return dataProvider.instanceService().find(room.getInstanceIdentifier())
.map(node -> new EntityInstance(node, dataProvider))
.orElseThrow();
}

View File

@ -1,10 +1,10 @@
package ru.dragonestia.picker.controller.graphql.entity.type;
import jakarta.validation.constraints.NotNull;
import ru.dragonestia.picker.service.NodeService;
import ru.dragonestia.picker.service.InstanceService;
import ru.dragonestia.picker.service.RoomService;
import ru.dragonestia.picker.service.UserService;
public record DataProvider(@NotNull NodeService nodeService,
public record DataProvider(@NotNull InstanceService instanceService,
@NotNull RoomService roomService,
@NotNull UserService userService) {}

View File

@ -5,7 +5,7 @@ import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import ru.dragonestia.picker.api.repository.type.RoomIdentifier;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.room.Room;
@Component
@ -13,7 +13,7 @@ import ru.dragonestia.picker.model.room.Room;
public class RoomFactory {
@Contract("_, _, _, _, _ -> new")
public @NotNull Room create(@NotNull RoomIdentifier identifier, @NotNull Node node, int slots, @NotNull String payload, boolean persist) {
return new Room(identifier, node, slots, payload, persist);
public @NotNull Room create(@NotNull RoomIdentifier identifier, @NotNull Instance instance, int slots, @NotNull String payload, boolean persist) {
return new Room(identifier, instance, slots, payload, persist);
}
}

View File

@ -1,4 +1,4 @@
package ru.dragonestia.picker.model.node;
package ru.dragonestia.picker.model.instance;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -8,13 +8,13 @@ import ru.dragonestia.picker.api.model.node.PickingMethod;
import ru.dragonestia.picker.api.model.node.ResponseNode;
import ru.dragonestia.picker.api.repository.type.NodeIdentifier;
public class Node implements INode {
public class Instance implements INode {
private final String identifier;
private final PickingMethod pickingMethod;
private final boolean persist;
public Node(@NotNull NodeIdentifier identifier, @NotNull PickingMethod pickingMethod, boolean persist) {
public Instance(@NotNull NodeIdentifier identifier, @NotNull PickingMethod pickingMethod, boolean persist) {
this.identifier = identifier.getValue();
this.pickingMethod = pickingMethod;
this.persist = persist;
@ -53,7 +53,7 @@ public class Node implements INode {
public boolean equals(Object object) {
if (object == this) return true;
if (object == null) return false;
if (object instanceof Node other) {
if (object instanceof Instance other) {
return identifier.equals(other.identifier);
}
return false;
@ -61,6 +61,6 @@ public class Node implements INode {
@Override
public String toString() {
return "{Node id='%s'}".formatted(identifier);
return "{Instance id='%s'}".formatted(identifier);
}
}

View File

@ -7,22 +7,22 @@ import ru.dragonestia.picker.api.model.room.ResponseRoom;
import ru.dragonestia.picker.api.model.room.RoomDetails;
import ru.dragonestia.picker.api.model.room.ShortResponseRoom;
import ru.dragonestia.picker.api.repository.type.RoomIdentifier;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import java.util.Objects;
public class Room implements IRoom {
private final String identifier;
private final String nodeIdentifier;
private final String instanceIdentifier;
private final int slots;
private final String payload;
private final boolean persist;
private boolean locked = false;
public Room(@NotNull RoomIdentifier identifier, @NotNull Node node, int slots, @NotNull String payload, boolean persist) {
public Room(@NotNull RoomIdentifier identifier, @NotNull Instance instance, int slots, @NotNull String payload, boolean persist) {
this.identifier = identifier.getValue();
this.nodeIdentifier = node.getIdentifier();
this.instanceIdentifier = instance.getIdentifier();
this.slots = slots;
this.payload = payload;
this.persist = persist;
@ -34,8 +34,8 @@ public class Room implements IRoom {
}
@Override
public @NotNull String getNodeIdentifier() {
return nodeIdentifier;
public @NotNull String getInstanceIdentifier() {
return instanceIdentifier;
}
@Override
@ -74,16 +74,16 @@ public class Room implements IRoom {
}
public @NotNull ResponseRoom toResponseObject() {
return new ResponseRoom(identifier, nodeIdentifier, slots, locked, payload);
return new ResponseRoom(identifier, instanceIdentifier, slots, locked, payload);
}
public @NotNull ShortResponseRoom toShortResponseObject() {
return new ShortResponseRoom(identifier, nodeIdentifier, slots, locked);
return new ShortResponseRoom(identifier, instanceIdentifier, slots, locked);
}
@Override
public int hashCode() {
return Objects.hash(identifier, nodeIdentifier);
return Objects.hash(identifier, instanceIdentifier);
}
@Override
@ -91,7 +91,7 @@ public class Room implements IRoom {
if (object == this) return true;
if (object == null) return false;
if (object instanceof Room other) {
return identifier.equals(other.identifier) && nodeIdentifier.equals(other.nodeIdentifier);
return identifier.equals(other.identifier) && instanceIdentifier.equals(other.instanceIdentifier);
}
return false;
}

View File

@ -0,0 +1,18 @@
package ru.dragonestia.picker.repository;
import ru.dragonestia.picker.api.exception.NodeAlreadyExistException;
import ru.dragonestia.picker.model.instance.Instance;
import java.util.List;
import java.util.Optional;
public interface InstanceRepository {
void create(Instance instance) throws NodeAlreadyExistException;
void delete(Instance instance);
Optional<Instance> findById(String nodeId);
List<Instance> all();
}

View File

@ -1,18 +0,0 @@
package ru.dragonestia.picker.repository;
import ru.dragonestia.picker.api.exception.NodeAlreadyExistException;
import ru.dragonestia.picker.model.node.Node;
import java.util.List;
import java.util.Optional;
public interface NodeRepository {
void create(Node node) throws NodeAlreadyExistException;
void delete(Node node);
Optional<Node> findById(String nodeId);
List<Node> all();
}

View File

@ -2,8 +2,8 @@ package ru.dragonestia.picker.repository;
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.api.exception.RoomAlreadyExistException;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.room.Room;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.user.User;
import java.util.Collection;
@ -16,9 +16,9 @@ public interface RoomRepository {
void remove(Room room);
Optional<Room> find(Node node, String identifier);
Optional<Room> find(Instance instance, String identifier);
Collection<Room> all(Node node);
Collection<Room> all(Instance instance);
Room pick(Node node, Set<User> users) throws NoRoomsAvailableException;
Room pick(Instance instance, Set<User> users) throws NoRoomsAvailableException;
}

View File

@ -3,8 +3,8 @@ package ru.dragonestia.picker.repository.impl;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import ru.dragonestia.picker.api.exception.NodeAlreadyExistException;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.repository.impl.container.NodeContainer;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
import ru.dragonestia.picker.repository.impl.type.UserTransaction;
import java.util.Collection;
@ -15,28 +15,28 @@ import java.util.concurrent.ConcurrentHashMap;
@Component
public class ContainerRepository {
private final Map<String, NodeContainer> containers = new ConcurrentHashMap<>();
private final Map<String, InstanceContainer> containers = new ConcurrentHashMap<>();
private UserTransaction.Listener transactionListener = transaction -> {};
public void create(Node node) throws NodeAlreadyExistException {
if (containers.containsKey(node.getIdentifier())) {
throw new NodeAlreadyExistException(node.getIdentifier());
public void create(Instance instance) throws NodeAlreadyExistException {
if (containers.containsKey(instance.getIdentifier())) {
throw new NodeAlreadyExistException(instance.getIdentifier());
}
var container = new NodeContainer(node, transactionListener);
containers.put(node.getIdentifier(), container);
var container = new InstanceContainer(instance, transactionListener);
containers.put(instance.getIdentifier(), container);
}
public void remove(@NotNull String nodeId) {
containers.remove(nodeId);
}
public @NotNull Optional<NodeContainer> findById(@NotNull String nodeId) {
public @NotNull Optional<InstanceContainer> findById(@NotNull String nodeId) {
return Optional.ofNullable(containers.get(nodeId));
}
public @NotNull Collection<NodeContainer> all() {
public @NotNull Collection<InstanceContainer> all() {
return containers.values();
}

View File

@ -0,0 +1,38 @@
package ru.dragonestia.picker.repository.impl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import ru.dragonestia.picker.api.exception.NodeAlreadyExistException;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.repository.InstanceRepository;
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
import java.util.List;
import java.util.Optional;
@Component
@RequiredArgsConstructor
public class InstanceRepositoryImpl implements InstanceRepository {
private final ContainerRepository containerRepository;
@Override
public void create(Instance instance) throws NodeAlreadyExistException {
containerRepository.create(instance);
}
@Override
public void delete(Instance instance) {
containerRepository.remove(instance.getIdentifier());
}
@Override
public Optional<Instance> findById(String nodeId) {
return containerRepository.findById(nodeId).map(InstanceContainer::getInstance);
}
@Override
public List<Instance> all() {
return containerRepository.all().stream().map(InstanceContainer::getInstance).toList();
}
}

View File

@ -1,38 +0,0 @@
package ru.dragonestia.picker.repository.impl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import ru.dragonestia.picker.api.exception.NodeAlreadyExistException;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.repository.NodeRepository;
import ru.dragonestia.picker.repository.impl.container.NodeContainer;
import java.util.List;
import java.util.Optional;
@Component
@RequiredArgsConstructor
public class NodeRepositoryImpl implements NodeRepository {
private final ContainerRepository containerRepository;
@Override
public void create(Node node) throws NodeAlreadyExistException {
containerRepository.create(node);
}
@Override
public void delete(Node node) {
containerRepository.remove(node.getIdentifier());
}
@Override
public Optional<Node> findById(String nodeId) {
return containerRepository.findById(nodeId).map(NodeContainer::getNode);
}
@Override
public List<Node> all() {
return containerRepository.all().stream().map(NodeContainer::getNode).toList();
}
}

View File

@ -5,7 +5,7 @@ import org.springframework.stereotype.Component;
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.api.exception.NodeNotFoundException;
import ru.dragonestia.picker.api.exception.RoomAlreadyExistException;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.room.Room;
import ru.dragonestia.picker.model.user.User;
import ru.dragonestia.picker.repository.RoomRepository;
@ -23,38 +23,38 @@ public class RoomRepositoryImpl implements RoomRepository {
@Override
public void create(Room room) throws RoomAlreadyExistException {
containerRepository.findById(room.getNodeIdentifier())
.orElseThrow(() -> new NodeNotFoundException(room.getNodeIdentifier()))
containerRepository.findById(room.getInstanceIdentifier())
.orElseThrow(() -> new NodeNotFoundException(room.getInstanceIdentifier()))
.addRoom(room);
}
@Override
public void remove(Room room) {
containerRepository.findById(room.getNodeIdentifier())
.orElseThrow(() -> new NodeNotFoundException(room.getNodeIdentifier()))
containerRepository.findById(room.getInstanceIdentifier())
.orElseThrow(() -> new NodeNotFoundException(room.getInstanceIdentifier()))
.removeRoom(room);
}
@Override
public Optional<Room> find(Node node, String identifier) {
return containerRepository.findById(node.getIdentifier())
.orElseThrow(() -> new NodeNotFoundException(node.getIdentifier()))
public Optional<Room> find(Instance instance, String identifier) {
return containerRepository.findById(instance.getIdentifier())
.orElseThrow(() -> new NodeNotFoundException(instance.getIdentifier()))
.findRoomById(identifier)
.map(RoomContainer::getRoom);
}
@Override
public Collection<Room> all(Node node) {
return containerRepository.findById(node.getIdentifier())
.orElseThrow(() -> new NodeNotFoundException(node.getIdentifier()))
public Collection<Room> all(Instance instance) {
return containerRepository.findById(instance.getIdentifier())
.orElseThrow(() -> new NodeNotFoundException(instance.getIdentifier()))
.allRooms()
.stream().map(RoomContainer::getRoom).toList();
}
@Override
public Room pick(Node node, Set<User> users) throws NoRoomsAvailableException {
return containerRepository.findById(node.getIdentifier())
.orElseThrow(() -> new NodeNotFoundException(node.getIdentifier()))
public Room pick(Instance instance, Set<User> users) throws NoRoomsAvailableException {
return containerRepository.findById(instance.getIdentifier())
.orElseThrow(() -> new NodeNotFoundException(instance.getIdentifier()))
.pick(users);
}
}

View File

@ -86,7 +86,7 @@ public class UserRepositoryImpl implements UserRepository {
var result = new HashMap<String, Integer>();
containerRepository.all().forEach(nodeContainer -> {
var nodeId = nodeContainer.getNode().getIdentifier();
var nodeId = nodeContainer.getInstance().getIdentifier();
nodeContainer.allRooms().forEach(roomContainer -> {
result.put(nodeId, result.getOrDefault(nodeId, 0) + roomContainer.countUsers());
@ -97,9 +97,9 @@ public class UserRepositoryImpl implements UserRepository {
}
private RoomContainer getRoomContainer(Room room) {
return containerRepository.findById(room.getNodeIdentifier())
.orElseThrow(() -> new NodeNotFoundException(room.getNodeIdentifier()))
return containerRepository.findById(room.getInstanceIdentifier())
.orElseThrow(() -> new NodeNotFoundException(room.getInstanceIdentifier()))
.findRoomById(room.getIdentifier())
.orElseThrow(() -> new RoomNotFoundException(room.getNodeIdentifier(), room.getIdentifier()));
.orElseThrow(() -> new RoomNotFoundException(room.getInstanceIdentifier(), room.getIdentifier()));
}
}

View File

@ -141,7 +141,7 @@ public class DynamicSortedMap<ITEM extends DynamicSortedMap.Item> {
@Override
public String toString() {
return "{Node id=%s, score=%s, removed=%s }".formatted(
return "{Instance id=%s, score=%s, removed=%s }".formatted(
object.getId(),
getScore(),
removed

View File

@ -126,7 +126,7 @@ public class QueuedLinkedList<ITEM extends QueuedLinkedList.Item> {
@Override
public String toString() {
return "{Node id=%s, prev=%s, next=%s, removed=%s }".formatted(
return "{Instance id=%s, prev=%s, next=%s, removed=%s }".formatted(
object.getId(),
prev == null? null : prev.object.getId(),
next == null? null : next.object.getId(),

View File

@ -3,7 +3,7 @@ package ru.dragonestia.picker.repository.impl.container;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import ru.dragonestia.picker.api.exception.RoomAlreadyExistException;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.room.Room;
import ru.dragonestia.picker.model.user.User;
import ru.dragonestia.picker.repository.impl.picker.LeastPickedPicker;
@ -17,24 +17,24 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class NodeContainer {
public class InstanceContainer {
@Getter
private final Node node;
private final Instance instance;
private final UserTransaction.Listener transactionListener;
private final RoomPicker picker;
private final ReadWriteLock roomLock = new ReentrantReadWriteLock();
private final Map<String, RoomContainer> rooms = new ConcurrentHashMap<>();
public NodeContainer(@NotNull Node node, @NotNull UserTransaction.Listener transactionListener) {
this.node = node;
public InstanceContainer(@NotNull Instance instance, @NotNull UserTransaction.Listener transactionListener) {
this.instance = instance;
this.transactionListener = transactionListener;
this.picker = initPicker();
}
private @NotNull RoomPicker initPicker() {
return switch (node.getPickingMethod()) {
return switch (instance.getPickingMethod()) {
case SEQUENTIAL_FILLING -> new SequentialFillingPicker(this);
case ROUND_ROBIN -> new RoundRobinPicker(this);
case LEAST_PICKED -> new LeastPickedPicker(this);
@ -45,7 +45,7 @@ public class NodeContainer {
roomLock.writeLock().lock();
try {
if (rooms.containsKey(room.getIdentifier())) {
throw new RoomAlreadyExistException(node.getIdentifier(), room.getIdentifier());
throw new RoomAlreadyExistException(instance.getIdentifier(), room.getIdentifier());
}
var container = new RoomContainer(room, this);

View File

@ -15,12 +15,12 @@ public class RoomContainer {
@Getter
private final Room room;
private final NodeContainer container;
private final InstanceContainer container;
private final ReadWriteLock usersLock = new ReentrantReadWriteLock(true);
private final Set<User> users = new HashSet<>();
public RoomContainer(@NotNull Room room, @NotNull NodeContainer container) {
public RoomContainer(@NotNull Room room, @NotNull InstanceContainer container) {
this.room = room;
this.container = container;
}
@ -32,7 +32,7 @@ public class RoomContainer {
users.addAll(toAdd);
noticePickersAboutUserNumberUpdate();
} else {
throw new RoomAreFullException(room.getNodeIdentifier(), room.getIdentifier());
throw new RoomAreFullException(room.getInstanceIdentifier(), room.getIdentifier());
}
} finally {
usersLock.writeLock().unlock();

View File

@ -6,7 +6,7 @@ import ru.dragonestia.picker.api.model.node.PickingMethod;
import ru.dragonestia.picker.model.room.Room;
import ru.dragonestia.picker.model.user.User;
import ru.dragonestia.picker.repository.impl.collection.DynamicSortedMap;
import ru.dragonestia.picker.repository.impl.container.NodeContainer;
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
import ru.dragonestia.picker.repository.impl.container.RoomContainer;
import java.util.Collection;
@ -14,7 +14,7 @@ import java.util.Collection;
@RequiredArgsConstructor
public class LeastPickedPicker implements RoomPicker {
private final NodeContainer container;
private final InstanceContainer container;
private final DynamicSortedMap<RoomWrapper> map = new DynamicSortedMap<>();
@Override
@ -41,7 +41,7 @@ public class LeastPickedPicker implements RoomPicker {
if (!wrapper.canAddUnits(users.size())) throw new RuntimeException();
} catch (RuntimeException ex) {
throw new NoRoomsAvailableException(container.getNode().getIdentifier());
throw new NoRoomsAvailableException(container.getInstance().getIdentifier());
}
}

View File

@ -5,7 +5,7 @@ import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.api.model.node.PickingMethod;
import ru.dragonestia.picker.model.user.User;
import ru.dragonestia.picker.repository.impl.collection.QueuedLinkedList;
import ru.dragonestia.picker.repository.impl.container.NodeContainer;
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
import ru.dragonestia.picker.repository.impl.container.RoomContainer;
import java.util.Collection;
@ -14,7 +14,7 @@ import java.util.concurrent.atomic.AtomicInteger;
@RequiredArgsConstructor
public class RoundRobinPicker implements RoomPicker {
private final NodeContainer container;
private final InstanceContainer container;
private final AtomicInteger addition = new AtomicInteger(0);
private final QueuedLinkedList<RoomWrapper> list = new QueuedLinkedList<>(wrapper -> wrapper.canAddUnits(addition.get()));
@ -42,7 +42,7 @@ public class RoundRobinPicker implements RoomPicker {
addition.set(amount);
wrapper = list.pick();
} catch (RuntimeException ex) {
throw new NoRoomsAvailableException(container.getNode().getIdentifier());
throw new NoRoomsAvailableException(container.getInstance().getIdentifier());
}
}

View File

@ -4,7 +4,7 @@ import lombok.RequiredArgsConstructor;
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.api.model.node.PickingMethod;
import ru.dragonestia.picker.model.user.User;
import ru.dragonestia.picker.repository.impl.container.NodeContainer;
import ru.dragonestia.picker.repository.impl.container.InstanceContainer;
import ru.dragonestia.picker.repository.impl.container.RoomContainer;
import java.util.Collection;
@ -14,7 +14,7 @@ import java.util.Map;
@RequiredArgsConstructor
public class SequentialFillingPicker implements RoomPicker {
private final NodeContainer container;
private final InstanceContainer container;
private final Map<String, RoomWrapper> wrappers = new LinkedHashMap<>();
@Override
@ -43,7 +43,7 @@ public class SequentialFillingPicker implements RoomPicker {
}
}
throw new NoRoomsAvailableException(container.getNode().getIdentifier());
throw new NoRoomsAvailableException(container.getInstance().getIdentifier());
}
@Override

View File

@ -0,0 +1,22 @@
package ru.dragonestia.picker.service;
import org.springframework.security.access.prepost.PreAuthorize;
import ru.dragonestia.picker.api.exception.InvalidInstanceIdentifierException;
import ru.dragonestia.picker.api.exception.NodeAlreadyExistException;
import ru.dragonestia.picker.model.instance.Instance;
import java.util.List;
import java.util.Optional;
public interface InstanceService {
@PreAuthorize("hasRole('NODE_MANAGEMENT')")
void create(Instance instance) throws InvalidInstanceIdentifierException, NodeAlreadyExistException;
@PreAuthorize("hasRole('NODE_MANAGEMENT')")
void remove(Instance instance);
List<Instance> all();
Optional<Instance> find(String nodeId);
}

View File

@ -1,22 +0,0 @@
package ru.dragonestia.picker.service;
import org.springframework.security.access.prepost.PreAuthorize;
import ru.dragonestia.picker.api.exception.InvalidNodeIdentifierException;
import ru.dragonestia.picker.api.exception.NodeAlreadyExistException;
import ru.dragonestia.picker.model.node.Node;
import java.util.List;
import java.util.Optional;
public interface NodeService {
@PreAuthorize("hasRole('NODE_MANAGEMENT')")
void create(Node node) throws InvalidNodeIdentifierException, NodeAlreadyExistException;
@PreAuthorize("hasRole('NODE_MANAGEMENT')")
void remove(Node node);
List<Node> all();
Optional<Node> find(String nodeId);
}

View File

@ -3,8 +3,8 @@ package ru.dragonestia.picker.service;
import ru.dragonestia.picker.api.exception.InvalidRoomIdentifierException;
import ru.dragonestia.picker.api.exception.RoomAlreadyExistException;
import ru.dragonestia.picker.api.repository.response.PickedRoomResponse;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.room.Room;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.user.User;
import java.util.Collection;
@ -17,11 +17,11 @@ public interface RoomService {
void remove(Room room);
Optional<Room> find(Node node, String roomId);
Optional<Room> find(Instance instance, String roomId);
Collection<Room> all(Node node);
Collection<Room> all(Instance instance);
PickedRoomResponse pickAvailable(Node node, Set<User> users);
PickedRoomResponse pickAvailable(Instance instance, Set<User> users);
void updateState(Room room);
}

View File

@ -0,0 +1,49 @@
package ru.dragonestia.picker.service.impl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import ru.dragonestia.picker.api.exception.InvalidInstanceIdentifierException;
import ru.dragonestia.picker.api.exception.NodeAlreadyExistException;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.repository.InstanceRepository;
import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.service.InstanceService;
import ru.dragonestia.picker.storage.InstanceAndRoomStorage;
import java.util.List;
import java.util.Optional;
@Service
@RequiredArgsConstructor
public class InstanceServiceImpl implements InstanceService {
private final InstanceRepository instanceRepository;
private final RoomRepository roomRepository;
private final InstanceAndRoomStorage storage;
@Override
public void create(Instance instance) throws InvalidInstanceIdentifierException, NodeAlreadyExistException {
instanceRepository.create(instance);
storage.saveInstance(instance);
}
@Override
public void remove(Instance instance) {
for (var room: roomRepository.all(instance)) {
storage.removeRoom(room);
}
instanceRepository.delete(instance);
storage.removeInstance(instance);
}
@Override
public List<Instance> all() {
return instanceRepository.all();
}
@Override
public Optional<Instance> find(String nodeId) {
return instanceRepository.findById(nodeId);
}
}

View File

@ -1,49 +0,0 @@
package ru.dragonestia.picker.service.impl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import ru.dragonestia.picker.api.exception.InvalidNodeIdentifierException;
import ru.dragonestia.picker.api.exception.NodeAlreadyExistException;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.repository.NodeRepository;
import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.service.NodeService;
import ru.dragonestia.picker.storage.NodeAndRoomStorage;
import java.util.List;
import java.util.Optional;
@Service
@RequiredArgsConstructor
public class NodeServiceImpl implements NodeService {
private final NodeRepository nodeRepository;
private final RoomRepository roomRepository;
private final NodeAndRoomStorage storage;
@Override
public void create(Node node) throws InvalidNodeIdentifierException, NodeAlreadyExistException {
nodeRepository.create(node);
storage.saveNode(node);
}
@Override
public void remove(Node node) {
for (var room: roomRepository.all(node)) {
storage.removeRoom(room);
}
nodeRepository.delete(node);
storage.removeNode(node);
}
@Override
public List<Node> all() {
return nodeRepository.all();
}
@Override
public Optional<Node> find(String nodeId) {
return nodeRepository.findById(nodeId);
}
}

View File

@ -9,13 +9,13 @@ import ru.dragonestia.picker.api.exception.NotPersistedNodeException;
import ru.dragonestia.picker.api.exception.RoomAlreadyExistException;
import ru.dragonestia.picker.api.repository.response.PickedRoomResponse;
import ru.dragonestia.picker.model.room.Room;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.user.User;
import ru.dragonestia.picker.repository.NodeRepository;
import ru.dragonestia.picker.repository.InstanceRepository;
import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.repository.UserRepository;
import ru.dragonestia.picker.service.RoomService;
import ru.dragonestia.picker.storage.NodeAndRoomStorage;
import ru.dragonestia.picker.storage.InstanceAndRoomStorage;
import ru.dragonestia.picker.util.NamingValidator;
import java.util.*;
@ -27,16 +27,16 @@ import java.util.stream.Collectors;
public class RoomServiceImpl implements RoomService {
private final RoomRepository roomRepository;
private final NodeRepository nodeRepository;
private final InstanceRepository instanceRepository;
private final UserRepository userRepository;
private final NamingValidator namingValidator;
private final NodeAndRoomStorage storage;
private final InstanceAndRoomStorage storage;
@Override
public void create(Room room) throws InvalidRoomIdentifierException, RoomAlreadyExistException, NotPersistedNodeException {
namingValidator.validateRoomId(room.getNodeIdentifier(), room.getIdentifier());
namingValidator.validateRoomId(room.getInstanceIdentifier(), room.getIdentifier());
var node = nodeRepository.findById(room.getNodeIdentifier()).orElseThrow(() -> new NodeNotFoundException(room.getNodeIdentifier()));
var node = instanceRepository.findById(room.getInstanceIdentifier()).orElseThrow(() -> new NodeNotFoundException(room.getInstanceIdentifier()));
if (!node.isPersist() && room.isPersist()) {
throw new NotPersistedNodeException(node.getIdentifier(), room.getIdentifier());
}
@ -52,22 +52,22 @@ public class RoomServiceImpl implements RoomService {
}
@Override
public Optional<Room> find(Node node, String roomId) {
return roomRepository.find(node, roomId);
public Optional<Room> find(Instance instance, String roomId) {
return roomRepository.find(instance, roomId);
}
@Override
public Collection<Room> all(Node node) {
return roomRepository.all(node);
public Collection<Room> all(Instance instance) {
return roomRepository.all(instance);
}
@Override
public PickedRoomResponse pickAvailable(Node node, Set<User> users) {
var room = roomRepository.pick(node, users);
public PickedRoomResponse pickAvailable(Instance instance, Set<User> users) {
var room = roomRepository.pick(instance, users);
var roomUsers = userRepository.usersOf(room);
return new PickedRoomResponse(
room.getNodeIdentifier(),
room.getInstanceIdentifier(),
room.getIdentifier(),
room.getPayload(),
room.getMaxSlots(),

View File

@ -0,0 +1,17 @@
package ru.dragonestia.picker.storage;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.room.Room;
public interface InstanceAndRoomStorage {
void loadAll();
void saveInstance(Instance instance);
void removeInstance(Instance instance);
void saveRoom(Room room);
void removeRoom(Room room);
}

View File

@ -1,17 +0,0 @@
package ru.dragonestia.picker.storage;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.room.Room;
public interface NodeAndRoomStorage {
void loadAll();
void saveNode(Node node);
void removeNode(Node node);
void saveRoom(Room room);
void removeRoom(Room room);
}

View File

@ -8,11 +8,11 @@ import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.room.Room;
import ru.dragonestia.picker.repository.NodeRepository;
import ru.dragonestia.picker.repository.InstanceRepository;
import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.storage.NodeAndRoomStorage;
import ru.dragonestia.picker.storage.InstanceAndRoomStorage;
import java.io.File;
import java.util.Objects;
@ -21,12 +21,12 @@ import java.util.Objects;
@Profile("!test")
@Component
@RequiredArgsConstructor
public class FileStorageImpl implements NodeAndRoomStorage {
public class FileStorageImpl implements InstanceAndRoomStorage {
@Value("${ROOMPICKER_DATA_PATH:./appdata}")
private String path;
private final NodeRepository nodeRepository;
private final InstanceRepository instanceRepository;
private final RoomRepository roomRepository;
private final ObjectMapper objectMapper;
@ -38,14 +38,14 @@ public class FileStorageImpl implements NodeAndRoomStorage {
if (!dir.exists()) dir.mkdirs();
var nodeDir = new File(path + "/nodes");
var nodeDir = new File(path + "/instances");
if (!nodeDir.exists()) nodeDir.mkdir();
for (var file: Objects.requireNonNull(nodeDir.listFiles(File::isFile))) {
try {
var node = reader.readValue(file, Node.class);
nodeRepository.create(node);
var instance = reader.readValue(file, Instance.class);
instanceRepository.create(instance);
} catch (Exception ex) {
log.error("Cannot read node file '%s'".formatted(file.getName()));
log.error("Cannot read instance file '%s'".formatted(file.getName()));
log.throwing(ex);
}
}
@ -64,31 +64,31 @@ public class FileStorageImpl implements NodeAndRoomStorage {
}
@Override
public void saveNode(Node node) {
if (!node.isPersist()) return;
var nodeFile = new File(path + "/nodes/" + node.getIdentifier() + ".json");
public void saveInstance(Instance instance) {
if (!instance.isPersist()) return;
var instanceFile = new File(path + "/instances/" + instance.getIdentifier() + ".json");
var writer = objectMapper.writer();
try {
writer.writeValue(nodeFile, node);
writer.writeValue(instanceFile, instance);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
@Override
public void removeNode(Node node) {
if (!node.isPersist()) return;
new File(path + "/nodes/" + node.getIdentifier() + ".json").delete();
public void removeInstance(Instance instance) {
if (!instance.isPersist()) return;
new File(path + "/nodes/" + instance.getIdentifier() + ".json").delete();
log.info("Removed node '%s' from disk storage".formatted(node.getIdentifier()));
log.info("Removed instance '%s' from disk storage".formatted(instance.getIdentifier()));
}
@SneakyThrows
@Override
public void saveRoom(Room room) {
if (!room.isPersist()) return;
var roomFile = new File("%s/rooms/%s.%s.json".formatted(path, room.getNodeIdentifier(), room.getIdentifier()));
var roomFile = new File("%s/rooms/%s.%s.json".formatted(path, room.getInstanceIdentifier(), room.getIdentifier()));
var writer = objectMapper.writer();
try {
@ -101,8 +101,8 @@ public class FileStorageImpl implements NodeAndRoomStorage {
@Override
public void removeRoom(Room room) {
if (!room.isPersist()) return;
new File("%s/rooms/%s.%s.json".formatted(path, room.getNodeIdentifier(), room.getIdentifier())).delete();
new File("%s/rooms/%s.%s.json".formatted(path, room.getInstanceIdentifier(), room.getIdentifier())).delete();
log.info("Removed room '%s/%s' from disk storage".formatted(room.getNodeIdentifier(), room.getIdentifier()));
log.info("Removed room '%s/%s' from disk storage".formatted(room.getInstanceIdentifier(), room.getIdentifier()));
}
}

View File

@ -2,22 +2,22 @@ package ru.dragonestia.picker.storage.impl;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.room.Room;
import ru.dragonestia.picker.storage.NodeAndRoomStorage;
import ru.dragonestia.picker.storage.InstanceAndRoomStorage;
@Profile("test")
@Component
public class NullStorageImpl implements NodeAndRoomStorage {
public class NullStorageImpl implements InstanceAndRoomStorage {
@Override
public void loadAll() {}
@Override
public void saveNode(Node node) {}
public void saveInstance(Instance instance) {}
@Override
public void removeNode(Node node) {}
public void removeInstance(Instance instance) {}
@Override
public void saveRoom(Room room) {}

View File

@ -1,7 +1,7 @@
package ru.dragonestia.picker.util;
import org.springframework.stereotype.Component;
import ru.dragonestia.picker.api.exception.InvalidNodeIdentifierException;
import ru.dragonestia.picker.api.exception.InvalidInstanceIdentifierException;
import ru.dragonestia.picker.api.exception.InvalidRoomIdentifierException;
import ru.dragonestia.picker.api.exception.InvalidUsernamesException;
import ru.dragonestia.picker.api.repository.type.UserIdentifier;
@ -14,10 +14,10 @@ import java.util.LinkedList;
@Component
public class NamingValidator {
public void validateNodeId(String input) throws InvalidNodeIdentifierException {
public void validateInstanceId(String input) throws InvalidInstanceIdentifierException {
if (IdentifierValidator.forNode(input)) return;
throw new InvalidNodeIdentifierException(input);
throw new InvalidInstanceIdentifierException(input);
}
public void validateRoomId(String nodeId, String input) throws InvalidRoomIdentifierException {

View File

@ -1,13 +1,13 @@
type Query {
allNodes: [Node]
nodeById(id: String!): Node
allInstances: [Instance]
instanceById(id: String!): Instance
allRooms(nodeId: String!): [Room]
roomById(nodeId: String!, roomId: String!): Room
userById(id: String!): User!
searchUser(input: String!): [User]
}
type Node {
type Instance {
id: String!
method: String!
rooms: [Room]
@ -17,8 +17,8 @@ type Node {
type Room {
id: String!
nodeId: String!
node: Node!
instanceId: String!
instance: Instance!
slots: Int!
payload: String!
locked: Boolean!

View File

@ -7,10 +7,10 @@ import ru.dragonestia.picker.api.model.node.PickingMethod;
import ru.dragonestia.picker.api.repository.type.NodeIdentifier;
import ru.dragonestia.picker.api.repository.type.RoomIdentifier;
import ru.dragonestia.picker.api.repository.type.UserIdentifier;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.user.User;
import ru.dragonestia.picker.model.factory.RoomFactory;
import ru.dragonestia.picker.repository.NodeRepository;
import ru.dragonestia.picker.repository.InstanceRepository;
import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.repository.UserRepository;
@ -39,7 +39,7 @@ public class FillingNodesConfig {
*/
@Autowired
private NodeRepository nodeRepository;
private InstanceRepository instanceRepository;
@Autowired
private RoomRepository roomRepository;
@ -50,45 +50,45 @@ public class FillingNodesConfig {
@Autowired
private RoomFactory roomFactory;
private Node seqNode;
private Node roundNode;
private Node leastNode;
private Instance seqInstance;
private Instance roundInstance;
private Instance leastInstance;
@Bean
void createSequentialFillingNode() {
var node = new Node(NodeIdentifier.of("seq"), PickingMethod.SEQUENTIAL_FILLING, false);
nodeRepository.create(node);
var node = new Instance(NodeIdentifier.of("seq"), PickingMethod.SEQUENTIAL_FILLING, false);
instanceRepository.create(node);
fillNode(node);
seqNode = node;
seqInstance = node;
}
@Bean
void createRoundRobinNode() {
var node = new Node(NodeIdentifier.of("round"), PickingMethod.ROUND_ROBIN, false);
nodeRepository.create(node);
var node = new Instance(NodeIdentifier.of("round"), PickingMethod.ROUND_ROBIN, false);
instanceRepository.create(node);
fillNode(node);
roundNode = node;
roundInstance = node;
}
@Bean
void createLeastPickerNode() {
var node = new Node(NodeIdentifier.of("least"), PickingMethod.LEAST_PICKED, false);
nodeRepository.create(node);
var node = new Instance(NodeIdentifier.of("least"), PickingMethod.LEAST_PICKED, false);
instanceRepository.create(node);
fillNode(node);
leastNode = node;
leastInstance = node;
}
private void fillNode(Node node) {
private void fillNode(Instance instance) {
for (int i = 0, n = 5; i < n; i++) {
for (int j = 0; j < 3; j++) {
var roomId = "room-" + i + "-" + j;
var room = roomFactory.create(RoomIdentifier.of(roomId), node, n, "", false);
var room = roomFactory.create(RoomIdentifier.of(roomId), instance, n, "", false);
roomRepository.create(room);
var users = n - i;
@ -103,17 +103,17 @@ public class FillingNodesConfig {
}
@Bean
Node seqNode() {
return seqNode;
Instance seqNode() {
return seqInstance;
}
@Bean
Node roundNode() {
return roundNode;
Instance roundNode() {
return roundInstance;
}
@Bean
Node leastNode() {
return leastNode;
Instance leastNode() {
return leastInstance;
}
}

View File

@ -12,7 +12,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.config.FillingNodesConfig;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.repository.UserRepository;
import ru.dragonestia.picker.util.UserFiller;
@ -35,15 +35,15 @@ public class LeastPickedTests {
@Qualifier("leastNode")
@Autowired
private Node node;
private Instance instance;
@Timeout(value = 1, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
@ParameterizedTest
@ArgumentsSource(PickingArgumentProvider.class)
void testPicking(String expectedRoomId, int usersAmount) {
var expectedRoomUsers = userRepository.usersOf(roomRepository.find(node, expectedRoomId).orElseThrow()).size();
var expectedRoomUsers = userRepository.usersOf(roomRepository.find(instance, expectedRoomId).orElseThrow()).size();
var room = roomRepository.pick(node, userFiller.createRandomUsers(usersAmount));
var room = roomRepository.pick(instance, userFiller.createRandomUsers(usersAmount));
var slots = room.getMaxSlots();
var users = userRepository.usersOf(room);
Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation
@ -74,6 +74,6 @@ public class LeastPickedTests {
@Timeout(value = 1, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
@Test
void testNoOneRoomExpected() { // Take 9 users. expected none result
Assertions.assertThrows(NoRoomsAvailableException.class, () -> roomRepository.pick(node, userFiller.createRandomUsers(9)));
Assertions.assertThrows(NoRoomsAvailableException.class, () -> roomRepository.pick(instance, userFiller.createRandomUsers(9)));
}
}

View File

@ -10,7 +10,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.config.FillingNodesConfig;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.repository.UserRepository;
import ru.dragonestia.picker.util.UserFiller;
@ -33,13 +33,13 @@ public class RoundRobinTests {
@Qualifier("roundNode")
@Autowired
private Node node;
private Instance instance;
@Timeout(value = 1, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
@ParameterizedTest
@ArgumentsSource(PickingArgumentProvider.class)
void testPicking(String expectedRoomId, int usersAmount) {
var room = roomRepository.pick(node, userFiller.createRandomUsers(usersAmount));
var room = roomRepository.pick(instance, userFiller.createRandomUsers(usersAmount));
var slots = room.getMaxSlots();
var users = userRepository.usersOf(room);
Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation
@ -66,6 +66,6 @@ public class RoundRobinTests {
@Timeout(value = 1, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
@Test
void testNoOneRoomExpected() { // Take 9 users. expected none result
Assertions.assertThrows(NoRoomsAvailableException.class, () -> roomRepository.pick(node, userFiller.createRandomUsers(9)));
Assertions.assertThrows(NoRoomsAvailableException.class, () -> roomRepository.pick(instance, userFiller.createRandomUsers(9)));
}
}

View File

@ -12,7 +12,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.config.FillingNodesConfig;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.repository.RoomRepository;
import ru.dragonestia.picker.repository.UserRepository;
import ru.dragonestia.picker.util.UserFiller;
@ -35,15 +35,15 @@ public class SequentialFillingTests {
@Qualifier("seqNode")
@Autowired
private Node node;
private Instance instance;
@Timeout(value = 1, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
@ParameterizedTest
@ArgumentsSource(PickingArgumentProvider.class)
void testPicking(String expectedRoomId, int usersAmount) {
var expectedRoomUsers = userRepository.usersOf(roomRepository.find(node, expectedRoomId).orElseThrow()).size();
var expectedRoomUsers = userRepository.usersOf(roomRepository.find(instance, expectedRoomId).orElseThrow()).size();
var room = roomRepository.pick(node, userFiller.createRandomUsers(usersAmount));
var room = roomRepository.pick(instance, userFiller.createRandomUsers(usersAmount));
var slots = room.getMaxSlots();
var users = userRepository.usersOf(room);
Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation
@ -71,6 +71,6 @@ public class SequentialFillingTests {
@Timeout(value = 1, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
@Test
void testNoOneRoomExpected() { // Take 9 users. expected none result
Assertions.assertThrows(NoRoomsAvailableException.class, () -> roomRepository.pick(node, userFiller.createRandomUsers(9)));
Assertions.assertThrows(NoRoomsAvailableException.class, () -> roomRepository.pick(instance, userFiller.createRandomUsers(9)));
}
}

View File

@ -0,0 +1,57 @@
package ru.dragonestia.picker.service;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import ru.dragonestia.picker.api.exception.NodeAlreadyExistException;
import ru.dragonestia.picker.api.model.node.PickingMethod;
import ru.dragonestia.picker.api.repository.type.NodeIdentifier;
import ru.dragonestia.picker.model.instance.Instance;
import java.util.List;
@SpringBootTest
public class InstanceServiceTests {
@Autowired
private InstanceService instanceService;
@WithMockUser(roles = {"NODE_MANAGEMENT"})
@Test
void test_nodeCreateAndRemove() {
var node = new Instance(NodeIdentifier.of("test"), PickingMethod.SEQUENTIAL_FILLING, false);
Assertions.assertDoesNotThrow(() -> instanceService.create(node));
Assertions.assertTrue(instanceService.find(node.getIdentifier()).isPresent());
Assertions.assertThrows(NodeAlreadyExistException.class, () -> instanceService.create(node));
instanceService.remove(node);
Assertions.assertFalse(() -> instanceService.find(node.getIdentifier()).isPresent());
}
@WithMockUser(roles = {"NODE_MANAGEMENT"})
@Test
void test_allNodes() {
instanceService.all().forEach(node -> instanceService.remove(node));
var nodes = List.of(
new Instance(NodeIdentifier.of("test1"), PickingMethod.SEQUENTIAL_FILLING, false),
new Instance(NodeIdentifier.of("test2"), PickingMethod.ROUND_ROBIN, false),
new Instance(NodeIdentifier.of("test3"), PickingMethod.ROUND_ROBIN, false)
);
nodes.forEach(node -> instanceService.create(node));
var list = instanceService.all();
Assertions.assertEquals(nodes.size(), list.size());
Assertions.assertTrue(list.containsAll(nodes));
nodes.forEach(node -> instanceService.remove(node));
Assertions.assertEquals(0, instanceService.all().size());
}
}

View File

@ -1,57 +0,0 @@
package ru.dragonestia.picker.service;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import ru.dragonestia.picker.api.exception.NodeAlreadyExistException;
import ru.dragonestia.picker.api.model.node.PickingMethod;
import ru.dragonestia.picker.api.repository.type.NodeIdentifier;
import ru.dragonestia.picker.model.node.Node;
import java.util.List;
@SpringBootTest
public class NodeServiceTests {
@Autowired
private NodeService nodeService;
@WithMockUser(roles = {"NODE_MANAGEMENT"})
@Test
void test_nodeCreateAndRemove() {
var node = new Node(NodeIdentifier.of("test"), PickingMethod.SEQUENTIAL_FILLING, false);
Assertions.assertDoesNotThrow(() -> nodeService.create(node));
Assertions.assertTrue(nodeService.find(node.getIdentifier()).isPresent());
Assertions.assertThrows(NodeAlreadyExistException.class, () -> nodeService.create(node));
nodeService.remove(node);
Assertions.assertFalse(() -> nodeService.find(node.getIdentifier()).isPresent());
}
@WithMockUser(roles = {"NODE_MANAGEMENT"})
@Test
void test_allNodes() {
nodeService.all().forEach(node -> nodeService.remove(node));
var nodes = List.of(
new Node(NodeIdentifier.of("test1"), PickingMethod.SEQUENTIAL_FILLING, false),
new Node(NodeIdentifier.of("test2"), PickingMethod.ROUND_ROBIN, false),
new Node(NodeIdentifier.of("test3"), PickingMethod.ROUND_ROBIN, false)
);
nodes.forEach(node -> nodeService.create(node));
var list = nodeService.all();
Assertions.assertEquals(nodes.size(), list.size());
Assertions.assertTrue(list.containsAll(nodes));
nodes.forEach(node -> nodeService.remove(node));
Assertions.assertEquals(0, nodeService.all().size());
}
}

View File

@ -15,7 +15,7 @@ import ru.dragonestia.picker.api.model.room.IRoom;
import ru.dragonestia.picker.api.repository.type.NodeIdentifier;
import ru.dragonestia.picker.api.repository.type.RoomIdentifier;
import ru.dragonestia.picker.api.repository.type.UserIdentifier;
import ru.dragonestia.picker.model.node.Node;
import ru.dragonestia.picker.model.instance.Instance;
import ru.dragonestia.picker.model.user.User;
import ru.dragonestia.picker.model.factory.RoomFactory;
@ -26,7 +26,7 @@ import java.util.Set;
public class RoomServiceTests {
@Autowired
private NodeService nodeService;
private InstanceService instanceService;
@Autowired
private RoomService roomService;
@ -34,44 +34,44 @@ public class RoomServiceTests {
@Autowired
private RoomFactory roomFactory;
private Node node;
private Instance instance;
@BeforeEach
void init() {
node = new Node(NodeIdentifier.of("test-rooms"), PickingMethod.SEQUENTIAL_FILLING, false);
instance = new Instance(NodeIdentifier.of("test-rooms"), PickingMethod.SEQUENTIAL_FILLING, false);
try {
nodeService.create(node);
instanceService.create(instance);
} catch (NodeAlreadyExistException ignore) {}
}
@WithMockUser(roles = {"NODE_MANAGEMENT"})
@Test
void test_createAndRemove() {
var room = roomFactory.create(RoomIdentifier.of("test-room"), node, IRoom.UNLIMITED_SLOTS, "", false);
var room = roomFactory.create(RoomIdentifier.of("test-room"), instance, IRoom.UNLIMITED_SLOTS, "", false);
roomService.create(room);
Assertions.assertTrue(roomService.find(node, room.getIdentifier()).isPresent());
Assertions.assertTrue(roomService.find(instance, room.getIdentifier()).isPresent());
Assertions.assertThrows(RoomAlreadyExistException.class, () -> roomService.create(room));
roomService.remove(room);
Assertions.assertFalse(roomService.find(node, room.getIdentifier()).isPresent());
Assertions.assertFalse(roomService.find(instance, room.getIdentifier()).isPresent());
}
@WithMockUser(roles = {"NODE_MANAGEMENT"})
@Test
void test_allRooms() {
var rooms = List.of(
roomFactory.create(RoomIdentifier.of("test-room1"), node, 1, "", false),
roomFactory.create(RoomIdentifier.of("test-room2"), node, 2, "", false),
roomFactory.create(RoomIdentifier.of("test-room3"), node, 3, "", false),
roomFactory.create(RoomIdentifier.of("test-room4"), node, IRoom.UNLIMITED_SLOTS, "", false)
roomFactory.create(RoomIdentifier.of("test-room1"), instance, 1, "", false),
roomFactory.create(RoomIdentifier.of("test-room2"), instance, 2, "", false),
roomFactory.create(RoomIdentifier.of("test-room3"), instance, 3, "", false),
roomFactory.create(RoomIdentifier.of("test-room4"), instance, IRoom.UNLIMITED_SLOTS, "", false)
);
rooms.forEach(room -> roomService.create(room));
var list = roomService.all(node);
var list = roomService.all(instance);
Assertions.assertEquals(rooms.size(), list.size());
Assertions.assertTrue(rooms.containsAll(list));
@ -81,7 +81,7 @@ public class RoomServiceTests {
@Test
void test_exceptNotPersistedNode() {
Assertions.assertThrows(NotPersistedNodeException.class, () -> {
roomService.create(roomFactory.create(RoomIdentifier.of("1"), node, IRoom.UNLIMITED_SLOTS, "", true));
roomService.create(roomFactory.create(RoomIdentifier.of("1"), instance, IRoom.UNLIMITED_SLOTS, "", true));
});
}
@ -89,10 +89,10 @@ public class RoomServiceTests {
@Test
void test_pickRoom() {
var rooms = List.of(
roomFactory.create(RoomIdentifier.of("test-room1"), node, 1, "", false),
roomFactory.create(RoomIdentifier.of("test-room2"), node, 2, "", false),
roomFactory.create(RoomIdentifier.of("test-room3"), node, 3, "", false),
roomFactory.create(RoomIdentifier.of("test-room4"), node, IRoom.UNLIMITED_SLOTS, "", false)
roomFactory.create(RoomIdentifier.of("test-room1"), instance, 1, "", false),
roomFactory.create(RoomIdentifier.of("test-room2"), instance, 2, "", false),
roomFactory.create(RoomIdentifier.of("test-room3"), instance, 3, "", false),
roomFactory.create(RoomIdentifier.of("test-room4"), instance, IRoom.UNLIMITED_SLOTS, "", false)
);
rooms.forEach(room -> roomService.create(room));
@ -107,21 +107,21 @@ public class RoomServiceTests {
);
Assertions.assertEquals("test-room4", roomService.pickAvailable(node, users).roomId());
Assertions.assertEquals("test-room4", roomService.pickAvailable(instance, users).roomId());
}
@WithMockUser(roles = {"NODE_MANAGEMENT"})
@Test
void test_removeNode() {
nodeService.remove(node);
instanceService.remove(instance);
Assertions.assertThrows(NodeNotFoundException.class, () -> roomService.all(node));
Assertions.assertThrows(NodeNotFoundException.class, () -> roomService.all(instance));
}
@WithMockUser(roles = {"NODE_MANAGEMENT"})
@Test
void test_nodeDoesNotExists() {
var node = new Node(NodeIdentifier.of("bruh"), PickingMethod.ROUND_ROBIN, false);
var node = new Instance(NodeIdentifier.of("bruh"), PickingMethod.ROUND_ROBIN, false);
var room = roomFactory.create(RoomIdentifier.of("test"), node, IRoom.UNLIMITED_SLOTS, "", false);
Assertions.assertThrows(NodeNotFoundException.class, () -> roomService.create(room));