Skip to content

Commit

Permalink
Add OpenSearchResponse DTO and refactor search handling in OpenSearch…
Browse files Browse the repository at this point in the history
…Service #deploy-dolly-search-service
  • Loading branch information
krharum committed Feb 20, 2025
1 parent ea8496e commit 2870e08
Show file tree
Hide file tree
Showing 14 changed files with 260 additions and 62 deletions.
1 change: 1 addition & 0 deletions apps/dolly-search-service/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ sonarqube {
}

dependencies {
implementation "no.nav.testnav.libs:data-transfer-objects"
implementation "no.nav.testnav.libs:data-transfer-search-objects"
implementation "no.nav.testnav.libs:reactive-core"
implementation "no.nav.testnav.libs:security-core"
Expand Down
1 change: 1 addition & 0 deletions apps/dolly-search-service/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ rootProject.name = 'dolly-search-service'

includeBuild "../../plugins/java"

includeBuild '../../libs/data-transfer-objects'
includeBuild '../../libs/data-transfer-search-objects'
includeBuild '../../libs/reactive-core'
includeBuild '../../libs/security-core'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@
public class Consumers {

private ServerProperties testnavPdlProxy;

private ServerProperties dollyBackend;
private ServerProperties dollyBackendDev;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package no.nav.testnav.dollysearchservice.consumer;

import no.nav.testnav.dollysearchservice.config.Consumers;
import no.nav.testnav.dollysearchservice.consumer.command.FinnesIDollyGetCommand;
import no.nav.testnav.dollysearchservice.dto.DollyBackendSelector;
import no.nav.testnav.libs.dto.dolly.v1.FinnesDTO;
import no.nav.testnav.libs.securitycore.domain.ServerProperties;
import no.nav.testnav.libs.servletsecurity.exchange.TokenExchange;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.util.Set;

import static no.nav.testnav.dollysearchservice.dto.DollyBackendSelector.REGULAR;

@Service
public class DollyBackendConsumer {

private final WebClient webClient;
private final WebClient webClientDev;
private final TokenExchange tokenExchange;
private final ServerProperties dollyBackendProperties;
private final ServerProperties dollyBackendPropertiesDev;

public DollyBackendConsumer(TokenExchange tokenExchange, Consumers serverProperties,
WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder
.baseUrl(serverProperties.getDollyBackend().getUrl())
.build();
this.webClientDev = webClientBuilder
.baseUrl(serverProperties.getDollyBackendDev().getUrl())
.build();
this.tokenExchange = tokenExchange;
this.dollyBackendProperties = serverProperties.getDollyBackend();
this.dollyBackendPropertiesDev = serverProperties.getDollyBackendDev();
}

public Mono<FinnesDTO> getFinnesInfo(Set<String> identer, DollyBackendSelector selector) {

var properties = selector == REGULAR ? dollyBackendProperties : dollyBackendPropertiesDev;
var client = selector == REGULAR ? webClient : webClientDev;
return tokenExchange.exchange(properties)
.flatMap(token -> new FinnesIDollyGetCommand(client, identer, token.getTokenValue()).call());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import no.nav.testnav.dollysearchservice.config.Consumers;
import no.nav.testnav.dollysearchservice.consumer.command.OpenSearchCommand;
import no.nav.testnav.dollysearchservice.dto.SearchRequest;
import no.nav.testnav.dollysearchservice.dto.SearchResponse;
import no.nav.testnav.dollysearchservice.dto.OpenSearchResponse;
import no.nav.testnav.libs.securitycore.domain.ServerProperties;
import no.nav.testnav.libs.servletsecurity.exchange.TokenExchange;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -39,7 +39,7 @@ public OpenSearchConsumer(
}

@SneakyThrows
public Flux<SearchResponse> search(SearchRequest request) {
public Flux<OpenSearchResponse> search(SearchRequest request) {
return tokenExchange.exchange(serverProperties)
.flatMapMany(token ->
new OpenSearchCommand(webClient, request.getQuery().indices()[0],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package no.nav.testnav.dollysearchservice.consumer.command;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import no.nav.testnav.libs.dto.dolly.v1.FinnesDTO;
import no.nav.testnav.libs.reactivecore.utils.WebClientFilter;
import org.springframework.http.HttpHeaders;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;

import java.time.Duration;
import java.util.Set;
import java.util.concurrent.Callable;

@Slf4j
@RequiredArgsConstructor
public class FinnesIDollyGetCommand implements Callable<Mono<FinnesDTO>> {

private static final String FINNES_URL = "/api/v1/ident/finnes";
private static final String IDENTER = "identer";

private final WebClient webClient;
private final Set<String> identer;
private final String token;

public Mono<FinnesDTO> call() {

return webClient
.get()
.uri(uriBuilder -> uriBuilder
.path(FINNES_URL)
.queryParam(IDENTER, identer)
.build())
.header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
.retrieve()
.bodyToMono(FinnesDTO.class)
.retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
.filter(WebClientFilter::is5xxException));
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package no.nav.testnav.dollysearchservice.consumer.command;

import lombok.RequiredArgsConstructor;
import no.nav.testnav.dollysearchservice.dto.SearchResponse;
import no.nav.testnav.dollysearchservice.dto.OpenSearchResponse;
import no.nav.testnav.libs.reactivecore.utils.WebClientFilter;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
Expand All @@ -17,7 +17,7 @@


@RequiredArgsConstructor
public class OpenSearchCommand implements Callable<Mono<SearchResponse>> {
public class OpenSearchCommand implements Callable<Mono<OpenSearchResponse>> {

private static final String SEARCH_URL = "/pdl-elastic/{index}/_search";

Expand All @@ -27,7 +27,7 @@ public class OpenSearchCommand implements Callable<Mono<SearchResponse>> {
private final Object body;

@Override
public Mono<SearchResponse> call() {
public Mono<OpenSearchResponse> call() {

return webClient.post()
.uri(uriBuilder -> uriBuilder
Expand All @@ -37,10 +37,10 @@ public Mono<SearchResponse> call() {
.header(AUTHORIZATION, "Bearer " + token)
.body(BodyInserters.fromValue(body))
.retrieve()
.bodyToMono(SearchResponse.class)
.bodyToMono(OpenSearchResponse.class)
.retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
.filter(WebClientFilter::is5xxException))
.onErrorResume(throwable -> Mono.just(SearchResponse.builder()
.onErrorResume(throwable -> Mono.just(OpenSearchResponse.builder()
.status(WebClientFilter.getStatus(throwable))
.error(WebClientFilter.getMessage(throwable))
.build()));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package no.nav.testnav.dollysearchservice.dto;

public enum DollyBackendSelector {
REGULAR,
DEV
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package no.nav.testnav.dollysearchservice.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import no.nav.testnav.libs.data.dollysearchservice.v1.SearchRequest;
import org.springframework.http.HttpStatus;

import java.util.List;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OpenSearchResponse {

private SearchRequest request;

private Integer took;
private Boolean timedOut;
private SearchHits hits;

private HttpStatus status;
private String error;

@Data
@NoArgsConstructor
@AllArgsConstructor
public static class SearchHits {

private Total total;
private float maxScore;
private List<SearchHit> hits;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Total {

private Long value;
private String relation;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
@SuppressWarnings("java:S116")
public static class SearchHit {

private String _index;
private String _type;
private String _id;
private Double _score;
private Object _source;
}
}
Original file line number Diff line number Diff line change
@@ -1,58 +1,24 @@
package no.nav.testnav.dollysearchservice.dto;

import com.fasterxml.jackson.databind.JsonNode;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import no.nav.testnav.libs.data.dollysearchservice.v1.SearchRequest;
import org.springframework.http.HttpStatus;

import java.util.List;
import java.util.Map;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SearchResponse {

private SearchRequest request;

private Integer took;
private Boolean timedOut;
private SearchHits hits;

private HttpStatus status;
private Long totalHits;
private String took;
private Integer side;
private Integer antall;
private Integer seed;
private Map<String, JsonNode> personer;
private String error;

@Data
@NoArgsConstructor
@AllArgsConstructor
public static class SearchHits {

private Total total;
private float maxScore;
private List<SearchHit> hits;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Total {

private Long value;
private String relation;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
@SuppressWarnings("java:S116")
public static class SearchHit {

private String _index;
private String _type;
private String _id;
private Double _score;
private Object _source;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
package no.nav.testnav.dollysearchservice.provider;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import no.nav.testnav.dollysearchservice.service.OpenSearchService;
import no.nav.testnav.libs.data.dollysearchservice.v1.SearchRequest;
import no.nav.testnav.libs.data.dollysearchservice.v1.SearchResponse;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import java.util.Map;

import static no.nav.testnav.dollysearchservice.dto.DollyBackendSelector.DEV;
import static no.nav.testnav.dollysearchservice.dto.DollyBackendSelector.REGULAR;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

@Slf4j
@RestController
@RequestMapping("/api/v1/opensearch")
@RequiredArgsConstructor
Expand All @@ -20,8 +31,17 @@ public class OpensearchController {

@PostMapping
@Operation(description = "Henter personer som matcher søk av persondetaljer i request")
public Mono<SearchResponse> getIdenterMed(@RequestBody SearchRequest request) {
public Mono<SearchResponse> getIdenterMed(@RequestHeader Map<String, String> headers,
@Schema(description = "Ikke filtrer søkeresultat for " +
"eksisterende personer (default er filtrering)")
@RequestParam(required = false) Boolean ikkeFiltrer,
@RequestBody SearchRequest request) {

var kallendeApp = isNotBlank(headers.get("Origin")) ? headers.get("Origin") : headers.get("origin");
log.info("Kallende applikasjon: {}", kallendeApp);

var selector = kallendeApp.contains("ekstern") ? REGULAR : DEV;

return openSearchService.search(request);
return openSearchService.search(request, selector, ikkeFiltrer);
}
}
Loading

0 comments on commit 2870e08

Please sign in to comment.