Skip to content

Comments

[FEAT] 작가 생성 토픽으로 작가 스케줄 생성 (#273)#277

Merged
redblackblossom merged 7 commits intomainfrom
feat/#273/photographer_schedule
Jan 24, 2026
Merged

[FEAT] 작가 생성 토픽으로 작가 스케줄 생성 (#273)#277
redblackblossom merged 7 commits intomainfrom
feat/#273/photographer_schedule

Conversation

@redblackblossom
Copy link
Contributor

@redblackblossom redblackblossom commented Jan 24, 2026

📌 관련 이슈

✨ PR 세부 내용

작가 생성 토픽으로 작가 스케줄 생성합니다.

컨슈메ㅓ에서 2번까지 재시도하며, 3번 실패시 DLT으로 이동합니다.

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 사진작가 생성 시 기본 일정이 자동으로 초기화됩니다(경합 상황 안전 처리 포함).
    • 사진작가 생성 이벤트를 수신해 일정 생성 작업을 트리거하는 이벤트 소비자와 이벤트 역직렬화 지원이 추가되었습니다.
    • 일정 저장/조회용 저장소 인터페이스가 추가되었습니다.
  • 테스트

    • 일정 서비스 및 이벤트 소비자에 대한 통합 및 단위 테스트, 저장소 테스트가 추가되었습니다.
  • Chores

    • 다중 모듈 빌드 및 컨테이너화 워크플로우가 개선되었습니다.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 24, 2026

Note

Other AI code review bot(s) detected

CodeRabbit 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.

📝 Walkthrough

Walkthrough

Kafka로 수신된 PhotographerCreated 이벤트를 역직렬화해 PhotographerScheduleService가 작가의 기본 스케줄을 idempotent하게 생성하도록 하는 기능과, Gradle 멀티모듈 빌드(Dockerfile) 및 event-schema-shared 포함을 위한 빌드 변경이 추가됩니다.

Changes

Cohort / File(s) 변경 요약
Docker & 빌드 구성
reservation/Dockerfile, reservation/build.gradle
Dockerfile을 멀티모듈 Gradle 흐름으로 변경; event-schema-shared를 포함하도록 settings/build 단계 조정; reservation/build.gradleproject(':event-schema-shared') 및 Kafka 의존성 추가
이벤트 설정
reservation/src/main/java/.../event/infrastructure/EventConfig.java
EventDeserializer 빈을 제공하는 @Configuration 클래스 추가
스케줄 서비스 & 저장소
reservation/src/main/java/.../schedule/application/PhotographerScheduleService.java, reservation/src/main/java/.../schedule/infrastructure/repository/PhotographerScheduleRepository.java
기본 스케줄 생성용 @Transactional 서비스 메서드 추가(멱등성, 동시성 예외 처리 포함); JPA 리포지토리 인터페이스 추가
Kafka 컨슈머
reservation/src/main/java/.../schedule/infrastructure/event/PhotographerCreatedEventConsumer.java
PhotographerCreated 토픽 구독 컨슈머 추가(재시도 정책 3회, 지수 백오프, DLT 핸들러 포함); 역직렬화 후 서비스 호출 및 DLT 로깅
테스트 — 통합/단위/리포지토리
reservation/src/test/java/.../PhotographerScheduleServiceIntegrationTest.java, reservation/src/test/java/.../schedule/infrastructure/event/PhotographerCreatedEventConsumerTest.java, reservation/src/test/java/.../schedule/infrastructure/repository/PhotographerScheduleRepositoryTest.java
서비스 멱등성·동작 검증, 컨슈머 역직렬화·DLT 검증, 리포지토리 조회/존재성 검증 테스트 추가
테스트 픽스처 및 설정
reservation/src/test/java/.../schedule/fixture/PhotographerScheduleFixture.java, reservation/src/test/resources/application.yml
테스트용 스케줄 생성 헬퍼와 테스트 DB 교체 정책 설정 추가

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항을 명확하게 요약하고 있습니다: 작가 생성 토픽으로 작가 스케줄을 생성하는 기능을 추가했습니다.
Description check ✅ Passed PR 설명에 관련 이슈 #273이 명시되어 있고, 주요 구현 내용(작가 생성 토픽 수신, 컨슈머 재시도 정책)이 포함되어 있습니다.
Linked Issues check ✅ Passed PR의 모든 변경사항이 이슈 #273의 요구사항을 충족합니다: 작가 생성 이벤트로 스케줄 생성, Kafka 컨슈머 구현, DLT 처리.
Out of Scope Changes check ✅ Passed 모든 변경사항이 작가 스케줄 생성 기능 구현에 직접 관련되어 있으며, 범위를 벗어난 변경사항은 없습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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 and usage tips.

@github-actions
Copy link

github-actions bot commented Jan 24, 2026

Test Results (reservation)

75 tests   75 ✅  2s ⏱️
 9 suites   0 💤
 9 files     0 ❌

Results for commit 5c4ce68.

♻️ This comment has been updated with latest results.

@codecov
Copy link

codecov bot commented Jan 24, 2026

Codecov Report

❌ Patch coverage is 91.66667% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...edule/application/PhotographerScheduleService.java 80.00% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Contributor

Copilot AI left a 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 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 PhotographerScheduleService with idempotent schedule creation logic
  • Added PhotographerScheduleRepository with 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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

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).

@redblackblossom redblackblossom merged commit 0399270 into main Jan 24, 2026
10 checks passed
@redblackblossom redblackblossom deleted the feat/#273/photographer_schedule branch January 24, 2026 11:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨feature 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 작가 생성 이벤트로 작가의 스케줄 테이블 생성

1 participant