Skip to content

Commit e478466

Browse files
authored
feature: Implementa mecanismo de cache (#60)
2 parents 71656a1 + a383331 commit e478466

File tree

14 files changed

+592
-28
lines changed

14 files changed

+592
-28
lines changed

README.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,3 @@ Comando para executar o projeto via imagem docker
117117
```bash
118118
docker pull ungaratto93/api-fx:latest
119119
```
120-
121-
## Backlog
122-
Proximas melhorias a serem implementadas
123-
- [ ] Aplicar o padrao de projeto proxy na consulta da taxa
124-
- O motivo da aplicacao deste padrao e para evitar a sobrecarga nos servicos de terceiros.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package br.com.ungaratto93.fx.domain.rate;
2+
3+
import br.com.ungaratto93.fx.domain.fiat.Symbol;
4+
import br.com.ungaratto93.fx.infra.fiat.FiatExchangeServiceWiseRates;
5+
import lombok.Getter;
6+
import lombok.Setter;
7+
import lombok.ToString;
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
10+
import org.springframework.beans.factory.annotation.Value;
11+
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
15+
16+
@Getter
17+
@Setter
18+
@ToString
19+
public class RateCache {
20+
21+
private Map<String, Rate> rates = new HashMap<>();
22+
23+
@Value("${cache.rate.limit.time.valid:900}")
24+
private long limitTimeForRateInCache;
25+
26+
private static final Logger LOGGER = LoggerFactory.getLogger(FiatExchangeServiceWiseRates.class);
27+
28+
public RateCache() {
29+
30+
}
31+
32+
public void putRateOnCache(Symbol source, Symbol target, double value, String time) {
33+
String keyName = generateKeyName(source, target);
34+
rates.put(
35+
keyName,
36+
Rate.builder()
37+
.source(source)
38+
.target(target)
39+
.value(value)
40+
.time(time)
41+
.build()
42+
);
43+
LOGGER.info("CACHE - A {} foi inserida no cache com time de {}", keyName, time);
44+
}
45+
46+
private String generateKeyName(Symbol source, Symbol target) {
47+
return source.name().concat("_").concat(target.name());
48+
}
49+
50+
public Rate getByKeyFromCache(String keyName) throws UnsupportedOperationException {
51+
if(!rates.isEmpty()) {
52+
LOGGER.info("CACHE - Recuperando taxas do cache local");
53+
return rates.get(keyName);
54+
} else
55+
throw new UnsupportedOperationException(String.format(" CACHE - A {} nao foi encontrada no cache", keyName));
56+
57+
}
58+
59+
public void removeByKeyFromCache(String keyName) throws UnsupportedOperationException {
60+
LOGGER.debug("CACHE - O tamanho do cache é {}", rates.size());
61+
if(!rates.isEmpty()) {
62+
rates.remove(keyName);
63+
LOGGER.info("CACHE - A {} foi removida do cache", keyName);
64+
} else
65+
throw new UnsupportedOperationException(String.format(" CACHE - A {} nao foi encontrada no cache", keyName));
66+
}
67+
68+
public boolean isEmpty() {
69+
return rates.isEmpty();
70+
}
71+
72+
public boolean isRateOld(Rate rate) {
73+
long rateTime = Long.parseLong(rate.getTime());
74+
long timeOfRateInCache = System.currentTimeMillis() - rateTime;
75+
76+
LOGGER.info("CACHE - O tempo desta rate no cache é {}", timeOfRateInCache);
77+
78+
return timeOfRateInCache > limitTimeForRateInCache ? Boolean.TRUE : Boolean.FALSE;
79+
}
80+
81+
public String getKeyName(Symbol source, Symbol target) {
82+
return generateKeyName(source, target);
83+
}
84+
85+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package br.com.ungaratto93.fx.infra.rate;
2+
3+
import br.com.ungaratto93.fx.domain.rate.*;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.stereotype.Service;
8+
9+
@Service
10+
public class ProxyRateService implements RateService {
11+
12+
private static final Logger LOGGER = LoggerFactory.getLogger(WiseRateService.class);
13+
14+
@Autowired
15+
private WiseRateService wiseRateService;
16+
17+
private final RateCache rateCache = new RateCache();
18+
19+
public ProxyRateService(WiseRateService wiseRateService) {
20+
this.wiseRateService = wiseRateService;
21+
}
22+
23+
@Override
24+
public RateOutPut getRates(RateInput rateInput) throws WiseRateServiceException {
25+
String keyName = rateCache.getKeyName(rateInput.source(), rateInput.target());
26+
LOGGER.info("CACHE - Chave gerada {}", keyName);
27+
try {
28+
LOGGER.info("CACHE - Recuperando taxas do cache local");
29+
Rate rate = rateCache.getByKeyFromCache(keyName);
30+
LOGGER.info("CACHE - Taxa encontrada no cache local, retornando-a");
31+
if(rateCache.isRateOld(rate))
32+
throw new UnsupportedOperationException("Rate com prazo excedida");
33+
34+
return new RateOutPut(rate.getSource(), rate.getTarget(), rate.getValue(), rate.getTime());
35+
} catch ( UnsupportedOperationException ex) {
36+
LOGGER.info("CACHE - Nao encontramos as taxas no cache local");
37+
LOGGER.info("CACHE - Vamos consultar o servico externo");
38+
RateOutPut out = wiseRateService.getRates(rateInput);
39+
40+
LOGGER.info("CACHE - Atualizando-o com a taxa {}", keyName);
41+
rateCache.putRateOnCache(
42+
out.source(),
43+
out.target(),
44+
out.value(),
45+
out.time()
46+
);
47+
return out;
48+
}
49+
}
50+
}

src/main/java/br/com/ungaratto93/fx/infra/rate/WiseRateService.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
package br.com.ungaratto93.fx.infra.rate;
22

3-
import br.com.ungaratto93.fx.domain.rate.Rate;
4-
import br.com.ungaratto93.fx.domain.rate.RateInput;
5-
import br.com.ungaratto93.fx.domain.rate.RateOutPut;
6-
import br.com.ungaratto93.fx.domain.rate.RateService;
7-
import br.com.ungaratto93.fx.domain.rate.FeignWiseClient;
8-
import br.com.ungaratto93.fx.domain.rate.WiseRateServiceException;
3+
import br.com.ungaratto93.fx.domain.rate.*;
94
import org.slf4j.Logger;
105
import org.slf4j.LoggerFactory;
116
import org.springframework.beans.factory.annotation.Autowired;
@@ -33,7 +28,7 @@ public RateOutPut getRates(RateInput rateInput) throws WiseRateServiceException
3328
"day");
3429
LOGGER.info("WISE - As taxas retornadas foram: {}", rates);
3530

36-
if(rates.isEmpty()) {
31+
if (rates.isEmpty()) {
3732
LOGGER.warn("WISE - Nao foi possivel retornar a taxa");
3833
throw new WiseRateServiceException(String.format("Ocorreu retorno de objeto invalido na consulta da taxa %s, na WISE", rateInput));
3934
}
@@ -46,6 +41,7 @@ public RateOutPut getRates(RateInput rateInput) throws WiseRateServiceException
4641
rate.getValue(),
4742
rate.getTime()
4843
);
44+
4945
LOGGER.info("WISE - Retornando a seguinte taxa: {}", out);
5046
return out;
5147
}

src/main/java/br/com/ungaratto93/fx/infra/spring/exception/RestControllerExceptionHandler.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,11 @@
22

33
import br.com.ungaratto93.fx.domain.rate.WiseRateServiceException;
44
import feign.RetryableException;
5-
import org.springframework.http.HttpStatus;
65
import org.springframework.http.ResponseEntity;
76
import org.springframework.http.converter.HttpMessageNotReadableException;
87
import org.springframework.web.bind.annotation.ExceptionHandler;
98
import org.springframework.web.bind.annotation.RestControllerAdvice;
109

11-
import java.util.Optional;
12-
1310
@RestControllerAdvice
1411
public class RestControllerExceptionHandler {
1512

src/main/java/br/com/ungaratto93/fx/ui/FiatExchangeController.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import org.springframework.beans.factory.annotation.Autowired;
1414
import org.springframework.context.annotation.Description;
1515
import org.springframework.http.ResponseEntity;
16-
import org.springframework.web.bind.annotation.GetMapping;
1716
import org.springframework.web.bind.annotation.PostMapping;
1817
import org.springframework.web.bind.annotation.RequestBody;
1918
import org.springframework.web.bind.annotation.RestController;

src/main/java/br/com/ungaratto93/fx/usecase/fiat/exchange/FiatExcxhangeUseCase.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import br.com.ungaratto93.fx.domain.fiat.FiatExchangeService;
44
import br.com.ungaratto93.fx.domain.fiat.FiatInputData;
55
import br.com.ungaratto93.fx.domain.fiat.FiatOutputData;
6-
import br.com.ungaratto93.fx.infra.fiat.FiatExchangeServiceWiseRates;
7-
import br.com.ungaratto93.fx.infra.rate.WiseRateService;
86
import br.com.ungaratto93.fx.domain.rate.*;
7+
import br.com.ungaratto93.fx.infra.fiat.FiatExchangeServiceWiseRates;
8+
import br.com.ungaratto93.fx.infra.rate.ProxyRateService;
99
import org.slf4j.Logger;
1010
import org.slf4j.LoggerFactory;
1111
import org.springframework.beans.factory.annotation.Autowired;
@@ -20,16 +20,16 @@ public class FiatExcxhangeUseCase {
2020
private final FiatExchangeService fiatEchangeService;
2121

2222
@Autowired
23-
private final WiseRateService wiseRateService;
23+
private final ProxyRateService rateService;
2424

25-
public FiatExcxhangeUseCase(WiseRateService wiseRateService, FiatExchangeService fiatExchangeService) {
26-
this.wiseRateService = wiseRateService;
25+
public FiatExcxhangeUseCase(ProxyRateService proxyRateService, FiatExchangeService fiatExchangeService) {
26+
this.rateService = proxyRateService;
2727
this.fiatEchangeService = fiatExchangeService;
2828
}
2929

3030
public FiatOutputData exec(FiatInputData fiatInputData) throws WiseRateServiceException {
3131
LOGGER.info("Obtendo a taxa para conversao de fiat");
32-
RateOutPut rateOutPutFromWiseService = this.wiseRateService.getRates(
32+
RateOutPut rateOutPutFromWiseService = this.rateService.getRates(
3333
new RateInput(
3434
fiatInputData.from(),
3535
fiatInputData.to(),
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
1+
# Parametro que define o limite de tempo em segundos para manter o cambio no cache
2+
cache.rate.limit.time.valid=900

src/test/java/br/com/ungaratto93/fx/integrate/ui/FiatExchangeControllerTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,17 @@ void shouldReturnFiatValueConvertedWhenRequestWithValidCurrenciesAndAmount() thr
3232

3333
}
3434

35+
@Test
36+
void shouldReturnFiatConvertedWhenReqValidBodyAndRateFromCache() throws WiseRateServiceException {
37+
38+
final var fiatOutputDataResponseEntity = controller.post(
39+
new FiatInputData(Symbol.USD, Symbol.BRL, 2.00)
40+
);
41+
42+
Assertions.assertNotNull(fiatOutputDataResponseEntity);
43+
Assertions.assertEquals(200, fiatOutputDataResponseEntity.getStatusCode().value());
44+
45+
}
46+
3547

3648
}

0 commit comments

Comments
 (0)