diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamDAO.java index d7abff76..641b83ed 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ExamDAO.java @@ -28,6 +28,17 @@ public interface ExamDAO extends ActivatableEntityDAO, BulkActionSup * happened */ Result> allIdsOfInstituion(Long institutionId); + /** Updates the exam status for specified exam + * + * @param examId The exam identifier + * @param status the exam status to update to + * @param updateId the update identifier to check update write lock + * @return Result refer to updated Exam or to an error if happened */ + @CacheEvict( + cacheNames = ExamSessionCacheService.CACHE_NAME_RUNNING_EXAM, + key = "#examId") + Result updateState(Long examId, ExamStatus status, String updateId); + /** Saves the Exam and updates the running exam cache. */ @Override @CacheEvict( diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java index 9bdd4435..0c304ef7 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java @@ -165,6 +165,29 @@ public class ExamDAOImpl implements ExamDAO { }); } + @Override + public Result updateState(final Long examId, final ExamStatus status, final String updateId) { + return recordById(examId) + .map(examRecord -> { + if (BooleanUtils.isTrue(BooleanUtils.toBooleanObject(examRecord.getUpdating()))) { + if (!updateId.equals(examRecord.getLastupdate())) { + throw new IllegalStateException("Exam is currently locked: " + examRecord); + } + } + + final ExamRecord newExamRecord = new ExamRecord( + examRecord.getId(), + null, null, null, null, null, null, null, null, + status.name(), + null, null, null, null); + + this.examRecordMapper.updateByPrimaryKeySelective(newExamRecord); + return this.examRecordMapper.selectByPrimaryKey(examId); + }) + .flatMap(this::toDomainModel) + .onError(TransactionHandler::rollback); + } + @Override @Transactional public Result save(final Exam exam) { @@ -173,7 +196,7 @@ public class ExamDAOImpl implements ExamDAO { // check internal persistent write-lock final ExamRecord oldRecord = this.examRecordMapper.selectByPrimaryKey(exam.id); if (BooleanUtils.isTrue(BooleanUtils.toBooleanObject(oldRecord.getUpdating()))) { - throw new IllegalStateException("Exam is currently locked: " + String.valueOf(exam)); + throw new IllegalStateException("Exam is currently locked: " + exam); } final ExamRecord examRecord = new ExamRecord( diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamSessionServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamSessionServiceImpl.java index bd9e9fba..51c1caf2 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamSessionServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamSessionServiceImpl.java @@ -177,7 +177,7 @@ public class ExamSessionServiceImpl implements ExamSessionService { flushCache(exam); } - log.warn("Exam {} is not currently running", examId); + log.info("Exam {} is not currently running", examId); return Result.ofError(new NoSuchElementException( "No currenlty running exam found for id: " + examId)); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamUpdateHandler.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamUpdateHandler.java index a0dfed68..bdcbe876 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamUpdateHandler.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/ExamUpdateHandler.java @@ -86,9 +86,10 @@ class ExamUpdateHandler { return this.examDAO .placeLock(exam.id, updateId) - .flatMap(e -> this.examDAO.save(new Exam( + .flatMap(e -> this.examDAO.updateState( exam.id, - ExamStatus.RUNNING))) + ExamStatus.RUNNING, + updateId)) .flatMap(this::applySebClientRestriction) .flatMap(e -> this.examDAO.releaseLock(e.id, updateId)) .onError(error -> this.examDAO.forceUnlock(exam.id) @@ -103,9 +104,10 @@ class ExamUpdateHandler { return this.examDAO .placeLock(exam.id, updateId) - .flatMap(e -> this.examDAO.save(new Exam( + .flatMap(e -> this.examDAO.updateState( exam.id, - ExamStatus.FINISHED))) + ExamStatus.FINISHED, + updateId)) .flatMap(this::releaseSebClientRestriction) .flatMap(e -> this.examDAO.releaseLock(e.id, updateId)) .onError(error -> this.examDAO.forceUnlock(exam.id))