From b3985d77fbf2ff8be91d6e4ecb2d8f0822a9a955 Mon Sep 17 00:00:00 2001 From: windpacer Date: Fri, 19 Jun 2026 05:44:11 +0900 Subject: [PATCH] =?UTF-8?q?fix(crawler):=20realtime=5Ftable=20id=20bigint(?= =?UTF-8?q?=EC=8B=9C=ED=80=80=EC=8A=A4=20=EC=98=A4=EB=B2=84=ED=94=8C?= =?UTF-8?q?=EB=A1=9C)=20+=20HCX=20=ED=8F=B4=EB=A7=81=20=EB=B9=84=ED=99=9C?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 운영 사고 재발 방지: - realtime_table.id가 SERIAL(int4)이라 매 poll의 nextval 소비로 2^31 도달 → 전체 realtime 업서트가 'reached maximum value of sequence'로 정지(현장에서 14h 무갱신 발생, bigint ALTER로 라이브 복구 완료). 신규 배포: CREATE를 BIGSERIAL로, 기존 배포: 기동 시 멱등 마이그레이션(integer일 때만 bigint+시퀀스 ALTER). - gateway-config: HCX(IP·맵 없는 플레이스홀더)가 enabled=true라 50055 연결거부 로그 양산 → enabled=false. Co-Authored-By: Claude Opus 4.8 --- config/gateway-config.json | 2 +- src/Infrastructure/Database/Hc900DbContext.cs | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/config/gateway-config.json b/config/gateway-config.json index 0700fc3..798162f 100644 --- a/config/gateway-config.json +++ b/config/gateway-config.json @@ -53,7 +53,7 @@ "grpcPort": 50055, "pollIntervalMs": 1000, "registerMapPath": "", - "enabled": true + "enabled": false } ] } \ No newline at end of file diff --git a/src/Infrastructure/Database/Hc900DbContext.cs b/src/Infrastructure/Database/Hc900DbContext.cs index d2e5a3d..4bc5ae7 100644 --- a/src/Infrastructure/Database/Hc900DbContext.cs +++ b/src/Infrastructure/Database/Hc900DbContext.cs @@ -705,7 +705,7 @@ public class Hc900DbService : IExperionDbService // realtime_table 생성 (실시간 모니터링 포인트) await _ctx.Database.ExecuteSqlRawAsync(""" CREATE TABLE IF NOT EXISTS realtime_table ( - id SERIAL PRIMARY KEY, + id BIGSERIAL PRIMARY KEY, tagname TEXT NOT NULL, node_id TEXT NOT NULL, livevalue TEXT, @@ -772,6 +772,21 @@ public class Hc900DbService : IExperionDbService ON event_history_table(tagname, event_type, event_time DESC); """); + // ── realtime_table.id int4→bigint 마이그레이션 (멱등) ─────────────── + // realtime_table은 upsert지만 매 poll마다 nextval을 소비 → SERIAL(int4)은 + // 2^31에서 오버플로해 전체 업서트가 멈춘다(운영 사고). 이미 bigint면 no-op. + await _ctx.Database.ExecuteSqlRawAsync(""" + DO $$ + BEGIN + IF (SELECT data_type FROM information_schema.columns + WHERE table_schema = current_schema() + AND table_name = 'realtime_table' AND column_name = 'id') = 'integer' THEN + ALTER TABLE realtime_table ALTER COLUMN id TYPE bigint; + ALTER SEQUENCE realtime_table_id_seq AS bigint MAXVALUE 9223372036854775807; + END IF; + END $$; + """); + // ── Multi-Controller Migration (controller_id) ───────────────────── // 기존 테이블에 controller_id 컬럼 추가 (멱등) await _ctx.Database.ExecuteSqlRawAsync(