Merge remote-tracking branch 'origin/dev-1.2' into development
This commit is contained in:
commit
e3ac612fb3
5 changed files with 77 additions and 18 deletions
|
@ -36,6 +36,14 @@ public interface ClientEventDAO extends EntityDAO<ClientEvent, ClientEvent> {
|
||||||
* @return Result refer to the specified ClientNotification or to an error when happened */
|
* @return Result refer to the specified ClientNotification or to an error when happened */
|
||||||
Result<ClientNotification> getPendingNotification(Long notificationId);
|
Result<ClientNotification> getPendingNotification(Long notificationId);
|
||||||
|
|
||||||
|
/** Get a pending notification by the notification value identifier (sent by SEB)
|
||||||
|
*
|
||||||
|
* @param notificationValueId notification value identifier (sent by SEB)
|
||||||
|
* @return Result refer to the specified ClientNotification or to an error when happened */
|
||||||
|
Result<ClientNotification> getPendingNotificationByValue(
|
||||||
|
Long clientConnectionId,
|
||||||
|
Long notificationValueId);
|
||||||
|
|
||||||
/** Get all pending notifications for a given client connection.
|
/** Get all pending notifications for a given client connection.
|
||||||
*
|
*
|
||||||
* @param clientConnectionId The client connection identifier
|
* @param clientConnectionId The client connection identifier
|
||||||
|
@ -51,9 +59,8 @@ public interface ClientEventDAO extends EntityDAO<ClientEvent, ClientEvent> {
|
||||||
/** Used to confirm a pending notification so that the notification is not pending anymore
|
/** Used to confirm a pending notification so that the notification is not pending anymore
|
||||||
*
|
*
|
||||||
* @param notificationId the notification identifier
|
* @param notificationId the notification identifier
|
||||||
* @param clientConnectionId the client connection identifier
|
|
||||||
* @return Result refer to the confirmed notification or to en error when happened */
|
* @return Result refer to the confirmed notification or to en error when happened */
|
||||||
Result<ClientNotification> confirmPendingNotification(Long notificationId, Long clientConnectionId);
|
Result<ClientNotification> confirmPendingNotification(Long notificationId);
|
||||||
|
|
||||||
Result<ClientEventRecord> initPingEvent(Long connectionId);
|
Result<ClientEventRecord> initPingEvent(Long connectionId);
|
||||||
|
|
||||||
|
|
|
@ -198,6 +198,43 @@ public class ClientEventDAOImpl implements ClientEventDAO {
|
||||||
.flatMap(ClientEventDAOImpl::toClientNotificationModel);
|
.flatMap(ClientEventDAOImpl::toClientNotificationModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public Result<ClientNotification> getPendingNotificationByValue(
|
||||||
|
final Long clientConnectionId,
|
||||||
|
final Long notificationValueId) {
|
||||||
|
|
||||||
|
return Result.tryCatch(() -> {
|
||||||
|
|
||||||
|
final List<ClientEventRecord> records = this.clientEventRecordMapper
|
||||||
|
.selectByExample()
|
||||||
|
.where(ClientEventRecordDynamicSqlSupport.clientConnectionId, isEqualTo(clientConnectionId))
|
||||||
|
.and(ClientEventRecordDynamicSqlSupport.type, isEqualTo(EventType.NOTIFICATION.id))
|
||||||
|
.build()
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Found notification for clientConnectionId: {} notification: {}",
|
||||||
|
clientConnectionId,
|
||||||
|
records);
|
||||||
|
}
|
||||||
|
|
||||||
|
return records.stream()
|
||||||
|
.filter(rec -> {
|
||||||
|
final BigDecimal numericValue = rec.getNumericValue();
|
||||||
|
if (numericValue == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return numericValue.longValue() == notificationValueId;
|
||||||
|
})
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new IllegalStateException(
|
||||||
|
"Failed to find pending notification event for confirm:" + notificationValueId));
|
||||||
|
|
||||||
|
})
|
||||||
|
.flatMap(ClientEventDAOImpl::toClientNotificationModel);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public Result<List<ClientNotification>> getPendingNotifications(final Long clientConnectionId) {
|
public Result<List<ClientNotification>> getPendingNotifications(final Long clientConnectionId) {
|
||||||
|
@ -240,8 +277,8 @@ public class ClientEventDAOImpl implements ClientEventDAO {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public Result<ClientNotification> confirmPendingNotification(final Long notificationId,
|
public Result<ClientNotification> confirmPendingNotification(final Long notificationId) {
|
||||||
final Long clientConnectionId) {
|
|
||||||
return Result.tryCatch(() -> {
|
return Result.tryCatch(() -> {
|
||||||
final Long pk = this.clientEventRecordMapper
|
final Long pk = this.clientEventRecordMapper
|
||||||
.selectIdsByExample()
|
.selectIdsByExample()
|
||||||
|
|
|
@ -10,10 +10,12 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.DateTimeZone;
|
import org.joda.time.DateTimeZone;
|
||||||
import org.mybatis.dynamic.sql.SqlBuilder;
|
import org.mybatis.dynamic.sql.SqlBuilder;
|
||||||
|
@ -153,10 +155,12 @@ public class ClientInstructionDAOImpl implements ClientInstructionDAO {
|
||||||
|
|
||||||
if (needsConfirmation) {
|
if (needsConfirmation) {
|
||||||
|
|
||||||
final Map<String, String> attrs = this.jsonMapper.readValue(
|
final Map<String, String> attrs = (StringUtils.isNotBlank(attributes))
|
||||||
attributes,
|
? this.jsonMapper.readValue(
|
||||||
new TypeReference<Map<String, String>>() {
|
attributes,
|
||||||
});
|
new TypeReference<Map<String, String>>() {
|
||||||
|
})
|
||||||
|
: new HashMap<>();
|
||||||
attrs.put(API.EXAM_API_PING_INSTRUCTION_CONFIRM, String.valueOf(clientInstructionRecord.getId()));
|
attrs.put(API.EXAM_API_PING_INSTRUCTION_CONFIRM, String.valueOf(clientInstructionRecord.getId()));
|
||||||
|
|
||||||
this.clientInstructionRecordMapper.updateByPrimaryKeySelective(
|
this.clientInstructionRecordMapper.updateByPrimaryKeySelective(
|
||||||
|
|
|
@ -115,12 +115,17 @@ public class SEBClientInstructionServiceImpl implements SEBClientInstructionServ
|
||||||
|
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
try {
|
try {
|
||||||
final String attributesString = this.jsonMapper.writeValueAsString(attributes);
|
|
||||||
|
final String attributesString = (attributes != null && !attributes.isEmpty())
|
||||||
|
? this.jsonMapper.writeValueAsString(attributes)
|
||||||
|
: null;
|
||||||
|
|
||||||
this.clientInstructionDAO
|
this.clientInstructionDAO
|
||||||
.insert(examId, type, attributesString, connectionToken, needsConfirm)
|
.insert(examId, type, attributesString, connectionToken, needsConfirm)
|
||||||
.map(this::putToCache)
|
.map(this::putToCache)
|
||||||
.onError(error -> log.error("Failed to register instruction: {}", error.getMessage()))
|
.onError(error -> log.error("Failed to register instruction: {}", error.getMessage()))
|
||||||
.getOrThrow();
|
.getOrThrow();
|
||||||
|
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
throw new RuntimeException("Unexpected: ", e);
|
throw new RuntimeException("Unexpected: ", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import ch.ethz.seb.sebserver.gbl.model.session.ClientInstruction.InstructionType
|
||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification;
|
import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification;
|
||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
|
||||||
import ch.ethz.seb.sebserver.gbl.util.Result;
|
import ch.ethz.seb.sebserver.gbl.util.Result;
|
||||||
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService;
|
||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientNotificationService;
|
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientNotificationService;
|
||||||
|
@ -44,6 +45,7 @@ public class SEBClientNotificationServiceImpl implements SEBClientNotificationSe
|
||||||
private static final String CONFIRM_INSTRUCTION_ATTR_TYPE = "type";
|
private static final String CONFIRM_INSTRUCTION_ATTR_TYPE = "type";
|
||||||
|
|
||||||
private final ClientEventDAO clientEventDAO;
|
private final ClientEventDAO clientEventDAO;
|
||||||
|
private final ClientConnectionDAO clientConnectionDAO;
|
||||||
private final SEBClientInstructionService sebClientInstructionService;
|
private final SEBClientInstructionService sebClientInstructionService;
|
||||||
private final Set<Long> pendingNotifications = new HashSet<>();
|
private final Set<Long> pendingNotifications = new HashSet<>();
|
||||||
private final Set<Long> examUpdate = new HashSet<>();
|
private final Set<Long> examUpdate = new HashSet<>();
|
||||||
|
@ -52,9 +54,11 @@ public class SEBClientNotificationServiceImpl implements SEBClientNotificationSe
|
||||||
|
|
||||||
public SEBClientNotificationServiceImpl(
|
public SEBClientNotificationServiceImpl(
|
||||||
final ClientEventDAO clientEventDAO,
|
final ClientEventDAO clientEventDAO,
|
||||||
|
final ClientConnectionDAO clientConnectionDAO,
|
||||||
final SEBClientInstructionService sebClientInstructionService) {
|
final SEBClientInstructionService sebClientInstructionService) {
|
||||||
|
|
||||||
this.clientEventDAO = clientEventDAO;
|
this.clientEventDAO = clientEventDAO;
|
||||||
|
this.clientConnectionDAO = clientConnectionDAO;
|
||||||
this.sebClientInstructionService = sebClientInstructionService;
|
this.sebClientInstructionService = sebClientInstructionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,13 +79,16 @@ public class SEBClientNotificationServiceImpl implements SEBClientNotificationSe
|
||||||
@Override
|
@Override
|
||||||
public void confirmPendingNotification(final ClientEvent event, final String connectionToken) {
|
public void confirmPendingNotification(final ClientEvent event, final String connectionToken) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
final ClientConnection clientConnection = this.clientConnectionDAO
|
||||||
|
.byConnectionToken(connectionToken)
|
||||||
|
.getOrThrow();
|
||||||
final Long notificationId = (long) event.getValue();
|
final Long notificationId = (long) event.getValue();
|
||||||
|
|
||||||
this.clientEventDAO.getPendingNotification(notificationId)
|
this.clientEventDAO.getPendingNotificationByValue(clientConnection.id, notificationId)
|
||||||
.flatMap(notification -> this.clientEventDAO.confirmPendingNotification(
|
.flatMap(notification -> this.clientEventDAO.confirmPendingNotification(notification.id))
|
||||||
notificationId,
|
.map(this::removeFromCache)
|
||||||
notification.connectionId))
|
.onError(error -> log.error("Failed to confirm pending notification: {}", event, error));
|
||||||
.map(this::removeFromCache);
|
|
||||||
|
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
log.error(
|
log.error(
|
||||||
|
@ -98,10 +105,9 @@ public class SEBClientNotificationServiceImpl implements SEBClientNotificationSe
|
||||||
|
|
||||||
return this.clientEventDAO.getPendingNotification(notificationId)
|
return this.clientEventDAO.getPendingNotification(notificationId)
|
||||||
.map(notification -> this.confirmClientSide(notification, examId, connectionToken))
|
.map(notification -> this.confirmClientSide(notification, examId, connectionToken))
|
||||||
.flatMap(notification -> this.clientEventDAO.confirmPendingNotification(
|
.flatMap(notification -> this.clientEventDAO.confirmPendingNotification(notificationId))
|
||||||
notificationId,
|
.map(this::removeFromCache)
|
||||||
notification.connectionId))
|
.onError(error -> log.error("Failed to confirm pending notification: {}", notificationId, error));
|
||||||
.map(this::removeFromCache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in a new issue