Merge remote-tracking branch 'origin/dev-1.3' into development
Conflicts: src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/InternalClientConnectionDataFactory.java src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientConnectionServiceImpl.java src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java
This commit is contained in:
commit
16582d0ce8
11 changed files with 202 additions and 152 deletions
|
@ -25,9 +25,12 @@ import org.springframework.stereotype.Component;
|
|||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.IndicatorValue;
|
||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.IndicatorDAO;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ClientIndicator;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator.DistributedIndicatorValueService;
|
||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator.PingIntervalClientIndicator;
|
||||
|
||||
@Lazy
|
||||
|
@ -39,27 +42,103 @@ public class ClientIndicatorFactory {
|
|||
|
||||
private final ApplicationContext applicationContext;
|
||||
private final IndicatorDAO indicatorDAO;
|
||||
private final DistributedIndicatorValueService distributedPingCache;
|
||||
private final boolean distributedSetup;
|
||||
private final boolean enableCaching;
|
||||
|
||||
@Autowired
|
||||
public ClientIndicatorFactory(
|
||||
final ApplicationContext applicationContext,
|
||||
final IndicatorDAO indicatorDAO,
|
||||
final DistributedIndicatorValueService distributedPingCache,
|
||||
@Value("${sebserver.webservice.distributed:false}") final boolean distributedSetup,
|
||||
@Value("${sebserver.webservice.api.exam.enable-indicator-cache:true}") final boolean enableCaching) {
|
||||
|
||||
this.applicationContext = applicationContext;
|
||||
this.indicatorDAO = indicatorDAO;
|
||||
this.distributedPingCache = distributedPingCache;
|
||||
this.distributedSetup = distributedSetup;
|
||||
this.enableCaching = distributedSetup ? false : enableCaching;
|
||||
}
|
||||
|
||||
public List<ClientIndicator> createFor(final ClientConnection clientConnection) {
|
||||
return createFor(clientConnection, false);
|
||||
public void initializeDistributedCaches(final ClientConnection clientConnection) {
|
||||
try {
|
||||
|
||||
if (!this.distributedSetup || clientConnection.examId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Collection<Indicator> examIndicators = this.indicatorDAO
|
||||
.allForExam(clientConnection.examId)
|
||||
.getOrThrow();
|
||||
|
||||
boolean pingIndicatorAvailable = false;
|
||||
for (final Indicator indicatorDef : examIndicators) {
|
||||
|
||||
this.distributedPingCache.createIndicatorForConnection(
|
||||
clientConnection.id,
|
||||
indicatorDef.type,
|
||||
indicatorDef.type == IndicatorType.LAST_PING ? Utils.getMillisecondsNow() : 0L);
|
||||
|
||||
if (!pingIndicatorAvailable) {
|
||||
pingIndicatorAvailable = indicatorDef.type == IndicatorType.LAST_PING;
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no ping interval indicator set from the exam, we add a hidden one
|
||||
// to at least create missing ping events and track missing state
|
||||
if (!pingIndicatorAvailable) {
|
||||
this.distributedPingCache.createIndicatorForConnection(
|
||||
clientConnection.id,
|
||||
IndicatorType.LAST_PING,
|
||||
Utils.getMillisecondsNow());
|
||||
}
|
||||
|
||||
} catch (final Exception e) {
|
||||
log.error("Unexpected error while trying to initialize distributed indicator value cache for: {}",
|
||||
clientConnection,
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ClientIndicator> createFor(
|
||||
final ClientConnection clientConnection,
|
||||
final boolean enableCachingOverride) {
|
||||
public List<? extends IndicatorValue> getIndicatorValues(final ClientConnection clientConnection) {
|
||||
|
||||
final List<ClientIndicator> result = new ArrayList<>();
|
||||
if (clientConnection.examId == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
final Collection<Indicator> examIndicators = this.indicatorDAO
|
||||
.allForExam(clientConnection.examId)
|
||||
.getOrThrow();
|
||||
|
||||
for (final Indicator indicatorDef : examIndicators) {
|
||||
try {
|
||||
|
||||
final ClientIndicator indicator = this.applicationContext
|
||||
.getBean(indicatorDef.type.name(), ClientIndicator.class);
|
||||
|
||||
indicator.init(
|
||||
indicatorDef,
|
||||
clientConnection.id,
|
||||
clientConnection.status.clientActiveStatus,
|
||||
true);
|
||||
|
||||
result.add(indicator);
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to create IndicatorValue for indicator: {}", indicatorDef, e);
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to create IndicatorValues for ClientConnection: {}", clientConnection);
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
|
||||
public List<ClientIndicator> createFor(final ClientConnection clientConnection) {
|
||||
|
||||
final List<ClientIndicator> result = new ArrayList<>();
|
||||
if (clientConnection.examId == null) {
|
||||
|
@ -73,7 +152,6 @@ public class ClientIndicatorFactory {
|
|||
.getOrThrow();
|
||||
|
||||
boolean pingIndicatorAvailable = false;
|
||||
|
||||
for (final Indicator indicatorDef : examIndicators) {
|
||||
try {
|
||||
|
||||
|
@ -88,11 +166,12 @@ public class ClientIndicatorFactory {
|
|||
indicatorDef,
|
||||
clientConnection.id,
|
||||
clientConnection.status.clientActiveStatus,
|
||||
this.enableCaching || enableCachingOverride);
|
||||
this.enableCaching);
|
||||
|
||||
result.add(indicator);
|
||||
} catch (final Exception e) {
|
||||
log.warn("No Indicator with type: {} found as registered bean. Ignore this one.", indicatorDef.type,
|
||||
log.warn("No Indicator with type: {} found as registered bean. Ignore this one.",
|
||||
indicatorDef.type,
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +196,7 @@ public class ClientIndicatorFactory {
|
|||
indicator,
|
||||
clientConnection.id,
|
||||
clientConnection.status.clientActiveStatus,
|
||||
this.enableCaching || enableCachingOverride);
|
||||
this.enableCaching);
|
||||
result.add(pingIndicator);
|
||||
}
|
||||
|
||||
|
|
|
@ -148,9 +148,7 @@ public class ExamSessionCacheService {
|
|||
if (clientConnection == null) {
|
||||
return null;
|
||||
} else {
|
||||
return this.internalClientConnectionDataFactory.createClientConnectionData(
|
||||
clientConnection,
|
||||
this.getRunningExam(clientConnection.examId) != null);
|
||||
return this.internalClientConnectionDataFactory.createClientConnectionData(clientConnection);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -292,8 +292,8 @@ public class ExamSessionServiceImpl implements ExamSessionService {
|
|||
throw new IllegalStateException("Missing exam identifier or requested exam is not running");
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Trying to get exam from InMemorySEBConfig");
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("Trying to get exam from InMemorySEBConfig");
|
||||
}
|
||||
|
||||
final InMemorySEBConfig sebConfigForExam = this.examSessionCacheService
|
||||
|
@ -306,14 +306,14 @@ public class ExamSessionServiceImpl implements ExamSessionService {
|
|||
|
||||
try {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("SEB exam configuration download request, start writing SEB exam configuration");
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("SEB exam configuration download request, start writing SEB exam configuration");
|
||||
}
|
||||
|
||||
out.write(sebConfigForExam.getData());
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("SEB exam configuration download request, finished writing SEB exam configuration");
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("SEB exam configuration download request, finished writing SEB exam configuration");
|
||||
}
|
||||
|
||||
} catch (final IOException e) {
|
||||
|
|
|
@ -32,17 +32,7 @@ public class InternalClientConnectionDataFactory {
|
|||
this.sebClientNotificationService = sebClientNotificationService;
|
||||
}
|
||||
|
||||
public ClientConnectionDataInternal createClientConnectionData(
|
||||
final ClientConnection clientConnection,
|
||||
final boolean examRunning) {
|
||||
|
||||
// if the exam is not running, we just create a cached indicator anyways
|
||||
if (!examRunning) {
|
||||
return new ClientConnectionDataInternal(
|
||||
clientConnection,
|
||||
() -> false,
|
||||
this.clientIndicatorFactory.createFor(clientConnection, true));
|
||||
}
|
||||
public ClientConnectionDataInternal createClientConnectionData(final ClientConnection clientConnection) {
|
||||
|
||||
if (clientConnection.status == ConnectionStatus.CLOSED
|
||||
|| clientConnection.status == ConnectionStatus.DISABLED) {
|
||||
|
|
|
@ -74,9 +74,8 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
|||
private final SEBClientConfigDAO sebClientConfigDAO;
|
||||
private final SEBClientInstructionService sebInstructionService;
|
||||
private final ExamAdminService examAdminService;
|
||||
private final ClientIndicatorFactory clientIndicatorFactory;
|
||||
// TODO get rid of this dependency and use application events for signaling client connection state changes
|
||||
private final DistributedIndicatorValueService distributedPingCache;
|
||||
private final ClientIndicatorFactory clientIndicatorFactory;
|
||||
private final boolean isDistributedSetup;
|
||||
|
||||
protected SEBClientConnectionServiceImpl(
|
||||
|
@ -85,8 +84,8 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
|||
final SEBClientConfigDAO sebClientConfigDAO,
|
||||
final SEBClientInstructionService sebInstructionService,
|
||||
final ExamAdminService examAdminService,
|
||||
final ClientIndicatorFactory clientIndicatorFactory,
|
||||
final DistributedIndicatorValueService distributedPingCache) {
|
||||
final DistributedIndicatorValueService distributedPingCache,
|
||||
final ClientIndicatorFactory clientIndicatorFactory) {
|
||||
|
||||
this.examSessionService = examSessionService;
|
||||
this.examSessionCacheService = examSessionService.getExamSessionCacheService();
|
||||
|
@ -168,6 +167,11 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
|||
null))
|
||||
.getOrThrow();
|
||||
|
||||
// initialize distributed indicator value caches if possible and needed
|
||||
if (clientConnection.examId != null && this.isDistributedSetup) {
|
||||
this.clientIndicatorFactory.initializeDistributedCaches(clientConnection);
|
||||
}
|
||||
|
||||
// load client connection data into cache
|
||||
final ClientConnectionDataInternal activeClientConnection = this.examSessionService
|
||||
.getConnectionDataInternal(connectionToken);
|
||||
|
@ -265,6 +269,11 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
|||
null))
|
||||
.getOrThrow();
|
||||
|
||||
// initialize distributed indicator value caches if possible and needed
|
||||
if (examId != null && this.isDistributedSetup) {
|
||||
this.clientIndicatorFactory.initializeDistributedCaches(clientConnection);
|
||||
}
|
||||
|
||||
final ClientConnectionDataInternal activeClientConnection =
|
||||
reloadConnectionCache(connectionToken);
|
||||
|
||||
|
@ -405,6 +414,11 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
|||
// check exam integrity for established connection
|
||||
checkExamIntegrity(establishedClientConnection.examId);
|
||||
|
||||
// initialize distributed indicator value caches if possible and needed
|
||||
if (examId != null && this.isDistributedSetup) {
|
||||
this.clientIndicatorFactory.initializeDistributedCaches(clientConnection);
|
||||
}
|
||||
|
||||
// if proctoring is enabled for exam, mark for room update
|
||||
if (proctoringEnabled) {
|
||||
this.clientConnectionDAO.markForProctoringUpdate(updatedClientConnection.id);
|
||||
|
@ -709,7 +723,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
|||
public Result<ClientConnectionData> getIndicatorValues(final ClientConnection clientConnection) {
|
||||
return Result.tryCatch(() -> new ClientConnectionData(
|
||||
clientConnection,
|
||||
this.clientIndicatorFactory.createFor(clientConnection, true)));
|
||||
this.clientIndicatorFactory.getIndicatorValues(clientConnection)));
|
||||
}
|
||||
|
||||
private void checkExamRunning(final Long examId) {
|
||||
|
@ -879,13 +893,6 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
|||
connection.getIndicatorMapping(EventType.ERROR_LOG)
|
||||
.forEach(indicator -> indicator.notifyValueChange(clientEventRecord));
|
||||
}
|
||||
|
||||
if (this.isDistributedSetup) {
|
||||
// mark for update and flush the cache
|
||||
this.clientConnectionDAO.save(connection.clientConnection);
|
||||
this.examSessionCacheService.evictClientConnection(
|
||||
connection.clientConnection.connectionToken);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -69,38 +69,25 @@ public abstract class AbstractClientIndicator implements ClientIndicator {
|
|||
this.cachingEnabled = cachingEnabled;
|
||||
|
||||
if (!this.cachingEnabled && this.active) {
|
||||
try {
|
||||
this.ditributedIndicatorValueRecordId =
|
||||
this.distributedIndicatorValueService.initIndicatorForConnection(
|
||||
connectionId,
|
||||
getType(),
|
||||
initValue());
|
||||
} catch (final Exception e) {
|
||||
tryRecoverIndicatorRecord();
|
||||
}
|
||||
|
||||
this.ditributedIndicatorValueRecordId = this.distributedIndicatorValueService
|
||||
.getIndicatorForConnection(connectionId, getType());
|
||||
|
||||
}
|
||||
|
||||
this.currentValue = computeValueAt(Utils.getMillisecondsNow());
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
protected long initValue() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected void tryRecoverIndicatorRecord() {
|
||||
this.ditributedIndicatorValueRecordId = this.distributedIndicatorValueService.getIndicatorForConnection(
|
||||
this.connectionId,
|
||||
getType());
|
||||
|
||||
if (log.isWarnEnabled()) {
|
||||
log.warn("*** Missing indicator value record for connection: {}. Try to recover...", this.connectionId);
|
||||
}
|
||||
|
||||
try {
|
||||
this.ditributedIndicatorValueRecordId = this.distributedIndicatorValueService.initIndicatorForConnection(
|
||||
if (this.ditributedIndicatorValueRecordId == null) {
|
||||
log.warn("Failed to recover from missing indicator value cache record: {} type: {}",
|
||||
this.connectionId,
|
||||
getType(),
|
||||
initValue());
|
||||
} catch (final Exception e) {
|
||||
log.error("Failed to recover indicator value record for connection: {}", this.connectionId, e);
|
||||
getType());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -129,100 +129,89 @@ public class DistributedIndicatorValueService implements DisposableBean {
|
|||
}
|
||||
}
|
||||
|
||||
/** This initializes a SEB client indicator on the persistent storage for a given SEB client
|
||||
* connection identifier and of given IndicatorType.
|
||||
* If there is already such an indicator for the specified SEB client connection identifier and type,
|
||||
* this returns the id of the existing one.
|
||||
/** This creates a distributed indicator value cache record for a given SEB connection and indicator
|
||||
* if it not already exists and returns the PK for the specified distributed indicator value cache record
|
||||
*
|
||||
* @param connectionId SEB client connection identifier
|
||||
* @param type indicator type
|
||||
* @param value the initial indicator value
|
||||
* @return SEB client indicator value identifier (PK) */
|
||||
* @param connectionId the client connection identifier
|
||||
* @param type the indicator type
|
||||
* @param value the initialization value
|
||||
* @return the PK of the created or existing distributed indicator value cache record or null when a unexpected
|
||||
* error happened */
|
||||
@Transactional
|
||||
public Long initIndicatorForConnection(
|
||||
public Long createIndicatorForConnection(
|
||||
final Long connectionId,
|
||||
final IndicatorType type,
|
||||
final Long value) {
|
||||
final long initValue) {
|
||||
|
||||
if (!this.webserviceInfo.isDistributed()) {
|
||||
log.warn("No distributed setup, skip createIndicatorForConnection");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.trace("*** Initialize indicator value record for SEB connection: {}", connectionId);
|
||||
// first check if the record already exists
|
||||
final Long recId = this.clientIndicatorValueMapper.indicatorRecordIdByConnectionId(
|
||||
connectionId,
|
||||
type);
|
||||
if (recId != null) {
|
||||
log.debug("Distributed indicator value cache already exists for: {}, {}", connectionId, type);
|
||||
return recId;
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
// if not, create new one and return PK
|
||||
final ClientIndicatorRecord clientEventRecord = new ClientIndicatorRecord(
|
||||
null, connectionId, type.id, initValue);
|
||||
this.clientIndicatorRecordMapper.insert(clientEventRecord);
|
||||
|
||||
Long recordId = null;
|
||||
try {
|
||||
// This also double-check by trying again. If we have more then one entry here
|
||||
// this will throw an exception that causes a rollback
|
||||
return this.clientIndicatorValueMapper
|
||||
.indicatorRecordIdByConnectionId(connectionId, type);
|
||||
|
||||
try {
|
||||
recordId = this.clientIndicatorValueMapper
|
||||
.indicatorRecordIdByConnectionId(connectionId, type);
|
||||
} catch (final Exception e) {
|
||||
// There is already more then one indicator record entry!!!
|
||||
// delete the second one and work on with the first one
|
||||
} catch (final Exception e) {
|
||||
|
||||
log.warn("Duplicate indicator entry detected for connectionId: {}, type: {} --> try to recover",
|
||||
connectionId, type);
|
||||
|
||||
try {
|
||||
final List<ClientIndicatorRecord> records = this.clientIndicatorRecordMapper.selectByExample()
|
||||
.where(ClientIndicatorRecordDynamicSqlSupport.clientConnectionId,
|
||||
isEqualTo(connectionId))
|
||||
.and(ClientIndicatorRecordDynamicSqlSupport.type, isEqualTo(type.id))
|
||||
.build()
|
||||
.execute();
|
||||
if (records.size() > 1) {
|
||||
this.clientIndicatorRecordMapper.deleteByPrimaryKey(records.get(1).getId());
|
||||
}
|
||||
|
||||
return records.get(0).getId();
|
||||
} catch (final Exception ee) {
|
||||
log.error("Failed to recover from duplicate indicator entry: ", ee);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (recordId == null) {
|
||||
if (!this.webserviceInfo.isMaster()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Skip indicator record init because this is no master instance");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final ClientIndicatorRecord clientEventRecord = new ClientIndicatorRecord(
|
||||
null, connectionId, type.id, value);
|
||||
|
||||
this.clientIndicatorRecordMapper.insert(clientEventRecord);
|
||||
|
||||
try {
|
||||
// This also double-check by trying again. If we have more then one entry here
|
||||
// this will throw an exception that causes a rollback
|
||||
return this.clientIndicatorValueMapper
|
||||
.indicatorRecordIdByConnectionId(connectionId, type);
|
||||
|
||||
} catch (final Exception e) {
|
||||
|
||||
log.warn(
|
||||
"Detected multiple client indicator entries for connection: {} and type: {}. Force rollback to prevent",
|
||||
connectionId, type);
|
||||
|
||||
// force rollback
|
||||
TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
|
||||
throw new RuntimeException("Detected multiple client indicator value entries");
|
||||
}
|
||||
}
|
||||
|
||||
return recordId;
|
||||
log.warn(
|
||||
"Detected multiple client indicator entries for connection: {} and type: {}. Force rollback to prevent",
|
||||
connectionId, type);
|
||||
|
||||
// force rollback
|
||||
TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
|
||||
throw new RuntimeException("Detected multiple client indicator value entries");
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
log.error(
|
||||
"Failed to initialize distributed indicator value cache in persistent store. connectionId: {} type: {}",
|
||||
connectionId, type, e);
|
||||
|
||||
log.error("Failed to initialize indicator value for connection -> {}", connectionId, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// force rollback
|
||||
TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
|
||||
throw new RuntimeException("Failed to initialize indicator value for connection -> " + connectionId, e);
|
||||
/** Get the distributed indicator value cache record PK for a given SEB connection and indicator if available.
|
||||
* If not existing for the specified connection and indicator this return null
|
||||
*
|
||||
* @param connectionId the client connection identifier
|
||||
* @param type the indicator type
|
||||
* @return the indicator value cache record PK or null of not defined */
|
||||
@Transactional(readOnly = true)
|
||||
public Long getIndicatorForConnection(final Long connectionId, final IndicatorType type) {
|
||||
try {
|
||||
|
||||
return this.clientIndicatorValueMapper
|
||||
.indicatorRecordIdByConnectionId(connectionId, type);
|
||||
|
||||
} catch (final Exception e) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Failed to get indicator PK for connection: {} type: {} cause: {}",
|
||||
connectionId,
|
||||
type,
|
||||
e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,7 +224,7 @@ public class DistributedIndicatorValueService implements DisposableBean {
|
|||
try {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("*** Delete indicator value record for SEB connection: {}", connectionId);
|
||||
log.debug("Delete indicator value record for SEB connection: {}", connectionId);
|
||||
}
|
||||
|
||||
final Collection<ClientIndicatorValueRecord> records = this.clientIndicatorValueMapper
|
||||
|
|
|
@ -20,7 +20,6 @@ import ch.ethz.seb.sebserver.gbl.Constants;
|
|||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
|
||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord;
|
||||
|
||||
@Lazy
|
||||
|
@ -40,11 +39,6 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
|
|||
this.cachingEnabled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long initValue() {
|
||||
return Utils.getMillisecondsNow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(
|
||||
final Indicator indicatorDefinition,
|
||||
|
|
|
@ -374,6 +374,7 @@ public class ExamProctoringRoomServiceImpl implements ExamProctoringRoomService
|
|||
examId,
|
||||
connectionToken,
|
||||
e);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -555,6 +555,11 @@ public class ZoomProctoringService implements ExamProctoringService {
|
|||
credentials,
|
||||
roomName);
|
||||
|
||||
final int statusCodeValue = createUser.getStatusCodeValue();
|
||||
if (statusCodeValue >= 400) {
|
||||
throw new RuntimeException("Failed to create new Zoom user for room: " + createUser.getBody());
|
||||
}
|
||||
|
||||
final UserResponse userResponse = this.jsonMapper.readValue(
|
||||
createUser.getBody(),
|
||||
UserResponse.class);
|
||||
|
|
|
@ -55,7 +55,7 @@ public class SebConnectionTest extends ExamAPIIntegrationTester {
|
|||
final String accessToken = super.obtainAccessToken("test", "test", "SEBClient");
|
||||
assertNotNull(accessToken);
|
||||
|
||||
final MockHttpServletResponse createConnection = super.createConnection(accessToken, 1L, null);
|
||||
final MockHttpServletResponse createConnection = super.createConnection(accessToken, 1L, 2L);
|
||||
assertNotNull(createConnection);
|
||||
|
||||
// check correct response
|
||||
|
@ -79,7 +79,7 @@ public class SebConnectionTest extends ExamAPIIntegrationTester {
|
|||
assertTrue(records.size() == 1);
|
||||
final ClientConnectionRecord clientConnectionRecord = records.get(0);
|
||||
assertEquals("1", String.valueOf(clientConnectionRecord.getInstitutionId()));
|
||||
assertNull(clientConnectionRecord.getExamId());
|
||||
assertEquals("2", clientConnectionRecord.getExamId().toString());
|
||||
assertEquals("CONNECTION_REQUESTED", String.valueOf(clientConnectionRecord.getStatus()));
|
||||
assertEquals(connectionToken, clientConnectionRecord.getConnectionToken());
|
||||
assertNotNull(clientConnectionRecord.getClientAddress());
|
||||
|
@ -321,7 +321,7 @@ public class SebConnectionTest extends ExamAPIIntegrationTester {
|
|||
final String accessToken = super.obtainAccessToken("test", "test", "SEBClient");
|
||||
assertNotNull(accessToken);
|
||||
|
||||
final MockHttpServletResponse createConnection = super.createConnection(accessToken, 1L, 2L);
|
||||
final MockHttpServletResponse createConnection = super.createConnection(accessToken, 1L, null);
|
||||
assertNotNull(createConnection);
|
||||
|
||||
final String connectionToken = createConnection.getHeader(API.EXAM_API_SEB_CONNECTION_TOKEN);
|
||||
|
@ -356,7 +356,7 @@ public class SebConnectionTest extends ExamAPIIntegrationTester {
|
|||
// check correct stored (no changes)
|
||||
final List<ClientConnectionRecord> records = this.clientConnectionRecordMapper
|
||||
.selectByExample()
|
||||
.where(ClientConnectionRecordDynamicSqlSupport.examId, SqlBuilder.isEqualTo(2L))
|
||||
.where(ClientConnectionRecordDynamicSqlSupport.examId, SqlBuilder.isNull())
|
||||
.build()
|
||||
.execute();
|
||||
|
||||
|
|
Loading…
Reference in a new issue