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…
	
	Add table
		
		Reference in a new issue
	
	 anhefti
						anhefti