|
|
@@ -10,9 +10,12 @@ import org.springframework.scheduling.annotation.Scheduled;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.time.Instant;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.time.ZoneOffset;
|
|
|
import java.util.List;
|
|
|
|
|
|
import static java.time.Instant.now;
|
|
|
+import static java.time.ZoneOffset.UTC;
|
|
|
import static java.time.temporal.ChronoUnit.DAYS;
|
|
|
|
|
|
@Service
|
|
|
@@ -22,21 +25,31 @@ public class StockHistoryService {
|
|
|
private final StockService service;
|
|
|
private final StockHistoryRepository repository;
|
|
|
|
|
|
- public static final String ONCE_PER_DAY_AT_11PM = "0 0 23 * * *";
|
|
|
+ public static final String ONCE_PER_DAY_AT_2AM = "0 0 2 * * *";
|
|
|
|
|
|
- @Scheduled(cron = ONCE_PER_DAY_AT_11PM)
|
|
|
+ @Scheduled(cron = ONCE_PER_DAY_AT_2AM)
|
|
|
@SchedulerLock(name = "StockQuoteService_saveQuotes", lockAtLeastFor = "PT5M", lockAtMostFor = "PT15M")
|
|
|
public void saveQuotes() {
|
|
|
- List<StockHistory> stocks = service.getAll().stream()
|
|
|
- .map(stock -> new StockHistory(stock.getCode(), stock.getCurrency(), stock.getPrice(), now()))
|
|
|
+ LocalDate today = LocalDate.now(UTC);
|
|
|
+ Instant startOfDay = today.atStartOfDay(UTC).toInstant();
|
|
|
+ Instant endOfDay = today.plusDays(1).atStartOfDay(UTC).toInstant();
|
|
|
+
|
|
|
+ List<StockHistory> stocksToSave = service.getAll().stream()
|
|
|
+ .filter(stock -> !repository.existsByCodeAndCreatedAtBetween(stock.getCode(), startOfDay, endOfDay))
|
|
|
+ .map(stock -> new StockHistory(
|
|
|
+ stock.getCode(),
|
|
|
+ stock.getCurrency(),
|
|
|
+ stock.getPrice(),
|
|
|
+ now()
|
|
|
+ ))
|
|
|
.toList();
|
|
|
|
|
|
- repository.saveAll(stocks);
|
|
|
+ repository.saveAll(stocksToSave);
|
|
|
}
|
|
|
|
|
|
@Cacheable(value = "stockHistory", key = "#code + '-' + #range")
|
|
|
public List<StockHistory> get(String code, String range) {
|
|
|
- Instant end = Instant.now();
|
|
|
+ Instant end = now();
|
|
|
Instant start = switch (range) {
|
|
|
case "5d" -> end.minus(5, DAYS);
|
|
|
case "30d" -> end.minus(30, DAYS);
|