Skip to content

Commit

Permalink
test(search): fallback to simple fulltext search on empty results
Browse files Browse the repository at this point in the history
  • Loading branch information
Stefan committed Apr 7, 2024
1 parent 950f626 commit d72c6aa
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.github.binpastes.paste.api;

import com.github.binpastes.paste.api.model.CreateCmd;
import com.github.binpastes.paste.api.model.DetailView;
import com.github.binpastes.paste.api.model.ListView;
import com.github.binpastes.paste.api.model.SearchView;
import com.github.binpastes.paste.api.model.SearchView.SearchItemView;
import com.github.binpastes.paste.api.model.DetailView;
import com.github.binpastes.paste.application.PasteService;
import com.github.binpastes.paste.domain.Paste;
import jakarta.validation.ConstraintViolationException;
Expand All @@ -24,6 +24,8 @@
import org.springframework.web.server.ResponseStatusException;
import reactor.core.publisher.Mono;

import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -91,7 +93,7 @@ public Mono<SearchView> searchPastes(
) {
response.getHeaders().setCacheControl(CacheControl.maxAge(60, TimeUnit.SECONDS));
return pasteService
.findByFullText(term)
.findByFullText(URLDecoder.decode(term, Charset.defaultCharset()))
.map(paste -> SearchItemView.of(paste, term))
.collectList()
.map(SearchView::of);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.github.binpastes.paste.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.stereotype.Component;
Expand All @@ -13,15 +12,14 @@
import static com.github.binpastes.paste.domain.Paste.PasteExposure;
import static com.github.binpastes.paste.domain.Paste.PasteSchema;

@Primary
@Profile("mysql")
@Component
class MySqlFullTextSupportImpl implements FullTextSearchSupport {
class MySqlFullTextSupport implements FullTextSearchSupport {

private final R2dbcEntityTemplate entityTemplate;

@Autowired
public MySqlFullTextSupportImpl(final R2dbcEntityTemplate entityTemplate) {
public MySqlFullTextSupport(final R2dbcEntityTemplate entityTemplate) {
this.entityTemplate = entityTemplate;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
package com.github.binpastes.paste.domain;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Sort;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.data.relational.core.query.Query;
import org.springframework.data.relational.core.query.Update;
import org.springframework.util.Assert;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.List;

import static com.github.binpastes.paste.domain.Paste.PasteExposure;
import static com.github.binpastes.paste.domain.Paste.PasteSchema;
import static org.springframework.data.relational.core.query.Query.query;

class PasteRepositoryCustomImpl implements PasteRepositoryCustom {

private static final Logger log = LoggerFactory.getLogger(PasteRepository.class);

private final R2dbcEntityTemplate entityTemplate;

private final FullTextSearchSupport fullTextSearchSupport;
private final List<FullTextSearchSupport> fullTextSearchSupport;

public PasteRepositoryCustomImpl(R2dbcEntityTemplate entityManager, FullTextSearchSupport fullTextSearchSupport) {
public PasteRepositoryCustomImpl(R2dbcEntityTemplate entityManager, List<FullTextSearchSupport> fullTextSearchSupport) {
Assert.isTrue(fullTextSearchSupport.size() <= 2, "Expected at most two FullTextSearchSupport implementations"); // ugly, but works for now
this.entityTemplate = entityManager;
this.fullTextSearchSupport = fullTextSearchSupport;
}
Expand Down Expand Up @@ -72,7 +79,15 @@ public Mono<Long> markExpiredPastesForDeletion() {

@Override
public Flux<Paste> searchAllLegitByFullText(String text) {
return fullTextSearchSupport.searchByFullText(text);
var flux = fullTextSearchSupport.getFirst().searchByFullText(text);

return fullTextSearchSupport.size() == 1
? flux
: flux.switchIfEmpty(subscriber -> {
log.warn("Fulltext search found nothing for: {}", text);
fullTextSearchSupport.getLast()
.searchByFullText(text)
.subscribe(subscriber);
});
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.binpastes.paste.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.domain.Sort;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.data.relational.core.query.Criteria;
Expand All @@ -14,12 +15,13 @@
import static com.github.binpastes.paste.domain.Paste.PasteSchema;

@Component
class SimpleFullTextSupportImpl implements FullTextSearchSupport {
@Order
class SimpleFullTextSupport implements FullTextSearchSupport {

private final R2dbcEntityTemplate entityTemplate;

@Autowired
public SimpleFullTextSupportImpl(final R2dbcEntityTemplate entityTemplate) {
public SimpleFullTextSupport(final R2dbcEntityTemplate entityTemplate) {
this.entityTemplate = entityTemplate;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
import static org.junit.jupiter.api.Named.named;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;

@WebFluxTest
class PasteControllerTest {
Expand All @@ -33,15 +35,15 @@ class PasteControllerTest {
@MockBean
private PasteService pasteService;

private static final String somePasteId = "4711471147114711471147114711471147114711";
private static final String samplePasteId = "47116941fd49eda1b6c8abec63dbf8afe2fad088";

@Test
@DisplayName("GET /{pasteId} - 404 on unknown paste, no caching")
void findUnknownPaste() {
doReturn(Mono.empty()).when(pasteService).find(anyString());

webClient.get()
.uri("/api/v1/paste/" + somePasteId)
.uri("/api/v1/paste/" + samplePasteId)
.exchange()
.expectStatus().isNotFound()
.expectHeader().cacheControl(CacheControl.empty());
Expand Down Expand Up @@ -72,11 +74,26 @@ void searchPastes() {
.expectBody().jsonPath("pastes", emptyList());
}

@Test
@DisplayName("GET /search - decode term parameter")
void searchPastesDecodesParameter() {
doReturn(Flux.empty()).when(pasteService).findByFullText(anyString());

webClient.get()
.uri("/api/v1/paste/search?term={term}", "%3A-)")
.exchange()
.expectStatus().isOk()
.expectHeader().cacheControl(CacheControl.maxAge(1, TimeUnit.MINUTES))
.expectBody().jsonPath("pastes", emptyList());

verify(pasteService).findByFullText(eq(":-)"));
}

@Test
@DisplayName("DELETE /{pasteId} - always return 204")
void deletePaste() {
webClient.delete()
.uri("/api/v1/paste/" + somePasteId)
.uri("/api/v1/paste/" + samplePasteId)
.exchange()
.expectStatus().isNoContent()
.expectBody().isEmpty();
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/Spinner/spinner.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
position: relative;
width: 80px;
height: 80px;
margin: 0 2rem;
}
.lds-ellipsis div {
background: var(--color-text);
Expand Down

0 comments on commit d72c6aa

Please sign in to comment.