Implemented all issues regarding Executor Pool. Did not complete the implementation of duplicate Ip/port check on adding a new executor

This commit is contained in:
reynisson 2021-10-17 00:17:13 +02:00
parent 050d11254c
commit 94e5742ad2
20 changed files with 515 additions and 1 deletions

View File

@ -45,6 +45,26 @@
<artifactId>json</artifactId>
<version>20210307</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
<dependency>
<groupId>ch.unisg</groupId>
<artifactId>tapas-tasks</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,40 @@
package ch.unisg.executorpool.adapter.in.web;
import ch.unisg.executorpool.application.port.in.AddNewExecutorToExecutorPoolUseCase;
import ch.unisg.executorpool.application.port.in.AddNewExecutorToExecutorPoolCommand;
import ch.unisg.executorpool.domain.ExecutorClass;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;
import javax.validation.ConstraintViolationException;
@RestController
public class AddNewExecutorToExecutorPoolWebController {
private final AddNewExecutorToExecutorPoolUseCase addNewExecutorToExecutorPoolUseCase;
public AddNewExecutorToExecutorPoolWebController(AddNewExecutorToExecutorPoolUseCase addNewExecutorToExecutorPoolUseCase){
this.addNewExecutorToExecutorPoolUseCase = addNewExecutorToExecutorPoolUseCase;
}
@PostMapping(path = "/executor-pool/AddExecutor", consumes = {ExecutorMediaType.EXECUTOR_MEDIA_TYPE})
public ResponseEntity<String> addNewExecutorToExecutorPool(@RequestBody ExecutorClass executorClass){
try{
AddNewExecutorToExecutorPoolCommand command = new AddNewExecutorToExecutorPoolCommand(
executorClass.getExecutorIp(), executorClass.getExecutorPort(), executorClass.getExecutorTaskType()
);
ExecutorClass newExecutor = addNewExecutorToExecutorPoolUseCase.addNewExecutorToExecutorPool(command);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add(HttpHeaders.CONTENT_TYPE, ExecutorMediaType.EXECUTOR_MEDIA_TYPE);
return new ResponseEntity<>(ExecutorMediaType.serialize(newExecutor), responseHeaders, HttpStatus.CREATED);
} catch (ConstraintViolationException e){
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage());
}
}
}

View File

@ -0,0 +1,33 @@
package ch.unisg.executorpool.adapter.in.web;
import ch.unisg.executorpool.domain.ExecutorClass;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.List;
final public class ExecutorMediaType {
public static final String EXECUTOR_MEDIA_TYPE = "application/json";
public static String serialize(ExecutorClass executorClass) {
JSONObject payload = new JSONObject();
payload.put("executorIp", executorClass.getExecutorIp().getValue());
payload.put("executorPort", executorClass.getExecutorPort().getValue());
payload.put("executorTaskType", executorClass.getExecutorTaskType().getValue());
return payload.toString();
}
public static String serialize(List<ExecutorClass> listOfExecutors) {
String serializedList = "[ \n";
for (ExecutorClass executor: listOfExecutors) {
serializedList += serialize(executor) + ",\n";
}
return serializedList + "\n ]";
}
private ExecutorMediaType() { }
}

View File

@ -0,0 +1,35 @@
package ch.unisg.executorpool.adapter.in.web;
import ch.unisg.executorpool.application.port.in.GetAllExecutorInExecutorPoolByTypeQuery;
import ch.unisg.executorpool.application.port.in.GetAllExecutorInExecutorPoolByTypeUseCase;
import ch.unisg.executorpool.domain.ExecutorClass;
import ch.unisg.executorpool.domain.ExecutorClass.ExecutorTaskType;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class GetAllExecutorInExecutorPoolByTypeWebController {
private final GetAllExecutorInExecutorPoolByTypeUseCase getAllExecutorInExecutorPoolByTypeUseCase;
public GetAllExecutorInExecutorPoolByTypeWebController(GetAllExecutorInExecutorPoolByTypeUseCase getAllExecutorInExecutorPoolByTypeUseCase){
this.getAllExecutorInExecutorPoolByTypeUseCase = getAllExecutorInExecutorPoolByTypeUseCase;
}
@GetMapping(path = "/executor-pool/GetAllExecutorInExecutorPoolByType/{taskType}")
public ResponseEntity<String> getAllExecutorInExecutorPoolByType(@PathVariable("taskType") String taskType){
GetAllExecutorInExecutorPoolByTypeQuery query = new GetAllExecutorInExecutorPoolByTypeQuery(new ExecutorTaskType(taskType));
List<ExecutorClass> matchedExecutors = getAllExecutorInExecutorPoolByTypeUseCase.getAllExecutorInExecutorPoolByType(query);
// Add the content type as a response header
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add(HttpHeaders.CONTENT_TYPE, ExecutorMediaType.EXECUTOR_MEDIA_TYPE);
return new ResponseEntity<>(ExecutorMediaType.serialize(matchedExecutors), responseHeaders, HttpStatus.OK);
}
}

View File

@ -0,0 +1,32 @@
package ch.unisg.executorpool.adapter.in.web;
import ch.unisg.executorpool.application.port.in.GetAllExecutorsInExecutorPoolUseCase;
import ch.unisg.executorpool.domain.ExecutorClass;
import ch.unisg.tapastasks.tasks.adapter.in.web.TaskMediaType;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class GetAllExecutorsInExecutorPoolWebController {
private final GetAllExecutorsInExecutorPoolUseCase getAllExecutorsInExecutorPoolUseCase;
public GetAllExecutorsInExecutorPoolWebController(GetAllExecutorsInExecutorPoolUseCase getAllExecutorsInExecutorPoolUseCase){
this.getAllExecutorsInExecutorPoolUseCase = getAllExecutorsInExecutorPoolUseCase;
}
@GetMapping(path = "executor-pool/GetAllExecutorsinExecutorPool")
public ResponseEntity<String> getAllExecutorsInExecutorPool(){
List<ExecutorClass> executorClassList = getAllExecutorsInExecutorPoolUseCase.getAllExecutorsInExecutorPool();
// Add the content type as a response header
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add(HttpHeaders.CONTENT_TYPE, ExecutorMediaType.EXECUTOR_MEDIA_TYPE);
return new ResponseEntity<>(ExecutorMediaType.serialize(executorClassList), responseHeaders, HttpStatus.OK);
}
}

View File

@ -0,0 +1,39 @@
package ch.unisg.executorpool.adapter.in.web;
import ch.unisg.executorpool.application.port.in.RemoveExecutorFromExecutorPoolCommand;
import ch.unisg.executorpool.application.port.in.RemoveExecutorFromExecutorPoolUseCase;
import ch.unisg.executorpool.domain.ExecutorClass;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;
import java.util.Optional;
@RestController
public class RemoveExecutorFromExecutorPoolWebController {
private final RemoveExecutorFromExecutorPoolUseCase removeExecutorFromExecutorPoolUseCase;
public RemoveExecutorFromExecutorPoolWebController(RemoveExecutorFromExecutorPoolUseCase removeExecutorFromExecutorPoolUseCase){
this.removeExecutorFromExecutorPoolUseCase = removeExecutorFromExecutorPoolUseCase;
}
@PostMapping(path = "/executor-pool/RemoveExecutor", consumes = {ExecutorMediaType.EXECUTOR_MEDIA_TYPE})
public ResponseEntity<String> removeExecutorFromExecutorPool(@RequestBody ExecutorClass executorClass){
RemoveExecutorFromExecutorPoolCommand command = new RemoveExecutorFromExecutorPoolCommand(executorClass.getExecutorIp(), executorClass.getExecutorPort());
Optional<ExecutorClass> removedExecutor = removeExecutorFromExecutorPoolUseCase.removeExecutorFromExecutorPool(command);
if(removedExecutor.isEmpty()){
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
}
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add(HttpHeaders.CONTENT_TYPE, ExecutorMediaType.EXECUTOR_MEDIA_TYPE);
return new ResponseEntity<>(ExecutorMediaType.serialize(removedExecutor.get()), responseHeaders,
HttpStatus.OK);
}
}

View File

@ -0,0 +1,28 @@
package ch.unisg.executorpool.application.port.in;
import ch.unisg.executorpool.domain.ExecutorPool;
import ch.unisg.tapastasks.common.SelfValidating;
import ch.unisg.executorpool.domain.ExecutorClass.ExecutorIp;
import ch.unisg.executorpool.domain.ExecutorClass.ExecutorPort;
import ch.unisg.executorpool.domain.ExecutorClass.ExecutorTaskType;
import lombok.Value;
import javax.validation.constraints.NotNull;
@Value
public class AddNewExecutorToExecutorPoolCommand extends SelfValidating<AddNewExecutorToExecutorPoolCommand> {
@NotNull
private final ExecutorIp executorIp;
@NotNull
private final ExecutorPort executorPort;
@NotNull
private final ExecutorTaskType executorTaskType;
public AddNewExecutorToExecutorPoolCommand(ExecutorIp executorIp, ExecutorPort executorPort, ExecutorTaskType executorTaskType){
this.executorIp = executorIp;
this.executorPort = executorPort;
this.executorTaskType = executorTaskType;
this.validateSelf();
}
}

View File

@ -0,0 +1,7 @@
package ch.unisg.executorpool.application.port.in;
import ch.unisg.executorpool.domain.ExecutorClass;
public interface AddNewExecutorToExecutorPoolUseCase {
ExecutorClass addNewExecutorToExecutorPool(AddNewExecutorToExecutorPoolCommand command);
}

View File

@ -0,0 +1,18 @@
package ch.unisg.executorpool.application.port.in;
import ch.unisg.executorpool.domain.ExecutorClass.ExecutorTaskType;
import ch.unisg.tapastasks.common.SelfValidating;
import lombok.Value;
import javax.validation.constraints.NotNull;
@Value
public class GetAllExecutorInExecutorPoolByTypeQuery extends SelfValidating<GetAllExecutorInExecutorPoolByTypeQuery> {
@NotNull
private final ExecutorTaskType executorTaskType;
public GetAllExecutorInExecutorPoolByTypeQuery(ExecutorTaskType executorTaskType){
this.executorTaskType = executorTaskType;
this.validateSelf();
}
}

View File

@ -0,0 +1,9 @@
package ch.unisg.executorpool.application.port.in;
import ch.unisg.executorpool.domain.ExecutorClass;
import java.util.List;
public interface GetAllExecutorInExecutorPoolByTypeUseCase {
List<ExecutorClass> getAllExecutorInExecutorPoolByType(GetAllExecutorInExecutorPoolByTypeQuery query);
}

View File

@ -0,0 +1,10 @@
package ch.unisg.executorpool.application.port.in;
import ch.unisg.executorpool.domain.ExecutorClass;
import ch.unisg.executorpool.domain.ExecutorPool;
import java.util.List;
public interface GetAllExecutorsInExecutorPoolUseCase {
List<ExecutorClass> getAllExecutorsInExecutorPool();
}

View File

@ -0,0 +1,24 @@
package ch.unisg.executorpool.application.port.in;
import ch.unisg.executorpool.domain.ExecutorClass;
import ch.unisg.tapastasks.common.SelfValidating;
import ch.unisg.executorpool.domain.ExecutorClass.ExecutorIp;
import ch.unisg.executorpool.domain.ExecutorClass.ExecutorPort;
import lombok.Value;
import javax.validation.constraints.NotNull;
@Value
public class RemoveExecutorFromExecutorPoolCommand extends SelfValidating<RemoveExecutorFromExecutorPoolCommand> {
@NotNull
private final ExecutorIp executorIp;
@NotNull
private final ExecutorPort executorPort;
public RemoveExecutorFromExecutorPoolCommand(ExecutorIp executorIp, ExecutorPort executorPort){
this.executorIp = executorIp;
this.executorPort = executorPort;
this.validateSelf();
}
}

View File

@ -0,0 +1,9 @@
package ch.unisg.executorpool.application.port.in;
import ch.unisg.executorpool.domain.ExecutorClass;
import java.util.Optional;
public interface RemoveExecutorFromExecutorPoolUseCase {
Optional<ExecutorClass> removeExecutorFromExecutorPool(RemoveExecutorFromExecutorPoolCommand command);
}

View File

@ -0,0 +1,25 @@
package ch.unisg.executorpool.application.service;
import ch.unisg.executorpool.application.port.in.AddNewExecutorToExecutorPoolUseCase;
import ch.unisg.executorpool.application.port.in.AddNewExecutorToExecutorPoolCommand;
import ch.unisg.executorpool.domain.ExecutorClass;
import ch.unisg.executorpool.domain.ExecutorPool;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.constructor.DuplicateKeyException;
import javax.transaction.Transactional;
import javax.validation.ConstraintViolationException;
@RequiredArgsConstructor
@Component
@Transactional
public class AddNewExecutorToExecutorPoolService implements AddNewExecutorToExecutorPoolUseCase {
@Override
public ExecutorClass addNewExecutorToExecutorPool(AddNewExecutorToExecutorPoolCommand command){
ExecutorPool executorPool = ExecutorPool.getExecutorPool();
return executorPool.addNewExecutor(command.getExecutorIp(), command.getExecutorPort(), command.getExecutorTaskType());
}
}

View File

@ -0,0 +1,24 @@
package ch.unisg.executorpool.application.service;
import ch.unisg.executorpool.application.port.in.GetAllExecutorInExecutorPoolByTypeQuery;
import ch.unisg.executorpool.application.port.in.GetAllExecutorInExecutorPoolByTypeUseCase;
import ch.unisg.executorpool.domain.ExecutorClass;
import ch.unisg.executorpool.domain.ExecutorPool;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import javax.transaction.Transactional;
import java.util.List;
@RequiredArgsConstructor
@Component
@Transactional
public class GetAllExecutorInExecutorPoolByTypeService implements GetAllExecutorInExecutorPoolByTypeUseCase {
@Override
public List<ExecutorClass> getAllExecutorInExecutorPoolByType(GetAllExecutorInExecutorPoolByTypeQuery query){
ExecutorPool executorPool = ExecutorPool.getExecutorPool();
return executorPool.getAllExecutorsByType(query.getExecutorTaskType());
}
}

View File

@ -0,0 +1,22 @@
package ch.unisg.executorpool.application.service;
import ch.unisg.executorpool.application.port.in.GetAllExecutorsInExecutorPoolUseCase;
import ch.unisg.executorpool.domain.ExecutorClass;
import ch.unisg.executorpool.domain.ExecutorPool;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import javax.transaction.Transactional;
import java.util.List;
@RequiredArgsConstructor
@Component
@Transactional
public class GetAllExecutorsInExecutorPoolService implements GetAllExecutorsInExecutorPoolUseCase {
@Override
public List<ExecutorClass> getAllExecutorsInExecutorPool(){
ExecutorPool executorPool = ExecutorPool.getExecutorPool();
return executorPool.getListOfExecutors().getValue();
}
}

View File

@ -0,0 +1,22 @@
package ch.unisg.executorpool.application.service;
import ch.unisg.executorpool.application.port.in.RemoveExecutorFromExecutorPoolCommand;
import ch.unisg.executorpool.application.port.in.RemoveExecutorFromExecutorPoolUseCase;
import ch.unisg.executorpool.domain.ExecutorClass;
import ch.unisg.executorpool.domain.ExecutorPool;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import javax.transaction.Transactional;
import java.util.Optional;
@RequiredArgsConstructor
@Component
@Transactional
public class RemoveExecutorFromExecutorPoolService implements RemoveExecutorFromExecutorPoolUseCase {
@Override
public Optional<ExecutorClass> removeExecutorFromExecutorPool(RemoveExecutorFromExecutorPoolCommand command){
ExecutorPool executorPool = ExecutorPool.getExecutorPool();
return executorPool.removeExecutorByIpAndPort(command.getExecutorIp(), command.getExecutorPort());
}
}

View File

@ -0,0 +1,42 @@
package ch.unisg.executorpool.domain;
import lombok.Getter;
import lombok.Value;
public class ExecutorClass {
@Getter
private final ExecutorIp executorIp;
@Getter
private final ExecutorPort executorPort;
@Getter
private final ExecutorTaskType executorTaskType;
public ExecutorClass(ExecutorIp executorIp, ExecutorPort executorPort, ExecutorTaskType executorTaskType){
this.executorIp = executorIp;
this.executorPort = executorPort;
this.executorTaskType = executorTaskType;
}
protected static ExecutorClass createExecutorClass(ExecutorIp executorIp, ExecutorPort executorPort, ExecutorTaskType executorTaskType){
System.out.println("New Task: " + executorIp.getValue() + " " + executorPort.getValue() + " " + executorTaskType.getValue());
return new ExecutorClass(executorIp, executorPort, executorTaskType);
}
@Value
public static class ExecutorIp {
private String value;
}
@Value
public static class ExecutorPort {
private String value;
}
@Value
public static class ExecutorTaskType {
private String value;
}
}

View File

@ -0,0 +1,74 @@
package ch.unisg.executorpool.domain;
import lombok.Getter;
import lombok.Value;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
public class ExecutorPool {
@Getter
private final ListOfExecutors listOfExecutors;
private static final ExecutorPool executorPool = new ExecutorPool();
private ExecutorPool(){
this.listOfExecutors = new ListOfExecutors(new LinkedList<ExecutorClass>());
}
public static ExecutorPool getExecutorPool() { return executorPool; }
public ExecutorClass addNewExecutor(ExecutorClass.ExecutorIp executorIp, ExecutorClass.ExecutorPort executorPort, ExecutorClass.ExecutorTaskType executorTaskType){
ExecutorClass newExecutor = ExecutorClass.createExecutorClass(executorIp, executorPort, executorTaskType);
listOfExecutors.value.add(newExecutor);
System.out.println("Number of executors: " + listOfExecutors.value.size());
return newExecutor;
}
public Optional<ExecutorClass> getExecutorByIpAndPort(ExecutorClass.ExecutorIp executorIp, ExecutorClass.ExecutorPort executorPort){
for (ExecutorClass executor : listOfExecutors.value ) {
// TODO can this be simplified by overwriting equals()?
if(executor.getExecutorIp().getValue().equalsIgnoreCase(executorIp.getValue()) &&
executor.getExecutorPort().getValue().equalsIgnoreCase(executorPort.getValue())){
return Optional.of(executor);
}
}
return Optional.empty();
}
public List<ExecutorClass> getAllExecutorsByType(ExecutorClass.ExecutorTaskType executorTaskType){
List<ExecutorClass> matchedExecutors = new LinkedList<ExecutorClass>();
for (ExecutorClass executor : listOfExecutors.value ) {
// TODO can this be simplified by overwriting equals()?
if(executor.getExecutorTaskType().getValue().equalsIgnoreCase(executorTaskType.getValue())){
matchedExecutors.add(executor);
}
}
return matchedExecutors;
}
public Optional<ExecutorClass> removeExecutorByIpAndPort(ExecutorClass.ExecutorIp executorIp, ExecutorClass.ExecutorPort executorPort){
for (ExecutorClass executor : listOfExecutors.value ) {
// TODO can this be simplified by overwriting equals()?
if(executor.getExecutorIp().getValue().equalsIgnoreCase(executorIp.getValue()) &&
executor.getExecutorPort().getValue().equalsIgnoreCase(executorPort.getValue())){
listOfExecutors.value.remove(executor);
return Optional.of(executor);
}
}
return Optional.empty();
}
@Value
public static class ListOfExecutors {
private List<ExecutorClass> value;
}
}

View File

@ -31,6 +31,7 @@ public class AddNewTaskToTaskListService implements AddNewTaskToTaskListUseCase
if (newTask != null) {
NewTaskAddedEvent newTaskAdded = new NewTaskAddedEvent(newTask.getTaskName().getValue(),
taskList.getTaskListName().getValue());
newTaskAddedEventPort.publishNewTaskAddedEvent(newTaskAdded);
}