43 lines
2.0 KiB
Markdown
43 lines
2.0 KiB
Markdown
---
|
||
title: error / scheduled-reaper-wrong-config-prefix-2026-06-09
|
||
source_type: error-note
|
||
status: raw
|
||
related_branches: [feature-rate-limit-idempotency-contract]
|
||
related_projects: [ca-skeleton]
|
||
tags: [error, ca-skeleton, spring, scheduling, configuration]
|
||
created: 2026-06-09
|
||
status_label: resolved
|
||
---
|
||
|
||
# error: scheduled-reaper-wrong-config-prefix-2026-06-09
|
||
|
||
> Layer: `raw/errors/` — 코드 리뷰(ca-quality-reviewer)가 잡은 silent config 키 불일치.
|
||
|
||
## Parent / 부모
|
||
|
||
- [[raw/branch-notes/feature-rate-limit-idempotency-contract]]
|
||
|
||
## 증상 / Symptom
|
||
|
||
`IdempotencyReaper`의 `@Scheduled(fixedDelayString = "${ca-skeleton.rate-limit.reaper-interval:PT10M}")`가
|
||
**잘못된 prefix**(`rate-limit`)를 참조. 실제 바인딩 속성은 `ca-skeleton.idempotency.reaper-interval`
|
||
(`IdempotencyProperties` 소유). 컴파일/테스트는 통과하지만 운영자가 `ca-skeleton.idempotency.reaper-interval`을
|
||
조정해도 무시되고 항상 하드코딩 기본값 `PT10M`로 동작. `IdempotencyProperties.reaperInterval`은 dead letter.
|
||
|
||
## 원인 / Root cause
|
||
|
||
`@Scheduled` SpEL placeholder는 키가 없으면 inline default(`:PT10M`)로 **조용히** 폴백 →
|
||
오타/잘못된 prefix가 런타임 예외 없이 묻힘. 빌드 게이트가 placeholder–property 정합을 검증하지 않음.
|
||
|
||
## 해결 / Resolution
|
||
|
||
`@Scheduled` 표현식을 `${ca-skeleton.idempotency.reaper-interval:PT10M}`로 수정. 정적 테스트로는
|
||
잡기 어려워 코드 리뷰 단계에서 포착됨(테스트는 `reap()` 반환값만 검증, 스케줄 wiring 미검증).
|
||
|
||
## 교훈 / Lesson
|
||
|
||
`@Scheduled(...:default)` / `@Value(...:default)` 처럼 **inline default가 있는 placeholder는
|
||
오타가 silent**. 같은 의미의 값이 두 곳(property record + 어노테이션 문자열)에 있으면 drift 위험.
|
||
가능하면 단일 출처(설정 record 주입)로 통일하거나, 키 정합을 검증하는 테스트를 둔다.
|
||
관련: [[raw/branch-notes/feature-rate-limit-idempotency-contract]]
|