Merge branch 'RED-9573-bp' into 'release/4.73.x'
RED-9517: Use redis for chaching report templates See merge request redactmanager/redaction-report-service!83
This commit is contained in:
commit
f8af6cbc79
@ -14,11 +14,7 @@ public interface ReportTemplateResource {
|
||||
|
||||
String REPORT_TEMPLATE_PATH = "/report-templates";
|
||||
|
||||
String REPORT_TEMPLATE_UPLOAD_PATH = "/upload-template";
|
||||
|
||||
String TEMPLATE_ID = "templateId";
|
||||
|
||||
String TEMPLATE_ID_PATH_VARIABLE = "/template-id/{" + TEMPLATE_ID + "}";
|
||||
String EVICT_REPORT_TEMPLATE_CACHE_PATH = "/evict-report-template-cache";
|
||||
|
||||
String DOSSIER_TEMPLATE_ID = "dossierTemplateId";
|
||||
|
||||
@ -29,7 +25,7 @@ public interface ReportTemplateResource {
|
||||
List<ReportTemplate> getReportTemplatesByPlaceholder(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId, @RequestBody JSONPrimitive<String> placeholder);
|
||||
|
||||
|
||||
@PostMapping(value = REPORT_TEMPLATE_UPLOAD_PATH + TEMPLATE_ID_PATH_VARIABLE)
|
||||
void uploadTemplate(@PathVariable(TEMPLATE_ID) String templateId);
|
||||
@PostMapping(value = EVICT_REPORT_TEMPLATE_CACHE_PATH)
|
||||
void evictReportTemplateCache();
|
||||
|
||||
}
|
||||
|
||||
@ -50,6 +50,9 @@ dependencies {
|
||||
implementation("org.springframework.cloud:spring-cloud-starter-openfeign:4.1.1")
|
||||
implementation("org.apache.commons:commons-lang3:3.12.0")
|
||||
|
||||
implementation("org.springframework.boot:spring-boot-starter-cache:${springBootStarterVersion}")
|
||||
implementation("org.springframework.boot:spring-boot-starter-data-redis:${springBootStarterVersion}")
|
||||
|
||||
implementation("com.github.ben-manes.caffeine:caffeine:3.1.8")
|
||||
|
||||
implementation("net.logstash.logback:logstash-logback-encoder:7.4")
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
package com.iqser.red.service.redaction.report.v1.server.cache;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.cache.RedisCacheConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
|
||||
@Configuration
|
||||
public class RedisCachingConfiguration {
|
||||
|
||||
@Bean
|
||||
public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
|
||||
|
||||
return (builder) -> builder.withCacheConfiguration("reportTemplateCache",
|
||||
RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(30)).disableCachingNullValues());
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
|
||||
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
return template;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.iqser.red.service.redaction.report.v1.server.cache;
|
||||
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ReportTemplateCache {
|
||||
|
||||
private final ReportStorageService reportStorageService;
|
||||
|
||||
@Cacheable(value = "reportTemplateCache")
|
||||
public byte[] getTemplate(String storageId) {
|
||||
|
||||
log.info("Putting report template with storageId {} into cache", storageId);
|
||||
return reportStorageService.getReportTemplate(storageId);
|
||||
}
|
||||
|
||||
|
||||
@CacheEvict(value = "reportTemplateCache", allEntries = true)
|
||||
public void evictReportTemplateCache() {
|
||||
log.info("Evicted cache for report templates");
|
||||
}
|
||||
|
||||
}
|
||||
@ -10,7 +10,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.common.JSON
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.ReportTemplate;
|
||||
import com.iqser.red.service.redaction.report.v1.api.resource.ReportTemplateResource;
|
||||
import com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService;
|
||||
import com.iqser.red.service.redaction.report.v1.server.utils.TemplateCache;
|
||||
import com.iqser.red.service.redaction.report.v1.server.cache.ReportTemplateCache;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
public class ReportTemplateController implements ReportTemplateResource {
|
||||
|
||||
private final PlaceholderService placeholderService;
|
||||
private final ReportTemplateCache reportTemplateCache;
|
||||
|
||||
|
||||
@Override
|
||||
@ -30,15 +31,10 @@ public class ReportTemplateController implements ReportTemplateResource {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If a template with the same id is uploaded we evict it from the cache.
|
||||
*
|
||||
* @param templateId The id for the uploaded template
|
||||
*/
|
||||
@Override
|
||||
public void uploadTemplate(String templateId) {
|
||||
public void evictReportTemplateCache(){
|
||||
|
||||
TemplateCache.evictCache(templateId);
|
||||
reportTemplateCache.evictReportTemplateCache();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEnt
|
||||
import com.iqser.red.service.redaction.report.v1.server.model.ReportTemplatesModel;
|
||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
|
||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageServiceAsyncWrapper;
|
||||
import com.iqser.red.service.redaction.report.v1.server.utils.TemplateCache;
|
||||
import com.iqser.red.service.redaction.report.v1.server.cache.ReportTemplateCache;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -37,6 +37,7 @@ public class ExcelReportTemplateService {
|
||||
ExcelReportGenerationService excelTemplateReportGenerationService;
|
||||
GeneratePlaceholderService generatePlaceholderService;
|
||||
ReportStorageServiceAsyncWrapper reportStorageServiceAsyncWrapper;
|
||||
ReportTemplateCache reportTemplateCache;
|
||||
|
||||
|
||||
public CompletableFuture<StoredFileInformation> createExcelReportFromTemplateAsync(Dossier dossier,
|
||||
@ -47,7 +48,7 @@ public class ExcelReportTemplateService {
|
||||
List<ReportRedactionEntry> reportEntries,
|
||||
ReportTemplate reportTemplate) {
|
||||
|
||||
byte[] excelTemplate = TemplateCache.getTemplate(reportTemplate.getStorageId(), reportStorageService);
|
||||
byte[] excelTemplate = reportTemplateCache.getTemplate(reportTemplate.getStorageId());
|
||||
try (ByteArrayInputStream is = new ByteArrayInputStream(excelTemplate)) {
|
||||
XSSFWorkbook readWorkbook = new XSSFWorkbook(is);
|
||||
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
||||
@ -80,7 +81,7 @@ public class ExcelReportTemplateService {
|
||||
|
||||
public void prepareExcelReportTemplates(String dossierTemplateId, String templateId, ReportTemplate reportTemplate, ReportTemplatesModel reportTemplatesModel) {
|
||||
|
||||
byte[] excelTemplate = TemplateCache.getTemplate(reportTemplate.getStorageId(), reportStorageService);
|
||||
byte[] excelTemplate = reportTemplateCache.getTemplate(reportTemplate.getStorageId());
|
||||
try (ByteArrayInputStream is = new ByteArrayInputStream(excelTemplate)) {
|
||||
XSSFWorkbook readWorkbook = new XSSFWorkbook(is);
|
||||
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
||||
|
||||
@ -7,9 +7,6 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -29,7 +26,6 @@ import com.iqser.red.service.redaction.report.v1.server.model.ReportTemplatesMod
|
||||
import com.iqser.red.service.redaction.report.v1.server.settings.ReportTemplateSettings;
|
||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
|
||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageServiceAsyncWrapper;
|
||||
import com.iqser.red.service.redaction.report.v1.server.utils.TemplateCache;
|
||||
|
||||
import io.micrometer.core.annotation.Timed;
|
||||
import lombok.AccessLevel;
|
||||
|
||||
@ -19,7 +19,7 @@ import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEnt
|
||||
import com.iqser.red.service.redaction.report.v1.server.model.ReportTemplatesModel;
|
||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
|
||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageServiceAsyncWrapper;
|
||||
import com.iqser.red.service.redaction.report.v1.server.utils.TemplateCache;
|
||||
import com.iqser.red.service.redaction.report.v1.server.cache.ReportTemplateCache;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -34,6 +34,7 @@ public class WordReportTemplateService {
|
||||
ReportStorageService reportStorageService;
|
||||
ReportStorageServiceAsyncWrapper reportStorageServiceAsyncWrapper;
|
||||
WordReportGenerationService wordReportGenerationService;
|
||||
ReportTemplateCache reportTemplateCache;
|
||||
|
||||
public CompletableFuture<StoredFileInformation> createWordReportFromTemplateAsync(Dossier dossier,
|
||||
FileModel fileStatus,
|
||||
@ -43,7 +44,7 @@ public class WordReportTemplateService {
|
||||
List<ReportRedactionEntry> reportEntries,
|
||||
ReportTemplate reportTemplate) {
|
||||
|
||||
byte[] wordTemplate = TemplateCache.getTemplate(reportTemplate.getStorageId(), reportStorageService);
|
||||
byte[] wordTemplate = reportTemplateCache.getTemplate(reportTemplate.getStorageId());
|
||||
try (ByteArrayInputStream is = new ByteArrayInputStream(wordTemplate)) {
|
||||
XWPFDocument doc = new XWPFDocument(is);
|
||||
wordReportGenerationService.generateWordReport(reportEntries, placeholderModel, templateName, doc, fileStatus, dossier, true);
|
||||
@ -60,7 +61,7 @@ public class WordReportTemplateService {
|
||||
|
||||
public void prepareWordReportTemplates(String templateId, ReportTemplate reportTemplate, ReportTemplatesModel reportTemplatesModel) {
|
||||
|
||||
byte[] wordTemplate = TemplateCache.getTemplate(reportTemplate.getStorageId(), reportStorageService);
|
||||
byte[] wordTemplate = reportTemplateCache.getTemplate(reportTemplate.getStorageId());
|
||||
try (ByteArrayInputStream is = new ByteArrayInputStream(wordTemplate)) {
|
||||
XWPFDocument doc = new XWPFDocument(is);
|
||||
MultiFileDocument multiFileDocument = new MultiFileDocument(wordTemplate, doc, templateId, reportTemplate.getFileName(), 0, 0);
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
package com.iqser.red.service.redaction.report.v1.server.utils;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* This is a caching mechanism for templates to avoid getting a template from storage for each file when we request a download,
|
||||
* since the templates are provided at startup.
|
||||
*/
|
||||
@Slf4j
|
||||
public class TemplateCache {
|
||||
|
||||
private static final Cache<String, byte[]> cache = Caffeine.newBuilder().maximumSize(500).build();
|
||||
|
||||
|
||||
public static byte[] getTemplate(String templateId, ReportStorageService reportStorageService) {
|
||||
|
||||
return cache.get(templateId, reportStorageService::getReportTemplate);
|
||||
}
|
||||
|
||||
|
||||
public static void evictCache(String templateId) {
|
||||
|
||||
log.info("Evicting cache for template {}", templateId);
|
||||
cache.invalidate(templateId);
|
||||
}
|
||||
|
||||
}
|
||||
@ -38,6 +38,8 @@ spring:
|
||||
max-attempts: 3
|
||||
max-interval: 15000
|
||||
prefetch: 1
|
||||
cache:
|
||||
type: redis
|
||||
data:
|
||||
mongodb:
|
||||
auto-index-creation: true
|
||||
@ -47,7 +49,12 @@ spring:
|
||||
port: ${MONGODB_PORT:27017}
|
||||
username: ${MONGODB_USER}
|
||||
password: ${MONGODB_PASSWORD}
|
||||
|
||||
redis:
|
||||
database: 0
|
||||
host: ${REDIS_HOST:localhost}
|
||||
port: ${REDIS_PORT:6379}
|
||||
password: ${REDIS_PASSWORD}
|
||||
timeout: 60000
|
||||
|
||||
management:
|
||||
endpoint:
|
||||
|
||||
@ -19,7 +19,7 @@ public final class OsUtils {
|
||||
if (isWindows() && StringUtils.isNotBlank(tmpdir)) {
|
||||
return tmpdir;
|
||||
}
|
||||
return "/tmp";
|
||||
return "/tmp/";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@ management:
|
||||
spring:
|
||||
main:
|
||||
allow-circular-references: true
|
||||
cache:
|
||||
type: SIMPLE
|
||||
data:
|
||||
mongodb:
|
||||
auto-index-creation: true
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user