Skip to content

Commit

Permalink
Refactor ImportService and update reactive dependencies #deploy-organ…
Browse files Browse the repository at this point in the history
…isasjon-forvalter

Simplified `ImportService` logic by removing redundant methods and using reactive streams. Replaced `commands` library with `reactive-core` to enhance error handling and logging across services. Updated `GenererNavnServiceConsumer` and related classes to improve efficiency with non-blocking calls.
  • Loading branch information
krharum committed Sep 11, 2024
1 parent 1999387 commit 141634f
Show file tree
Hide file tree
Showing 15 changed files with 121 additions and 266 deletions.
2 changes: 1 addition & 1 deletion apps/organisasjon-forvalter/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ dependencies {
implementation 'no.nav.testnav.libs:security-core'
implementation 'no.nav.testnav.libs:database'
implementation 'no.nav.testnav.libs:servlet-security'
implementation 'no.nav.testnav.libs:commands'
implementation 'no.nav.testnav.libs:reactive-core'
implementation 'no.nav.testnav.libs:data-transfer-objects'

implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
Expand Down
2 changes: 1 addition & 1 deletion apps/organisasjon-forvalter/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ rootProject.name = 'organisasjon-forvalter'
includeBuild "../../plugins/java"

includeBuild '../../libs/avro-schema'
includeBuild '../../libs/commands'
includeBuild '../../libs/data-transfer-objects'
includeBuild '../../libs/database'
includeBuild '../../libs/kafka-config'
includeBuild '../../libs/kafka-producers'
includeBuild '../../libs/security-core'
includeBuild '../../libs/servlet-core'
includeBuild '../../libs/reactive-core'
includeBuild '../../libs/servlet-security'
includeBuild '../../libs/testing'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,16 @@

import lombok.extern.slf4j.Slf4j;
import no.nav.organisasjonforvalter.config.Consumers;
import no.nav.testnav.libs.commands.generernavnservice.v1.GenererNavnCommand;
import no.nav.organisasjonforvalter.consumer.command.GenererNavnCommand;
import no.nav.testnav.libs.securitycore.domain.ServerProperties;
import no.nav.testnav.libs.servletsecurity.exchange.TokenExchange;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static java.lang.String.format;
import static java.lang.System.currentTimeMillis;
import static java.util.Objects.requireNonNull;

@Slf4j
@Service
Expand All @@ -40,30 +34,16 @@ public GenererNavnServiceConsumer(

public List<String> getOrgName(Integer antall) {

long startTime = currentTimeMillis();
try {
var accessToken = tokenExchange.exchange(serverProperties);
var navn = new GenererNavnCommand(webClient, accessToken.block().getTokenValue(), antall).call();

log.info("Generer-navn-service svarte etter {} ms", currentTimeMillis() - startTime);
return Arrays.stream(navn)
.map(value -> format("%s %s", value.getAdjektiv(), value.getSubstantiv()))
.collect(Collectors.toList());

} catch (WebClientResponseException e) {
log.error(e.getMessage(), e);
throw new HttpClientErrorException(e.getStatusCode(), requireNonNull(e.getMessage()));

} catch (RuntimeException e) {

log.error(e.getMessage(), e);
throw new HttpClientErrorException(HttpStatus.GATEWAY_TIMEOUT, e.getMessage());
}
return tokenExchange.exchange(serverProperties)
.flatMapMany(token -> new GenererNavnCommand(webClient, antall, token.getTokenValue()).call())
.map(value -> format("%s %s", value.getAdjektiv(), value.getSubstantiv()))
.collect(Collectors.toList())
.block();
}

public String getOrgName() {

List<String> orgName = getOrgName(1);
return orgName.isEmpty() ? null : orgName.get(0);
return orgName.isEmpty() ? null : orgName.getFirst();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
Expand All @@ -33,7 +34,6 @@ public MiljoerServiceConsumer(
this.tokenExchange = tokenExchange;
}

// @Cacheable(CACHE_MILJOER)
public Set<String> getOrgMiljoer() {

return tokenExchange.exchange(serverProperties)
Expand All @@ -43,6 +43,7 @@ public Set<String> getOrgMiljoer() {
.filter(env -> !env.equals("t13") && !env.equals("qx"))
.collect(Collectors.toSet()))
.flatMap(Mono::from)
.cache(Duration.ofMinutes(5))
.block();
}
}
Original file line number Diff line number Diff line change
@@ -1,38 +1,27 @@
package no.nav.organisasjonforvalter.consumer;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import no.nav.organisasjonforvalter.config.Consumers;
import no.nav.testnav.libs.commands.organisasjonservice.v1.GetOrganisasjonCommand;
import no.nav.organisasjonforvalter.consumer.command.OrganisasjonServiceCommand;
import no.nav.testnav.libs.dto.organisasjon.v1.OrganisasjonDTO;
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.Flux;
import reactor.core.publisher.Mono;

import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static java.lang.System.currentTimeMillis;
import static java.util.Objects.nonNull;

@Slf4j
@Service
public class OrganisasjonServiceConsumer {

private final TokenExchange tokenExchange;
private final WebClient webClient;
private final ServerProperties serverProperties;
private final ExecutorService executorService;

public OrganisasjonServiceConsumer(
Consumers consumers,
Expand All @@ -42,107 +31,20 @@ public OrganisasjonServiceConsumer(
.baseUrl(serverProperties.getUrl())
.build();
this.tokenExchange = tokenExchange;
this.executorService = Executors.newFixedThreadPool(serverProperties.getThreads());
}

public Optional<OrganisasjonDTO> getStatus(String orgnummer, String miljoe) {

try {
return getStatus(Set.of(orgnummer), Set.of(miljoe)).get(miljoe).get(orgnummer);
} catch (RuntimeException e) {
log.error(e.getMessage(), e);
return Optional.empty();
}
}

public Map<String, Map<String, Optional<OrganisasjonDTO>>> getStatus(Set<String> orgnummer, Set<String> miljoer) {

long startTime = currentTimeMillis();

var token = tokenExchange.exchange(serverProperties).block().getTokenValue();

var completables = miljoer.stream()
.map(miljoe -> OrgFutureDTO.builder()
.miljoe(miljoe)
.futureDto(orgnummer.stream()
.map(orgnr -> FutureDTO.builder()
.orgnr(orgnr)
.completableFuture(
CompletableFuture.supplyAsync(() ->
new GetOrganisasjonCommand(webClient, token, orgnr, miljoe).call(),
executorService))
.build())
.collect(Collectors.toMap(entry -> entry.getOrgnr(), entry -> entry.getCompletableFuture())))
.build())
.collect(Collectors.toMap(entry -> entry.getMiljoe(), entry -> entry.getFutureDto()));

var organisasjoner = completables.keySet().stream()
.map(miljoe -> MiljoeOrgnrOrgDTO.builder()
.miljoe(miljoe)
.orgnrOrgDTO(
completables.get(miljoe).keySet().stream()
.map(orgnr ->
OrganisasjonServiceConsumer.OrgnrOrgDTO.builder()
.orgnr(orgnr)
.organisasjonDTO(resolveCompleteable(completables.get(miljoe).get(orgnr)))
.build())
.collect(Collectors.toMap(entry -> entry.getOrgnr(), entry -> entry.getOrganisasjonDTO())))
.build())
.collect(Collectors.toMap(entry -> entry.getMiljoe(), entry -> entry.getOrgnrOrgDTO()));

log.info("Organisasjon-Service svarte med funnet etter {} ms", currentTimeMillis() - startTime);

return organisasjoner;
}

private Optional<OrganisasjonDTO> resolveCompleteable(CompletableFuture<OrganisasjonDTO> future) {

try {
var result = future.get();
return nonNull(result) ? Optional.of(result) : Optional.empty();
} catch (Exception e) {
log.error(e.getMessage(), e);
return Optional.empty();
}
}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
private static class OrgFutureDTO {

private String miljoe;
private Map<String, CompletableFuture<OrganisasjonDTO>> futureDto;
}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
private static class FutureDTO {

private String orgnr;
private CompletableFuture<OrganisasjonDTO> completableFuture;
}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
private static class MiljoeOrgnrOrgDTO {
public Flux<Map<String, OrganisasjonDTO>> getStatus(String orgnummer, String miljoe) {

private String miljoe;
private Map<String, Optional<OrganisasjonDTO>> orgnrOrgDTO;
return getStatus(Set.of(orgnummer), Set.of(miljoe));
}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
private static class OrgnrOrgDTO {
public Flux<Map<String, OrganisasjonDTO>> getStatus(Set<String> orgnummere, Set<String> miljoer) {

private String orgnr;
private Optional<OrganisasjonDTO> organisasjonDTO;
return tokenExchange.exchange(serverProperties)
.flatMapMany(token -> Flux.fromIterable(miljoer)
.map(orgnr -> Flux.fromIterable(orgnummere)
.flatMap(miljoe -> new OrganisasjonServiceCommand(webClient, orgnr, miljoe, token.getTokenValue()).call())
.collect(Collectors.toMap(orgMap -> orgnr, orgMap -> orgMap))))
.flatMap(Mono::flux);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package no.nav.organisasjonforvalter.consumer.command;

import lombok.RequiredArgsConstructor;
import no.nav.testnav.libs.commands.utils.WebClientFilter;
import no.nav.testnav.libs.dto.adresseservice.v1.VegadresseDTO;
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;
Expand All @@ -28,6 +28,7 @@ public Mono<VegadresseDTO[]> call() {
.header(HttpHeaders.AUTHORIZATION, "Bearer " + token)
.retrieve()
.bodyToMono(VegadresseDTO[].class)
.doOnError(WebClientFilter::logErrorMessage)
.retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
.filter(WebClientFilter::is5xxException));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package no.nav.organisasjonforvalter.consumer.command;

import lombok.RequiredArgsConstructor;
import no.nav.testnav.libs.dto.generernavnservice.v1.NavnDTO;
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.Flux;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;

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

@RequiredArgsConstructor
public class GenererNavnCommand implements Callable<Flux<NavnDTO>> {

private final WebClient webClient;
private final Integer antall;
private final String accessToken;

@Override
public Flux<NavnDTO> call() {
return webClient
.get()
.uri(builder -> builder
.path("/api/v1/navn")
.queryParam("antall", antall)
.build())
.header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)
.retrieve()
.bodyToFlux(NavnDTO.class)
.doOnError(WebClientFilter::logErrorMessage)
.retryWhen(Retry.backoff(3, Duration.ofSeconds(5))
.filter(WebClientFilter::is5xxException))
.onErrorResume(throwable -> Mono.empty());
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package no.nav.organisasjonforvalter.consumer.command;

import lombok.RequiredArgsConstructor;
import no.nav.testnav.libs.commands.utils.WebClientFilter;
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import no.nav.organisasjonforvalter.jpa.entity.Status;
import no.nav.testnav.libs.commands.utils.WebClientFilter;
import no.nav.testnav.libs.reactivecore.utils.WebClientFilter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
Expand Down Expand Up @@ -32,7 +32,7 @@ public Mono<Status> call() {
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(String[].class)
.doOnNext(resultat -> log.info("Melding mottatt {}", resultat))
.doOnNext(resultat -> log.info("Melding mottatt {}", Arrays.toString(resultat)))
.map(resultat -> Arrays.stream(resultat)
.mapToInt(Integer::parseInt)
.max()
Expand Down
Loading

0 comments on commit 141634f

Please sign in to comment.