SEBSERV-195 fixed ping caching

This commit is contained in:
anhefti 2021-07-21 11:32:04 +02:00
parent 2e7fb8e8dc
commit d96816311b
8 changed files with 53 additions and 31 deletions

View file

@ -33,7 +33,7 @@ public interface ClientEventLastPingMapper {
@SelectProvider(type = SqlProviderAdapter.class, method = "select")
@ResultType(ClientEventLastPingRecord.class)
@ConstructorArgs({
@Arg(column = "client_connection_id", javaType = Long.class, jdbcType = JdbcType.BIGINT),
@Arg(column = "id", javaType = Long.class, jdbcType = JdbcType.BIGINT),
@Arg(column = "server_time", javaType = Long.class, jdbcType = JdbcType.BIGINT),
})
Collection<ClientEventLastPingRecord> selectMany(SelectStatementProvider select);
@ -42,7 +42,7 @@ public interface ClientEventLastPingMapper {
return SelectDSL.selectWithMapper(
this::selectMany,
ClientEventRecordDynamicSqlSupport.clientConnectionId.as("client_connection_id"),
ClientEventRecordDynamicSqlSupport.clientConnectionId.as("id"),
ClientEventRecordDynamicSqlSupport.serverTime.as("server_time"))
.from(ClientEventRecordDynamicSqlSupport.clientEventRecord);
@ -50,14 +50,14 @@ public interface ClientEventLastPingMapper {
final class ClientEventLastPingRecord {
public final Long connectionId;
public final Long id;
public final Long lastPingTime;
public ClientEventLastPingRecord(
final Long client_connection_id,
final Long id,
final Long server_time) {
this.connectionId = client_connection_id;
this.id = id;
this.lastPingTime = server_time;
}
}

View file

@ -14,7 +14,6 @@ import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@ -296,20 +295,38 @@ public class ClientEventDAOImpl implements ClientEventDAO {
@Transactional
public Result<Collection<EntityKey>> delete(final Set<EntityKey> all) {
return Result.tryCatch(() -> {
return all
final List<Long> pks = all
.stream()
.map(EntityKey::getModelId)
.map(Long::parseLong)
.map(pk -> {
final int deleted = this.clientEventRecordMapper.deleteByPrimaryKey(pk);
if (deleted == 1) {
return new EntityKey(String.valueOf(pk), EntityType.CLIENT_EVENT);
} else {
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
this.clientEventRecordMapper
.deleteByExample()
.where(ClientEventRecordDynamicSqlSupport.id, isIn(pks))
.build()
.execute();
return pks
.stream()
.map(pk -> new EntityKey(String.valueOf(pk), EntityType.CLIENT_EVENT))
.collect(Collectors.toList());
// return all
// .stream()
// .map(EntityKey::getModelId)
// .map(Long::parseLong)
// .map(pk -> {
// final int deleted = this.clientEventRecordMapper.deleteByPrimaryKey(pk);
// if (deleted == 1) {
// return new EntityKey(String.valueOf(pk), EntityType.CLIENT_EVENT);
// } else {
// return null;
// }
// })
// .filter(Objects::nonNull)
// .collect(Collectors.toList());
});
}
@ -368,7 +385,7 @@ public class ClientEventDAOImpl implements ClientEventDAO {
public Result<Long> getLastPing(final Long pk) {
return Result.tryCatch(() -> this.clientEventRecordMapper
.selectByPrimaryKey(pk)
.getClientTime());
.getServerTime());
}
private Result<ClientEventRecord> recordById(final Long id) {

View file

@ -75,7 +75,7 @@ public class ClientConnectionDataInternal extends ClientConnectionData {
@Override
@JsonProperty(ATTR_MISSING_PING)
public Boolean getMissingPing() {
return this.pingIndicator.isMissingPing();
return this.pingIndicator != null && this.pingIndicator.isMissingPing();
}
@Override

View file

@ -512,6 +512,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
final Cache cache = this.cacheManager.getCache(ExamSessionCacheService.CACHE_NAME_ACTIVE_CLIENT_CONNECTION);
final long now = Utils.getMillisecondsNow();
final Consumer<ClientConnectionDataInternal> missingPingUpdate = missingPingUpdate(now);
this.examSessionService
.getExamDAO()
.allRunningExamIds()
@ -529,8 +530,8 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
.map(token -> cache.get(token, ClientConnectionDataInternal.class))
.filter(Objects::nonNull)
.filter(connection -> connection.pingIndicator != null &&
connection.clientConnection.status.establishedStatus)
.forEach(missingPingUpdate(now));
connection.clientConnection.status.clientActiveStatus)
.forEach(connection -> missingPingUpdate.accept(connection));
} catch (final Exception e) {
log.error("Failed to update ping events: ", e);

View file

@ -8,9 +8,10 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import org.joda.time.DateTimeUtils;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ClientIndicator;
public abstract class AbstractClientIndicator implements ClientIndicator {
@ -63,15 +64,14 @@ public abstract class AbstractClientIndicator implements ClientIndicator {
@Override
public double getValue() {
final long now = DateTimeUtils.currentTimeMillis();
if (!this.valueInitializes) {
final long now = Utils.getMillisecondsNow();
this.currentValue = computeValueAt(now);
this.lastPersistentUpdate = now;
this.valueInitializes = true;
}
if (!this.cachingEnabled && this.active) {
final long now = System.currentTimeMillis();
if (now - this.lastPersistentUpdate > PERSISTENT_UPDATE_INTERVAL) {
this.currentValue = computeValueAt(now);
this.lastPersistentUpdate = now;

View file

@ -13,6 +13,7 @@ import java.util.EnumSet;
import java.util.Set;
import org.joda.time.DateTime;
import org.joda.time.DateTimeUtils;
import org.joda.time.DateTimeZone;
import ch.ethz.seb.sebserver.gbl.Constants;
@ -61,7 +62,7 @@ public abstract class AbstractPingIndicator extends AbstractClientIndicator {
if (!this.cachingEnabled && this.pingRecord != null) {
// Update last ping time on persistent storage
final long millisecondsNow = System.currentTimeMillis();
final long millisecondsNow = DateTimeUtils.currentTimeMillis();
if (millisecondsNow - this.lastUpdate > INTERVAL_FOR_PERSISTENT_UPDATE) {
this.pingRecord.setClientTime(timestamp);
this.pingRecord.setServerTime(millisecondsNow);

View file

@ -11,8 +11,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import java.math.BigDecimal;
import java.util.Comparator;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.DateTimeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -28,7 +27,6 @@ import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
import ch.ethz.seb.sebserver.gbl.util.Result;
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;
@ -51,7 +49,6 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
public PingIntervalClientIndicator(final ClientEventDAO clientEventDAO) {
super(clientEventDAO);
this.cachingEnabled = true;
this.currentValue = computeValueAt(Utils.getMillisecondsNow());
}
@Override
@ -63,6 +60,8 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
super.init(indicatorDefinition, connectionId, active, cachingEnabled);
this.currentValue = computeValueAt(DateTimeUtils.currentTimeMillis());
try {
indicatorDefinition
.getThresholds()
@ -77,7 +76,8 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
if (!cachingEnabled) {
try {
this.missingPing = this.pingErrorThreshold < getValue();
final double value = getValue();
this.missingPing = this.pingErrorThreshold < value;
} catch (final Exception e) {
log.error("Failed to initialize missingPing: {}", e.getMessage());
this.missingPing = false;
@ -108,7 +108,7 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
@Override
public double getValue() {
final long now = DateTime.now(DateTimeZone.UTC).getMillis();
final long now = DateTimeUtils.currentTimeMillis();
return now - super.getValue();
}
@ -134,6 +134,9 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
.getLastPing(super.pingRecord.getId());
if (!lastPing.hasError()) {
if (Double.isNaN(this.currentValue)) {
return lastPing.get().doubleValue();
}
return Math.max(this.currentValue, lastPing.get().doubleValue());
} else {
log.error("Failed to get last ping from persistent: {}", lastPing.getError().getMessage());

View file

@ -596,7 +596,7 @@ sebserver.exam.indicator.type.WLAN_STATUS=WiFi Status
sebserver.exam.indicator.type.description.LAST_PING=This indicator shows the time in milliseconds since<br/> the last ping has been received from a SEB Client.<br/>This indicator can be used to track a SEB Client connection and indicate connection loss.<br/><br/>The value is in milliseconds.
sebserver.exam.indicator.type.description.ERROR_COUNT=This indicator shows the number of error log messages that<br/> has been received from a SEB Client.<br/>This indicator can be used to track errors of connected SEB Clients<br/><br/>The value is a natural number.
sebserver.exam.indicator.type.description.WARN_COUNT=This indicator shows the number of warn log messages that<br/> has been received from a SEB Client.<br/>This indicator can be used to track warnings of connected SEB Clients<br/><br/>The value is a natural number.
sebserver.exam.indicator.type.description.INFO_COUNT=This indicator shows the number of warn log messages that<br/> has been received from a SEB Client.<br/>This indicator can be used to track warnings of connected SEB Clients<br/><br/>The value is a natural number.
sebserver.exam.indicator.type.description.INFO_COUNT=This indicator shows the number of info log messages that<br/> has been received from a SEB Client.<br/>This indicator can be used to track warnings of connected SEB Clients<br/><br/>The value is a natural number.
sebserver.exam.indicator.type.description.BATTERY_STATUS=This indicator shows the percentage of the battery load level of a SEB Client.
sebserver.exam.indicator.type.description.WLAN_STATUS=This indicator shows the percentage of the WiFi connection status of a SEB Client.