SEBSERV-195 improved ping indicator for distributed setups

This commit is contained in:
anhefti 2021-07-15 14:50:06 +02:00
parent 494c6a08ec
commit 3296b7c004
6 changed files with 16 additions and 35 deletions

View file

@ -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;

View file

@ -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<EventType> 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);
}

View file

@ -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

View file

@ -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

View file

@ -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<br/> unexpected behavior within automated SEB restriction on LMS.<br/><br/> Do you want to import this course as exam anyway?
sebserver.quizdiscovery.quiz.import.existing=This course was already imported as an exam.<br/> You will find it in the Exam section.
sebserver.quizdiscovery.quiz.import.existing=This course was already imported as an exam.<br/>Please find it in the Exam section.
sebserver.quizdiscovery.quiz.details.title=LMS Exam Details
sebserver.quizdiscovery.quiz.details.institution=Institution

View file

@ -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,