From 52ff4a67b3c8d0f900b68ac1f738f36edf309543 Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Thu, 23 May 2024 23:55:33 +0200 Subject: [PATCH] fix: NbpService cache & tests fixes --- .../eu/ztsh/wymiana/service/NbpService.java | 24 +++++++++++++++++-- .../ztsh/wymiana/service/NbpServiceTest.java | 11 +++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/main/java/eu/ztsh/wymiana/service/NbpService.java b/src/main/java/eu/ztsh/wymiana/service/NbpService.java index 7406c93..da26238 100644 --- a/src/main/java/eu/ztsh/wymiana/service/NbpService.java +++ b/src/main/java/eu/ztsh/wymiana/service/NbpService.java @@ -13,6 +13,8 @@ import java.time.DayOfWeek; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAdjusters; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; /** * NBP exchange rates service @@ -26,12 +28,30 @@ public class NbpService { private static final String URI_PATTERN = "/api/exchangerates/rates/c/{code}/{date}/"; private final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + private final ConcurrentMap cache = new ConcurrentHashMap<>(1); + public double getSellRate(String currency) { - return fetchData(currency, dtf.format(getFetchDate())).getRates().get(0).getAsk(); + return getCurrency(currency).sell(); } public double getBuyRate(String currency) { - return fetchData(currency, dtf.format(getFetchDate())).getRates().get(0).getBid(); + return getCurrency(currency).buy(); + } + + private synchronized RatesCache getCurrency(String currency) { + var today = getFetchDate(); + var cacheObject = cache.get(currency); + if (cacheObject == null || cacheObject.date().isBefore(today)) { + var fresh = fetchData(currency, dtf.format(today)); + var rate = fresh.getRates().get(0); + cacheObject = new RatesCache( + LocalDate.parse(rate.getEffectiveDate(), dtf), + rate.getBid(), + rate.getAsk() + ); + cache.put(fresh.getCode(), cacheObject); + } + return cacheObject; } /** diff --git a/src/test/java/eu/ztsh/wymiana/service/NbpServiceTest.java b/src/test/java/eu/ztsh/wymiana/service/NbpServiceTest.java index b244083..7424fbe 100644 --- a/src/test/java/eu/ztsh/wymiana/service/NbpServiceTest.java +++ b/src/test/java/eu/ztsh/wymiana/service/NbpServiceTest.java @@ -2,7 +2,6 @@ package eu.ztsh.wymiana.service; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.tomakehurst.wiremock.client.WireMock; import eu.ztsh.wymiana.EntityCreator; import eu.ztsh.wymiana.WireMockExtension; import eu.ztsh.wymiana.exception.NoDataException; @@ -81,20 +80,22 @@ class NbpServiceTest { WireMockExtension.response(url, 200, new ObjectMapper().writeValueAsString(EntityCreator.rates(date))); try { assertThat(nbpService.getSellRate(EntityCreator.Constants.USD_SYMBOL)).isEqualTo(EntityCreator.Constants.SELL_RATE); - assertThat(nbpService.getBuyRate(EntityCreator.Constants.USD_SYMBOL)).isEqualTo(EntityCreator.Constants.BUY_RATE); } finally { - WireMockExtension.verifyGet(2, url); + WireMockExtension.verifyGet(1, url); } } @DisplayName("Fetch rates from cache") @Test - void getWithCacheTest() { + void getWithCacheTest() throws JsonProcessingException { var date = dtf.format(updateClock(DayOfWeek.FRIDAY)); var url = "/api/exchangerates/rates/c/usd/%s/".formatted(date); + WireMockExtension.response(url, 200, new ObjectMapper().writeValueAsString(EntityCreator.rates(date))); + // save to cache assertThat(nbpService.getSellRate(EntityCreator.Constants.USD_SYMBOL)).isEqualTo(EntityCreator.Constants.SELL_RATE); + // get from cache assertThat(nbpService.getBuyRate(EntityCreator.Constants.USD_SYMBOL)).isEqualTo(EntityCreator.Constants.BUY_RATE); - WireMockExtension.verifyGet(0, url); + WireMockExtension.verifyGet(1, url); } @DisplayName("Support 404: invalid currency or no data")