| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- package com.danielbohry.stocks.service.stock;
- import com.danielbohry.stocks.domain.StockHistory;
- import com.danielbohry.stocks.exception.BadRequestException;
- import com.danielbohry.stocks.repository.stock.StockHistoryRepository;
- import lombok.AllArgsConstructor;
- import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
- import org.springframework.cache.annotation.Cacheable;
- 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
- @AllArgsConstructor
- public class StockHistoryService {
- private final StockService service;
- private final StockHistoryRepository repository;
- public static final String ONCE_PER_DAY_AT_2AM = "0 0 2 * * *";
- @Scheduled(cron = ONCE_PER_DAY_AT_2AM)
- @SchedulerLock(name = "StockQuoteService_saveQuotes", lockAtLeastFor = "PT5M", lockAtMostFor = "PT15M")
- public void saveQuotes() {
- 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(stocksToSave);
- }
- @Cacheable(value = "stockHistory", key = "#code + '-' + #range")
- public List<StockHistory> get(String code, String range) {
- Instant end = now();
- Instant start = switch (range) {
- case "5d" -> end.minus(5, DAYS);
- case "30d" -> end.minus(30, DAYS);
- case "6m" -> end.minus(180, DAYS);
- case "1y" -> end.minus(365, DAYS);
- default -> throw new BadRequestException("Unsupported range: " + range);
- };
- return repository.findByCodeAndCreatedAtBetween(code, start, end);
- }
- }
|