[Feat/#199] 마트 공휴일 휴무 지원 및 영업중 여부 판별에 공휴일 반영 - #201
Conversation
|
Warning Review limit reached
Next review available in: 9 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthrough공휴일 API 조회·Redis 캐시를 추가하고, 공휴일 휴무 설정에 따라 영업 여부를 판정하도록 변경했습니다. 시장 등록·수정 요청과 시장·전단 조회 응답에도 공휴일 휴무 정보가 반영됩니다. Changes공휴일 영업시간 지원
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant MarketQueryFacade
participant HolidayService
participant HolidayReader
participant RedisHolidayCache
participant DataGoKrHolidayClient
participant MarketResponse
MarketQueryFacade->>HolidayService: getHolidays(baseDate)
HolidayService->>HolidayReader: getHolidays(baseDate)
HolidayReader->>RedisHolidayCache: get(year)
RedisHolidayCache-->>HolidayReader: cached holidays or miss
HolidayReader->>DataGoKrHolidayClient: fetchHolidays(year)
DataGoKrHolidayClient-->>HolidayReader: holiday dates
HolidayReader->>RedisHolidayCache: put(year, holidays)
HolidayReader-->>HolidayService: merged holiday dates
MarketQueryFacade->>MarketResponse: isOpenAt(now, holidays)
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 6 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (6 passed)
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 |
There was a problem hiding this comment.
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
`@api/owner-api/src/main/kotlin/kr/dongchimi/api/owner/flyer/FlyerPreviewQueryFacade.kt`:
- Around line 33-35: Refactor getPeriodicPreview and getDailyPreview so
holidayService.getHolidays(today) executes outside the `@Transactional`(readOnly =
true) scope, avoiding database connection retention during external API calls.
Preserve the existing preview response data and transactional behavior for the
database-backed operations, using separate transaction boundaries where needed.
In
`@infrastructure/redis/src/main/kotlin/kr/dongchimi/infrastructure/redis/RedisHolidayCache.kt`:
- Around line 14-34: Update the runCatching blocks in RedisHolidayCache.get,
put, and putFallback to attach onFailure handlers that log the Redis exception
using the project’s existing logger implementation, while preserving the current
fail-open behavior and return values.
🪄 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: ASSERTIVE
Plan: Pro Plus
Run ID: 43ca2e15-bb2f-43b9-bab5-47c7b0bcc991
📒 Files selected for processing (25)
.env.exampleapi/owner-api/src/main/kotlin/kr/dongchimi/api/owner/flyer/FlyerPreviewQueryFacade.ktapi/owner-api/src/main/kotlin/kr/dongchimi/api/owner/flyer/response/FlyerDailyPreviewResponse.ktapi/owner-api/src/main/kotlin/kr/dongchimi/api/owner/flyer/response/FlyerPreviewResponse.ktapi/owner-api/src/main/kotlin/kr/dongchimi/api/owner/market/request/MarketRegisterRequest.ktapi/owner-api/src/main/kotlin/kr/dongchimi/api/owner/market/request/MarketRequestSupport.ktapi/owner-api/src/main/kotlin/kr/dongchimi/api/owner/market/request/MarketUpdateRequest.ktapi/owner-api/src/main/kotlin/kr/dongchimi/api/owner/market/response/OwnerMarketDetailResponse.ktapi/user-api/src/main/kotlin/kr/dongchimi/api/user/market/MarketDetailQueryFacade.ktapi/user-api/src/main/kotlin/kr/dongchimi/api/user/market/NearbyMarketQueryFacade.ktapi/user-api/src/main/kotlin/kr/dongchimi/api/user/market/response/MarketDetailResponse.ktapi/user-api/src/main/kotlin/kr/dongchimi/api/user/market/response/NearbyMarketResponse.ktcore/src/main/kotlin/kr/dongchimi/core/holiday/HolidayCache.ktcore/src/main/kotlin/kr/dongchimi/core/holiday/HolidayClient.ktcore/src/main/kotlin/kr/dongchimi/core/holiday/HolidayReader.ktcore/src/main/kotlin/kr/dongchimi/core/holiday/HolidayService.ktcore/src/main/kotlin/kr/dongchimi/core/market/BusinessHours.ktinfrastructure/client/src/main/kotlin/kr/dongchimi/client/holiday/DataGoKrHolidayClient.ktinfrastructure/client/src/main/kotlin/kr/dongchimi/client/holiday/HolidayApiProperties.ktinfrastructure/client/src/main/kotlin/kr/dongchimi/client/holiday/HolidayRestClientConfig.ktinfrastructure/client/src/main/resources/application-infrastructure-client.ymlinfrastructure/redis/src/main/kotlin/kr/dongchimi/infrastructure/redis/HolidayCacheProperties.ktinfrastructure/redis/src/main/kotlin/kr/dongchimi/infrastructure/redis/HolidayRedisKeys.ktinfrastructure/redis/src/main/kotlin/kr/dongchimi/infrastructure/redis/RedisHolidayCache.ktinfrastructure/redis/src/main/resources/application-infrastructure-redis.yml
| // Redis 장애 시 miss로 간주 → HolidayReader가 외부 API 조회로 fallback한다(fail-open). | ||
| override fun get(year: Int): Set<LocalDate>? = | ||
| runCatching { | ||
| stringRedisTemplate.opsForValue().get(HolidayRedisKeys.holidays(year))?.toHolidays() | ||
| }.getOrNull() | ||
|
|
||
| override fun put( | ||
| year: Int, | ||
| holidays: Set<LocalDate>, | ||
| ) { | ||
| runCatching { | ||
| stringRedisTemplate.opsForValue().set(HolidayRedisKeys.holidays(year), holidays.toValue(), properties.ttl) | ||
| } | ||
| } | ||
|
|
||
| override fun putFallback(year: Int) { | ||
| runCatching { | ||
| stringRedisTemplate.opsForValue().set(HolidayRedisKeys.holidays(year), EMPTY_VALUE, properties.fallbackTtl) | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Redis 예외를 삼키지 말고 에러 로그를 남길 것을 권장합니다.
Redis 장애 시 runCatching을 통해 예외를 삼키고 외부 API로 폴백(fail-open)하는 전략은 서비스 안정성 측면에서 올바릅니다. 하지만 예외를 완전히 삼키면 인프라 구성 오류나 연결 장애를 조기에 인지하기 어렵습니다.
운영 환경에서의 가시성을 확보하기 위해 onFailure를 활용하여 에러 로그를 남기는 것을 권장합니다.
💡 에러 로깅 추가 예시
프로젝트에서 사용하는 로거 구현체(예: KotlinLogging 등)에 맞게 주석 부분을 수정해 적용해 주세요.
// Redis 장애 시 miss로 간주 → HolidayReader가 외부 API 조회로 fallback한다(fail-open).
override fun get(year: Int): Set<LocalDate>? =
runCatching {
stringRedisTemplate.opsForValue().get(HolidayRedisKeys.holidays(year))?.toHolidays()
- }.getOrNull()
+ }.onFailure {
+ // logger.warn(it) { "Redis 공휴일 캐시 조회 실패: year=$year" }
+ }.getOrNull()
override fun put(
year: Int,
holidays: Set<LocalDate>,
) {
runCatching {
stringRedisTemplate.opsForValue().set(HolidayRedisKeys.holidays(year), holidays.toValue(), properties.ttl)
+ }.onFailure {
+ // logger.warn(it) { "Redis 공휴일 캐시 저장 실패: year=$year" }
}
}
override fun putFallback(year: Int) {
runCatching {
stringRedisTemplate.opsForValue().set(HolidayRedisKeys.holidays(year), EMPTY_VALUE, properties.fallbackTtl)
+ }.onFailure {
+ // logger.warn(it) { "Redis 공휴일 캐시 Fallback 저장 실패: year=$year" }
}
}🤖 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
`@infrastructure/redis/src/main/kotlin/kr/dongchimi/infrastructure/redis/RedisHolidayCache.kt`
around lines 14 - 34, Update the runCatching blocks in RedisHolidayCache.get,
put, and putFallback to attach onFailure handlers that log the Redis exception
using the project’s existing logger implementation, while preserving the current
fail-open behavior and return values.
imddoy
left a comment
There was a problem hiding this comment.
주기적으로 가져오도로고 해야 하나 했는데, 이렇게 Redis에 만료시간을 설정해서 미스가 발생하면 가져오게 할 수 있군요!! 수고하셨습니다!
#️⃣연관된 이슈
📝작업 내용
1. 마트 영업시간에 공휴일 휴무 여부(
isHolidayClosed) 추가BusinessHoursJSONB에slots와 같은 위계로isHolidayClosed: Boolean추가 (기본값false→ 기존 데이터 마이그레이션 불필요)false), owner·user 상세 및 전단 프리뷰 응답에 노출2. 공휴일 API 연동 및 isOpenNow 반영
HolidayService→HolidayReader→HolidayCache/HolidayClient인터페이스 (레이어 규칙 준수)getRestDeInfo) 클라이언트 — 전용holidayRestClient빈, serviceKey는 URI 변수 확장으로 엄격 인코딩(+/= 이중 인코딩 함정 회피)holiday:{year}, TTL 1일) — API 월 10,000회 제한 대응, 다중 인스턴스 공유. API 장애 시 짧은 TTL(10분) 빈 값 캐싱으로 재시도 폭주 방지isOpenAt(now, holidays): 공휴일 휴무 마트는 공휴일에 휴무 처리, 전날이 공휴일이면 자정 넘김 꼬리 영업도 휴무 처리💬리뷰 요구사항(선택)
HOLIDAY_API_SERVICE_KEY(data.go.kr Decoding 키) 등록이 필요합니다. 키가 없어도 앱은 뜨고 요일 기준으로만 판별합니다.