added some cleanup after exam finished

This commit is contained in:
anhefti 2022-03-23 12:31:56 +01:00
parent c53336f1d4
commit 9cc020712a
5 changed files with 63 additions and 0 deletions

View file

@ -15,6 +15,7 @@ import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord;
@ -180,4 +181,10 @@ public interface ClientConnectionDAO extends
* @return Result refer to the relevant VDI pair connection if exists or to an error if not */ * @return Result refer to the relevant VDI pair connection if exists or to an error if not */
Result<ClientConnectionRecord> getVDIPairCompanion(Long examId, String clientName); Result<ClientConnectionRecord> getVDIPairCompanion(Long examId, String clientName);
/** Deletes all client indicator value entries within the client_indicator table for a given exam.
*
* @param exam the Exam to delete all currently registered indicator value entries
* @return Result refer to the given Exam or to an error when happened. */
Result<Exam> deleteClientIndicatorValues(Exam exam);
} }

View file

@ -32,6 +32,7 @@ import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.api.EntityType;
import ch.ethz.seb.sebserver.gbl.model.EntityDependency; import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityKey;
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus; import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection.ConnectionStatus;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
@ -694,6 +695,33 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
}); });
} }
@Override
@Transactional
public Result<Exam> deleteClientIndicatorValues(final Exam exam) {
return Result.tryCatch(() -> {
final List<Long> clientConnections = this.clientConnectionRecordMapper.selectIdsByExample()
.where(
ClientConnectionRecordDynamicSqlSupport.examId,
SqlBuilder.isEqualTo(exam.id))
.build()
.execute();
if (clientConnections == null || clientConnections.isEmpty()) {
return exam;
}
this.clientIndicatorRecordMapper.deleteByExample()
.where(
ClientIndicatorRecordDynamicSqlSupport.clientConnectionId,
SqlBuilder.isIn(clientConnections))
.build()
.execute();
return exam;
});
}
private Result<ClientConnectionRecord> recordById(final Long id) { private Result<ClientConnectionRecord> recordById(final Long id) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {

View file

@ -182,6 +182,13 @@ public interface ExamSessionService {
* @return Result refer to the collection of connection tokens or to an error when happened. */ * @return Result refer to the collection of connection tokens or to an error when happened. */
Result<Collection<String>> getActiveConnectionTokens(Long examId); Result<Collection<String>> getActiveConnectionTokens(Long examId);
/** Called to notify that the given exam has just been finished.
* This cleanup all exam session caches for the given exam and also cleanup session based stores on the persistent.
*
* @param exam the Exam that has just been finished
* @return Result refer to the finished exam or to an error when happened. */
Result<Exam> notifyExamFinished(final Exam exam);
/** Use this to check if the current cached running exam is up to date /** Use this to check if the current cached running exam is up to date
* and if not to flush the cache. * and if not to flush the cache.
* *

View file

@ -29,6 +29,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.WebserviceInfo; import ch.ethz.seb.sebserver.webservice.WebserviceInfo;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringRoomService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringRoomService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientConnectionService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientConnectionService;
@Service @Service
@ -42,6 +43,7 @@ public class ExamSessionControlTask implements DisposableBean {
private final ExamUpdateHandler examUpdateHandler; private final ExamUpdateHandler examUpdateHandler;
private final ExamProctoringRoomService examProcotringRoomService; private final ExamProctoringRoomService examProcotringRoomService;
private final WebserviceInfo webserviceInfo; private final WebserviceInfo webserviceInfo;
private final ExamSessionService examSessionService;
private final Long examTimePrefix; private final Long examTimePrefix;
private final Long examTimeSuffix; private final Long examTimeSuffix;
@ -54,6 +56,7 @@ public class ExamSessionControlTask implements DisposableBean {
final ExamUpdateHandler examUpdateHandler, final ExamUpdateHandler examUpdateHandler,
final ExamProctoringRoomService examProcotringRoomService, final ExamProctoringRoomService examProcotringRoomService,
final WebserviceInfo webserviceInfo, final WebserviceInfo webserviceInfo,
final ExamSessionService examSessionService,
@Value("${sebserver.webservice.api.exam.time-prefix:3600000}") final Long examTimePrefix, @Value("${sebserver.webservice.api.exam.time-prefix:3600000}") final Long examTimePrefix,
@Value("${sebserver.webservice.api.exam.time-suffix:3600000}") final Long examTimeSuffix, @Value("${sebserver.webservice.api.exam.time-suffix:3600000}") final Long examTimeSuffix,
@Value("${sebserver.webservice.api.exam.update-interval:1 * * * * *}") final String examTaskCron, @Value("${sebserver.webservice.api.exam.update-interval:1 * * * * *}") final String examTaskCron,
@ -63,6 +66,7 @@ public class ExamSessionControlTask implements DisposableBean {
this.sebClientConnectionService = sebClientConnectionService; this.sebClientConnectionService = sebClientConnectionService;
this.examUpdateHandler = examUpdateHandler; this.examUpdateHandler = examUpdateHandler;
this.webserviceInfo = webserviceInfo; this.webserviceInfo = webserviceInfo;
this.examSessionService = examSessionService;
this.examTimePrefix = examTimePrefix; this.examTimePrefix = examTimePrefix;
this.examTimeSuffix = examTimeSuffix; this.examTimeSuffix = examTimeSuffix;
this.examTaskCron = examTaskCron; this.examTaskCron = examTaskCron;
@ -185,6 +189,7 @@ public class ExamSessionControlTask implements DisposableBean {
.filter(exam -> exam.endTime != null && exam.endTime.plus(this.examTimeSuffix).isBefore(now)) .filter(exam -> exam.endTime != null && exam.endTime.plus(this.examTimeSuffix).isBefore(now))
.flatMap(exam -> Result.skipOnError(this.examUpdateHandler.setFinished(exam, updateId))) .flatMap(exam -> Result.skipOnError(this.examUpdateHandler.setFinished(exam, updateId)))
.flatMap(exam -> Result.skipOnError(this.examProcotringRoomService.disposeRoomsForExam(exam))) .flatMap(exam -> Result.skipOnError(this.examProcotringRoomService.disposeRoomsForExam(exam)))
.flatMap(exam -> Result.skipOnError(this.examSessionService.notifyExamFinished(exam)))
.collect(Collectors.toMap(Exam::getId, Exam::getName)); .collect(Collectors.toMap(Exam::getId, Exam::getName));
if (!updated.isEmpty()) { if (!updated.isEmpty()) {

View file

@ -393,6 +393,22 @@ public class ExamSessionServiceImpl implements ExamSessionService {
.getActiveConnctionTokens(examId); .getActiveConnctionTokens(examId);
} }
@Override
public Result<Exam> notifyExamFinished(final Exam exam) {
return Result.tryCatch(() -> {
if (!isExamRunning(exam.id)) {
this.flushCache(exam);
if (this.distributedSetup) {
this.clientConnectionDAO
.deleteClientIndicatorValues(exam)
.getOrThrow();
}
}
return exam;
});
}
@Override @Override
public Result<Exam> updateExamCache(final Long examId) { public Result<Exam> updateExamCache(final Long examId) {