SEBSERV-445 code cleanup

This commit is contained in:
anhefti 2023-06-01 09:03:22 +02:00
parent b344ee22e5
commit 8cab729401
12 changed files with 65 additions and 132 deletions

View file

@ -84,30 +84,6 @@ public class SEBServer {
return firewall;
}
// @Bean
// public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer() {
// return (tomcat) -> tomcat.addConnectorCustomizers((connector) -> {
// if (connector.getProtocolHandler() instanceof AbstractHttp11Protocol) {
// System.out.println("*************** tomcatCustomizer");
// final AbstractHttp11Protocol<?> protocolHandler = (AbstractHttp11Protocol<?>) connector
// .getProtocolHandler();
// protocolHandler.setKeepAliveTimeout(60000);
// protocolHandler.setMaxKeepAliveRequests(3000);
// protocolHandler.setUseKeepAliveResponseHeader(true);
// protocolHandler.setMinSpareThreads(200);
// protocolHandler.setProcessorCache(-1);
// protocolHandler.setTcpNoDelay(true);
// protocolHandler.setThreadPriority(Thread.NORM_PRIORITY + 1);
// protocolHandler.setMaxConnections(2000);
// if (protocolHandler instanceof Http11NioProtocol) {
// System.out.println("*************** Http11NioProtocol");
// ((Http11NioProtocol) protocolHandler).setPollerThreadPriority(Thread.MAX_PRIORITY);
// }
//
// }
// });
// }
private Connector redirectConnector(final Environment env) {
final String sslPort = env.getRequiredProperty("server.port");
final String httpPort = env.getProperty("sebserver.ssl.redirect.html.port", "80");

View file

@ -29,4 +29,28 @@ public class WebserviceConfig {
return aes256jnCryptor;
}
// @Bean
// public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer() {
// return (tomcat) -> tomcat.addConnectorCustomizers((connector) -> {
// if (connector.getProtocolHandler() instanceof AbstractHttp11Protocol) {
// System.out.println("*************** tomcatCustomizer");
// final AbstractHttp11Protocol<?> protocolHandler = (AbstractHttp11Protocol<?>) connector
// .getProtocolHandler();
// protocolHandler.setKeepAliveTimeout(60000);
// protocolHandler.setMaxKeepAliveRequests(3000);
// protocolHandler.setUseKeepAliveResponseHeader(true);
// protocolHandler.setMinSpareThreads(200);
// protocolHandler.setProcessorCache(-1);
// protocolHandler.setTcpNoDelay(true);
// protocolHandler.setThreadPriority(Thread.NORM_PRIORITY + 1);
// protocolHandler.setMaxConnections(2000);
// if (protocolHandler instanceof Http11NioProtocol) {
// System.out.println("*************** Http11NioProtocol");
// ((Http11NioProtocol) protocolHandler).setPollerThreadPriority(Thread.MAX_PRIORITY);
// }
//
// }
// });
// }
}

View file

@ -28,11 +28,10 @@ public interface SEBClientSessionService {
/** Notify a ping for a certain client connection.
*
* @param connectionToken the connection token
* @param timestamp the ping time-stamp
* @param pingNumber the ping number
* @param instructionConfirm instruction confirm sent by the SEB client or null
* @return SEB instruction if available */
String notifyPing(String connectionToken, long timestamp, int pingNumber, String instructionConfirm);
String notifyPing(String connectionToken, int pingNumber, String instructionConfirm);
/** Notify a SEB client event for live indication and storing to database.
*

View file

@ -378,6 +378,7 @@ public class ExamSessionServiceImpl implements ExamSessionService {
@Override
public ClientConnectionDataInternal getConnectionDataInternal(final String connectionToken) {
// TODO do we really need to synchronize here?
synchronized (ExamSessionCacheService.CLIENT_CONNECTION_CREATION_LOCK) {
return this.examSessionCacheService.getClientConnection(connectionToken);
}

View file

@ -44,9 +44,9 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientNotificati
@Lazy
@Component
@WebServiceProfile
public class SEBClientEventBatchStore {
public class SEBClientEventBatchService {
private static final Logger log = LoggerFactory.getLogger(SEBClientEventBatchStore.class);
private static final Logger log = LoggerFactory.getLogger(SEBClientEventBatchService.class);
private final SEBClientNotificationService sebClientNotificationService;
private final SqlSessionFactory sqlSessionFactory;
@ -57,7 +57,7 @@ public class SEBClientEventBatchStore {
private final SqlSessionTemplate sqlSessionTemplate;
private final ClientEventRecordMapper clientEventMapper;
public SEBClientEventBatchStore(
public SEBClientEventBatchService(
final SEBClientNotificationService sebClientNotificationService,
final SqlSessionFactory sqlSessionFactory,
final PlatformTransactionManager transactionManager,
@ -94,14 +94,12 @@ public class SEBClientEventBatchStore {
@Scheduled(
fixedDelayString = "${sebserver.webservice.api.exam.session.event.batch.interval:1000}",
initialDelay = 1000)
initialDelay = 100)
public void processEvents() {
final long startTime = Utils.getMillisecondsNow();
final int size = this.eventDataQueue.size();
if (size > 1000) {
log.warn("******* There are more then 1000 SEB client logs in the waiting queue: {}", size);
log.warn("-----> There are more then 1000 SEB client logs in the waiting queue: {}", size);
}
try {
@ -130,15 +128,6 @@ public class SEBClientEventBatchStore {
this.sqlSessionTemplate.flushStatements();
if (log.isTraceEnabled()) {
log.trace("Processing {} SEB events tuck: {}",
this.events.size(),
Utils.getMillisecondsNow() - startTime);
}
// TODO just for debugging
System.out.println("***** Processing " + this.events.size() + " SEB events tuck: "
+ (Utils.getMillisecondsNow() - startTime));
} catch (final Exception e) {
log.error("Failed to process SEB events from eventDataQueue: ", e);
}

View file

@ -27,9 +27,9 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructio
@Lazy
@Component
@WebServiceProfile
public class SEBClientPingService {
public class SEBClientPingBatchService {
private static final Logger log = LoggerFactory.getLogger(SEBClientPingService.class);
private static final Logger log = LoggerFactory.getLogger(SEBClientPingBatchService.class);
private final ExamSessionCacheService examSessionCacheService;
private final SEBClientInstructionService sebClientInstructionService;
@ -37,7 +37,7 @@ public class SEBClientPingService {
private final Map<String, String> pings = new ConcurrentHashMap<>();
private final Map<String, String> instructions = new ConcurrentHashMap<>();
public SEBClientPingService(
public SEBClientPingBatchService(
final ExamSessionCacheService examSessionCacheService,
final SEBClientInstructionService sebClientInstructionService) {
@ -45,19 +45,15 @@ public class SEBClientPingService {
this.sebClientInstructionService = sebClientInstructionService;
}
@Scheduled(
fixedDelayString = "${sebserver.webservice.api.exam.session.ping.batch.interval:500}",
initialDelay = 1000)
@Scheduled(fixedDelayString = "${sebserver.webservice.api.exam.session.ping.batch.interval:500}")
public void processPings() {
if (this.pings.isEmpty()) {
return;
}
final long startTime = Utils.getMillisecondsNow();
final int size = this.pings.size();
if (size > 1000) {
log.warn("******* There are more then 1000 SEB client logs in the waiting queue: {}", size);
log.warn("----> There are more then 1000 SEB client logs in the waiting queue: {}", size);
}
try {
@ -68,17 +64,6 @@ public class SEBClientPingService {
this.pings.remove(cid),
Utils.getMillisecondsNow()));
// pp.entrySet()
// .stream()
// .forEach(entry -> processPing(entry.getKey(), entry.getValue(), startTime));
if (log.isTraceEnabled()) {
log.trace("****** Processing {} SEB pings tuck: {}", Utils.getMillisecondsNow() - startTime);
}
// TODO just for debugging
System.out.println("***** Processing " + size + " SEB pings tuck: "
+ (Utils.getMillisecondsNow() - startTime));
} catch (final Exception e) {
log.error("Failed to process SEB pings from pingDataQueue: ", e);
}

View file

@ -31,7 +31,7 @@ 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.SEBClientSessionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientVersionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.SEBClientEventBatchStore.EventData;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.SEBClientEventBatchService.EventData;
@Lazy
@Service
@ -42,29 +42,27 @@ public class SEBClientSessionServiceImpl implements SEBClientSessionService {
private final ClientConnectionDAO clientConnectionDAO;
private final ExamSessionService examSessionService;
private final ExamSessionCacheService examSessionCacheService;
private final SEBClientEventBatchStore sebClientEventBatchStore;
private final SEBClientEventBatchService sebClientEventBatchStore;
private final SEBClientInstructionService sebInstructionService;
private final ClientIndicatorFactory clientIndicatorFactory;
private final InternalClientConnectionDataFactory internalClientConnectionDataFactory;
private final SecurityKeyService securityKeyService;
private final SEBClientVersionService sebClientVersionService;
private final SEBClientPingService sebClientPingService;
private final SEBClientPingBatchService sebClientPingService;
public SEBClientSessionServiceImpl(
final ClientConnectionDAO clientConnectionDAO,
final ExamSessionService examSessionService,
final SEBClientEventBatchStore sebClientEventBatchStore,
final SEBClientEventBatchService sebClientEventBatchStore,
final SEBClientInstructionService sebInstructionService,
final ClientIndicatorFactory clientIndicatorFactory,
final InternalClientConnectionDataFactory internalClientConnectionDataFactory,
final SecurityKeyService securityKeyService,
final SEBClientVersionService sebClientVersionService,
final SEBClientPingService sebClientPingService) {
final SEBClientPingBatchService sebClientPingService) {
this.clientConnectionDAO = clientConnectionDAO;
this.examSessionService = examSessionService;
this.examSessionCacheService = examSessionService.getExamSessionCacheService();
this.sebClientEventBatchStore = sebClientEventBatchStore;
this.sebInstructionService = sebInstructionService;
this.clientIndicatorFactory = clientIndicatorFactory;
@ -114,29 +112,12 @@ public class SEBClientSessionServiceImpl implements SEBClientSessionService {
@Override
public String notifyPing(
final String connectionToken,
final long timestamp,
final int pingNumber,
final String instructionConfirm) {
return this.sebClientPingService.notifyPing(connectionToken, instructionConfirm);
}
// @Override
// public String notifyPing(
// final String connectionToken,
// final long timestamp,
// final int pingNumber,
// final String instructionConfirm) {
//
// processPing(connectionToken, timestamp, pingNumber);
//
// if (instructionConfirm != null) {
// this.sebInstructionService.confirmInstructionDone(connectionToken, instructionConfirm);
// }
//
// return this.sebInstructionService.getInstructionJSON(connectionToken);
// }
@Override
public final void notifyClientEvent(final String connectionToken, final String jsonBody) {
this.sebClientEventBatchStore.accept(connectionToken, jsonBody);
@ -155,16 +136,6 @@ public class SEBClientSessionServiceImpl implements SEBClientSessionService {
this.internalClientConnectionDataFactory.getGroupIds(clientConnection)));
}
// private void processPing(final String connectionToken, final long timestamp, final int pingNumber) {
//
// final ClientConnectionDataInternal activeClientConnection = this.examSessionCacheService
// .getClientConnection(connectionToken);
//
// if (activeClientConnection != null) {
// activeClientConnection.notifyPing(timestamp);
// }
// }
private void missingPingUpdate(final ClientConnectionDataInternal connection) {
if (connection.pingIndicator.changeOnIncident()) {

View file

@ -344,10 +344,8 @@ public class DistributedIndicatorValueService implements DisposableBean {
}
/** Update last ping time on persistent storage asynchronously within a defines thread pool with no
* waiting queue to skip further ping updates if all update threads are busy
*
* TODO: we need a better handling strategy here.
* Try to apply a batch update and store the pings in a concurrent hash map **/
* waiting queue to skip further ping updates if all update threads are busy **/
// TODO: we need a better handling strategy here. Try to apply a batch update managed by SEBClientPingBatchService
void updatePingAsync(final Long pingRecord) {
try {
this.indicatorValueUpdateExecutor
@ -363,6 +361,7 @@ public class DistributedIndicatorValueService implements DisposableBean {
/** Update indicator value on persistent storage asynchronously within a defined thread pool with no
* waiting queue to skip further indicator value updates if all update threads are busy **/
// TODO: we need a better handling strategy here. Try to apply a batch update managed by SEBClientEventBatchStore
boolean updateIndicatorValueAsync(final Long pk, final Long value) {
try {
this.indicatorValueUpdateExecutor

View file

@ -325,32 +325,25 @@ public class ExamAPI_V1_Controller {
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
public CompletableFuture<Void> ping(final HttpServletRequest request, final HttpServletResponse response) {
return CompletableFuture.runAsync(
() -> {
final String connectionToken = request.getHeader(API.EXAM_API_SEB_CONNECTION_TOKEN);
//final String pingNumString = request.getParameter(API.EXAM_API_PING_NUMBER);
final String instructionConfirm = request.getParameter(API.EXAM_API_PING_INSTRUCTION_CONFIRM);
public void ping(final HttpServletRequest request, final HttpServletResponse response) {
final String instruction = this.sebClientSessionService
.notifyPing(
connectionToken,
0,
0,
instructionConfirm);
final String connectionToken = request.getHeader(API.EXAM_API_SEB_CONNECTION_TOKEN);
//final String pingNumString = request.getParameter(API.EXAM_API_PING_NUMBER);
final String instructionConfirm = request.getParameter(API.EXAM_API_PING_INSTRUCTION_CONFIRM);
if (instruction == null) {
response.setStatus(HttpStatus.NO_CONTENT.value());
} else {
try {
response.setStatus(HttpStatus.OK.value());
response.getOutputStream().write(instruction.getBytes(StandardCharsets.UTF_8));
} catch (final IOException e) {
log.error("Failed to send instruction as response: {}", connectionToken, e);
}
}
},
this.executor);
final String instruction = this.sebClientSessionService
.notifyPing(connectionToken, 0, instructionConfirm);
if (instruction == null) {
response.setStatus(HttpStatus.NO_CONTENT.value());
} else {
try {
response.setStatus(HttpStatus.OK.value());
response.getOutputStream().write(instruction.getBytes(StandardCharsets.UTF_8));
} catch (final IOException e) {
log.error("Failed to send instruction as response: {}", connectionToken, e);
}
}
}
@RequestMapping(

View file

@ -314,8 +314,6 @@ public class ExamMonitoringController {
name = API.EXAM_MONITORING_CLIENT_GROUP_FILTER,
required = false) final String hiddenClientGroups) {
final long now = Utils.getMillisecondsNow();
final Exam runningExam = checkPrivileges(institutionId, examId);
final MonitoringSEBConnectionData monitoringSEBConnectionData = this.examSessionService
@ -342,8 +340,6 @@ public class ExamMonitoringController {
Collections.emptyList());
}
System.out.println("%%%%%%%% --> monitoring tuck: " + (Utils.getMillisecondsNow() - now));
return monitoringFullPageData;
}

View file

@ -42,7 +42,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.ClientConnectionDataInternal;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.ExamSessionCacheService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.SEBClientEventBatchStore;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.SEBClientEventBatchService;
@Sql(scripts = { "classpath:schema-test.sql", "classpath:data-test.sql", "classpath:data-test-additional.sql" })
public class SebConnectionTest extends ExamAPIIntegrationTester {
@ -58,7 +58,7 @@ public class SebConnectionTest extends ExamAPIIntegrationTester {
@Autowired
private LmsAPIService lmsAPIService;
@Autowired
private SEBClientEventBatchStore sebClientEventBatchStore;
private SEBClientEventBatchService sebClientEventBatchStore;
@Before
public void init() {

View file

@ -32,7 +32,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ClientIndicator;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientConnectionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientSessionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.SEBClientEventBatchStore;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.SEBClientEventBatchService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator.AbstractLogIndicator;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator.AbstractLogLevelCountIndicator;
@ -48,7 +48,7 @@ public class ClientEventServiceTest extends AdministrationAPIIntegrationTester {
@Autowired
private SEBClientSessionService sebClientSessionService;
@Autowired
private SEBClientEventBatchStore sebClientEventBatchStore;
private SEBClientEventBatchService sebClientEventBatchStore;
// @Autowired
// @Qualifier(AsyncServiceSpringConfig.EXAM_API_EXECUTOR_BEAN_NAME)
// private Executor executor;