Skip to content

Commit

Permalink
[CHORE] Simple caching
Browse files Browse the repository at this point in the history
  • Loading branch information
Luke Sikina committed Nov 1, 2024
1 parent 1dd78ac commit 5fca24b
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 2 deletions.
10 changes: 10 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@
<artifactId>spring-data-commons</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>

<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.8</version>
</dependency>

<dependency>
<groupId>org.postgresql</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class DictionaryApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import edu.harvard.dbmi.avillach.dictionary.concept.model.ContinuousConcept;
import edu.harvard.dbmi.avillach.dictionary.filter.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

Expand All @@ -26,6 +27,7 @@ public ConceptService(ConceptRepository conceptRepository, ConceptDecoratorServi
this.conceptDecoratorService = conceptDecoratorService;
}

@Cacheable("concepts")
public List<Concept> listConcepts(Filter filter, Pageable page) {
return conceptRepository.getConcepts(filter, page);
}
Expand All @@ -40,6 +42,7 @@ public List<Concept> listDetailedConcepts(Filter filter, Pageable page) {
}).toList();
}

@Cacheable("concepts_count")
public long countConcepts(Filter filter) {
return conceptRepository.countConcepts(filter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import edu.harvard.dbmi.avillach.dictionary.filter.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
Expand All @@ -17,6 +18,7 @@ public FacetService(FacetRepository repository) {
this.repository = repository;
}

@Cacheable("facets")
public List<FacetCategory> getFacets(Filter filter) {
return repository.getFacets(filter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;

@ControllerAdvice
public class FilterPreProcessor implements RequestBodyAdvice {
Expand All @@ -30,8 +34,23 @@ public Object afterBodyRead(
Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType
) {
if (body instanceof Filter filter && StringUtils.hasLength(filter.search())) {
return new Filter(filter.facets(), filter.search().replaceAll("_", "/"), filter.consents());
if (body instanceof Filter filter) {
List<Facet> newFacets = filter.facets();
List<String> newConsents = filter.consents();
if (filter.facets() != null) {
newFacets = new ArrayList<>(filter.facets());
newFacets.sort(Comparator.comparing(Facet::name));
}
if (filter.consents() != null) {
newConsents = new ArrayList<>(newConsents);
newConsents.sort(Comparator.comparing(Function.identity()));
}
filter = new Filter(newFacets, filter.search(), newConsents);

if (StringUtils.hasLength(filter.search())) {
filter = new Filter(filter.facets(), filter.search().replaceAll("_", "/"), filter.consents());
}
return filter;
}
return body;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package edu.harvard.dbmi.avillach.dictionary.util;

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

@Configuration
public class CacheConfig {
@Bean
public Caffeine caffeineConfig() {
return Caffeine.newBuilder().expireAfterAccess(15, TimeUnit.MINUTES).maximumSize(5000);
}

@Bean
public CacheManager cacheManager(Caffeine caffeine) {
CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
caffeineCacheManager.setCaffeine(caffeine);
return caffeineCacheManager;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ class ConceptServiceTest {
@Autowired
ConceptService subject;

@Test
void shouldCacheConcepts() {
List<Concept> concepts = List.of(new CategoricalConcept("Path", "DS"));
Filter filter = new Filter(List.of(), "", List.of());
Pageable pageable = Pageable.ofSize(10);
Mockito.when(repository.getConcepts(filter, pageable)).thenReturn(concepts);

subject.listConcepts(filter, pageable);
subject.listConcepts(filter, pageable);
Mockito.verify(repository, Mockito.times(1)).getConcepts(filter, pageable);
}

@Test
void shouldListConcepts() {
List<Concept> expected = List.of(new CategoricalConcept("A", "a", "A", "invalid.invalid", null, List.of(), true, "", null, null));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ class FilterPreProcessorTest {
@Autowired
private FilterPreProcessor subject;

@Test
void shouldSortFilter() {
Filter filter = new Filter(List.of(new Facet("b", ""), new Facet("a", "")), "", List.of("c", "b", "a"));
Filter actual = (Filter) subject.afterBodyRead(
filter, Mockito.mock(HttpInputMessage.class), Mockito.mock(MethodParameter.class), SimpleType.constructUnsafe(Filter.class),
null
);

Filter expected = new Filter(List.of(new Facet("a", ""), new Facet("b", "")), "", List.of("a", "b", "c"));
Assertions.assertEquals(expected, actual);

}

@Test
void shouldProcessFilter() {
Object processedFilter = subject.afterBodyRead(
Expand Down

0 comments on commit 5fca24b

Please sign in to comment.