일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- NORI
- api cache
- mysql
- Elastic
- ann
- Analyzer
- TSLA
- aggs
- redis
- 아이온큐
- KNN
- Elasticsearch
- request cache
- aqqle
- Selenium
- Cache
- Docker
- file download
- JPA
- Aggregation
- dbeaver
- API
- Query
- java
- java crawler
- elasticsearch cache
- 양자컴퓨터
- vavr
- IONQ
- 테슬라
Archives
- Today
- Total
아빠는 개발자
[Aqqle] YahooDataService 의 execute 본문
728x90
반응형
Ya후의 stock 서비를 크롤링해서 데이터를 훔처오는 service 인데 대충 만들다보니 리팩토링좀 해야할듯..
기존소스의 개선점
- 예외 처리 로직 강화
- 병렬 처리 최적화 (CompletableFuture.allOf)
- 하드코딩된 경로 제거
- 가독성과 유지보수성 향상
package com.doo.aqqle.service;
import com.doo.aqqle.annotation.Timer;
import com.doo.aqqle.repository.StockDataRepository;
import com.doo.aqqle.repository.StockRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@Slf4j
@Service("YahooDataService")
public class YahooDataService extends ExtractService implements AqqleExtract {
private final YahooDataTaskService yahooDataTaskService;
private List<CompletableFuture<Integer>> completableFutures = new ArrayList<>();
public YahooDataService(StockRepository stockRepository, StockDataRepository stockDataRepository, YahooDataTaskService yahooDataTaskService) {
super(stockRepository, stockDataRepository);
this.yahooDataTaskService = yahooDataTaskService;
}
@Override
@Timer
public void execute() {
String type = "yahoo";
String extractPath = "/data/" + type + "/static/";
File file = new File(extractPath);
if (file.exists() && file.isDirectory()) {
try {
FileUtils.cleanDirectory(file);
} catch (IOException e) {
e.getStackTrace();
}
}
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
String directory = extractPath + LocalDateTime.now().format(dateTimeFormatter).toString();
System.out.println(directory);
IndexFileService.createDirectory(directory);
long count = stockDataRepository.count();
int chunk = 500;
double endPage = Math.ceil(count / chunk);
for (int i = 0; i < endPage + 1; i++) {
CompletableFuture<Integer> completableFuture = yahooDataTaskService.task(i, chunk, directory);
completableFutures.add(completableFuture);
}
for (CompletableFuture<Integer> future : completableFutures) {
try {
future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
1. 예외 처리 개선
문제점:
현재 IOException, InterruptedException, ExecutionException에 대해 e.printStackTrace()로만 예외 처리를 하고 있습니다. 이는 충분히 의미 있는 로그 정보를 제공하지 않습니다.
개선 방법:
- 명확한 로그 메시지를 추가하고 예외 정보를 함께 출력합니다.
- 예외 발생 시 적절한 조치를 취할 수 있도록 코드를 작성합니다.
2. CompletableFuture 병렬 처리 최적화
문제점:
모든 CompletableFuture의 결과를 순차적으로 기다리며 future.get()을 호출합니다. 이는 비효율적입니다.
개선 방법:
- CompletableFuture.allOf()로 모든 작업이 완료되기를 비동기적으로 기다립니다.
3. 디렉터리 경로 관리
문제점:
경로 /data/yahoo/static/가 하드코딩되어 있습니다.
이는 운영 환경에서 관리가 어렵고 유연성이 부족합니다.
개선 방법:
- 환경 변수나 설정 파일 (application.yml)을 통해 경로를 관리합니다.
4. 코드 가독성 개선
- 불필요한 toString() 호출 제거
- List<CompletableFuture<Integer>> completableFutures는 메서드 내부에서 선언하여 코드 간섭을 줄입니다.
수정된 코드
package com.doo.aqqle.service;
import com.doo.aqqle.annotation.Timer;
import com.doo.aqqle.repository.StockDataRepository;
import com.doo.aqqle.repository.StockRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@Slf4j
@Service("YahooDataService")
public class YahooDataService extends ExtractService implements AqqleExtract {
@Value("${app.extract-path}")
private String extractPath;
private final YahooDataTaskService yahooDataTaskService;
private List<CompletableFuture<Integer>> completableFutures = new ArrayList<>();
public YahooDataService(StockRepository stockRepository, StockDataRepository stockDataRepository, YahooDataTaskService yahooDataTaskService) {
super(stockRepository, stockDataRepository);
this.yahooDataTaskService = yahooDataTaskService;
}
@Override
@Timer
public void execute() {
String type = "yahoo";
File file = new File(extractPath);
if (file.exists() && file.isDirectory()) {
try {
FileUtils.cleanDirectory(file);
} catch (IOException e) {
log.error("Failed to clean directory: {}", extractPath, e);
}
}
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
String directory = extractPath + LocalDateTime.now().format(dateTimeFormatter).toString();
log.info("directory path : {}", directory);
IndexFileService.createDirectory(directory);
long count = stockDataRepository.count();
int chunk = 500;
double endPage = Math.ceil(count / chunk);
for (int i = 0; i < endPage + 1; i++) {
CompletableFuture<Integer> completableFuture = yahooDataTaskService.task(i, chunk, directory);
completableFutures.add(completableFuture);
}
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
completableFutures.toArray(new CompletableFuture[0])
);
try {
allFutures.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("Thread interrupted during task execution", e);
} catch (ExecutionException e) {
log.error("Task execution failed", e);
}
}
}
728x90
반응형
'Aqqle > EXTRACT' 카테고리의 다른 글
[Aqqle] 데이터 추출 (0) | 2024.02.03 |
---|