Skip to content

Commit

Permalink
Merge pull request #59 from ls1intum/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
valentin-boehm authored Nov 28, 2023
2 parents 87ee58b + 1ee6da4 commit ec63dd2
Show file tree
Hide file tree
Showing 19 changed files with 365 additions and 242 deletions.
1 change: 1 addition & 0 deletions src/main/java/de/tum/cit/ase/domain/SimulationRun.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,6 @@ public enum Status {
RUNNING,
FINISHED,
FAILED,
CANCELLED,
}
}
126 changes: 16 additions & 110 deletions src/main/java/de/tum/cit/ase/service/artemis/ArtemisConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,86 +10,32 @@ public class ArtemisConfiguration {
@Value("${artemis.local.url}")
private String localUrl;

@Value("${artemis.local.websocket_url}")
private String localWebsocketUrl;

@Value("${artemis.local.username_template}")
private String localUsername;

@Value("${artemis.local.password_template}")
private String localPassword;

@Value("${artemis.local.admin_username}")
private String localAdminUsername;

@Value("${artemis.local.admin_password}")
private String localAdminPassword;
@Value("${artemis.local.cleanup-enabled}")
private boolean localCleanup;

@Value("${artemis.ts1.url}")
private String test1Url;

@Value("${artemis.ts1.websocket_url}")
private String test1WebsocketUrl;

@Value("${artemis.ts1.username_template}")
private String test1Username;

@Value("${artemis.ts1.password_template}")
private String test1Password;

@Value("${artemis.ts1.admin_username}")
private String test1AdminUsername;

@Value("${artemis.ts1.admin_password}")
private String test1AdminPassword;
@Value("${artemis.ts1.cleanup-enabled}")
private boolean test1Cleanup;

@Value("${artemis.ts3.url}")
private String test3Url;

@Value("${artemis.ts3.websocket_url}")
private String test3WebsocketUrl;

@Value("${artemis.ts3.username_template}")
private String test3Username;

@Value("${artemis.ts3.password_template}")
private String test3Password;

@Value("${artemis.ts3.admin_username}")
private String test3AdminUsername;

@Value("${artemis.ts3.admin_password}")
private String test3AdminPassword;
@Value("${artemis.ts3.cleanup-enabled}")
private boolean test3Cleanup;

@Value("${artemis.staging.url}")
private String stagingUrl;

@Value("${artemis.staging.websocket_url}")
private String stagingWebsocketUrl;

@Value("${artemis.staging.username_template}")
private String stagingUsername;

@Value("${artemis.staging.password_template}")
private String stagingPassword;

@Value("${artemis.staging.admin_username}")
private String stagingAdminUsername;

@Value("${artemis.staging.admin_password}")
private String stagingAdminPassword;
@Value("${artemis.staging.cleanup-enabled}")
private boolean stagingCleanup;

@Value("${artemis.production.url}")
private String productionUrl;

@Value("${artemis.production.websocket_url}")
private String productionWebsocketUrl;

@Value("${artemis.production.username_template}")
private String productionUsername;

@Value("${artemis.production.password_template}")
private String productionPassword;
@Value("${artemis.production.cleanup-enabled}")
private boolean productionCleanup;

public String getUrl(ArtemisServer server) {
return switch (server) {
Expand All @@ -101,53 +47,13 @@ public String getUrl(ArtemisServer server) {
};
}

public String getWebsocketUrl(ArtemisServer server) {
return switch (server) {
case LOCAL -> localWebsocketUrl;
case TS1 -> test1WebsocketUrl;
case TS3 -> test3WebsocketUrl;
case STAGING -> stagingWebsocketUrl;
case PRODUCTION -> productionWebsocketUrl;
};
}

public String getUsernameTemplate(ArtemisServer server) {
return switch (server) {
case LOCAL -> localUsername;
case TS1 -> test1Username;
case TS3 -> test3Username;
case STAGING -> stagingUsername;
case PRODUCTION -> productionUsername;
};
}

public String getPasswordTemplate(ArtemisServer server) {
return switch (server) {
case LOCAL -> localPassword;
case TS1 -> test1Password;
case TS3 -> test3Password;
case STAGING -> stagingPassword;
case PRODUCTION -> productionPassword;
};
}

public String getAdminUsername(ArtemisServer server) {
return switch (server) {
case LOCAL -> localAdminUsername;
case TS1 -> test1AdminUsername;
case TS3 -> test3AdminUsername;
case STAGING -> stagingAdminUsername;
case PRODUCTION -> throw new UnsupportedOperationException("Admin username not supported for production server");
};
}

public String getAdminPassword(ArtemisServer server) {
public boolean getCleanup(ArtemisServer server) {
return switch (server) {
case LOCAL -> localAdminPassword;
case TS1 -> test1AdminPassword;
case TS3 -> test3AdminPassword;
case STAGING -> stagingAdminPassword;
case PRODUCTION -> throw new UnsupportedOperationException("Admin password not supported for production server");
case LOCAL -> localCleanup;
case TS1 -> test1Cleanup;
case TS3 -> test3Cleanup;
case STAGING -> stagingCleanup;
case PRODUCTION -> productionCleanup;
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ public void prepareExam(long courseId, long examId) {
do {
try {
sleep(1000);
} catch (InterruptedException ignored) {}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}

status =
webClient
Expand Down Expand Up @@ -369,28 +371,31 @@ public void registerStudentsForCourse(long courseId, SimulatedArtemisStudent[] s
ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(threadCount);
Scheduler scheduler = Schedulers.from(threadPoolExecutor);

Flowable
.range(0, students.length)
.parallel(threadCount)
.runOn(scheduler)
.doOnNext(i -> {
try {
webClient
.post()
.uri(uriBuilder ->
uriBuilder.pathSegment("api", "courses", String.valueOf(courseId), "students", students[i].username).build()
)
.retrieve()
.toBodilessEntity()
.block();
} catch (Exception e) {
log.warn("Could not register student {{}} for course: {{}}", students[i].username, e.getMessage());
}
})
.sequential()
.blockingSubscribe();
threadPoolExecutor.shutdownNow();
scheduler.shutdown();
try {
Flowable
.range(0, students.length)
.parallel(threadCount)
.runOn(scheduler)
.doOnNext(i -> {
try {
webClient
.post()
.uri(uriBuilder ->
uriBuilder.pathSegment("api", "courses", String.valueOf(courseId), "students", students[i].username).build()
)
.retrieve()
.toBodilessEntity()
.block();
} catch (Exception e) {
log.warn("Could not register student {{}} for course: {{}}", students[i].username, e.getMessage());
}
})
.sequential()
.blockingSubscribe();
} finally {
threadPoolExecutor.shutdownNow();
scheduler.shutdown();
}
}

/**
Expand Down Expand Up @@ -439,4 +444,17 @@ public void deleteCourse(long courseId) {
.toBodilessEntity()
.block();
}

public void deleteExam(long courseId, long examId) {
if (!authenticated) {
throw new IllegalStateException("User " + username + " is not logged in or does not have the necessary access rights.");
}

webClient
.delete()
.uri(uriBuilder -> uriBuilder.pathSegment("api", "courses", String.valueOf(courseId), "exams", String.valueOf(examId)).build())
.retrieve()
.toBodilessEntity()
.block();
}
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,49 @@
package de.tum.cit.ase.service.simulation;

import static de.tum.cit.ase.util.NumberRangeParser.numberRangeRegex;
import static java.lang.Thread.sleep;
import static java.time.ZonedDateTime.now;

import de.tum.cit.ase.domain.*;
import de.tum.cit.ase.repository.LogMessageRepository;
import de.tum.cit.ase.repository.SimulationRepository;
import de.tum.cit.ase.repository.SimulationRunRepository;
import de.tum.cit.ase.service.artemis.ArtemisConfiguration;
import de.tum.cit.ase.util.ArtemisAccountDTO;
import de.tum.cit.ase.util.ArtemisServer;
import de.tum.cit.ase.util.NumberRangeParser;
import de.tum.cit.ase.web.websocket.SimulationWebsocketService;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class SimulationDataService {

private final Logger log = LoggerFactory.getLogger(SimulationDataService.class);

private final SimulationRepository simulationRepository;
private final SimulationRunRepository simulationRunRepository;
private final SimulationRunQueueService simulationRunQueueService;
private final SimulationWebsocketService simulationWebsocketService;
private final LogMessageRepository logMessageRepository;
private final ArtemisConfiguration artemisConfiguration;

public SimulationDataService(
SimulationRepository simulationRepository,
SimulationRunRepository simulationRunRepository,
SimulationRunQueueService simulationRunQueueService,
SimulationWebsocketService simulationWebsocketService
SimulationWebsocketService simulationWebsocketService,
LogMessageRepository logMessageRepository,
ArtemisConfiguration artemisConfiguration
) {
this.simulationRepository = simulationRepository;
this.simulationRunRepository = simulationRunRepository;
this.simulationRunQueueService = simulationRunQueueService;
this.simulationWebsocketService = simulationWebsocketService;
this.logMessageRepository = logMessageRepository;
this.artemisConfiguration = artemisConfiguration;
}

public Simulation createSimulation(Simulation simulation) {
Expand Down Expand Up @@ -115,4 +128,56 @@ public boolean validateSimulation(Simulation simulation) {
}
);
}

/**
* Cancel the currently active simulation run.
* @param runId the ID of the simulation run to cancel
* @throws IllegalArgumentException if run with given ID is not active
*/
public void cancelActiveRun(long runId) {
var run = simulationRunRepository.findById(runId).orElseThrow();
if (run.getStatus() != SimulationRun.Status.RUNNING) {
throw new IllegalArgumentException("Simulation run is not active!");
} else {
log.info("Cancelling simulation run {}", runId);

simulationRunQueueService.abortSimulationExecution();
try {
sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
run = simulationRunRepository.findById(runId).orElseThrow();

run.setStatus(SimulationRun.Status.CANCELLED);
simulationWebsocketService.sendRunStatusUpdate(run);

var logMsg = new LogMessage();
logMsg.setTimestamp(now());
logMsg.setMessage("Run cancelled");
logMsg.setSimulationRun(run);
logMsg.setError(true);
run.getLogMessages().add(logMsg);
simulationWebsocketService.sendRunLogMessage(run, logMsg);
log.info("Simulation run {} cancelled", runId);
simulationRunRepository.save(run);
logMessageRepository.save(logMsg);

simulationRunQueueService.restartSimulationExecution();
}
}

/**
* Get a list of all Artemis servers that have cleanup enabled.
* @return a list of all Artemis servers that have cleanup enabled
*/
public List<ArtemisServer> getServersWithCleanupEnabled() {
List<ArtemisServer> servers = new ArrayList<>();
for (ArtemisServer server : ArtemisServer.values()) {
if (artemisConfiguration.getCleanup(server)) {
servers.add(server);
}
}
return servers;
}
}
Loading

0 comments on commit ec63dd2

Please sign in to comment.