implemented event handling for start and finish exams
This commit is contained in:
		
							parent
							
								
									b6433c7c99
								
							
						
					
					
						commit
						ebbbf56314
					
				
					 8 changed files with 140 additions and 37 deletions
				
			
		|  | @ -22,6 +22,7 @@ import org.apache.commons.lang3.StringUtils; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| import org.springframework.context.annotation.Lazy; | import org.springframework.context.annotation.Lazy; | ||||||
|  | import org.springframework.context.event.EventListener; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| import org.springframework.transaction.annotation.Transactional; | import org.springframework.transaction.annotation.Transactional; | ||||||
| 
 | 
 | ||||||
|  | @ -38,6 +39,8 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ExamDAO; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SEBRestrictionService; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SEBRestrictionService; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigService; | import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.ExamConfigService; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamFinishedEvent; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamStartedEvent; | ||||||
| 
 | 
 | ||||||
| @Lazy | @Lazy | ||||||
| @Service | @Service | ||||||
|  | @ -188,6 +191,30 @@ public class SEBRestrictionServiceImpl implements SEBRestrictionService { | ||||||
|                 .flatMap(this.examDAO::byPK); |                 .flatMap(this.examDAO::byPK); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @EventListener | ||||||
|  |     public void notifyExamStarted(final ExamStartedEvent event) { | ||||||
|  | 
 | ||||||
|  |         log.info("ExamStartedEvent received, process applySEBClientRestriction..."); | ||||||
|  | 
 | ||||||
|  |         applySEBClientRestriction(event.exam) | ||||||
|  |                 .onError(error -> log.error( | ||||||
|  |                         "Failed to apply SEB restrictions for started exam: {}", | ||||||
|  |                         event.exam, | ||||||
|  |                         error)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @EventListener | ||||||
|  |     public void notifyExamFinished(final ExamFinishedEvent event) { | ||||||
|  | 
 | ||||||
|  |         log.info("ExamFinishedEvent received, process releaseSEBClientRestriction..."); | ||||||
|  | 
 | ||||||
|  |         releaseSEBClientRestriction(event.exam) | ||||||
|  |                 .onError(error -> log.error( | ||||||
|  |                         "Failed to release SEB restrictions for finished exam: {}", | ||||||
|  |                         event.exam, | ||||||
|  |                         error)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Result<Exam> applySEBClientRestriction(final Exam exam) { |     public Result<Exam> applySEBClientRestriction(final Exam exam) { | ||||||
|         return Result.tryCatch(() -> { |         return Result.tryCatch(() -> { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,26 @@ | ||||||
|  | /* | ||||||
|  |  * Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET) | ||||||
|  |  * | ||||||
|  |  * This Source Code Form is subject to the terms of the Mozilla Public | ||||||
|  |  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||
|  |  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package ch.ethz.seb.sebserver.webservice.servicelayer.session; | ||||||
|  | 
 | ||||||
|  | import org.springframework.context.ApplicationEvent; | ||||||
|  | 
 | ||||||
|  | import ch.ethz.seb.sebserver.gbl.model.exam.Exam; | ||||||
|  | 
 | ||||||
|  | /** This event is fired just after an exam has been finished */ | ||||||
|  | public class ExamFinishedEvent extends ApplicationEvent { | ||||||
|  | 
 | ||||||
|  |     private static final long serialVersionUID = -1528880878532843063L; | ||||||
|  | 
 | ||||||
|  |     public final Exam exam; | ||||||
|  | 
 | ||||||
|  |     public ExamFinishedEvent(final Exam exam) { | ||||||
|  |         super(exam); | ||||||
|  |         this.exam = exam; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -191,13 +191,6 @@ 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. | ||||||
|      * |      * | ||||||
|  |  | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | /* | ||||||
|  |  * Copyright (c) 2022 ETH Zürich, Educational Development and Technology (LET) | ||||||
|  |  * | ||||||
|  |  * This Source Code Form is subject to the terms of the Mozilla Public | ||||||
|  |  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||
|  |  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package ch.ethz.seb.sebserver.webservice.servicelayer.session; | ||||||
|  | 
 | ||||||
|  | import org.springframework.context.ApplicationEvent; | ||||||
|  | 
 | ||||||
|  | import ch.ethz.seb.sebserver.gbl.model.exam.Exam; | ||||||
|  | 
 | ||||||
|  | /** This event is fired just after an exam has been started */ | ||||||
|  | public class ExamStartedEvent extends ApplicationEvent { | ||||||
|  | 
 | ||||||
|  |     private static final long serialVersionUID = -6564345490588661010L; | ||||||
|  | 
 | ||||||
|  |     public final Exam exam; | ||||||
|  | 
 | ||||||
|  |     public ExamStartedEvent(final Exam exam) { | ||||||
|  |         super(exam); | ||||||
|  |         this.exam = exam; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -29,7 +29,6 @@ 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 | ||||||
|  | @ -43,7 +42,6 @@ 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; | ||||||
|  | @ -56,7 +54,6 @@ 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, | ||||||
|  | @ -66,7 +63,6 @@ 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; | ||||||
|  | @ -188,8 +184,6 @@ public class ExamSessionControlTask implements DisposableBean { | ||||||
|                     .stream() |                     .stream() | ||||||
|                     .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.examSessionService.notifyExamFinished(exam))) |  | ||||||
|                     .collect(Collectors.toMap(Exam::getId, Exam::getName)); |                     .collect(Collectors.toMap(Exam::getId, Exam::getName)); | ||||||
| 
 | 
 | ||||||
|             if (!updated.isEmpty()) { |             if (!updated.isEmpty()) { | ||||||
|  |  | ||||||
|  | @ -26,6 +26,7 @@ import org.slf4j.LoggerFactory; | ||||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||||
| import org.springframework.cache.CacheManager; | import org.springframework.cache.CacheManager; | ||||||
| import org.springframework.context.annotation.Lazy; | import org.springframework.context.annotation.Lazy; | ||||||
|  | import org.springframework.context.event.EventListener; | ||||||
| import org.springframework.security.access.AccessDeniedException; | import org.springframework.security.access.AccessDeniedException; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| 
 | 
 | ||||||
|  | @ -47,6 +48,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.IndicatorDAO; | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.IndicatorDAO; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SEBRestrictionService; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SEBRestrictionService; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamFinishedEvent; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService; | import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService; | ||||||
| 
 | 
 | ||||||
| @Lazy | @Lazy | ||||||
|  | @ -402,20 +404,23 @@ public class ExamSessionServiceImpl implements ExamSessionService { | ||||||
|                 .getActiveConnctionTokens(examId); |                 .getActiveConnctionTokens(examId); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @EventListener | ||||||
|     public Result<Exam> notifyExamFinished(final Exam exam) { |     public void notifyExamFinished(final ExamFinishedEvent event) { | ||||||
|         return Result.tryCatch(() -> { | 
 | ||||||
|             if (!isExamRunning(exam.id)) { |         log.info("ExamFinishedEvent received, process exam session cleanup..."); | ||||||
|                 this.flushCache(exam); | 
 | ||||||
|  |         try { | ||||||
|  |             if (!isExamRunning(event.exam.id)) { | ||||||
|  |                 this.flushCache(event.exam); | ||||||
|                 if (this.distributedSetup) { |                 if (this.distributedSetup) { | ||||||
|                     this.clientConnectionDAO |                     this.clientConnectionDAO | ||||||
|                             .deleteClientIndicatorValues(exam) |                             .deleteClientIndicatorValues(event.exam) | ||||||
|                             .getOrThrow(); |                             .getOrThrow(); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 |         } catch (final Exception e) { | ||||||
|             return exam; |             log.error("Failed to cleanup on finished exam: {}", event.exam, e); | ||||||
|         }); |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ import org.joda.time.DateTimeZone; | ||||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||||
|  | import org.springframework.context.ApplicationEventPublisher; | ||||||
| import org.springframework.context.annotation.Lazy; | import org.springframework.context.annotation.Lazy; | ||||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||||
| 
 | 
 | ||||||
|  | @ -24,6 +25,8 @@ import ch.ethz.seb.sebserver.gbl.util.Utils; | ||||||
| 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.lms.SEBRestrictionService; | import ch.ethz.seb.sebserver.webservice.servicelayer.lms.SEBRestrictionService; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamFinishedEvent; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamStartedEvent; | ||||||
| 
 | 
 | ||||||
| @Lazy | @Lazy | ||||||
| @Service | @Service | ||||||
|  | @ -33,17 +36,20 @@ class ExamUpdateHandler { | ||||||
|     private static final Logger log = LoggerFactory.getLogger(ExamUpdateHandler.class); |     private static final Logger log = LoggerFactory.getLogger(ExamUpdateHandler.class); | ||||||
| 
 | 
 | ||||||
|     private final ExamDAO examDAO; |     private final ExamDAO examDAO; | ||||||
|  |     private final ApplicationEventPublisher applicationEventPublisher; | ||||||
|     private final SEBRestrictionService sebRestrictionService; |     private final SEBRestrictionService sebRestrictionService; | ||||||
|     private final String updatePrefix; |     private final String updatePrefix; | ||||||
|     private final Long examTimeSuffix; |     private final Long examTimeSuffix; | ||||||
| 
 | 
 | ||||||
|     public ExamUpdateHandler( |     public ExamUpdateHandler( | ||||||
|             final ExamDAO examDAO, |             final ExamDAO examDAO, | ||||||
|  |             final ApplicationEventPublisher applicationEventPublisher, | ||||||
|             final SEBRestrictionService sebRestrictionService, |             final SEBRestrictionService sebRestrictionService, | ||||||
|             final WebserviceInfo webserviceInfo, |             final WebserviceInfo webserviceInfo, | ||||||
|             @Value("${sebserver.webservice.api.exam.time-suffix:3600000}") final Long examTimeSuffix) { |             @Value("${sebserver.webservice.api.exam.time-suffix:3600000}") final Long examTimeSuffix) { | ||||||
| 
 | 
 | ||||||
|         this.examDAO = examDAO; |         this.examDAO = examDAO; | ||||||
|  |         this.applicationEventPublisher = applicationEventPublisher; | ||||||
|         this.sebRestrictionService = sebRestrictionService; |         this.sebRestrictionService = sebRestrictionService; | ||||||
|         this.updatePrefix = webserviceInfo.getLocalHostAddress() |         this.updatePrefix = webserviceInfo.getLocalHostAddress() | ||||||
|                 + "_" + webserviceInfo.getServerPort() + "_"; |                 + "_" + webserviceInfo.getServerPort() + "_"; | ||||||
|  | @ -79,14 +85,21 @@ class ExamUpdateHandler { | ||||||
| 
 | 
 | ||||||
|         return this.examDAO |         return this.examDAO | ||||||
|                 .placeLock(exam.id, updateId) |                 .placeLock(exam.id, updateId) | ||||||
|                 .flatMap(e -> this.examDAO.updateState( |                 .flatMap(e -> this.examDAO.updateState(exam.id, ExamStatus.RUNNING, updateId)) | ||||||
|                         exam.id, |                 .map(e -> { | ||||||
|                         ExamStatus.RUNNING, |                     this.examDAO | ||||||
|                         updateId)) |                             .releaseLock(e, updateId) | ||||||
|                 .flatMap(this.sebRestrictionService::applySEBClientRestriction) |                             .onError(error -> this.examDAO | ||||||
|                 .flatMap(e -> this.examDAO.releaseLock(e, updateId)) |                                     .forceUnlock(exam.id) | ||||||
|                 .onError(error -> this.examDAO.forceUnlock(exam.id) |                                     .onError(unlockError -> log.error( | ||||||
|                         .onError(unlockError -> log.error("Failed to force unlock update look for exam: {}", exam.id))); |                                             "Failed to force unlock update look for exam: {}", | ||||||
|  |                                             exam.id))); | ||||||
|  |                     return e; | ||||||
|  |                 }) | ||||||
|  |                 .map(e -> { | ||||||
|  |                     this.applicationEventPublisher.publishEvent(new ExamStartedEvent(exam)); | ||||||
|  |                     return exam; | ||||||
|  |                 }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Result<Exam> setFinished(final Exam exam, final String updateId) { |     Result<Exam> setFinished(final Exam exam, final String updateId) { | ||||||
|  | @ -96,13 +109,21 @@ class ExamUpdateHandler { | ||||||
| 
 | 
 | ||||||
|         return this.examDAO |         return this.examDAO | ||||||
|                 .placeLock(exam.id, updateId) |                 .placeLock(exam.id, updateId) | ||||||
|                 .flatMap(e -> this.examDAO.updateState( |                 .flatMap(e -> this.examDAO.updateState(exam.id, ExamStatus.FINISHED, updateId)) | ||||||
|                         exam.id, |                 .map(e -> { | ||||||
|                         ExamStatus.FINISHED, |                     this.examDAO | ||||||
|                         updateId)) |                             .releaseLock(e, updateId) | ||||||
|                 .flatMap(this.sebRestrictionService::releaseSEBClientRestriction) |                             .onError(error -> this.examDAO | ||||||
|                 .flatMap(e -> this.examDAO.releaseLock(e, updateId)) |                                     .forceUnlock(exam.id) | ||||||
|                 .onError(error -> this.examDAO.forceUnlock(exam.id)); |                                     .onError(unlockError -> log.error( | ||||||
|  |                                             "Failed to force unlock update look for exam: {}", | ||||||
|  |                                             exam.id))); | ||||||
|  |                     return e; | ||||||
|  |                 }) | ||||||
|  |                 .map(e -> { | ||||||
|  |                     this.applicationEventPublisher.publishEvent(new ExamFinishedEvent(exam)); | ||||||
|  |                     return exam; | ||||||
|  |                 }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -40,6 +40,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.RemoteProctoringRoomDAO; | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.RemoteProctoringRoomDAO; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl.ExamDeletionEvent; | import ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl.ExamDeletionEvent; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService; | import ch.ethz.seb.sebserver.webservice.servicelayer.exam.ExamAdminService; | ||||||
|  | import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamFinishedEvent; | ||||||
| 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.ExamProctoringService; | import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamProctoringService; | ||||||
| import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService; | import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService; | ||||||
|  | @ -155,6 +156,15 @@ public class ExamProctoringRoomServiceImpl implements ExamProctoringRoomService | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @EventListener | ||||||
|  |     public void notifyExamFinished(final ExamFinishedEvent event) { | ||||||
|  | 
 | ||||||
|  |         log.info("ExamFinishedEvent received, process disposeRoomsForExam..."); | ||||||
|  | 
 | ||||||
|  |         disposeRoomsForExam(event.exam) | ||||||
|  |                 .onError(error -> log.error("Failed to dispose rooms for finished exam: {}", event.exam, error)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     public Result<Exam> disposeRoomsForExam(final Exam exam) { |     public Result<Exam> disposeRoomsForExam(final Exam exam) { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti