Skip to content

[Test] 실제 MinIO 업로드 동시성 검증 - #30

Merged
Gimini-3 merged 1 commit into
developfrom
feature/27
Jul 16, 2026
Merged

[Test] 실제 MinIO 업로드 동시성 검증#30
Gimini-3 merged 1 commit into
developfrom
feature/27

Conversation

@Gimini-3

@Gimini-3 Gimini-3 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

변경 사항

  • 실제 MinIO 저장 이후 Barrier에서 두 요청을 동기화하는 통합 테스트를 추가했습니다.
  • 동일 파일로 새 Document를 동시에 생성할 때 FileObject와 MinIO Object가 하나만 남는지 검증했습니다.
  • 같은 Document에 동일 수정 파일을 동시에 업로드할 때 Version 하나만 성공하고 실패 후보가 삭제되는지 검증했습니다.
  • 기본 테스트와 분리된 minioIntegrationTest Gradle task 및 전용 profile을 추가했습니다.
  • DocumentVersionUploadFacade의 저장 실패·DB 실패·보상 삭제 분기 단위 테스트 6개를 추가했습니다.
  • 실제 요청 조건, 검증 SQL, Object Key, 실행 결과와 분석을 docs/test-results/에 기록했습니다.

배경

기존 통합 테스트는 실제 DB를 사용했지만 파일 저장소는 Mock이어서 delete() 호출만 확인할 수 있었습니다. DB Unique Constraint는 FileObject 중복 row를 막지만, MinIO에 먼저 저장된 경합 패자 Object의 실제 삭제까지 보장하지 않습니다.

이번 PR은 실제 MinIO에 후보 두 개를 저장한 뒤 DB 경합을 발생시키고, 패자 후보가 실제로 사라지며 DB의 object_key와 잔존 Object Key가 일치하는지 검증합니다.

검증 결과

  • 기본 ./gradlew test 성공
  • 실제 ./gradlew minioIntegrationTest 성공
  • 문서화된 MinIO 동시성 반복 테스트 7회, 14/14 성공
  • PR 게시 전 실제 MinIO 테스트 추가 실행 성공
  • timeout 및 간헐 실패 0건
  • Object 크기, Content-Type, SHA-256과 DB 값 일치
  • 테스트 종료 후 DB 잔존 데이터 0건
  • 테스트 전용 MinIO bucket 잔존 0건

테스트 시나리오

신규 Document 경합

  • 요청 2건 모두 성공
  • Document, Version, Job 각각 2건
  • FileObject 1건
  • 실제 MinIO 후보 2개 저장, 패자 1개 삭제, 최종 1개 잔존

새 Version 경합

  • 성공 1건, DOCUMENT_VERSION_IN_PROGRESS 실패 1건
  • Version 2 및 PENDING Job 각각 1건
  • 기존 current_version_id 유지
  • 수정 파일 후보 2개 저장, 실패 요청 후보 1개 삭제

문서

제외 범위

프로세스 강제 종료와 기존 고아 Object Reconciliation은 후속 운영 기능으로 분리합니다.

Closes #27

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed 실제 MinIO 전용 프로필·task, Barrier 기반 동시성 테스트, 정리, 단위 테스트, 결과 문서가 이슈 #27의 요구를 충족합니다.
Out of Scope Changes check ✅ Passed 빌드·테스트·문서 변경만 포함되어 있으며, 이슈 범위를 벗어난 별도 기능 추가는 보이지 않습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed 제목이 실제 MinIO 업로드 동시성 검증이라는 핵심 변경을 간결하게 잘 요약합니다.
Description check ✅ Passed 필수 항목(작업 내용, 배경, 검증 결과, 시나리오, 문서, Closes #27)을 대부분 포함해 템플릿 취지를 충족합니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/27

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/test/java/com/opensource/docgrid/domain/document/integration/minio/MinioUploadConcurrencyIntegrationTest.java`:
- Around line 126-140: Update both ExecutorService cleanup blocks in
MinioUploadConcurrencyIntegrationTest.java (lines 126-140 and 188-201): cancel
the submitted futures during cleanup, call shutdownNow(), and awaitTermination
before allowing teardown to continue, handling interruption while preserving the
interrupt status.
- Around line 107-113: Update tearDown() so cleanupBucket() and
storageService.clearObservations() execute even when cleanupDatabase() throws,
while preserving barrierControl.disarm() execution and allowing teardown
failures to be reported appropriately.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f118440e-daa9-4a98-b369-73f39469f762

📥 Commits

Reviewing files that changed from the base of the PR and between 8aafcbb and 4a16c17.

📒 Files selected for processing (5)
  • build.gradle
  • docs/test-results/pr-2.2-minio-concurrency-integration-test.md
  • src/test/java/com/opensource/docgrid/domain/document/integration/minio/MinioUploadConcurrencyIntegrationTest.java
  • src/test/java/com/opensource/docgrid/domain/document/service/DocumentVersionUploadFacadeTest.java
  • src/test/resources/application-minio-integration.yml

Comment on lines +107 to +113
@AfterEach
void tearDown() throws Exception {
barrierControl.disarm();
cleanupDatabase();
cleanupBucket();
storageService.clearObservations();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

DB 정리 실패와 무관하게 MinIO 정리를 실행하세요.

cleanupDatabase()가 예외를 던지면 cleanupBucket()과 관측값 초기화가 생략되어 실제 Object와 bucket이 남고 다음 테스트를 오염시킵니다.

수정 예시
     void tearDown() throws Exception {
         barrierControl.disarm();
-        cleanupDatabase();
-        cleanupBucket();
-        storageService.clearObservations();
+        try {
+            cleanupDatabase();
+        } finally {
+            try {
+                cleanupBucket();
+            } finally {
+                storageService.clearObservations();
+            }
+        }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@AfterEach
void tearDown() throws Exception {
barrierControl.disarm();
cleanupDatabase();
cleanupBucket();
storageService.clearObservations();
}
`@AfterEach`
void tearDown() throws Exception {
barrierControl.disarm();
try {
cleanupDatabase();
} finally {
try {
cleanupBucket();
} finally {
storageService.clearObservations();
}
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/opensource/docgrid/domain/document/integration/minio/MinioUploadConcurrencyIntegrationTest.java`
around lines 107 - 113, Update tearDown() so cleanupBucket() and
storageService.clearObservations() execute even when cleanupDatabase() throws,
while preserving barrierControl.disarm() execution and allowing teardown
failures to be reported appropriately.

Comment on lines +126 to +140
ExecutorService executor = Executors.newFixedThreadPool(CONCURRENT_REQUESTS);
DocumentUploadResponse firstResponse;
DocumentUploadResponse secondResponse;
try {
Future<DocumentUploadResponse> first = executor.submit(
() -> uploadAndTrack(firstRequest)
);
Future<DocumentUploadResponse> second = executor.submit(
() -> uploadAndTrack(secondRequest)
);
firstResponse = first.get(FUTURE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
secondResponse = second.get(FUTURE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
} finally {
executor.shutdownNow();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

정리 전에 Executor 종료를 확실히 기다리세요.

shutdownNow()는 interrupt만 요청하므로 작업 종료를 보장하지 않습니다. timeout이나 예외 발생 시 worker가 DB·MinIO를 계속 변경하는 동안 @AfterEach가 정리를 시작할 수 있습니다. 두 경로 모두 future 취소 후 awaitTermination으로 종료를 확인하세요.

  • src/test/java/com/opensource/docgrid/domain/document/integration/minio/MinioUploadConcurrencyIntegrationTest.java#L126-L140: 신규 문서 경합 Executor의 종료를 기다리세요.
  • src/test/java/com/opensource/docgrid/domain/document/integration/minio/MinioUploadConcurrencyIntegrationTest.java#L188-L201: 버전 경합 Executor에도 동일한 종료 절차를 적용하세요.
📍 Affects 1 file
  • src/test/java/com/opensource/docgrid/domain/document/integration/minio/MinioUploadConcurrencyIntegrationTest.java#L126-L140 (this comment)
  • src/test/java/com/opensource/docgrid/domain/document/integration/minio/MinioUploadConcurrencyIntegrationTest.java#L188-L201
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/opensource/docgrid/domain/document/integration/minio/MinioUploadConcurrencyIntegrationTest.java`
around lines 126 - 140, Update both ExecutorService cleanup blocks in
MinioUploadConcurrencyIntegrationTest.java (lines 126-140 and 188-201): cancel
the submitted futures during cleanup, call shutdownNow(), and awaitTermination
before allowing teardown to continue, handling interruption while preserving the
interrupt status.

@Gimini-3
Gimini-3 marked this pull request as ready for review July 16, 2026 12:15
@Gimini-3
Gimini-3 merged commit 0f798a2 into develop Jul 16, 2026
1 check passed
@Gimini-3 Gimini-3 changed the title test: 실제 MinIO 업로드 동시성 검증 [Test] 실제 MinIO 업로드 동시성 검증 Jul 16, 2026
@Gimini-3 Gimini-3 self-assigned this Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Test] 실제 MinIO 업로드 동시성 검증

1 participant