-
Notifications
You must be signed in to change notification settings - Fork 1
fix: 오픈 API 비동기 호출로 인한 Too Many Requests Error 발생 #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
✅ 테스트 결과 for PRBuild: success 🧪 테스트 실행 with Gradle |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR refactors the auction history scheduler to batch process categories by top-level groupings with configurable delays, adds local development Docker environment support, and updates documentation.
- Refactored
AuctionHistorySchedulerto group item categories by top category and process/save them in batches with configurable delays between API calls - Added
docker-compose-local.ymland.env.local.samplefor local development with MySQL container - Updated Dockerfile to support both ARM64 and AMD64 architectures by removing alpine variant
Reviewed Changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
src/main/java/until/the/eternity/auctionhistory/application/scheduler/AuctionHistoryScheduler.java |
Refactored scheduler to group categories by top category, process in batches with delays, and save per top category |
docker-compose-local.yml |
Added new Docker Compose configuration for local development environment with MySQL |
docker-compose-dev.yaml |
Added explicit build configuration with context and dockerfile |
.env.local.sample |
Added environment variable template for local development |
Dockerfile |
Removed alpine variant for multi-architecture support |
README.md |
Added local development section with Docker instructions |
.gitignore |
Added .env.local to ignored files and updated comments |
docs/CD_PIPELINE_GUIDE.md |
Updated step names from docker-compose.yaml to docker-compose-dev.yaml |
.github/workflows/push-cd-dev.yml |
Updated step name from docker-compose.yaml to docker-compose-dev.yaml |
.github/workflows/push-cd-prod.yml |
Updated step name from docker-compose.yaml to docker-compose-dev.yaml |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
docker-compose-local.yml
Outdated
| image: open-api-batch-server:local | ||
| container_name: spring-app-local | ||
| ports: | ||
| - |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incomplete port mapping configuration. Line 16 has a dangling '-' without a port mapping, while line 17 has the actual port mapping. This will cause a YAML parsing error. Remove line 16.
| - |
| private final AuctionHistoryPersister persister; | ||
|
|
||
| @Value("${openapi.auction-history.delay-ms}") | ||
| private long delayMs; |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using @Value to inject configuration into a field of a @RequiredArgsConstructor class can lead to NullPointerException if the field is accessed before Spring initializes it. Consider using constructor injection with @ConfigurationProperties or changing to setter injection with a @PostConstruct validation method to ensure the value is properly initialized.
| private long delayMs; | |
| private final long delayMs; |
| log.debug( | ||
| "> [SCHEDULE] Waiting {}ms before processing next category", | ||
| delayMs); | ||
| Thread.sleep(delayMs); |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using Thread.sleep() in a scheduler method can block the scheduler thread pool, potentially affecting other scheduled tasks. Consider using @Async with CompletableFuture and non-blocking delays, or ensure the scheduler is configured with an appropriate thread pool size to handle blocking operations.
| log.debug( | ||
| "> [SCHEDULE] Waiting {}ms before processing next top category", | ||
| delayMs); | ||
| Thread.sleep(delayMs); |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using Thread.sleep() in a scheduler method can block the scheduler thread pool, potentially affecting other scheduled tasks. Consider using @Async with CompletableFuture and non-blocking delays, or ensure the scheduler is configured with an appropriate thread pool size to handle blocking operations.
| } catch (InterruptedException e) { | ||
| log.error( | ||
| "> [SCHEDULE] Thread interrupted during delay for category [{}]", | ||
| category.getSubCategory(), | ||
| e); | ||
| Thread.currentThread().interrupt(); | ||
| break; |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When breaking out of the inner loop due to InterruptedException, the outer loop continues processing subsequent top categories. Consider propagating the interrupt state to break out of the outer loop as well, or document why continuing with other top categories is the desired behavior.
|
|
||
| - **로컬 개발**: 코드 수정 시마다 `--build` 옵션으로 재빌드 필요 | ||
| - **메모리 설정**: 로컬 환경은 메모리 사용량이 낮게 설정되어 있음 (512MB) | ||
| - **데이터베이스**: `DB_IP=host.docker.internal`로 호스트 머신의 MySQL에 접근 |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation states that DB_IP=host.docker.internal is used to access MySQL on the host machine, but according to the docker-compose-local.yml (line 31), it's set to mysql which refers to the MySQL container service name, not the host. This documentation is inconsistent with the actual implementation. Update to reflect that the local setup uses a containerized MySQL service.
| - **데이터베이스**: `DB_IP=host.docker.internal`로 호스트 머신의 MySQL에 접근 | |
| - **데이터베이스**: `DB_IP=mysql`로 Docker Compose의 MySQL 컨테이너에 접근 (`mysql`은 서비스 이름) |
| - name: Copy docker-compose.yaml to server | ||
| - name: Copy docker-compose-dev.yaml to server | ||
| run: | | ||
| scp -i ~/.ssh/my-key.pem docker-compose.yaml ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:/home/${{ secrets.SERVER_USER }}/app/ |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The step name says 'Copy docker-compose-dev.yaml to server' but the command copies 'docker-compose.yaml'. Either update the command to scp docker-compose-dev.yaml to match the step name, or revert the step name change if 'docker-compose.yaml' is the correct file to copy.
| scp -i ~/.ssh/my-key.pem docker-compose.yaml ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:/home/${{ secrets.SERVER_USER }}/app/ | |
| scp -i ~/.ssh/my-key.pem docker-compose-dev.yaml ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:/home/${{ secrets.SERVER_USER }}/app/ |
| ssh -i ~/.ssh/my-key.pem ${{ secrets.PROD_SERVER_USER }}@${{ secrets.PROD_SERVER_HOST }} "mkdir -p /home/${{ secrets.PROD_SERVER_USER }}/app/logs" | ||
| - name: Copy docker-compose.yaml to server | ||
| - name: Copy docker-compose-dev.yaml to server |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The step name says 'Copy docker-compose-dev.yaml to server' but the command copies 'docker-compose.yaml'. Either update the command to scp docker-compose-dev.yaml to match the step name, or revert the step name change if 'docker-compose.yaml' is the correct file to copy.
| - name: Copy docker-compose-dev.yaml to server | |
| - name: Copy docker-compose.yaml to server |
|
|
||
| | 환경 | Docker Compose 파일 | 설명 | | ||
| |------|---------------------|------| | ||
| | **로컬 개발** | `docker-compose.local.yml` | 로컬 코드 빌드, 낮은 리소스 사용 | |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filename inconsistency: The table references docker-compose.local.yml but the actual filename is docker-compose-local.yml (with hyphen, not dot). Update the table to use the correct filename.
| | **로컬 개발** | `docker-compose.local.yml` | 로컬 코드 빌드, 낮은 리소스 사용 | | |
| | **로컬 개발** | `docker-compose-local.yml` | 로컬 코드 빌드, 낮은 리소스 사용 | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 10 out of 11 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - name: Copy docker-compose.yaml to server | ||
| - name: Copy docker-compose-dev.yaml to server | ||
| run: | | ||
| scp -i ~/.ssh/my-key.pem docker-compose.yaml ${{ secrets.PROD_SERVER_USER }}@${{ secrets.PROD_SERVER_HOST }}:/home/${{ secrets.PROD_SERVER_USER }}/app/ |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The step name says 'Copy docker-compose-dev.yaml' but the actual command copies 'docker-compose.yaml'. This mismatch will cause the deployment to fail as the file being copied doesn't exist in the repository. Change the filename in the scp command to 'docker-compose-dev.yaml'.
| scp -i ~/.ssh/my-key.pem docker-compose.yaml ${{ secrets.PROD_SERVER_USER }}@${{ secrets.PROD_SERVER_HOST }}:/home/${{ secrets.PROD_SERVER_USER }}/app/ | |
| scp -i ~/.ssh/my-key.pem docker-compose-dev.yaml ${{ secrets.PROD_SERVER_USER }}@${{ secrets.PROD_SERVER_HOST }}:/home/${{ secrets.PROD_SERVER_USER }}/app/ |
| # ============================================================================= | ||
| # Database Configuration | ||
| # ============================================================================= | ||
| # 로컬 MySQL 사용 시 (Docker로 MySQL 실행하는 경우) |
Copilot
AI
Nov 4, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The .env.local.sample suggests using DB_IP=host.docker.internal for accessing a MySQL on the host machine, but docker-compose-local.yml line 30 overrides this with DB_IP: mysql (the Docker service name) in the environment section. This configuration in the sample file will be ignored and may confuse users. Update the comment to clarify that the MySQL service is included in the compose file and the DB_IP is overridden.
| # 로컬 MySQL 사용 시 (Docker로 MySQL 실행하는 경우) | |
| # 로컬 MySQL 사용 시 | |
| # ⚠️ docker-compose.local.yml을 사용할 경우, DB_IP는 'mysql'(서비스 이름)로 오버라이드됩니다. | |
| # 아래 값은 Docker Compose를 사용하지 않고 직접 실행할 때만 적용됩니다. |
📋 상세 설명
📊 체크리스트
📆 마감일