From 30b0c931865f0bdb1e028e703b3db79d8b0270c2 Mon Sep 17 00:00:00 2001 From: anhefti Date: Wed, 5 Jan 2022 09:00:31 +0100 Subject: [PATCH] SEBSERV-255 added automated deletion of client notification on exam deletion --- .../gbl/model/session/ClientNotification.java | 6 +++ .../servicelayer/dao/ClientEventDAO.java | 9 ++++ .../dao/impl/ClientEventDAOImpl.java | 44 +++++++++++++++++++ .../servicelayer/dao/impl/ExamDAOImpl.java | 2 +- .../SEBClientNotificationServiceImpl.java | 14 ++++++ 5 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientNotification.java b/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientNotification.java index 4b33cb27..1da1b8e4 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientNotification.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/model/session/ClientNotification.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import ch.ethz.seb.sebserver.gbl.Constants; +import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.util.Pair; @@ -95,6 +96,11 @@ public class ClientNotification extends ClientEvent { return this.notificationType; } + @Override + public EntityType entityType() { + return EntityType.CLIENT_NOTIFICATION; + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientEventDAO.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientEventDAO.java index f9a38284..c80b28b7 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientEventDAO.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/ClientEventDAO.java @@ -13,6 +13,7 @@ import java.util.List; import java.util.Set; import java.util.function.Predicate; +import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent; import ch.ethz.seb.sebserver.gbl.model.session.ClientNotification; import ch.ethz.seb.sebserver.gbl.model.session.ExtendedClientEvent; @@ -67,4 +68,12 @@ public interface ClientEventDAO extends EntityDAO { * @return Result refer to the confirmed notification or to en error when happened */ Result confirmPendingNotification(Long notificationId); + /** Used to get all client notification identifiers/PKs that are mapped to a specified exam. + * + * @param examId The identifier/PK of the exam + * @return Result refer to a set of client notification identifiers or to an error when happened */ + Result> getNotificationIdsForExam(Long examId); + + Result> deleteClientNotification(Set keys); + } diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientEventDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientEventDAOImpl.java index a13ac8c6..4f45949a 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientEventDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ClientEventDAOImpl.java @@ -204,6 +204,26 @@ public class ClientEventDAOImpl implements ClientEventDAO { .flatMap(ClientEventDAOImpl::toDomainModel); } + @Override + @Transactional(readOnly = true) + public Result> getNotificationIdsForExam(final Long examId) { + return Result.tryCatch(() -> this.clientNotificationRecordMapper + .selectByExample() + .leftJoin(ClientConnectionRecordDynamicSqlSupport.clientConnectionRecord) + .on( + ClientConnectionRecordDynamicSqlSupport.id, + equalTo(ClientNotificationRecordDynamicSqlSupport.clientConnectionId)) + .where( + ClientConnectionRecordDynamicSqlSupport.examId, + isEqualToWhenPresent(examId)) + .build() + .execute() + .stream() + .map(ClientNotificationRecord::getClientConnectionId) + .map(id -> new EntityKey(id, EntityType.CLIENT_NOTIFICATION)) + .collect(Collectors.toSet())); + } + @Override @Transactional(readOnly = true) public Result getPendingNotificationByValue( @@ -377,6 +397,30 @@ public class ClientEventDAOImpl implements ClientEventDAO { }); } + @Override + @Transactional + public Result> deleteClientNotification(final Set keys) { + return Result.tryCatch(() -> { + + final List pks = keys + .stream() + .map(EntityKey::getModelId) + .map(Long::parseLong) + .collect(Collectors.toList()); + + this.clientNotificationRecordMapper + .deleteByExample() + .where(ClientNotificationRecordDynamicSqlSupport.id, isIn(pks)) + .build() + .execute(); + + return pks + .stream() + .map(pk -> new EntityKey(String.valueOf(pk), EntityType.CLIENT_NOTIFICATION)) + .collect(Collectors.toList()); + }); + } + private Result recordById(final Long id) { return Result.tryCatch(() -> { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java index cfe5aad8..2249129b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamDAOImpl.java @@ -451,7 +451,7 @@ public class ExamDAOImpl implements ExamDAO { final List ids = extractListOfPKs(all); - // notify exam deletition listener about following deletion, to cleanup stuff before deletion + // notify exam deletion listener about following deletion, to cleanup stuff before deletion this.applicationEventPublisher.publishEvent(new ExamDeletionEvent(ids)); this.examRecordMapper.deleteByExample() diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientNotificationServiceImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientNotificationServiceImpl.java index 0dbc2d82..21f43e49 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientNotificationServiceImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/session/impl/SEBClientNotificationServiceImpl.java @@ -18,6 +18,7 @@ import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Lazy; +import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import ch.ethz.seb.sebserver.gbl.Constants; @@ -32,6 +33,7 @@ import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.webservice.WebserviceInfo; 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.impl.ExamDeletionEvent; import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientInstructionService; import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientNotificationService; @@ -122,6 +124,18 @@ public class SEBClientNotificationServiceImpl implements SEBClientNotificationSe .onError(error -> log.error("Failed to store new client notification: {}", notification, error)); } + @EventListener(ExamDeletionEvent.class) + public void notifyExamDeletionEvent(final ExamDeletionEvent event) { + // delete all notifications for given exams + event.ids.forEach(id -> this.clientEventDAO.getNotificationIdsForExam(id) + .flatMap(this.clientEventDAO::deleteClientNotification) + .map(deleted -> { + log.debug("Deleted client notifications during exam deletion: {}", deleted); + return deleted; + }) + .onError(error -> log.error("Failed to delete client notifications for exam: {}", id, error))); + } + private ClientNotification notifyNewNotifiaction(final ClientNotification notification) { if (notification.eventType == EventType.NOTIFICATION) { this.pendingNotifications.add(notification.id);