[FEAT] 작가 생성 토픽으로 작가 스케줄 생성 (#273)#277
Conversation
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughKafka로 수신된 PhotographerCreated 이벤트를 역직렬화해 PhotographerScheduleService가 작가의 기본 스케줄을 idempotent하게 생성하도록 하는 기능과, Gradle 멀티모듈 빌드(Dockerfile) 및 event-schema-shared 포함을 위한 빌드 변경이 추가됩니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Kafka as Kafka Topic<br/>(PhotographerCreated)
participant Consumer as PhotographerCreatedEventConsumer
participant Deserializer as EventDeserializer
participant Service as PhotographerScheduleService
participant Repository as PhotographerScheduleRepository
participant DB as Database
Kafka->>Consumer: EventEnvelope (payload bytes)
Consumer->>Deserializer: deserialize(bytes, PhotographerCreated.class)
Deserializer-->>Consumer: PhotographerCreated
Consumer->>Service: createDefaultSchedule(photographerId)
Service->>Repository: existsByPhotographerId(photographerId)
Repository->>DB: SELECT ... FROM photographer_schedule
DB-->>Repository: exists result
Repository-->>Service: boolean
alt not exists
Service->>Service: PhotographerSchedule.initSchedule(photographerId)
Service->>Repository: saveAndFlush(schedule)
Repository->>DB: INSERT photographer_schedule
DB-->>Repository: success
Repository-->>Service: saved schedule
Service-->>Consumer: log success
else exists
Service-->>Consumer: return (idempotent)
else DataIntegrityViolationException
Service-->>Consumer: catch & log concurrent creation
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
Test Results (reservation)75 tests 75 ✅ 2s ⏱️ Results for commit 5c4ce68. ♻️ This comment has been updated with latest results. |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
This PR implements an event-driven feature to automatically create photographer schedules when a photographer is created in the member-service. The implementation uses Kafka consumers to listen for PhotographerCreated events and creates default schedules with proper idempotency guarantees.
Changes:
- Added Kafka consumer infrastructure with retry mechanism (3 attempts) and Dead Letter Topic (DLT) handling
- Implemented
PhotographerScheduleServicewith idempotent schedule creation logic - Added
PhotographerScheduleRepositorywith queries for finding schedules by photographer ID - Comprehensive test coverage including unit tests, integration tests, and repository tests
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| reservation/build.gradle | Added Kafka and event-schema-shared module dependencies |
| reservation/Dockerfile | Updated to include event-schema-shared module in build process with optimized dependency caching |
| reservation/src/test/resources/application.yml | Configured test database to not replace datasource (prevents H2 auto-configuration conflicts) |
| reservation/src/main/java/net/catsnap/CatsnapReservation/schedule/infrastructure/repository/PhotographerScheduleRepository.java | Created repository with methods to find and check existence of schedules by photographer ID |
| reservation/src/main/java/net/catsnap/CatsnapReservation/schedule/application/PhotographerScheduleService.java | Implemented service with idempotent schedule creation handling concurrent requests gracefully |
| reservation/src/main/java/net/catsnap/CatsnapReservation/schedule/infrastructure/event/PhotographerCreatedEventConsumer.java | Kafka consumer with retry logic (3 attempts, exponential backoff) and DLT handler |
| reservation/src/main/java/net/catsnap/CatsnapReservation/event/infrastructure/EventConfig.java | Configuration for event deserialization using Avro |
| reservation/src/test/java/net/catsnap/CatsnapReservation/schedule/infrastructure/repository/PhotographerScheduleRepositoryTest.java | Repository integration tests verifying query methods |
| reservation/src/test/java/net/catsnap/CatsnapReservation/schedule/application/PhotographerScheduleServiceIntegrationTest.java | Service integration tests verifying idempotency and concurrent request handling |
| reservation/src/test/java/net/catsnap/CatsnapReservation/schedule/infrastructure/event/PhotographerCreatedEventConsumerTest.java | Unit tests for consumer event handling and DLT logic |
| reservation/src/test/java/net/catsnap/CatsnapReservation/schedule/fixture/PhotographerScheduleFixture.java | Test fixture for creating photographer schedule test data |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
...p/CatsnapReservation/schedule/infrastructure/event/PhotographerCreatedEventConsumerTest.java
Show resolved
Hide resolved
...p/CatsnapReservation/schedule/infrastructure/event/PhotographerCreatedEventConsumerTest.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@reservation/Dockerfile`:
- Around line 21-22: 현재 Dockerfile의 의존성 프리패치 RUN 단계에서 "./gradlew
:reservation:dependencies --no-daemon || true"로 실패를 무시하고 있어 캐시 단계 오류를 감추므로, "||
true"를 제거하여 "./gradlew :reservation:dependencies --no-daemon" 명령이 실패할 경우 빌드를
중단하도록 수정하세요; 필요하면 실패 시 로그를 더 자세히 남기도록 gradle에 --stacktrace 또는 --info 옵션을 추가해 디버깅
정보를 확보하십시오.
In
`@reservation/src/main/java/net/catsnap/CatsnapReservation/schedule/application/PhotographerScheduleService.java`:
- Around line 31-43: The catch for DataIntegrityViolationException in
PhotographerScheduleService.createDefaultSchedule is treating all integrity
violations as concurrent duplicate inserts; update it to re-check
photographerScheduleRepository.existsByPhotographerId(photographerId) inside the
catch and only swallow the exception if the schedule now exists (indicating a
true concurrent insert), otherwise rethrow the exception so genuine data
integrity errors surface; keep the initial optimistic exists-check and the save
via photographerScheduleRepository.saveAndFlush(schedule) and reference
PhotographerSchedule.initSchedule when recreating the schedule before save.
In
`@reservation/src/main/java/net/catsnap/CatsnapReservation/schedule/infrastructure/event/PhotographerCreatedEventConsumer.java`:
- Around line 59-66: The code in consume(EventEnvelope) currently calls
envelope.getPayload().array(), which is unsafe for direct/positioned
ByteBuffers; instead allocate a byte[] of size
envelope.getPayload().remaining(), copy bytes via
envelope.getPayload().duplicate().get(bytes), and pass that bytes array to
eventDeserializer.deserialize when deserializing PhotographerCreated to avoid
UnsupportedOperationException and incorrect payloads.
In
`@reservation/src/test/java/net/catsnap/CatsnapReservation/schedule/infrastructure/event/PhotographerCreatedEventConsumerTest.java`:
- Around line 9-12: The test relies on platform default charset when converting
payload bytes; update PhotographerCreatedEventConsumerTest to use
StandardCharsets.UTF_8 explicitly wherever strings are converted to/from bytes
(e.g., uses of String.getBytes(...) and new String(byteArray, ...)) and add the
StandardCharsets import; target the conversions around the ByteBuffer creation
and the payload assertions (occurrences near the ByteBuffer usage and the
payload encoding/decoding spots referenced in the diff).
📌 관련 이슈
✨ PR 세부 내용
작가 생성 토픽으로 작가 스케줄 생성합니다.
컨슈메ㅓ에서 2번까지 재시도하며, 3번 실패시 DLT으로 이동합니다.
Summary by CodeRabbit
릴리스 노트
새로운 기능
테스트
Chores
✏️ Tip: You can customize this high-level summary in your review settings.