added configurable ping strategies
This commit is contained in:
parent
0e1ee3330a
commit
99ea2472f4
10 changed files with 249 additions and 25 deletions
|
@ -78,7 +78,7 @@ public class AsyncServiceSpringConfig implements AsyncConfigurer {
|
||||||
@Bean
|
@Bean
|
||||||
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
|
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
|
||||||
final ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
|
final ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
|
||||||
threadPoolTaskScheduler.setPoolSize(5);
|
threadPoolTaskScheduler.setPoolSize(10);
|
||||||
threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(false);
|
threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(false);
|
||||||
threadPoolTaskScheduler.setThreadNamePrefix("SEB-Server-BgTask-");
|
threadPoolTaskScheduler.setThreadNamePrefix("SEB-Server-BgTask-");
|
||||||
return threadPoolTaskScheduler;
|
return threadPoolTaskScheduler;
|
||||||
|
|
|
@ -23,6 +23,7 @@ import ch.ethz.seb.sebserver.SEBServerInit;
|
||||||
import ch.ethz.seb.sebserver.SEBServerInitEvent;
|
import ch.ethz.seb.sebserver.SEBServerInitEvent;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.WebserviceInfoDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.WebserviceInfoDAO;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.SEBClientPingServiceFactory;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@WebServiceProfile
|
@WebServiceProfile
|
||||||
|
@ -38,6 +39,7 @@ public class WebserviceInit implements ApplicationListener<ApplicationReadyEvent
|
||||||
private final WebserviceInfoDAO webserviceInfoDAO;
|
private final WebserviceInfoDAO webserviceInfoDAO;
|
||||||
private final DBIntegrityChecker dbIntegrityChecker;
|
private final DBIntegrityChecker dbIntegrityChecker;
|
||||||
private final SEBServerMigrationStrategy sebServerMigrationStrategy;
|
private final SEBServerMigrationStrategy sebServerMigrationStrategy;
|
||||||
|
private final SEBClientPingServiceFactory sebClientPingServiceFactory;
|
||||||
|
|
||||||
protected WebserviceInit(
|
protected WebserviceInit(
|
||||||
final SEBServerInit sebServerInit,
|
final SEBServerInit sebServerInit,
|
||||||
|
@ -47,7 +49,8 @@ public class WebserviceInit implements ApplicationListener<ApplicationReadyEvent
|
||||||
final WebserviceInfoDAO webserviceInfoDAO,
|
final WebserviceInfoDAO webserviceInfoDAO,
|
||||||
final DBIntegrityChecker dbIntegrityChecker,
|
final DBIntegrityChecker dbIntegrityChecker,
|
||||||
final ApplicationContext applicationContext,
|
final ApplicationContext applicationContext,
|
||||||
final SEBServerMigrationStrategy sebServerMigrationStrategy) {
|
final SEBServerMigrationStrategy sebServerMigrationStrategy,
|
||||||
|
final SEBClientPingServiceFactory sebClientPingServiceFactory) {
|
||||||
|
|
||||||
this.applicationContext = applicationContext;
|
this.applicationContext = applicationContext;
|
||||||
this.sebServerInit = sebServerInit;
|
this.sebServerInit = sebServerInit;
|
||||||
|
@ -58,6 +61,7 @@ public class WebserviceInit implements ApplicationListener<ApplicationReadyEvent
|
||||||
this.webserviceInfoDAO = webserviceInfoDAO;
|
this.webserviceInfoDAO = webserviceInfoDAO;
|
||||||
this.dbIntegrityChecker = dbIntegrityChecker;
|
this.dbIntegrityChecker = dbIntegrityChecker;
|
||||||
this.sebServerMigrationStrategy = sebServerMigrationStrategy;
|
this.sebServerMigrationStrategy = sebServerMigrationStrategy;
|
||||||
|
this.sebClientPingServiceFactory = sebClientPingServiceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApplicationContext getApplicationContext() {
|
public ApplicationContext getApplicationContext() {
|
||||||
|
@ -120,6 +124,10 @@ public class WebserviceInit implements ApplicationListener<ApplicationReadyEvent
|
||||||
this.environment.getProperty("sebserver.webservice.distributed.connectionUpdate", "2000"));
|
this.environment.getProperty("sebserver.webservice.distributed.connectionUpdate", "2000"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SEBServerInit.INIT_LOGGER.info("----> ");
|
||||||
|
SEBServerInit.INIT_LOGGER.info("----> Working with ping service: {}",
|
||||||
|
this.sebClientPingServiceFactory.getWorkingServiceType());
|
||||||
|
|
||||||
SEBServerInit.INIT_LOGGER.info("----> ");
|
SEBServerInit.INIT_LOGGER.info("----> ");
|
||||||
SEBServerInit.INIT_LOGGER.info("----> Server address: {}", this.environment.getProperty("server.address"));
|
SEBServerInit.INIT_LOGGER.info("----> Server address: {}", this.environment.getProperty("server.address"));
|
||||||
SEBServerInit.INIT_LOGGER.info("----> Server port: {}", this.environment.getProperty("server.port"));
|
SEBServerInit.INIT_LOGGER.info("----> Server port: {}", this.environment.getProperty("server.port"));
|
||||||
|
|
|
@ -530,13 +530,15 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.clientConnectionRecordMapper
|
final List<ClientConnectionRecord> execute = this.clientConnectionRecordMapper
|
||||||
.selectByExample()
|
.selectByExample()
|
||||||
.where(ClientConnectionRecordDynamicSqlSupport.screenProctoringGroupId, isNull())
|
.where(ClientConnectionRecordDynamicSqlSupport.screenProctoringGroupId, isNull())
|
||||||
.and(ClientConnectionRecordDynamicSqlSupport.examId, isIn(examIds))
|
.and(ClientConnectionRecordDynamicSqlSupport.examId, isIn(examIds))
|
||||||
.and(ClientConnectionRecordDynamicSqlSupport.status, isEqualTo(ConnectionStatus.ACTIVE.name()))
|
.and(ClientConnectionRecordDynamicSqlSupport.status, isEqualTo(ConnectionStatus.ACTIVE.name()))
|
||||||
.build()
|
.build()
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
return execute;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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;
|
||||||
|
|
||||||
|
public interface SEBClientPingService {
|
||||||
|
|
||||||
|
static enum PingServiceType {
|
||||||
|
BLOCKING,
|
||||||
|
BATCH
|
||||||
|
}
|
||||||
|
|
||||||
|
PingServiceType pingServiceType();
|
||||||
|
|
||||||
|
String notifyPing(String connectionToken, String instructionConfirm);
|
||||||
|
|
||||||
|
}
|
|
@ -533,7 +533,7 @@ public class ExamSessionServiceImpl implements ExamSessionService {
|
||||||
public Result<Exam> updateExamCache(final Long examId) {
|
public Result<Exam> updateExamCache(final Long examId) {
|
||||||
|
|
||||||
// TODO check how often this is called in distributed environments
|
// TODO check how often this is called in distributed environments
|
||||||
System.out.println("************** performance check: updateExamCache");
|
//System.out.println("************** performance check: updateExamCache");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final Cache cache = this.cacheManager.getCache(ExamSessionCacheService.CACHE_NAME_RUNNING_EXAM);
|
final Cache cache = this.cacheManager.getCache(ExamSessionCacheService.CACHE_NAME_RUNNING_EXAM);
|
||||||
|
|
|
@ -11,41 +11,67 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.ehcache.impl.internal.concurrent.ConcurrentHashMap;
|
import org.ehcache.impl.internal.concurrent.ConcurrentHashMap;
|
||||||
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.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientPingService;
|
||||||
|
|
||||||
@Lazy
|
@Lazy
|
||||||
@Component
|
@Component
|
||||||
@WebServiceProfile
|
@WebServiceProfile
|
||||||
public class SEBClientPingBatchService {
|
public class SEBClientPingBatchService implements SEBClientPingService {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(SEBClientPingBatchService.class);
|
private static final Logger log = LoggerFactory.getLogger(SEBClientPingBatchService.class);
|
||||||
|
|
||||||
private final ExamSessionCacheService examSessionCacheService;
|
private final ExamSessionCacheService examSessionCacheService;
|
||||||
private final SEBClientInstructionService sebClientInstructionService;
|
private final SEBClientInstructionService sebClientInstructionService;
|
||||||
|
private final ThreadPoolTaskScheduler threadPoolTaskScheduler;
|
||||||
|
private final long schendulerInterval;
|
||||||
|
|
||||||
private final Map<String, String> pings = new ConcurrentHashMap<>();
|
private final Map<String, String> pings = new ConcurrentHashMap<>();
|
||||||
private final Map<String, String> instructions = new ConcurrentHashMap<>();
|
private final Map<String, String> instructions = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private ScheduledFuture<?> scheduleAtFixedRate = null;
|
||||||
|
|
||||||
public SEBClientPingBatchService(
|
public SEBClientPingBatchService(
|
||||||
final ExamSessionCacheService examSessionCacheService,
|
final ExamSessionCacheService examSessionCacheService,
|
||||||
final SEBClientInstructionService sebClientInstructionService) {
|
final SEBClientInstructionService sebClientInstructionService,
|
||||||
|
final ThreadPoolTaskScheduler threadPoolTaskScheduler,
|
||||||
|
@Value("${sebserver.webservice.api.exam.session.ping.batch.interval:500}") final long schendulerInterval) {
|
||||||
|
|
||||||
this.examSessionCacheService = examSessionCacheService;
|
this.examSessionCacheService = examSessionCacheService;
|
||||||
this.sebClientInstructionService = sebClientInstructionService;
|
this.sebClientInstructionService = sebClientInstructionService;
|
||||||
|
this.threadPoolTaskScheduler = threadPoolTaskScheduler;
|
||||||
|
this.schendulerInterval = schendulerInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(fixedDelayString = "${sebserver.webservice.api.exam.session.ping.batch.interval:500}")
|
void init() {
|
||||||
|
if (this.scheduleAtFixedRate == null) {
|
||||||
|
|
||||||
|
log.info(
|
||||||
|
"Initialize SEBClientPingBatchService for schedule batch update at a rate of {} milliseconds",
|
||||||
|
this.schendulerInterval);
|
||||||
|
|
||||||
|
this.scheduleAtFixedRate = this.threadPoolTaskScheduler.scheduleAtFixedRate(
|
||||||
|
() -> processPings(),
|
||||||
|
this.schendulerInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@Scheduled(fixedDelayString = "${sebserver.webservice.api.exam.session.ping.batch.interval:500}")
|
||||||
public void processPings() {
|
public void processPings() {
|
||||||
if (this.pings.isEmpty()) {
|
if (this.pings.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -69,17 +95,34 @@ public class SEBClientPingBatchService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PingServiceType pingServiceType() {
|
||||||
|
return PingServiceType.BATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final String notifyPing(
|
public final String notifyPing(
|
||||||
final String connectionToken,
|
final String connectionToken,
|
||||||
final String instructionConfirm) {
|
final String instructionConfirm) {
|
||||||
|
|
||||||
|
final String instruction = this.instructions.remove(connectionToken);
|
||||||
|
|
||||||
if (instructionConfirm != null) {
|
if (instructionConfirm != null) {
|
||||||
|
System.out.println("************ put instructionConfirm: " + instructionConfirm + " instructions: "
|
||||||
|
+ this.instructions);
|
||||||
this.pings.put(connectionToken, instructionConfirm);
|
this.pings.put(connectionToken, instructionConfirm);
|
||||||
|
// TODO is this a good idea or is there another better way to deal with instruction confirm synchronization?
|
||||||
|
if (instruction != null && instruction.contains("\"instruction-confirm\":\"" + instructionConfirm + "\"")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
} else if (!this.pings.containsKey(connectionToken)) {
|
} else if (!this.pings.containsKey(connectionToken)) {
|
||||||
this.pings.put(connectionToken, StringUtils.EMPTY);
|
this.pings.put(connectionToken, StringUtils.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.instructions.remove(connectionToken);
|
// System.out.println(
|
||||||
|
// "**************** notifyPing instructionConfirm: " + instructionConfirm + " pings: " + this.pings);
|
||||||
|
|
||||||
|
return instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processPing(
|
private void processPing(
|
||||||
|
@ -110,4 +153,11 @@ public class SEBClientPingBatchService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
protected void shutdown() {
|
||||||
|
if (this.scheduleAtFixedRate != null) {
|
||||||
|
this.scheduleAtFixedRate.cancel(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.impl;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientPingService;
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
@Component
|
||||||
|
@WebServiceProfile
|
||||||
|
public class SEBClientPingBlockingService implements SEBClientPingService {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SEBClientPingBlockingService.class);
|
||||||
|
|
||||||
|
private final ExamSessionCacheService examSessionCacheService;
|
||||||
|
private final SEBClientInstructionService sebClientInstructionService;
|
||||||
|
|
||||||
|
public SEBClientPingBlockingService(
|
||||||
|
final ExamSessionCacheService examSessionCacheService,
|
||||||
|
final SEBClientInstructionService sebClientInstructionService) {
|
||||||
|
|
||||||
|
this.examSessionCacheService = examSessionCacheService;
|
||||||
|
this.sebClientInstructionService = sebClientInstructionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PingServiceType pingServiceType() {
|
||||||
|
return PingServiceType.BLOCKING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String notifyPing(final String connectionToken, final String instructionConfirm) {
|
||||||
|
if (connectionToken == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ClientConnectionDataInternal activeClientConnection = this.examSessionCacheService
|
||||||
|
.getClientConnection(connectionToken);
|
||||||
|
|
||||||
|
if (activeClientConnection != null) {
|
||||||
|
activeClientConnection.notifyPing(Utils.getMillisecondsNow());
|
||||||
|
} else {
|
||||||
|
log.error("Failed to get ClientConnectionDataInternal for: {}", connectionToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instructionConfirm != StringUtils.EMPTY) {
|
||||||
|
this.sebClientInstructionService.confirmInstructionDone(connectionToken, instructionConfirm);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.sebClientInstructionService.getInstructionJSON(connectionToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.impl;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientPingService;
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
@Component
|
||||||
|
@WebServiceProfile
|
||||||
|
public class SEBClientPingServiceFactory {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SEBClientPingServiceFactory.class);
|
||||||
|
|
||||||
|
private final EnumMap<SEBClientPingService.PingServiceType, SEBClientPingService> serviceMapping =
|
||||||
|
new EnumMap<>(SEBClientPingService.PingServiceType.class);
|
||||||
|
private final SEBClientPingService.PingServiceType workingServiceType;
|
||||||
|
|
||||||
|
public SEBClientPingServiceFactory(
|
||||||
|
final Collection<SEBClientPingService> serviceBeans,
|
||||||
|
@Value("${sebserver.webservice.api.exam.session.ping.service.type:BLOCKING}") final String serviceType) {
|
||||||
|
|
||||||
|
SEBClientPingService.PingServiceType serviceTypeToSet = SEBClientPingService.PingServiceType.BLOCKING;
|
||||||
|
try {
|
||||||
|
serviceTypeToSet = SEBClientPingService.PingServiceType.valueOf(serviceType);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
serviceTypeToSet = SEBClientPingService.PingServiceType.BLOCKING;
|
||||||
|
}
|
||||||
|
this.workingServiceType = serviceTypeToSet;
|
||||||
|
|
||||||
|
serviceBeans.stream().forEach(service -> this.serviceMapping.putIfAbsent(service.pingServiceType(), service));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SEBClientPingService.PingServiceType getWorkingServiceType() {
|
||||||
|
return this.workingServiceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SEBClientPingService getSEBClientPingService() {
|
||||||
|
|
||||||
|
log.info("Work with SEBClientPingService of type: {}", this.workingServiceType);
|
||||||
|
|
||||||
|
switch (this.workingServiceType) {
|
||||||
|
case BATCH: {
|
||||||
|
final SEBClientPingService service =
|
||||||
|
this.serviceMapping.get(SEBClientPingService.PingServiceType.BATCH);
|
||||||
|
if (service != null) {
|
||||||
|
((SEBClientPingBatchService) service).init();
|
||||||
|
return service;
|
||||||
|
} else {
|
||||||
|
return this.serviceMapping.get(SEBClientPingService.PingServiceType.BLOCKING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return this.serviceMapping.get(SEBClientPingService.PingServiceType.BLOCKING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.institution.SecurityKeyService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.institution.SecurityKeyService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ExamSessionService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientPingService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientSessionService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientSessionService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientVersionService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientVersionService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.SEBClientEventBatchService.EventData;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.SEBClientEventBatchService.EventData;
|
||||||
|
@ -48,7 +49,7 @@ public class SEBClientSessionServiceImpl implements SEBClientSessionService {
|
||||||
private final InternalClientConnectionDataFactory internalClientConnectionDataFactory;
|
private final InternalClientConnectionDataFactory internalClientConnectionDataFactory;
|
||||||
private final SecurityKeyService securityKeyService;
|
private final SecurityKeyService securityKeyService;
|
||||||
private final SEBClientVersionService sebClientVersionService;
|
private final SEBClientVersionService sebClientVersionService;
|
||||||
private final SEBClientPingBatchService sebClientPingService;
|
private final SEBClientPingService sebClientPingService;
|
||||||
|
|
||||||
public SEBClientSessionServiceImpl(
|
public SEBClientSessionServiceImpl(
|
||||||
final ClientConnectionDAO clientConnectionDAO,
|
final ClientConnectionDAO clientConnectionDAO,
|
||||||
|
@ -59,7 +60,7 @@ public class SEBClientSessionServiceImpl implements SEBClientSessionService {
|
||||||
final InternalClientConnectionDataFactory internalClientConnectionDataFactory,
|
final InternalClientConnectionDataFactory internalClientConnectionDataFactory,
|
||||||
final SecurityKeyService securityKeyService,
|
final SecurityKeyService securityKeyService,
|
||||||
final SEBClientVersionService sebClientVersionService,
|
final SEBClientVersionService sebClientVersionService,
|
||||||
final SEBClientPingBatchService sebClientPingService) {
|
final SEBClientPingServiceFactory sebClientPingServiceFactory) {
|
||||||
|
|
||||||
this.clientConnectionDAO = clientConnectionDAO;
|
this.clientConnectionDAO = clientConnectionDAO;
|
||||||
this.examSessionService = examSessionService;
|
this.examSessionService = examSessionService;
|
||||||
|
@ -69,7 +70,7 @@ public class SEBClientSessionServiceImpl implements SEBClientSessionService {
|
||||||
this.internalClientConnectionDataFactory = internalClientConnectionDataFactory;
|
this.internalClientConnectionDataFactory = internalClientConnectionDataFactory;
|
||||||
this.securityKeyService = securityKeyService;
|
this.securityKeyService = securityKeyService;
|
||||||
this.sebClientVersionService = sebClientVersionService;
|
this.sebClientVersionService = sebClientVersionService;
|
||||||
this.sebClientPingService = sebClientPingService;
|
this.sebClientPingService = sebClientPingServiceFactory.getSEBClientPingService();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -319,14 +319,14 @@ public class ScreenProctoringServiceImpl implements ScreenProctoringService {
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Failed to apply screen proctoring session to SEB with connection: ", ccRecord, e);
|
log.error("Failed to apply screen proctoring session to SEB with connection: ", ccRecord, e);
|
||||||
|
|
||||||
// if (placeReservedInGroup != null) {
|
if (placeReservedInGroup != null) {
|
||||||
// // release reserved place in group
|
// release reserved place in group
|
||||||
// this.screenProctoringGroupDAO.releasePlaceInCollectingGroup(
|
this.screenProctoringGroupDAO.releasePlaceInCollectingGroup(
|
||||||
// ccRecord.getExamId(),
|
ccRecord.getExamId(),
|
||||||
// placeReservedInGroup)
|
placeReservedInGroup)
|
||||||
// .onError(
|
.onError(
|
||||||
// error -> log.warn("Failed to release reserved place in group: {}", error.getMessage()));
|
error -> log.warn("Failed to release reserved place in group: {}", error.getMessage()));
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ public class ScreenProctoringServiceImpl implements ScreenProctoringService {
|
||||||
|
|
||||||
if (!exam.additionalAttributes.containsKey(ScreenProctoringSettings.ATTR_COLLECTING_STRATEGY)) {
|
if (!exam.additionalAttributes.containsKey(ScreenProctoringSettings.ATTR_COLLECTING_STRATEGY)) {
|
||||||
log.warn("Can't verify collecting strategy for exam: {} use default group assignment.", exam.id);
|
log.warn("Can't verify collecting strategy for exam: {} use default group assignment.", exam.id);
|
||||||
return applyToDefaultGroup(ccRecord, exam);
|
return applyToDefaultGroup(ccRecord.getId(), ccRecord.getConnectionToken(), exam);
|
||||||
}
|
}
|
||||||
|
|
||||||
final CollectingStrategy strategy = CollectingStrategy.valueOf(exam.additionalAttributes
|
final CollectingStrategy strategy = CollectingStrategy.valueOf(exam.additionalAttributes
|
||||||
|
@ -350,20 +350,21 @@ public class ScreenProctoringServiceImpl implements ScreenProctoringService {
|
||||||
case EXAM:
|
case EXAM:
|
||||||
case FIX_SIZE:
|
case FIX_SIZE:
|
||||||
default: {
|
default: {
|
||||||
return applyToDefaultGroup(ccRecord, exam);
|
return applyToDefaultGroup(ccRecord.getId(), ccRecord.getConnectionToken(), exam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScreenProctoringGroup applyToDefaultGroup(
|
private ScreenProctoringGroup applyToDefaultGroup(
|
||||||
final ClientConnectionRecord ccRecord,
|
final Long connectioId,
|
||||||
|
final String connectionToken,
|
||||||
final Exam exam) {
|
final Exam exam) {
|
||||||
|
|
||||||
final ScreenProctoringGroup screenProctoringGroup = reservePlaceOnProctoringGroup(exam);
|
final ScreenProctoringGroup screenProctoringGroup = reservePlaceOnProctoringGroup(exam);
|
||||||
this.clientConnectionDAO.assignToScreenProctoringGroup(
|
this.clientConnectionDAO.assignToScreenProctoringGroup(
|
||||||
exam.id,
|
connectioId,
|
||||||
ccRecord.getConnectionToken(),
|
connectionToken,
|
||||||
screenProctoringGroup.id)
|
screenProctoringGroup.id)
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue