finished up to allow pings and instructions (quit) before connection
is fully established (also in requested status)
This commit is contained in:
parent
b61166674c
commit
8381b5d621
9 changed files with 51 additions and 33 deletions
|
@ -25,17 +25,21 @@ import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
|
|||
public final class ClientConnection implements GrantEntity {
|
||||
|
||||
public enum ConnectionStatus {
|
||||
UNDEFINED(false),
|
||||
CONNECTION_REQUESTED(false),
|
||||
AUTHENTICATED(true),
|
||||
ACTIVE(true),
|
||||
CLOSED(false),
|
||||
DISABLED(false);
|
||||
UNDEFINED(false, false),
|
||||
CONNECTION_REQUESTED(true, false),
|
||||
AUTHENTICATED(true, true),
|
||||
ACTIVE(false, true),
|
||||
CLOSED(false, false),
|
||||
DISABLED(false, false);
|
||||
|
||||
public final boolean connectingStatus;
|
||||
public final boolean establishedStatus;
|
||||
public final boolean indicatorActiveStatus;
|
||||
|
||||
ConnectionStatus(final boolean establishedStatus) {
|
||||
ConnectionStatus(final boolean connectingStatus, final boolean establishedStatus) {
|
||||
this.connectingStatus = connectingStatus;
|
||||
this.establishedStatus = establishedStatus;
|
||||
this.indicatorActiveStatus = connectingStatus || establishedStatus;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -364,7 +364,7 @@ public class MonitoringClientConnection implements TemplateComposer {
|
|||
})
|
||||
.noEventPropagation()
|
||||
.publishIf(() -> currentUser.get().hasRole(UserRole.EXAM_SUPPORTER) &&
|
||||
connectionData.clientConnection.status == ConnectionStatus.ACTIVE);
|
||||
connectionData.clientConnection.status.indicatorActiveStatus);
|
||||
|
||||
if (connectionData.clientConnection.status == ConnectionStatus.ACTIVE) {
|
||||
final ProctoringServiceSettings procotringSettings = restService
|
||||
|
|
|
@ -34,7 +34,6 @@ import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
|||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
||||
import ch.ethz.seb.sebserver.gbl.model.exam.ProctoringServiceSettings;
|
||||
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.ClientConnectionData;
|
||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
|
||||
|
@ -420,7 +419,7 @@ public class MonitoringRunningExam implements TemplateComposer {
|
|||
|
||||
private Set<EntityKey> selectionForQuitInstruction(final ClientConnectionTable clientTable) {
|
||||
final Set<String> connectionTokens = clientTable.getConnectionTokens(
|
||||
ClientConnection.getStatusPredicate(ConnectionStatus.ACTIVE),
|
||||
cc -> cc.status.indicatorActiveStatus,
|
||||
true);
|
||||
if (connectionTokens == null || connectionTokens.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
|
|
|
@ -189,7 +189,7 @@ public class ClientConnectionDetails {
|
|||
final double value = indValue.getValue();
|
||||
final String displayValue = IndicatorValue.getDisplayValue(indValue);
|
||||
|
||||
if (!this.connectionData.clientConnection.status.establishedStatus) {
|
||||
if (!this.connectionData.clientConnection.status.indicatorActiveStatus) {
|
||||
|
||||
form.setFieldValue(
|
||||
indData.indicator.name,
|
||||
|
|
|
@ -576,7 +576,7 @@ public final class ClientConnectionTable {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!this.connectionData.clientConnection.status.establishedStatus) {
|
||||
if (!this.connectionData.clientConnection.status.indicatorActiveStatus) {
|
||||
final String value = (indicatorData.indicator.type.showOnlyInActiveState)
|
||||
? Constants.EMPTY_NOTE
|
||||
: IndicatorValue.getDisplayValue(indicatorValue);
|
||||
|
|
|
@ -72,7 +72,9 @@ public class InstructionProcessor {
|
|||
final PageContext pageContext) {
|
||||
|
||||
final Set<String> connectionTokens = selectionFunction
|
||||
.apply(ClientConnection.getStatusPredicate(ConnectionStatus.ACTIVE));
|
||||
.apply(ClientConnection.getStatusPredicate(
|
||||
ConnectionStatus.CONNECTION_REQUESTED,
|
||||
ConnectionStatus.ACTIVE));
|
||||
|
||||
if (connectionTokens.isEmpty()) {
|
||||
log.warn("Empty selection");
|
||||
|
|
|
@ -145,28 +145,27 @@ public interface ClientConnectionDAO extends
|
|||
* @return Result refer to the ClientConnection for the specified connection token or to an error if happened */
|
||||
Result<ClientConnection> byConnectionToken(String connectionToken);
|
||||
|
||||
/** Indicates if the client connection for exam and connection token is an active connection.
|
||||
*
|
||||
* @param examId the exam identifier
|
||||
* @param connectionToken the connection token
|
||||
* @return Result refer to the active connection flag or to an error when happened */
|
||||
Result<Boolean> isActiveConnection(Long examId, String connectionToken);
|
||||
|
||||
/** Use this to check whether a single ClientConnection is up to date or needs a refresh.
|
||||
*
|
||||
* @param clientConnection the actual ClientConnection (from the internal cache)
|
||||
* @return Result refer to true if the given ClientConnection is up to date */
|
||||
Result<Boolean> isUpToDate(ClientConnection clientConnection);
|
||||
|
||||
/** Indicates if the client connection for given exam and connection token is
|
||||
* in a ready state to send instructions.
|
||||
*
|
||||
* @param examId the exam identifier
|
||||
* @param connectionToken the connection token
|
||||
* @return Result refer to the active connection flag or to an error when happened */
|
||||
Result<Boolean> isInInstructionStatus(Long examId, String connectionToken);
|
||||
|
||||
/** Filters a set of client connection tokens to a set containing only
|
||||
* connection tokens of active client connections.
|
||||
* connection tokens of client connections that are in a ready state to send instructions.
|
||||
*
|
||||
* Use this if you have a bunch of client connections to filter only the active connections
|
||||
*
|
||||
* @param examId
|
||||
* @param connectionToken
|
||||
* @return */
|
||||
Result<Set<String>> filterActive(Long examId, Set<String> connectionToken);
|
||||
* @param examId the exam identifier
|
||||
* @param connectionToken a Set of connection tokens to filter
|
||||
* @return Result refer to filtered Set of connection tokens or to an error when happened */
|
||||
Result<Set<String>> filterForInstructionStatus(Long examId, Set<String> connectionToken);
|
||||
|
||||
/** Used to get the VDI paired connection if it already exsits.
|
||||
*
|
||||
|
|
|
@ -530,8 +530,7 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Result<Boolean> isActiveConnection(final Long examId, final String connectionToken) {
|
||||
public Result<Boolean> isInInstructionStatus(final Long examId, final String connectionToken) {
|
||||
return Result.tryCatch(() -> this.clientConnectionRecordMapper
|
||||
.selectByExample()
|
||||
.where(
|
||||
|
@ -540,6 +539,12 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
|
|||
.and(
|
||||
ClientConnectionRecordDynamicSqlSupport.examId,
|
||||
SqlBuilder.isEqualTo(examId))
|
||||
.and(
|
||||
ClientConnectionRecordDynamicSqlSupport.status,
|
||||
SqlBuilder.isEqualTo(ConnectionStatus.ACTIVE.name()))
|
||||
.or(
|
||||
ClientConnectionRecordDynamicSqlSupport.status,
|
||||
SqlBuilder.isEqualTo(ConnectionStatus.CONNECTION_REQUESTED.name()))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
|
@ -566,7 +571,7 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
|
|||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Result<Set<String>> filterActive(final Long examId, final Set<String> connectionToken) {
|
||||
public Result<Set<String>> filterForInstructionStatus(final Long examId, final Set<String> connectionToken) {
|
||||
if (connectionToken == null || connectionToken.isEmpty()) {
|
||||
return Result.ofRuntimeError("Null or empty set reference");
|
||||
}
|
||||
|
@ -578,10 +583,15 @@ public class ClientConnectionDAOImpl implements ClientConnectionDAO {
|
|||
.and(
|
||||
ClientConnectionRecordDynamicSqlSupport.examId,
|
||||
SqlBuilder.isEqualTo(examId))
|
||||
.and(
|
||||
ClientConnectionRecordDynamicSqlSupport.status,
|
||||
SqlBuilder.isEqualTo(ConnectionStatus.ACTIVE.name()))
|
||||
.or(
|
||||
ClientConnectionRecordDynamicSqlSupport.status,
|
||||
SqlBuilder.isEqualTo(ConnectionStatus.CONNECTION_REQUESTED.name()))
|
||||
.build()
|
||||
.execute()
|
||||
.stream()
|
||||
.filter(cc -> ConnectionStatus.ACTIVE.name().equals(cc.getStatus()))
|
||||
.map(ClientConnectionRecord::getConnectionToken)
|
||||
.collect(Collectors.toSet()));
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ public class SEBClientInstructionServiceImpl implements SEBClientInstructionServ
|
|||
return Result.tryCatch(() -> {
|
||||
|
||||
final boolean isActive = this.clientConnectionDAO
|
||||
.isActiveConnection(examId, connectionToken)
|
||||
.isInInstructionStatus(examId, connectionToken)
|
||||
.getOr(false);
|
||||
|
||||
if (isActive) {
|
||||
|
@ -124,6 +124,10 @@ public class SEBClientInstructionServiceImpl implements SEBClientInstructionServ
|
|||
} catch (final Exception e) {
|
||||
throw new RuntimeException("Unexpected: ", e);
|
||||
}
|
||||
} else {
|
||||
log.warn(
|
||||
"The SEB client connection : {} is not in a ready state to process instructions. Instruction registration has been skipped",
|
||||
connectionToken);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -140,7 +144,7 @@ public class SEBClientInstructionServiceImpl implements SEBClientInstructionServ
|
|||
|
||||
final String attributesString = Utils.toJsonObject(attributes);
|
||||
final Set<String> activeConnections = this.clientConnectionDAO
|
||||
.filterActive(examId, connectionTokens)
|
||||
.filterForInstructionStatus(examId, connectionTokens)
|
||||
.getOrElse(Collections::emptySet);
|
||||
|
||||
connectionTokens
|
||||
|
|
Loading…
Reference in a new issue