P0 셀프서비스 결정론 리포트 — 적산·물질수지 폐합·cleaning 마스크 (+ P1 온라인 스펙) #1
@@ -96,7 +96,7 @@
|
||||
|
||||
## 7. 단계 (제안)
|
||||
- **P0 (MVP)**: §4 슬라이스 — 메트릭 3종 + 엑셀폼 1개 + history 소스 + 1컬럼(C-6111). **상세 코딩설계 → [`작업플랜-셀프서비스-분석리포트-MVP-P0-상세설계.md`](작업플랜-셀프서비스-분석리포트-MVP-P0-상세설계.md)**
|
||||
- **P1**: fast_record 소스 + `dynamics` 메트릭(루프 stiction/헌팅, step-test 셀프서비스).
|
||||
- **P1**: 온라인 히스토리안(1초 링버퍼+연속집계) + 실시간 KPI 누적기/알람 + `dynamics` 메트릭. **상세 → [`작업플랜-셀프서비스-분석리포트-P1-온라인히스토리안-스펙.md`](작업플랜-셀프서비스-분석리포트-P1-온라인히스토리안-스펙.md)**
|
||||
- **P2**: 토큰 파서 일반화 + 템플릿 업로드 UI + Daily 스케줄 자동생성.
|
||||
- **P3**: 멀티컬럼/멀티플랜트(KB 매핑 확장) + Monthly/Yearly + 모델학습 데이터 적재 연계.
|
||||
|
||||
|
||||
123
docs/작업플랜-셀프서비스-분석리포트-P1-온라인히스토리안-스펙.md
Normal file
123
docs/작업플랜-셀프서비스-분석리포트-P1-온라인히스토리안-스펙.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# P1 스펙 — 온라인 히스토리안 + 실시간 KPI/알람
|
||||
|
||||
> 2026-06-14. 상위: [`작업플랜-셀프서비스-분석리포트-MVP.md`](작업플랜-셀프서비스-분석리포트-MVP.md) · 기반: [`작업플랜-셀프서비스-분석리포트-MVP-P0-상세설계.md`](작업플랜-셀프서비스-분석리포트-MVP-P0-상세설계.md).
|
||||
> **목표:** P0의 결정론 메트릭(마스크·적산·리셋)을 **온라인(실시간)** 으로 확장. 핵심 근거 = 메트릭 로직이 전부 **causal/incremental** 이라, *시각 T의 온라인 결과 = [시작~T] 배치 결과와 동일* → 로직 변경 없이 스트리밍 가능.
|
||||
|
||||
---
|
||||
|
||||
## 0. 4대 컴포넌트
|
||||
```
|
||||
gateway(1s poll) ─► Hc900RealtimeService
|
||||
├─ realtime_table (현재값 upsert, 기존)
|
||||
└─ history_1s (A. 1초 append — 큐레이션 태그, 링버퍼 보존 N일)
|
||||
└─(B. 연속집계)─► history_1min (장기·무손실 롤업)
|
||||
Hc900LiveKpiService (C. 온라인 누적기) ─► live_kpi ─► (D. 알람엔진) ─► kpi_alert
|
||||
메트릭엔진(P0): source = { history_1s | history_1min | history_table(60s) | fast_record }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## A. 1초 링버퍼 (`history_1s`) — 디스크 상한 고정
|
||||
|
||||
상시 1초 누적은 디스크 무한증가 → **윈도 고정 링버퍼**로 상한을 못박는다(시스템을 1년 돌려도 디스크 동일).
|
||||
|
||||
```sql
|
||||
CREATE TABLE hc900.history_1s (
|
||||
tagname text NOT NULL, recorded_at timestamptz NOT NULL,
|
||||
value text, controller_id text
|
||||
);
|
||||
SELECT create_hypertable('hc900.history_1s','recorded_at', chunk_time_interval => INTERVAL '1 hour');
|
||||
SELECT add_compression_policy('hc900.history_1s', INTERVAL '6 hours');
|
||||
SELECT add_retention_policy('hc900.history_1s', INTERVAL '14 days'); -- ← 윈도 = 디스크 예산 손잡이
|
||||
CREATE INDEX ON hc900.history_1s (tagname, recorded_at DESC);
|
||||
```
|
||||
- 보존정책 = **청크 DROP**(행 DELETE 아님)이라 비용 ≈ 0. 14일 후 자동 증발.
|
||||
- **디스크 = 태그수 × 윈도(초) × 행크기**. 예: 200태그 × 14일 × 1초 ≈ 2.4억 행, 압축(10~20×) 후 수~십 GB.
|
||||
|
||||
**적재**: `Hc900RealtimeService`(또는 신규 `Hc900FastHistoryService`)가 매 폴(1s)마다 **큐레이션 태그셋만** 배치 append(기존 500행/배치 패턴 재사용). realtime_table upsert와 병행.
|
||||
|
||||
## B. 연속집계 (`history_1min`) — 버퍼 evict 전 롤업, 무손실
|
||||
|
||||
1초가 버퍼에서 밀려나기 *전에* 60초로 materialize → 장기 이력 보존.
|
||||
```sql
|
||||
CREATE MATERIALIZED VIEW hc900.history_1min WITH (timescaledb.continuous) AS
|
||||
SELECT time_bucket('1 min', recorded_at) bucket, tagname,
|
||||
last(value::float, recorded_at) value, last(controller_id, recorded_at) controller_id
|
||||
FROM hc900.history_1s GROUP BY 1,2;
|
||||
SELECT add_continuous_aggregate_policy('hc900.history_1min',
|
||||
start_offset => INTERVAL '3 hours', end_offset => INTERVAL '10 minutes',
|
||||
schedule_interval => INTERVAL '5 minutes');
|
||||
```
|
||||
- **불변식: 집계 lag < 보존 윈도** (3h ≪ 14d) → raw 삭제 시 이미 집계 완료. 손실 0.
|
||||
- **2계층**: `history_1s`(최근 14일, 온라인·동특성·정밀 cleaning) + `history_1min`/기존 `history_table`(장기, 일·월·연 롤업).
|
||||
|
||||
## C. 온라인 KPI 누적기 (`Hc900LiveKpiService`)
|
||||
|
||||
배치처럼 윈도 재계산 대신 **러닝 상태** 유지(부하↓, 실시간↑). 기존 `Hc900HistoryService` BackgroundService 패턴.
|
||||
|
||||
```csharp
|
||||
// 컬럼×태그별 러닝 상태 (P0 QvDeltaAsync의 스트리밍 버전)
|
||||
record QvState { double Accum; double? PrevValue; bool PrevClean; }
|
||||
|
||||
// 매 1s 샘플(또는 1min tick)마다:
|
||||
foreach (col)
|
||||
cleaning = vac>VacMax || product<ProductMin || feed<FeedMin; // P0와 동일 마스크
|
||||
foreach (tag in [feed, product, lights, heavies, steam])
|
||||
if (!cleaning && !st.PrevClean && st.PrevValue is double p && v>=p && v-p<5e4)
|
||||
st.Accum += v - p; // P0와 동일 양증분합산
|
||||
st.PrevValue = v; st.PrevClean = cleaning;
|
||||
closure = 100 * (prodAccum+lightsAccum+heaviesAccum) / feedAccum;
|
||||
upsert live_kpi(col, 'closure'|'production'|'yield'|'energy', value, window_start, state, updated_at);
|
||||
```
|
||||
```sql
|
||||
CREATE TABLE hc900.live_kpi (
|
||||
column_id text, kpi text, value double precision,
|
||||
window_start timestamptz, state text, -- normal|cleaning|drawdown|transfer
|
||||
excluded_min int, updated_at timestamptz,
|
||||
PRIMARY KEY (column_id, kpi, window_start));
|
||||
```
|
||||
- **윈도 정책**: 일(日) 리셋(KST 자정 window_start 갱신) — 기존 누적은 `history_1min`/배치로 보존. (또는 trailing-24h 롤링 옵션.)
|
||||
- **크래시 복구**: 기동 시 `history_1s` 버퍼에서 현재 윈도를 **리플레이**해 상태 재구성(causal이라 동일 결과).
|
||||
- **인과성 보장**: 상태기반 = 매 샘플 현재값만 사용 → 누적기 결과(T) ≡ 배치(시작~T). 수용기준 §아래에서 동치 검증.
|
||||
|
||||
## D. 실시간 알람 (`kpi_alert`)
|
||||
|
||||
| 규칙 | 조건 | 의미 |
|
||||
|---|---|---|
|
||||
| cleaning 진입 | 진공>300 또는 제품<10 지속 | 세정 시작 |
|
||||
| drawdown 진입 | feed<10 & 제품>0 | 인벤토리 인출/컬럼간 이송 |
|
||||
| 폐합 이탈 | \|closure−100\|>2% 지속 M분 (정상구간서) | **계량 드리프트/누설/미계량 이송** |
|
||||
| 생산 정지 | production Δ≈0인데 비-cleaning | 트립/이상 |
|
||||
→ 기존 `event_history_table`/알림 경로 재사용. (마스크 자체가 cleaning/drawdown 판정을 이미 제공.)
|
||||
|
||||
---
|
||||
|
||||
## 큐레이션 태그셋 (1초 버퍼 대상)
|
||||
컬럼당(7컬럼): 유량 `FICQ-*01/13/14/16/18`·`FIQ-*15` 의 **.PV + .QV**, 진공 `PICA-*`, 민감단 `TI-*C`, 하부 `TICA-*A`(.PV/.SP/.OP), 핵심 압력/레벨. ≈ 25~30/컬럼 × 7 ≈ **~200 태그**. (전체 900 아님 — 메트릭·진단 관련만.) config 목록.
|
||||
|
||||
## P0 연계 (변경 최소)
|
||||
- 메트릭엔진 `source`에 `history_1s`/`history_1min` 추가 — **마스크 QvDelta SQL은 테이블만 교체**(이미 source 파라미터화). cleaning config 동일.
|
||||
- 웹 summary에 **live 모드**(live_kpi 직독) + source 셀렉터.
|
||||
|
||||
## 리스크 / 단서
|
||||
- 윈도(14일)보다 오래된 건 1초로 없음 → 60초만. 1초가 필요한 분석(전환 포렌식)은 최근 구간 한정. 일·월 리포트는 60초로 충분.
|
||||
- **불변식 집계 lag < 보존 윈도** 반드시 유지(아니면 장기 손실).
|
||||
- 태그셋 규율(900 전부 금지). 윈도 = 디스크 예산.
|
||||
- 진행 중 캠페인/이송(C-9111↔C-10111) 시 일중 폐합 ≠100%는 정상(KPI가 transfer 상태로 표시).
|
||||
- `realtime_table`은 upsert(시계열 아님) → 버퍼/메트릭 소스는 `history_1s`.
|
||||
|
||||
## 단계
|
||||
- **P1a**: `history_1s` 버퍼 + 보존/압축 + 큐레이션 적재(`Hc900FastHistoryService`).
|
||||
- **P1b**: 연속집계 `history_1min`(장기 무손실).
|
||||
- **P1c**: `Hc900LiveKpiService` 누적기 + `live_kpi` + summary live 모드.
|
||||
- **P1d**: 알람엔진 + `kpi_alert`.
|
||||
- (병행) `dynamics` 메트릭(fast/1s 전용: FOPDT·stiction), 월/연 롤업, C-9111↔C-10111 시스템 통합수지.
|
||||
|
||||
## 수용 기준
|
||||
1. `history_1s`가 정확히 최근 14일치 1초 보유, **디스크 상한 고정**; 그 이전은 `history_1min`에 보존(손실 0).
|
||||
2. **동치 검증**: `live_kpi`의 당일 closure == 같은 윈도 배치 `summary` 값(causal 동치).
|
||||
3. 합성 cleaning/drawdown 주입 시 상태 전이 + 알람 발화.
|
||||
4. 누적기 강제 재기동 → 버퍼 리플레이로 상태 동일 복구.
|
||||
|
||||
---
|
||||
*근거: P0 결정론 마스크/적산이 causal → 온라인 동치. TimescaleDB 하이퍼테이블/보존/연속집계(기존 history_table 동일 인프라), BackgroundService 패턴(Hc900RealtimeService/HistoryService). 관련 메모리: [[qv-cleaning-mask-and-column-links]], [[product-pivot-selfservice-reporting]].*
|
||||
Reference in New Issue
Block a user