Merge remote-tracking branch 'origin/main' into develop

This commit is contained in:
htlee 2026-03-18 08:58:09 +09:00
커밋 7fabe16f4f
3개의 변경된 파일23개의 추가작업 그리고 28개의 파일을 삭제

파일 보기

@ -85,43 +85,40 @@ jobs:
- name: Restart backend via SSH - name: Restart backend via SSH
env: env:
DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }} DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
DEPLOY_HOST: 192.168.1.20
run: | run: |
mkdir -p ~/.ssh mkdir -p ~/.ssh
echo "$DEPLOY_KEY" > ~/.ssh/id_deploy printf '%s\n' "$DEPLOY_KEY" > ~/.ssh/id_deploy
chmod 600 ~/.ssh/id_deploy chmod 600 ~/.ssh/id_deploy
# Docker 컨테이너 → 호스트: bridge gateway(172.17.0.1) 경유 ssh-keyscan -T 5 $DEPLOY_HOST >> ~/.ssh/known_hosts 2>/dev/null || true
DOCKER_HOST_IP=172.17.0.1
ssh-keyscan $DOCKER_HOST_IP >> ~/.ssh/known_hosts 2>/dev/null || true
SSH_CMD="ssh -i ~/.ssh/id_deploy -o StrictHostKeyChecking=no root@$DOCKER_HOST_IP" SSH_CMD="ssh -i ~/.ssh/id_deploy -o StrictHostKeyChecking=no -o ConnectTimeout=10 root@$DEPLOY_HOST"
$SSH_CMD bash -s << 'RESTART' $SSH_CMD bash -s << 'RESTART'
set -e
DEPLOY_DIR=/devdata/services/kcg/backend DEPLOY_DIR=/devdata/services/kcg/backend
SYSTEMD_DIR=/etc/systemd/system SYSTEMD_DIR=/etc/systemd/system
# systemd 서비스 파일 갱신 # systemd 서비스 파일 갱신
CHANGED=0
if [ -f "$DEPLOY_DIR/kcg-backend.service" ] && ! diff -q "$DEPLOY_DIR/kcg-backend.service" "$SYSTEMD_DIR/kcg-backend.service" >/dev/null 2>&1; then if [ -f "$DEPLOY_DIR/kcg-backend.service" ] && ! diff -q "$DEPLOY_DIR/kcg-backend.service" "$SYSTEMD_DIR/kcg-backend.service" >/dev/null 2>&1; then
cp "$DEPLOY_DIR/kcg-backend.service" "$SYSTEMD_DIR/kcg-backend.service" cp "$DEPLOY_DIR/kcg-backend.service" "$SYSTEMD_DIR/kcg-backend.service"
CHANGED=1 systemctl daemon-reload
fi fi
[ "$CHANGED" = "1" ] && systemctl daemon-reload
# 백엔드 재시작 # 백엔드 재시작
echo "--- Restarting kcg-backend ---" echo "--- Restarting kcg-backend ---"
systemctl restart kcg-backend systemctl restart kcg-backend
# 기동 확인 (최대 30초) # 기동 확인 (최대 60초)
for i in $(seq 1 30); do for i in $(seq 1 60); do
if curl -sf http://localhost:8080/api/aircraft > /dev/null 2>&1; then HTTP=$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8080/api/aircraft 2>/dev/null || echo "000")
echo "Backend started successfully (${i}s)" if [ "$HTTP" = "200" ] || [ "$HTTP" = "401" ] || [ "$HTTP" = "403" ]; then
echo "Backend started successfully (${i}s, HTTP $HTTP)"
exit 0 exit 0
fi fi
sleep 1 sleep 1
done done
echo "WARNING: Startup timeout. Recent logs:" echo "WARNING: Startup timeout"
journalctl -u kcg-backend --no-pager -n 20 journalctl -u kcg-backend --no-pager -n 10
exit 1 exit 1
RESTART RESTART

파일 보기

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

파일 보기

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