SEBSERV-195 fixed ping caching
This commit is contained in:
parent
2e7fb8e8dc
commit
d96816311b
8 changed files with 53 additions and 31 deletions
|
@ -33,7 +33,7 @@ public interface ClientEventLastPingMapper {
|
||||||
@SelectProvider(type = SqlProviderAdapter.class, method = "select")
|
@SelectProvider(type = SqlProviderAdapter.class, method = "select")
|
||||||
@ResultType(ClientEventLastPingRecord.class)
|
@ResultType(ClientEventLastPingRecord.class)
|
||||||
@ConstructorArgs({
|
@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),
|
@Arg(column = "server_time", javaType = Long.class, jdbcType = JdbcType.BIGINT),
|
||||||
})
|
})
|
||||||
Collection<ClientEventLastPingRecord> selectMany(SelectStatementProvider select);
|
Collection<ClientEventLastPingRecord> selectMany(SelectStatementProvider select);
|
||||||
|
@ -42,7 +42,7 @@ public interface ClientEventLastPingMapper {
|
||||||
return SelectDSL.selectWithMapper(
|
return SelectDSL.selectWithMapper(
|
||||||
this::selectMany,
|
this::selectMany,
|
||||||
|
|
||||||
ClientEventRecordDynamicSqlSupport.clientConnectionId.as("client_connection_id"),
|
ClientEventRecordDynamicSqlSupport.clientConnectionId.as("id"),
|
||||||
ClientEventRecordDynamicSqlSupport.serverTime.as("server_time"))
|
ClientEventRecordDynamicSqlSupport.serverTime.as("server_time"))
|
||||||
|
|
||||||
.from(ClientEventRecordDynamicSqlSupport.clientEventRecord);
|
.from(ClientEventRecordDynamicSqlSupport.clientEventRecord);
|
||||||
|
@ -50,14 +50,14 @@ public interface ClientEventLastPingMapper {
|
||||||
|
|
||||||
final class ClientEventLastPingRecord {
|
final class ClientEventLastPingRecord {
|
||||||
|
|
||||||
public final Long connectionId;
|
public final Long id;
|
||||||
public final Long lastPingTime;
|
public final Long lastPingTime;
|
||||||
|
|
||||||
public ClientEventLastPingRecord(
|
public ClientEventLastPingRecord(
|
||||||
final Long client_connection_id,
|
final Long id,
|
||||||
final Long server_time) {
|
final Long server_time) {
|
||||||
|
|
||||||
this.connectionId = client_connection_id;
|
this.id = id;
|
||||||
this.lastPingTime = server_time;
|
this.lastPingTime = server_time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -296,20 +295,38 @@ public class ClientEventDAOImpl implements ClientEventDAO {
|
||||||
@Transactional
|
@Transactional
|
||||||
public Result<Collection<EntityKey>> delete(final Set<EntityKey> all) {
|
public Result<Collection<EntityKey>> delete(final Set<EntityKey> all) {
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
return all
|
|
||||||
|
final List<Long> pks = all
|
||||||
.stream()
|
.stream()
|
||||||
.map(EntityKey::getModelId)
|
.map(EntityKey::getModelId)
|
||||||
.map(Long::parseLong)
|
.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());
|
.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) {
|
public Result<Long> getLastPing(final Long pk) {
|
||||||
return Result.tryCatch(() -> this.clientEventRecordMapper
|
return Result.tryCatch(() -> this.clientEventRecordMapper
|
||||||
.selectByPrimaryKey(pk)
|
.selectByPrimaryKey(pk)
|
||||||
.getClientTime());
|
.getServerTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Result<ClientEventRecord> recordById(final Long id) {
|
private Result<ClientEventRecord> recordById(final Long id) {
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class ClientConnectionDataInternal extends ClientConnectionData {
|
||||||
@Override
|
@Override
|
||||||
@JsonProperty(ATTR_MISSING_PING)
|
@JsonProperty(ATTR_MISSING_PING)
|
||||||
public Boolean getMissingPing() {
|
public Boolean getMissingPing() {
|
||||||
return this.pingIndicator.isMissingPing();
|
return this.pingIndicator != null && this.pingIndicator.isMissingPing();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -512,6 +512,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
||||||
|
|
||||||
final Cache cache = this.cacheManager.getCache(ExamSessionCacheService.CACHE_NAME_ACTIVE_CLIENT_CONNECTION);
|
final Cache cache = this.cacheManager.getCache(ExamSessionCacheService.CACHE_NAME_ACTIVE_CLIENT_CONNECTION);
|
||||||
final long now = Utils.getMillisecondsNow();
|
final long now = Utils.getMillisecondsNow();
|
||||||
|
final Consumer<ClientConnectionDataInternal> missingPingUpdate = missingPingUpdate(now);
|
||||||
this.examSessionService
|
this.examSessionService
|
||||||
.getExamDAO()
|
.getExamDAO()
|
||||||
.allRunningExamIds()
|
.allRunningExamIds()
|
||||||
|
@ -529,8 +530,8 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
|
||||||
.map(token -> cache.get(token, ClientConnectionDataInternal.class))
|
.map(token -> cache.get(token, ClientConnectionDataInternal.class))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.filter(connection -> connection.pingIndicator != null &&
|
.filter(connection -> connection.pingIndicator != null &&
|
||||||
connection.clientConnection.status.establishedStatus)
|
connection.clientConnection.status.clientActiveStatus)
|
||||||
.forEach(missingPingUpdate(now));
|
.forEach(connection -> missingPingUpdate.accept(connection));
|
||||||
|
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Failed to update ping events: ", e);
|
log.error("Failed to update ping events: ", e);
|
||||||
|
|
|
@ -8,9 +8,10 @@
|
||||||
|
|
||||||
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
|
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.Constants;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
|
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;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ClientIndicator;
|
||||||
|
|
||||||
public abstract class AbstractClientIndicator implements ClientIndicator {
|
public abstract class AbstractClientIndicator implements ClientIndicator {
|
||||||
|
@ -63,15 +64,14 @@ public abstract class AbstractClientIndicator implements ClientIndicator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getValue() {
|
public double getValue() {
|
||||||
|
final long now = DateTimeUtils.currentTimeMillis();
|
||||||
if (!this.valueInitializes) {
|
if (!this.valueInitializes) {
|
||||||
final long now = Utils.getMillisecondsNow();
|
|
||||||
this.currentValue = computeValueAt(now);
|
this.currentValue = computeValueAt(now);
|
||||||
this.lastPersistentUpdate = now;
|
this.lastPersistentUpdate = now;
|
||||||
this.valueInitializes = true;
|
this.valueInitializes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.cachingEnabled && this.active) {
|
if (!this.cachingEnabled && this.active) {
|
||||||
final long now = System.currentTimeMillis();
|
|
||||||
if (now - this.lastPersistentUpdate > PERSISTENT_UPDATE_INTERVAL) {
|
if (now - this.lastPersistentUpdate > PERSISTENT_UPDATE_INTERVAL) {
|
||||||
this.currentValue = computeValueAt(now);
|
this.currentValue = computeValueAt(now);
|
||||||
this.lastPersistentUpdate = now;
|
this.lastPersistentUpdate = now;
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.EnumSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
import org.joda.time.DateTimeUtils;
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
|
|
||||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||||
|
@ -61,7 +62,7 @@ public abstract class AbstractPingIndicator extends AbstractClientIndicator {
|
||||||
if (!this.cachingEnabled && this.pingRecord != null) {
|
if (!this.cachingEnabled && this.pingRecord != null) {
|
||||||
|
|
||||||
// Update last ping time on persistent storage
|
// 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) {
|
if (millisecondsNow - this.lastUpdate > INTERVAL_FOR_PERSISTENT_UPDATE) {
|
||||||
this.pingRecord.setClientTime(timestamp);
|
this.pingRecord.setClientTime(timestamp);
|
||||||
this.pingRecord.setServerTime(millisecondsNow);
|
this.pingRecord.setServerTime(millisecondsNow);
|
||||||
|
|
|
@ -11,8 +11,7 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTimeUtils;
|
||||||
import org.joda.time.DateTimeZone;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
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;
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
|
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.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.datalayer.batis.model.ClientEventRecord;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO;
|
||||||
|
|
||||||
|
@ -51,7 +49,6 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
|
||||||
public PingIntervalClientIndicator(final ClientEventDAO clientEventDAO) {
|
public PingIntervalClientIndicator(final ClientEventDAO clientEventDAO) {
|
||||||
super(clientEventDAO);
|
super(clientEventDAO);
|
||||||
this.cachingEnabled = true;
|
this.cachingEnabled = true;
|
||||||
this.currentValue = computeValueAt(Utils.getMillisecondsNow());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,6 +60,8 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
|
||||||
|
|
||||||
super.init(indicatorDefinition, connectionId, active, cachingEnabled);
|
super.init(indicatorDefinition, connectionId, active, cachingEnabled);
|
||||||
|
|
||||||
|
this.currentValue = computeValueAt(DateTimeUtils.currentTimeMillis());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
indicatorDefinition
|
indicatorDefinition
|
||||||
.getThresholds()
|
.getThresholds()
|
||||||
|
@ -77,7 +76,8 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
|
||||||
|
|
||||||
if (!cachingEnabled) {
|
if (!cachingEnabled) {
|
||||||
try {
|
try {
|
||||||
this.missingPing = this.pingErrorThreshold < getValue();
|
final double value = getValue();
|
||||||
|
this.missingPing = this.pingErrorThreshold < value;
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error("Failed to initialize missingPing: {}", e.getMessage());
|
log.error("Failed to initialize missingPing: {}", e.getMessage());
|
||||||
this.missingPing = false;
|
this.missingPing = false;
|
||||||
|
@ -108,7 +108,7 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getValue() {
|
public double getValue() {
|
||||||
final long now = DateTime.now(DateTimeZone.UTC).getMillis();
|
final long now = DateTimeUtils.currentTimeMillis();
|
||||||
return now - super.getValue();
|
return now - super.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,6 +134,9 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
|
||||||
.getLastPing(super.pingRecord.getId());
|
.getLastPing(super.pingRecord.getId());
|
||||||
|
|
||||||
if (!lastPing.hasError()) {
|
if (!lastPing.hasError()) {
|
||||||
|
if (Double.isNaN(this.currentValue)) {
|
||||||
|
return lastPing.get().doubleValue();
|
||||||
|
}
|
||||||
return Math.max(this.currentValue, lastPing.get().doubleValue());
|
return Math.max(this.currentValue, lastPing.get().doubleValue());
|
||||||
} else {
|
} else {
|
||||||
log.error("Failed to get last ping from persistent: {}", lastPing.getError().getMessage());
|
log.error("Failed to get last ping from persistent: {}", lastPing.getError().getMessage());
|
||||||
|
|
|
@ -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.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.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.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.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.
|
sebserver.exam.indicator.type.description.WLAN_STATUS=This indicator shows the percentage of the WiFi connection status of a SEB Client.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue