SEBSERV-250 made disableConnection call asynchronous when there are more
then one connection involved. This result in immediately response on UI side.
This commit is contained in:
parent
863511dbc7
commit
d7c71ea930
3 changed files with 47 additions and 8 deletions
|
@ -9,7 +9,9 @@
|
||||||
package ch.ethz.seb.sebserver.webservice.servicelayer.session;
|
package ch.ethz.seb.sebserver.webservice.servicelayer.session;
|
||||||
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
|
||||||
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.ClientEvent;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
|
@ -124,6 +126,17 @@ public interface SEBClientConnectionService {
|
||||||
* @return A Result refer to the closed ClientConnection instance, or refer to an error if happened */
|
* @return A Result refer to the closed ClientConnection instance, or refer to an error if happened */
|
||||||
Result<ClientConnection> disableConnection(String connectionToken, Long institutionId);
|
Result<ClientConnection> disableConnection(String connectionToken, Long institutionId);
|
||||||
|
|
||||||
|
/** This is used to disable multiple undefined or requested ClientConnection attempt from the SEB Server side
|
||||||
|
* <p>
|
||||||
|
* This will save the existing ClientConnections that are in UNDEFINED or REQUESTED state, in new DISABLED state and
|
||||||
|
* flush caches.
|
||||||
|
*
|
||||||
|
* @param connectionTokens String array of connection tokens of connections to disable
|
||||||
|
* @param institutionId institution identifier
|
||||||
|
* @return A Result refer to a list of EntityKey of the closed ClientConnection instances, or refer to an error if
|
||||||
|
* happened */
|
||||||
|
Result<Collection<EntityKey>> disableConnections(final String[] connectionTokens, final Long institutionId);
|
||||||
|
|
||||||
/** Used to check current cached ping times of all running connections and
|
/** Used to check current cached ping times of all running connections and
|
||||||
* if a ping time is overflowing, creating a ping overflow event or if an
|
* if a ping time is overflowing, creating a ping overflow event or if an
|
||||||
* overflowed ping is back to normal, a ping back to normal event. */
|
* overflowed ping is back to normal, a ping back to normal event. */
|
||||||
|
|
|
@ -10,10 +10,13 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -24,6 +27,7 @@ import org.springframework.cache.CacheManager;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
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.Exam;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig;
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig.VDIType;
|
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SEBClientConfig.VDIType;
|
||||||
|
@ -571,6 +575,20 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<Collection<EntityKey>> disableConnections(final String[] connectionTokens, final Long institutionId) {
|
||||||
|
return Result.tryCatch(() -> {
|
||||||
|
|
||||||
|
return Stream.of(connectionTokens)
|
||||||
|
.map(token -> disableConnection(token, institutionId)
|
||||||
|
.onError(error -> log.error("Failed to disable SEB client connection: {}", token))
|
||||||
|
.getOr(null))
|
||||||
|
.filter(clientConnection -> clientConnection != null)
|
||||||
|
.map(clientConnection -> clientConnection.getEntityKey())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updatePingEvents() {
|
public void updatePingEvents() {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -11,6 +11,7 @@ package ch.ethz.seb.sebserver.webservice.weblayer.api;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
@ -18,6 +19,7 @@ import javax.validation.Valid;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.web.bind.WebDataBinder;
|
import org.springframework.web.bind.WebDataBinder;
|
||||||
|
@ -34,6 +36,7 @@ import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.API;
|
import ch.ethz.seb.sebserver.gbl.api.API;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
import ch.ethz.seb.sebserver.gbl.api.EntityType;
|
||||||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
|
||||||
|
import ch.ethz.seb.sebserver.gbl.async.AsyncServiceSpringConfig;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
import ch.ethz.seb.sebserver.gbl.model.Domain;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.Page;
|
import ch.ethz.seb.sebserver.gbl.model.Page;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
import ch.ethz.seb.sebserver.gbl.model.exam.Exam;
|
||||||
|
@ -67,13 +70,15 @@ public class ExamMonitoringController {
|
||||||
private final AuthorizationService authorization;
|
private final AuthorizationService authorization;
|
||||||
private final PaginationService paginationService;
|
private final PaginationService paginationService;
|
||||||
private final SEBClientNotificationService sebClientNotificationService;
|
private final SEBClientNotificationService sebClientNotificationService;
|
||||||
|
private final Executor executor;
|
||||||
|
|
||||||
public ExamMonitoringController(
|
public ExamMonitoringController(
|
||||||
final SEBClientConnectionService sebClientConnectionService,
|
final SEBClientConnectionService sebClientConnectionService,
|
||||||
final SEBClientInstructionService sebClientInstructionService,
|
final SEBClientInstructionService sebClientInstructionService,
|
||||||
final AuthorizationService authorization,
|
final AuthorizationService authorization,
|
||||||
final PaginationService paginationService,
|
final PaginationService paginationService,
|
||||||
final SEBClientNotificationService sebClientNotificationService) {
|
final SEBClientNotificationService sebClientNotificationService,
|
||||||
|
@Qualifier(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME) final Executor executor) {
|
||||||
|
|
||||||
this.sebClientConnectionService = sebClientConnectionService;
|
this.sebClientConnectionService = sebClientConnectionService;
|
||||||
this.examSessionService = sebClientConnectionService.getExamSessionService();
|
this.examSessionService = sebClientConnectionService.getExamSessionService();
|
||||||
|
@ -81,6 +86,7 @@ public class ExamMonitoringController {
|
||||||
this.authorization = authorization;
|
this.authorization = authorization;
|
||||||
this.paginationService = paginationService;
|
this.paginationService = paginationService;
|
||||||
this.sebClientNotificationService = sebClientNotificationService;
|
this.sebClientNotificationService = sebClientNotificationService;
|
||||||
|
this.executor = executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This is called by Spring to initialize the WebDataBinder and is used here to
|
/** This is called by Spring to initialize the WebDataBinder and is used here to
|
||||||
|
@ -293,14 +299,16 @@ public class ExamMonitoringController {
|
||||||
|
|
||||||
checkPrivileges(institutionId, examId);
|
checkPrivileges(institutionId, examId);
|
||||||
|
|
||||||
// TODO do this async like registerInstruction
|
|
||||||
if (connectionToken.contains(Constants.LIST_SEPARATOR)) {
|
if (connectionToken.contains(Constants.LIST_SEPARATOR)) {
|
||||||
final String[] tokens = StringUtils.split(connectionToken, Constants.LIST_SEPARATOR);
|
// If we have a bunch of client connections to disable, make it asynchronously and respond to the caller immediately
|
||||||
for (int i = 0; i < tokens.length; i++) {
|
this.executor.execute(() -> {
|
||||||
final String token = tokens[i];
|
final String[] tokens = StringUtils.split(connectionToken, Constants.LIST_SEPARATOR);
|
||||||
this.sebClientConnectionService.disableConnection(token, institutionId)
|
this.sebClientConnectionService
|
||||||
.onError(error -> log.error("Failed to disable SEB client connection: {}", token));
|
.disableConnections(tokens, institutionId)
|
||||||
}
|
.onError(error -> log.error(
|
||||||
|
"Unexpected error while disable connection. See previous logs for more information.",
|
||||||
|
error));
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.sebClientConnectionService
|
this.sebClientConnectionService
|
||||||
.disableConnection(connectionToken, institutionId)
|
.disableConnection(connectionToken, institutionId)
|
||||||
|
|
Loading…
Reference in a new issue