diff --git a/iris-client-bff/src/main/java/iris/client_bff/iris_messages/IrisMessage.java b/iris-client-bff/src/main/java/iris/client_bff/iris_messages/IrisMessage.java index aa158e7c3..09aef8bae 100644 --- a/iris-client-bff/src/main/java/iris/client_bff/iris_messages/IrisMessage.java +++ b/iris-client-bff/src/main/java/iris/client_bff/iris_messages/IrisMessage.java @@ -69,7 +69,7 @@ public class IrisMessage extends Aggregate dataAttachments = new ArrayList<>(); @EqualsAndHashCode(callSuper = false) diff --git a/iris-client-bff/src/main/java/iris/client_bff/iris_messages/IrisMessageDeleteJob.java b/iris-client-bff/src/main/java/iris/client_bff/iris_messages/IrisMessageDeleteJob.java new file mode 100644 index 000000000..ae331b7e6 --- /dev/null +++ b/iris-client-bff/src/main/java/iris/client_bff/iris_messages/IrisMessageDeleteJob.java @@ -0,0 +1,73 @@ +package iris.client_bff.iris_messages; + +import iris.client_bff.iris_messages.IrisMessage.IrisMessageIdentifier; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.time.Duration; +import java.time.Instant; +import java.util.stream.Collectors; + +import javax.transaction.Transactional; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConstructorBinding; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * This class collects all old events and deletes this. + * + * @author Jens Kutzsche + */ +@Component +@Slf4j +@RequiredArgsConstructor +class IrisMessageDeleteJob { + + private final @NonNull IrisMessageRepository messageRepo; + private final @NonNull Properties properties; + + @Transactional + @Scheduled(cron = "${iris.client.message.delete-cron:-}") + void deleteMessages() { + + var refDate = Instant.now().minus(properties.getDeleteAfter()); + + var oldMessages = messageRepo.findByMetadataCreatedIsBefore(refDate).toList(); + + if (oldMessages.isEmpty()) { + return; + } + + log.debug("{} IRIS message(s) are deleted with period {} after their creation!", + oldMessages.size(), + properties.getDeleteAfter(), + oldMessages.get(0).getCreatedAt()); + + messageRepo.deleteAll(oldMessages); + + log.info("{} IRIS message(s) (IDs: {}) were deleted with period {} after their creation at {}!", + oldMessages.size(), + oldMessages.stream() + .map(IrisMessage::getId) + .map(IrisMessageIdentifier::toString) + .collect(Collectors.joining(", ")), + properties.getDeleteAfter(), + oldMessages.get(0).getCreatedAt()); + } + + @ConstructorBinding + @RequiredArgsConstructor + @ConfigurationProperties("iris.client.message") + @Getter + public static class Properties { + + /** + * Defines the {@link Duration} after that a IRIS message will be deleted starting from the creation date. + */ + private final Duration deleteAfter; + } +} diff --git a/iris-client-bff/src/main/java/iris/client_bff/iris_messages/IrisMessageRepository.java b/iris-client-bff/src/main/java/iris/client_bff/iris_messages/IrisMessageRepository.java index bdc9acc0b..4aa2af48c 100644 --- a/iris-client-bff/src/main/java/iris/client_bff/iris_messages/IrisMessageRepository.java +++ b/iris-client-bff/src/main/java/iris/client_bff/iris_messages/IrisMessageRepository.java @@ -1,9 +1,12 @@ package iris.client_bff.iris_messages; +import java.time.Instant; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.util.Streamable; public interface IrisMessageRepository extends JpaRepository { @@ -15,4 +18,11 @@ public interface IrisMessageRepository extends JpaRepository findAllByFolderIdOrderByIsReadAsc(IrisMessageFolder.IrisMessageFolderIdentifier folder, Pageable pageable); + /** + * Returns the {@link IrisMessage}s created before the given {@link Instant}. + * + * @param refDate must not be {@literal null}. + * @return + */ + Streamable findByMetadataCreatedIsBefore(Instant refDate); } diff --git a/iris-client-bff/src/main/resources/application.properties b/iris-client-bff/src/main/resources/application.properties index cc44c411b..b0caa9988 100644 --- a/iris-client-bff/src/main/resources/application.properties +++ b/iris-client-bff/src/main/resources/application.properties @@ -18,6 +18,8 @@ iris.client.vaccinfo.delete-after=6m iris.client.vaccinfo.delete-cron=0 32 1 * * * iris.client.vaccinfo.announcement.delete-after=2h iris.client.vaccinfo.announcement.delete-cron=0 10 * * * * +iris.client.message.delete-after=180d +iris.client.message.delete-cron=0 33 1 * * * iris.client.message.build-recipient-list.delay=900000 iris.client.vaccinfo.expiration-duration=2h diff --git a/iris-client-bff/src/test/java/iris/client_bff/iris_messages/IrisMessageDeleteJobIntegrationTests.java b/iris-client-bff/src/test/java/iris/client_bff/iris_messages/IrisMessageDeleteJobIntegrationTests.java new file mode 100644 index 000000000..2c7d90303 --- /dev/null +++ b/iris-client-bff/src/test/java/iris/client_bff/iris_messages/IrisMessageDeleteJobIntegrationTests.java @@ -0,0 +1,61 @@ +package iris.client_bff.iris_messages; + +import static java.time.Duration.*; +import static org.assertj.core.api.Assertions.*; + +import iris.client_bff.IrisWebIntegrationTest; +import iris.client_bff.core.IrisDateTimeProvider; +import lombok.RequiredArgsConstructor; + +import org.junit.jupiter.api.Test; + +/** + * @author Jens Kutzsche + */ +@IrisWebIntegrationTest +@RequiredArgsConstructor +class IrisMessageDeleteJobIntegrationTests { + + private final IrisMessageRepository messageRepo; + private final IrisMessageDataRepository dataRepo; + private final IrisMessageFolderRepository folderRepo; + private final IrisDateTimeProvider dateTimeProvider; + private final IrisMessageDeleteJob deleteJob; + + @Test + void testDeleteMessages() { + + var messagesSize = messageRepo.findAll().size(); + var dataSize = dataRepo.findAll().size(); + + // in time + dateTimeProvider.setDelta(ofDays(-179)); + + createMessage(); + + // to old + dateTimeProvider.setDelta(ofDays(-181)); + + createMessage(); + + dateTimeProvider.reset(); + + // extra element from data initialization + assertThat(messageRepo.findAll()).hasSize(messagesSize + 2); + assertThat(dataRepo.findAll()).hasSize(dataSize + 2); + + deleteJob.deleteMessages(); + + assertThat(messageRepo.findAll()).hasSize(messagesSize + 1); + assertThat(dataRepo.findAll()).hasSize(dataSize + 1); + } + + private void createMessage() { + + var testData = new IrisMessageTestData(); + + var folder = this.folderRepo.findFirstByContextAndParentFolderIsNull(IrisMessageContext.INBOX).get(); + + messageRepo.save(testData.getTestInboxMessage(folder)); + } +}