From 3296b7c004970a8edf86ff2da1a0dd826552d2c4 Mon Sep 17 00:00:00 2001 From: anhefti Date: Thu, 15 Jul 2021 14:50:06 +0200 Subject: [PATCH] SEBSERV-195 improved ping indicator for distributed setups --- .../indicator/AbstractClientIndicator.java | 2 +- .../impl/indicator/AbstractPingIndicator.java | 34 ++++++------------- .../config/application-dev-gui.properties | 4 +-- .../config/application-dev-ws.properties | 2 +- src/main/resources/messages.properties | 2 +- .../api/exam/SebConnectionTest.java | 7 ---- 6 files changed, 16 insertions(+), 35 deletions(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java index 10a62d5a..bf01df3e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractClientIndicator.java @@ -15,7 +15,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.session.ClientIndicator; public abstract class AbstractClientIndicator implements ClientIndicator { - private static final long PERSISTENT_UPDATE_INTERVAL = 1 * Constants.SECOND_IN_MILLIS; + private static final long PERSISTENT_UPDATE_INTERVAL = Constants.SECOND_IN_MILLIS; protected Long indicatorId; protected Long examId; diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractPingIndicator.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractPingIndicator.java index 2a9beb58..d0419be5 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractPingIndicator.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/indicator/AbstractPingIndicator.java @@ -15,26 +15,21 @@ import java.util.Set; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; -import com.fasterxml.jackson.annotation.JsonIgnore; - +import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.model.exam.Indicator; import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType; -import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO; public abstract class AbstractPingIndicator extends AbstractClientIndicator { - private static final int PING_COUNT_INTERVAL_FOR_PERSISTENT_UPDATE = 2; + private static final long INTERVAL_FOR_PERSISTENT_UPDATE = Constants.SECOND_IN_MILLIS; private final Set EMPTY_SET = Collections.unmodifiableSet(EnumSet.noneOf(EventType.class)); protected final ClientEventDAO clientEventDAO; - protected long pingLatency; - protected int pingCount = 0; - protected int pingNumber = 0; - + private long lastUpdate = 0; protected ClientEventRecord pingRecord = null; protected AbstractPingIndicator(final ClientEventDAO clientEventDAO) { @@ -60,21 +55,19 @@ public abstract class AbstractPingIndicator extends AbstractClientIndicator { public final void notifyPing(final long timestamp, final int pingNumber) { final long now = DateTime.now(DateTimeZone.UTC).getMillis(); - this.pingLatency = now - timestamp; super.currentValue = now; - this.pingCount++; - this.pingNumber = pingNumber; super.lastPersistentUpdate = now; - if (!this.cachingEnabled && - this.pingCount > PING_COUNT_INTERVAL_FOR_PERSISTENT_UPDATE && - this.pingRecord != null) { + if (!this.cachingEnabled && this.pingRecord != null) { // Update last ping time on persistent storage - this.pingRecord.setClientTime(timestamp); - this.pingRecord.setServerTime(Utils.getMillisecondsNow()); - this.clientEventDAO.updatePingEvent(this.pingRecord); - this.pingCount = 0; + final long millisecondsNow = System.currentTimeMillis(); + if (millisecondsNow - this.lastUpdate > INTERVAL_FOR_PERSISTENT_UPDATE) { + this.pingRecord.setClientTime(timestamp); + this.pingRecord.setServerTime(millisecondsNow); + this.clientEventDAO.updatePingEvent(this.pingRecord); + this.lastUpdate = millisecondsNow; + } } } @@ -83,11 +76,6 @@ public abstract class AbstractPingIndicator extends AbstractClientIndicator { return this.EMPTY_SET; } - @JsonIgnore - public int getPingNumber() { - return this.pingNumber; - } - public abstract ClientEventRecord updateLogEvent(final long now); } diff --git a/src/main/resources/config/application-dev-gui.properties b/src/main/resources/config/application-dev-gui.properties index 8069b264..a22c98bc 100644 --- a/src/main/resources/config/application-dev-gui.properties +++ b/src/main/resources/config/application-dev-gui.properties @@ -1,11 +1,11 @@ server.address=localhost -server.port=8080 +server.port=8090 sebserver.gui.http.external.scheme=http sebserver.gui.entrypoint=/gui sebserver.gui.webservice.protocol=http sebserver.gui.webservice.address=localhost -sebserver.gui.webservice.port=8080 +sebserver.gui.webservice.port=8090 sebserver.gui.webservice.apipath=/admin-api/v1 # defines the polling interval that is used to poll the webservice for client connection data on a monitored exam page sebserver.gui.webservice.poll-interval=1000 diff --git a/src/main/resources/config/application-dev-ws.properties b/src/main/resources/config/application-dev-ws.properties index 81ac2bc0..277c15de 100644 --- a/src/main/resources/config/application-dev-ws.properties +++ b/src/main/resources/config/application-dev-ws.properties @@ -22,7 +22,7 @@ sebserver.webservice.clean-db-on-startup=false # webservice configuration sebserver.init.adminaccount.gen-on-init=false -sebserver.webservice.distributed=false +sebserver.webservice.distributed=true sebserver.webservice.master.delay.threshold=10000 sebserver.webservice.http.external.scheme=http sebserver.webservice.http.external.servername=localhost diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index d0c97e2e..e71be1e7 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -380,7 +380,7 @@ sebserver.quizdiscovery.action.import=Import as Exam sebserver.quizdiscovery.quiz.import.out.dated=The Selected LMS exam is already finished and can't be imported sebserver.quizdiscovery.action.details=Show LMS Exam Details sebserver.quizdiscovery.quiz.import.existing.confirm=This course was already imported and importing it twice may lead to
unexpected behavior within automated SEB restriction on LMS.

Do you want to import this course as exam anyway? -sebserver.quizdiscovery.quiz.import.existing=This course was already imported as an exam.
You will find it in the Exam section. +sebserver.quizdiscovery.quiz.import.existing=This course was already imported as an exam.
Please find it in the Exam section. sebserver.quizdiscovery.quiz.details.title=LMS Exam Details sebserver.quizdiscovery.quiz.details.institution=Institution diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/exam/SebConnectionTest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/exam/SebConnectionTest.java index 589957bc..fb47b578 100644 --- a/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/exam/SebConnectionTest.java +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/integration/api/exam/SebConnectionTest.java @@ -38,7 +38,6 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRe import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord; 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.indicator.AbstractPingIndicator; @Sql(scripts = { "classpath:schema-test.sql", "classpath:data-test.sql", "classpath:data-test-additional.sql" }) public class SebConnectionTest extends ExamAPIIntegrationTester { @@ -468,20 +467,15 @@ public class SebConnectionTest extends ExamAPIIntegrationTester { assertFalse(ccdi.indicatorValues.isEmpty()); final IndicatorValue pingIndicator = ccdi.indicatorValues.iterator().next(); assertTrue(pingIndicator.getType() == IndicatorType.LAST_PING); - assertEquals("0", String.valueOf(((AbstractPingIndicator) pingIndicator).getPingNumber())); super.sendPing(accessToken, connectionToken, 1); Thread.sleep(200); - assertEquals("1", String.valueOf(((AbstractPingIndicator) pingIndicator).getPingNumber())); super.sendPing(accessToken, connectionToken, 2); Thread.sleep(200); - assertEquals("2", String.valueOf(((AbstractPingIndicator) pingIndicator).getPingNumber())); super.sendPing(accessToken, connectionToken, 3); Thread.sleep(200); - assertEquals("3", String.valueOf(((AbstractPingIndicator) pingIndicator).getPingNumber())); super.sendPing(accessToken, connectionToken, 5); Thread.sleep(200); - assertEquals("5", String.valueOf(((AbstractPingIndicator) pingIndicator).getPingNumber())); } @Test @@ -531,7 +525,6 @@ public class SebConnectionTest extends ExamAPIIntegrationTester { assertFalse(ccdi.indicatorValues.isEmpty()); final IndicatorValue pingIndicator = ccdi.indicatorValues.iterator().next(); assertTrue(pingIndicator.getType() == IndicatorType.LAST_PING); - assertEquals("0", String.valueOf(((AbstractPingIndicator) pingIndicator).getPingNumber())); MockHttpServletResponse sendEvent = super.sendEvent( accessToken,