RED-3036-As an admin I would like to adjust the softDeleteCleanupTime

- first implementation
- junit added
This commit is contained in:
devplant 2022-04-29 15:16:43 +03:00
parent 2caa4704a3
commit 9f2d8edce9
15 changed files with 241 additions and 19 deletions

View File

@ -0,0 +1,17 @@
package com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.configuration;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ApplicationConfig {
private int downloadCleanupDownloadFilesHours;
private int downloadCleanupNotDownloadFilesHours;
private int softDeleteCleanupTime;
}

View File

@ -0,0 +1,23 @@
package com.iqser.red.service.persistence.service.v1.api.resources;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.configuration.ApplicationConfig;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.OK)
public interface ApplicationConfigurationResource {
String APPLICATION_CONFIG_PATH = "/app-config";
@ResponseStatus(value = HttpStatus.CREATED)
@PostMapping(value = APPLICATION_CONFIG_PATH, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
ApplicationConfig createOrUpdateAppConfig(@RequestBody ApplicationConfig appConfig);
@ResponseStatus(value = HttpStatus.OK)
@GetMapping(value = APPLICATION_CONFIG_PATH, produces = MediaType.APPLICATION_JSON_VALUE)
ApplicationConfig getCurrentApplicationConfig();
}

View File

@ -0,0 +1,34 @@
package com.iqser.red.service.persistence.management.v1.processor.entity.configuration;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Data
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "application_configuration")
public class ApplicationConfigurationEntity {
public final static String ID = "APPLICATION_CONFIG_ID";
@Id
private final String id = ApplicationConfigurationEntity.ID;
@Column
private int downloadCleanupDownloadFilesHours = 8;
@Column
private int downloadCleanupNotDownloadFilesHours = 72;
@Column
private int softDeleteCleanupTime = 96;
}

View File

@ -0,0 +1,25 @@
package com.iqser.red.service.persistence.management.v1.processor.service;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.ApplicationConfigurationEntity;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.ApplicationConfigRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@RequiredArgsConstructor
public class ApplicationConfigService {
private final ApplicationConfigRepository applicationConfigRepository;
public ApplicationConfigurationEntity getApplicationConfig() {
return applicationConfigRepository.findById(ApplicationConfigurationEntity.ID)
.orElseThrow(() -> new NotFoundException("Application Configuration not found"));
}
public ApplicationConfigurationEntity saveApplicationConfiguration(ApplicationConfigurationEntity appConfig) {
return applicationConfigRepository.save(appConfig);
}
}

View File

@ -0,0 +1,7 @@
package com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.ApplicationConfigurationEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ApplicationConfigRepository extends JpaRepository<ApplicationConfigurationEntity, String> {
}

View File

@ -0,0 +1,32 @@
package com.iqser.red.service.peristence.v1.server.controller;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.ApplicationConfigurationEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.configuration.WatermarkEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.ApplicationConfigService;
import com.iqser.red.service.persistence.management.v1.processor.service.WatermarkService;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.configuration.ApplicationConfig;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.configuration.Watermark;
import com.iqser.red.service.persistence.service.v1.api.resources.ApplicationConfigurationResource;
import com.iqser.red.service.persistence.service.v1.api.resources.WatermarkResource;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import static com.iqser.red.service.persistence.management.v1.processor.utils.MagicConverter.convert;
@RestController
@RequiredArgsConstructor
public class ApplicationConfigurationController implements ApplicationConfigurationResource {
private final ApplicationConfigService applicationConfigService;
public ApplicationConfig createOrUpdateAppConfig(@RequestBody ApplicationConfig appConfig) {
return convert(applicationConfigService.saveApplicationConfiguration(convert(appConfig, ApplicationConfigurationEntity.class)), ApplicationConfig.class);
}
public ApplicationConfig getCurrentApplicationConfig() {
return convert(applicationConfigService.getApplicationConfig(), ApplicationConfig.class);
}
}

View File

@ -3,6 +3,7 @@ package com.iqser.red.service.peristence.v1.server.service.job;
import java.time.OffsetDateTime;
import java.util.List;
import com.iqser.red.service.persistence.management.v1.processor.service.ApplicationConfigService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.stereotype.Service;
@ -10,7 +11,6 @@ import org.springframework.stereotype.Service;
import com.iqser.red.service.peristence.v1.server.service.DossierService;
import com.iqser.red.service.peristence.v1.server.service.FileService;
import com.iqser.red.service.peristence.v1.server.service.FileStatusService;
import com.iqser.red.service.peristence.v1.server.settings.FileManagementServiceSettings;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
import lombok.RequiredArgsConstructor;
@ -24,7 +24,7 @@ public class DeletedFilesCleanupJob implements Job {
private final DossierService dossierService;
private final FileStatusService fileStatusService;
private final FileService fileService;
private final FileManagementServiceSettings settings;
private final ApplicationConfigService applicationConfigService;
@Override
@ -32,10 +32,11 @@ public class DeletedFilesCleanupJob implements Job {
var now = OffsetDateTime.now();
List<DossierEntity> dossiers = dossierService.getAllDossiers();
var applicationConfigurationEntity = applicationConfigService.getApplicationConfig();
for (DossierEntity dossierEntity : dossiers) {
if (dossierEntity.getSoftDeletedTime() != null && dossierEntity.getHardDeletedTime() == null) {
if (dossierEntity.getSoftDeletedTime().isBefore(now.minusHours(settings.getSoftDeleteCleanupTime()))) {
if (dossierEntity.getSoftDeletedTime().isBefore(now.minusHours(applicationConfigurationEntity.getSoftDeleteCleanupTime()))) {
dossierService.hardDeleteDossier(dossierEntity.getId());
log.info("Hard deleted dossier with dossier id {} ", dossierEntity.getId());
}
@ -43,7 +44,7 @@ public class DeletedFilesCleanupJob implements Job {
var files = fileStatusService.getDossierStatus(dossierEntity.getId());
for (var file : files) {
if (file.getHardDeletedTime() == null && file.getDeleted() != null && file.getDeleted()
.isBefore(now.minusHours(settings.getSoftDeleteCleanupTime()))) {
.isBefore(now.minusHours(applicationConfigurationEntity.getSoftDeleteCleanupTime()))) {
fileService.hardDeleteFile(dossierEntity.getId(), file.getId());
fileStatusService.setFileStatusHardDeleted(file.getId());
log.info("Hard deleted file with dossier id {} and file id {}", dossierEntity.getId(), file.getId());

View File

@ -1,8 +1,8 @@
package com.iqser.red.service.peristence.v1.server.service.job;
import com.iqser.red.service.peristence.v1.server.service.DossierService;
import com.iqser.red.service.peristence.v1.server.settings.FileManagementServiceSettings;
import com.iqser.red.service.persistence.management.v1.processor.entity.download.DownloadStatusEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.ApplicationConfigService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DownloadStatusPersistenceService;
import com.iqser.red.storage.commons.service.StorageService;
import lombok.RequiredArgsConstructor;
@ -22,8 +22,8 @@ public class DownloadCleanupJob implements Job {
private final DownloadStatusPersistenceService downloadStatusPersistenceService;
private final StorageService storageService;
private final FileManagementServiceSettings settings;
private final DossierService dossierService;
private final ApplicationConfigService applicationConfigService;
@Override
public void execute(JobExecutionContext jobExecutionContext) {
@ -34,20 +34,20 @@ public class DownloadCleanupJob implements Job {
downloadStatusList.forEach(downloadStatus -> {
var dossier = downloadStatus.getDossier();
var applicationConfigurationEntity = applicationConfigService.getApplicationConfig();
if (downloadStatus.getLastDownload() != null && downloadStatus.getLastDownload()
.plusHours(settings.getDownloadCleanupDownloadFilesHours())
.plusHours(applicationConfigurationEntity.getDownloadCleanupDownloadFilesHours())
.isBefore(now)) {
log.info("1. Deleting download status {} because DownloadCleanupDownloadFilesHours is {} and c+h {} is after {}", downloadStatus, settings
.getDownloadCleanupDownloadFilesHours(), downloadStatus.getCreationDate()
.plusHours(settings.getDownloadCleanupDownloadFilesHours()), now);
log.info("1. Deleting download status {} because DownloadCleanupDownloadFilesHours is {} and c+h {} is after {}", downloadStatus,
applicationConfigurationEntity.getDownloadCleanupDownloadFilesHours(), downloadStatus.getCreationDate()
.plusHours(applicationConfigurationEntity.getDownloadCleanupDownloadFilesHours()), now);
deleteDownload(downloadStatus);
} else if (downloadStatus.getLastDownload() == null && downloadStatus.getCreationDate()
.plusHours(settings.getDownloadCleanupNotDownloadFilesHours())
.plusHours(applicationConfigurationEntity.getDownloadCleanupNotDownloadFilesHours())
.isBefore(now)) {
log.info("2. Deleting download status {} because DownloadCleanupNotDownloadFilesHours is {} and c+h {} is after {}", downloadStatus, settings
.getDownloadCleanupNotDownloadFilesHours(), downloadStatus.getCreationDate()
.plusHours(settings.getDownloadCleanupNotDownloadFilesHours()), now);
log.info("2. Deleting download status {} because DownloadCleanupNotDownloadFilesHours is {} and c+h {} is after {}", downloadStatus,
applicationConfigurationEntity.getDownloadCleanupNotDownloadFilesHours(), downloadStatus.getCreationDate()
.plusHours(applicationConfigurationEntity.getDownloadCleanupNotDownloadFilesHours()), now);
deleteDownload(downloadStatus);
} else if (dossierService.getDossierById(dossier.getId()).getSoftDeletedTime() != null) {
log.info("3. Deleting download {}, because dossier does not exist", downloadStatus.getStorageId());

View File

@ -16,10 +16,10 @@ public class FileManagementServiceSettings {
private int maxRetryAttempts = 20;
private int downloadCleanupFetchLimit = 200;
private int downloadCleanupDownloadFilesHours = 8;
private int downloadCleanupNotDownloadFilesHours = 72;
private int softDeleteCleanupTime = 96;
// private int downloadCleanupDownloadFilesHours = 8;
// private int downloadCleanupNotDownloadFilesHours = 72;
//
// private int softDeleteCleanupTime = 96;
private boolean imageServiceEnabled = true;
private boolean nerServiceEnabled = true;

View File

@ -0,0 +1,25 @@
databaseChangeLog:
- changeSet:
id: application-config-table
author: corina (generated)
changes:
- createTable:
columns:
- column:
constraints:
nullable: false
primaryKey: true
primaryKeyName: application_configuration_pkey
name: id
type: VARCHAR(255)
- column:
name: download_cleanup_download_files_hours
type: INTEGER
- column:
name: download_cleanup_not_download_files_hours
type: INTEGER
- column:
name: soft_delete_cleanup_time
type: INTEGER
tableName: application_configuration

View File

@ -61,3 +61,7 @@ databaseChangeLog:
file: db/changelog/24-add-unique-constraint-for-dictionary.yaml
- include:
file: db/changelog/25-add-index-to-dictionary-entry-tables.yaml
- include:
file: db/changelog/26-application-config-table.changelog.yaml
- include:
file: db/changelog/sql/26-initiliaze-application-configuration-table.sql

View File

@ -0,0 +1,2 @@
insert into application_configuration (id, download_cleanup_download_files_hours, download_cleanup_not_download_files_hours, soft_delete_cleanup_time)
values ('APPLICATION_CONFIG_ID', 8, 72, 96);

View File

@ -0,0 +1,8 @@
package com.iqser.red.service.peristence.v1.server.integration.client;
import com.iqser.red.service.persistence.service.v1.api.resources.ApplicationConfigurationResource;
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient(name = "ApplicationConfigClient", url = "http://localhost:${server.port}")
public interface ApplicationConfigClient extends ApplicationConfigurationResource {
}

View File

@ -0,0 +1,40 @@
package com.iqser.red.service.peristence.v1.server.integration.tests;
import com.iqser.red.service.peristence.v1.server.integration.client.ApplicationConfigClient;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.configuration.ApplicationConfig;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import static org.assertj.core.api.Assertions.assertThat;
public class ApplicationConfigTest extends AbstractPersistenceServerServiceTest {
@Autowired
private ApplicationConfigClient appConfigClient;
@Test
public void testAppConfig() {
ApplicationConfig appConfig = new ApplicationConfig().builder()
.downloadCleanupDownloadFilesHours(8).downloadCleanupNotDownloadFilesHours(72).softDeleteCleanupTime(96).build();
var result = appConfigClient.createOrUpdateAppConfig(appConfig);
assertThat(result.getSoftDeleteCleanupTime()).isEqualTo(appConfig.getSoftDeleteCleanupTime());
assertThat(result.getDownloadCleanupDownloadFilesHours()).isEqualTo(appConfig.getDownloadCleanupDownloadFilesHours());
assertThat(result.getDownloadCleanupNotDownloadFilesHours()).isEqualTo(appConfig.getDownloadCleanupNotDownloadFilesHours());
var getResult = appConfigClient.getCurrentApplicationConfig();
assertThat(getResult.getSoftDeleteCleanupTime()).isEqualTo(appConfig.getSoftDeleteCleanupTime());
assertThat(getResult.getDownloadCleanupDownloadFilesHours()).isEqualTo(appConfig.getDownloadCleanupDownloadFilesHours());
assertThat(getResult.getDownloadCleanupNotDownloadFilesHours()).isEqualTo(appConfig.getDownloadCleanupNotDownloadFilesHours());
appConfig.setDownloadCleanupDownloadFilesHours(16);
appConfig.setDownloadCleanupNotDownloadFilesHours(80);
appConfig.setSoftDeleteCleanupTime(100);
appConfigClient.createOrUpdateAppConfig(appConfig);
getResult = appConfigClient.getCurrentApplicationConfig();
assertThat(getResult.getSoftDeleteCleanupTime()).isEqualTo(appConfig.getSoftDeleteCleanupTime());
assertThat(getResult.getDownloadCleanupDownloadFilesHours()).isEqualTo(appConfig.getDownloadCleanupDownloadFilesHours());
assertThat(getResult.getDownloadCleanupNotDownloadFilesHours()).isEqualTo(appConfig.getDownloadCleanupNotDownloadFilesHours());
}
}

View File

@ -134,6 +134,9 @@ public abstract class AbstractPersistenceServerServiceTest {
@Autowired
protected FalseRecommendationEntryRepository falseRecommendationEntryRepository;
@Autowired
protected ApplicationConfigRepository applicationConfigRepository;
@Before
public void setupOptimize() {
@ -211,6 +214,7 @@ public abstract class AbstractPersistenceServerServiceTest {
dossierTemplateRepository.deleteAll();
notificationPreferencesRepository.deleteAll();
indexInformationRepository.deleteAll();
applicationConfigRepository.deleteAll();
}
static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {