added some cleanup after exam finished
This commit is contained in:
		
							parent
							
								
									c53336f1d4
								
							
						
					
					
						commit
						9cc020712a
					
				
					 5 changed files with 63 additions and 0 deletions
				
			
		| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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(() -> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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()) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue