fix(deploy): health check 401 대응 + PressureCollector 중복 방지

- deploy.yml: health check에서 HTTP 401/403도 정상 기동으로 판정 (인증 필요 엔드포인트)
- health check timeout 30초 → 60초
- PressureCollector: save 전 existsByStationAndReadingTime으로 중복 확인
  (JPA unique constraint 예외 → Hibernate 세션 오염 방지)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
htlee 2026-03-18 08:25:33 +09:00
부모 c63af7abe0
커밋 67fc341fc8
3개의 변경된 파일16개의 추가작업 그리고 17개의 파일을 삭제

파일 보기

@ -112,10 +112,11 @@ jobs:
echo "--- Restarting kcg-backend ---"
systemctl restart kcg-backend
# 기동 확인 (최대 30초)
for i in $(seq 1 30); do
if curl -sf http://localhost:8080/api/aircraft > /dev/null 2>&1; then
echo "Backend started successfully (${i}s)"
# 기동 확인 (최대 60초, 401=인증필요=정상 기동)
for i in $(seq 1 60); do
HTTP=$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8080/api/aircraft 2>/dev/null)
if [ "$HTTP" = "200" ] || [ "$HTTP" = "401" ] || [ "$HTTP" = "403" ]; then
echo "Backend started successfully (${i}s, HTTP $HTTP)"
exit 0
fi
sleep 1

파일 보기

@ -91,19 +91,16 @@ public class PressureCollector {
try {
// Open-Meteo 시간 형식: "2026-03-18T07:00" (Z 없음) Z 추가
Instant readingTime = OffsetDateTime.parse(timeStr + "Z").toInstant();
try {
repository.save(PressureReading.builder()
.station(station)
.lat(lat)
.lng(lng)
.pressureHpa(pressure)
.readingTime(readingTime)
.collectedAt(now)
.build());
saved++;
} catch (Exception ignored) {
// unique constraint violation = 이미 존재, 무시
}
if (repository.existsByStationAndReadingTime(station, readingTime)) continue;
repository.save(PressureReading.builder()
.station(station)
.lat(lat)
.lng(lng)
.pressureHpa(pressure)
.readingTime(readingTime)
.collectedAt(now)
.build());
saved++;
} catch (DateTimeParseException e) {
log.debug("기압 시간 파싱 실패: {}", timeStr);
}

파일 보기

@ -6,6 +6,7 @@ import java.time.Instant;
import java.util.List;
public interface PressureReadingRepository extends JpaRepository<PressureReading, Long> {
boolean existsByStationAndReadingTime(String station, Instant readingTime);
List<PressureReading> findByStationAndReadingTimeAfterOrderByReadingTimeAsc(String station, Instant since);
List<PressureReading> findByReadingTimeAfterOrderByReadingTimeAsc(Instant since);
}