package com.danielbohry.stocks.service; import com.danielbohry.stocks.client.FinanceClient; import com.danielbohry.stocks.domain.Quote; import com.danielbohry.stocks.domain.StockInfo; import com.danielbohry.stocks.exception.NotFoundException; import com.danielbohry.stocks.repository.StockInfoRepository; import com.danielbohry.stocks.repository.StockRepository; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.util.List; import java.util.Set; import static java.util.stream.Collectors.toSet; @Slf4j @Service @AllArgsConstructor public class StockInfoService { private FinanceClient client; private StockRepository stockRepository; private StockInfoRepository infoRepository; @Cacheable(value = "stockInfo", key = "#code") public StockInfo get(String code) { return infoRepository.findById(code) .orElseThrow(() -> new NotFoundException("No stock found with id: " + code)); } @Async("stockInfoExecutor") public void generate() { List stocks = stockRepository.findAll(); Set existingIds = infoRepository.findAllById( stocks.stream() .map(Quote::getCode) .collect(toSet()) ).stream() .map(StockInfo::getCode) .collect(toSet()); List request = stocks.stream() .filter(stock -> !existingIds.contains(stock.getCode())) .filter(stock -> !stock.getCode().contains(":")) .toList(); int batchSize = 20; for (int i = 0; i < request.size(); i += batchSize) { int end = Math.min(i + batchSize, request.size()); List batch = request.subList(i, end); List stockInfos = client.fetchStockInfo(batch); infoRepository.saveAll(stockInfos); } } }