171 lines
24 KiB
Markdown
171 lines
24 KiB
Markdown
# 35개 Scene 동등성 완료 매트릭스
|
|
|
|
기준 시각은 2026-07-12이다. 원본 `C:\Users\MD\source\repos\MBN_STOCK_N`은 읽기 전용으로만 분석했으며, 이 문서 작업에서도 원본 파일을 수정하지 않았다. 원본 35개 builder의 파일 해시는 [`legacy-scene-source-hashes.json`](legacy-scene-source-hashes.json), 원본 구조 기준선 검사는 [`Test-LegacySceneBaseline.ps1`](../scripts/Test-LegacySceneBaseline.ps1)에 있다.
|
|
|
|
이 문서에서 **구현 완료**는 DTO → mutation builder, 실제 데이터 loader, playlist selection resolver 또는 명시적 runtime route, 자동 테스트가 모두 존재한다는 뜻이다. **자동 동등성 완료**는 원본 35개 builder의 source hash/inventory 기준선을 고정하고, 원본 구현에서 도출한 오브젝트·mutation·호출 순서·45개 alias·PageN 기대값을 새 구현의 매트릭스와 자동 suite로 검증했다는 뜻이다. 실행 중인 구 구현과 새 구현을 같은 입력으로 직접 호출해 의미를 대조하는 comparator가 있다는 뜻은 아니다. **실제 Tornado 검증**은 승인된 scene과 회차에만 적용한다. 현재 마이그레이션 기준선은 완료됐지만 실제 PGM 증거를 승인되지 않은 나머지 scene으로 확대 해석하지 않는다.
|
|
|
|
## 현재 판정
|
|
|
|
| 항목 | 상태 | 근거와 제한 |
|
|
|---|---|---|
|
|
| 원본 inventory와 hash 기준선 | 완료 | 35/35 builder, 원본 기준선 스크립트 35/35 |
|
|
| DTO와 mutation builder | 완료 | registry가 정확히 35개 builder를 발견하고 catalog와 1:1 대조 |
|
|
| loader와 runtime route | 완료 | MainForm 도달 가능 builder 34개, active alias 45개를 fail-closed route로 등록; `s8086`은 원본과 같이 무alias 진단 전용 |
|
|
| 자동 테스트 | 완료 | Core 1,116/1,116, Playout 374/374, Infrastructure 125/125가 Debug/Release x64에서 각각 통과했다. 구성별 1,615개, 전체 3,230개이며 실패·skip·경고는 0건이다. Web 235/235와 원본 baseline 35/35도 통과 |
|
|
| Visual Studio 2026 빌드 | 완료 | MSBuild `18.7.8.30822`로 Debug x64와 signed Release x64 앱 패키지 빌드 성공 |
|
|
| Release x64 MSIX | 완료 | `1.0.2.0` 서명·설치·내용 감사와 package-context 실행 통과. SHA-256 `4A4ED867D16B75C1C82CB55DA5111E0502573F486B8B897889069843D9DF5072`; Web 24개가 source와 일치하고 금지 자산은 0건이며 기본 `DryRun`에서 전체 UI와 실제 DB 종목 검색을 확인. Round H의 승인된 실제 송출 증거는 아래 별도 행과 운영 문서에 보존 |
|
|
| 실제 데이터 전체 장면 smoke | 완료 | 34개 도달 가능 builder 전체 통과: 33개 Oracle/MariaDB loader와 `s5025` trusted 외부 CP949 파일. 무alias `s8086` diagnostic도 통과했고 실제 Oracle/MariaDB query 55/55가 성공했다. |
|
|
| 이번 마이그레이션의 실제 Tornado2/PGM | **승인 범위 완료** | 계획 SHA-256 `55C7755C2F874B4B012239117D4AB717BBCE194E7DCC8DA9B0E40D094FF8CA19`의 `MBNWEB-20260711-H`에서 `5001 → 자동 refresh 1회 → 5074 page 1 → page 2 → TAKE OUT`을 PGM과 Network Monitoring으로 함께 확인. 최종 검은 화면, retry 0, `OutcomeUnknown = false` |
|
|
|
|
Round H의 실제 Network Monitoring 합계는 `SCENE_PREPARE 5001 = 3`, `SCENE_PREPARE 5074 = 2`, `PLAY = 4`, `SCENE_PLAYED = 4`, `FAILURE = 0`, `ERROR = 0`이다. PGM은 5001 데이터, 5074의 page 1과 page 2를 순서대로 렌더링했고 TAKE OUT 뒤 검은 화면이 됐다. 이 증거는 승인된 두 scene에만 유효하다. 과거 실패 회차와 고정 runner는 장애 복구·기본 연결 근거로 보존하되 Round H의 동등성 근거를 대신하거나 확장하지 않는다.
|
|
|
|
## 표기
|
|
|
|
Mutation 약어는 실제 COM 메서드를 Web 입력에 노출하지 않는 COM-neutral 모델을 뜻한다.
|
|
|
|
| 약어 | mutation |
|
|
|---|---|
|
|
| `V` | `PlayoutSetValue` |
|
|
| `A` | `PlayoutSetAssetValue` |
|
|
| `Vis` | `PlayoutSetVisible` |
|
|
| `C` | `PlayoutSetFaceColor` |
|
|
| `Pos` | `PlayoutSetPosition` |
|
|
| `PosK` | `PlayoutSetPositionKey` |
|
|
| `Scale` | `PlayoutSetScale` |
|
|
| `Crop` | `PlayoutSetCropKey` |
|
|
| `Angle` | `PlayoutSetCircleAngleKey` |
|
|
| `Path` | `PlayoutSetPathPoints` |
|
|
| `Shape` | `PlayoutSetPathShapePoints` |
|
|
| `BgV` | `PlayoutSetBackgroundVideo` 및 background 사용 상태 |
|
|
|
|
실제 데이터 상태는 다음과 같이 기록한다.
|
|
|
|
- `DB-P`: 실제 Oracle/MariaDB 조회 → typed DTO → mutation preflight가 통과했다.
|
|
- `FILE-P`: `s5025`의 trusted 외부 CP949 수동 파일 → DTO → mutation preflight가 통과했다. 실제 파일과 디렉터리는 계속 Git 밖에 둔다.
|
|
- `DB-DP`: 원본 MainForm에서 도달하지 않는 `s8086` diagnostic 조회와 mutation preflight가 통과했다. 이 결과로 runtime alias를 만들지는 않는다.
|
|
- `TOR-W`: 이번 마이그레이션 runtime으로 해당 scene을 실제 Tornado2/PGM에서 검증하지 않았다. 회차 승인 전에는 실행하지 않는다.
|
|
- `TOR-H`: Round H의 승인된 WebView Live 회차에서 PGM 화면과 Network Monitoring을 함께 검증했다.
|
|
- `TOR-NA`: active alias가 없어 운영 송출 대상이 아니다.
|
|
|
|
## 자동 테스트 묶음
|
|
|
|
아래 묶음은 최신 Core Debug/Release x64 전체 실행에 포함돼 실패 0건으로 통과했다. 모든 행에는 공통으로 `LegacySceneCatalogTests`, `LegacySceneMutationBuilderRegistryTests`, `LegacySceneRuntimeCoverageTests`, `LegacySceneDataSourceRouterTests`가 적용된다.
|
|
|
|
| 코드 | 테스트 파일 |
|
|
|---|---|
|
|
| `T-PARAM` | `ParameterizedMarketSceneBuildersTests`, `ParameterizedMarketSceneDataLoadersTests`, `LegacyParameterizedSceneRequestResolverTests` |
|
|
| `T-PANEL` | `ReadOnlyPanelSceneBuildersTests`, `EquityPanelSceneDataLoadersTests`, `PanelSceneDataLoadersTests`, `MarketPanelSceneDataLoadersTests` |
|
|
| `T-GRID` | `TabularMarketSceneBuildersTests`, `FoundationalSceneBuildersTests`, `GridMarketSceneDataLoadersTests`, `TraderQuoteSceneDataLoadersTests`, `LegacyGridMarketSceneRequestResolverTests` |
|
|
| `T-MANUAL` | `TrustedManualSceneDataLoader5025Tests`, Infrastructure의 `S5025TrustedManualFileDataSourceTests` |
|
|
| `T-COMP` | `ComparisonAndYieldSceneBuildersTests`, `ComparisonAndYieldSceneDataLoadersTests`, `ComparisonAndYieldLegacyRequestResolverTests` |
|
|
| `T-CHART` | `ChartSceneBuilders5078To5084Tests`, `ChartSceneDataLoadersTests`, `ChartLegacySceneRequestResolverTests` |
|
|
| `T-PAGED` | `PagedQuoteSceneBuildersTests`, `PagedQuoteSceneDataLoadersTests`, `ScenePagingTests`, `LegacyPlayoutWorkflowTests` |
|
|
| `T-FOUND` | `FoundationalSceneBuildersTests`, `ManualSceneDataLoadersTests`, 해당 panel/grid loader 테스트 |
|
|
| `T-5082` | `GridSceneBuilder5082Tests` |
|
|
| `T-CANDLE` | `CandleSceneBuilderTests`, `CandleSceneDataLoaderTests` |
|
|
|
|
## 35개 builder별 완료 판정
|
|
|
|
| Builder / alias / page | 원본 기능 | 새 builder → loader → resolver/route | mutation | 자동 테스트 | 실제 데이터 | 실제 Tornado |
|
|
|---|---|---|---|---|---|---|
|
|
| `s5001` / `5001`, `N5001` / — | 국내·NXT·해외 지수, 환율, 업종, 종목 단일 시세와 등락 표식 | `S5001SceneMutationBuilder` → `S5001SceneDataLoader` → `LegacyParameterizedSceneRequestResolver` | `V, Vis, A` | `T-PARAM` 통과 | `DB-P` | `TOR-H` (`5001`) |
|
|
| `s5006` / `5006` / — | 국내·NXT 종목 현재·시가·고가·저가와 비율, 등락 상태, 큐브 배경 영상 | `S5006SceneMutationBuilder` → `S5006DomesticSceneDataLoader`/`S5006NxtSceneDataLoader` → market 직접 route | `V, Vis, C, BgV` | `T-PANEL` 통과 | `DB-P`; `Video\큐브배경.vrv` 외부 자산 누락 | `TOR-W` |
|
|
| `s5011` / `5011` / — | 국내·NXT 종목 시세, 액면가, 자본금, 시가총액, 순위 | `S5011SceneMutationBuilder` → `S5011SceneDataLoader` → branch 직접 route | `V, Vis, C` | `T-PANEL` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5016` / `5016` / — | 미국·중화권·유럽·아시아 지수와 채권·환율·원자재 3열 panel | `S5016SceneMutationBuilder` → `S5016SceneDataLoader` → closed target 직접 route | `V, Vis` | `T-PANEL` 통과 | `DB-P` | `TOR-W` |
|
|
| `s50160` / `50160` / — | 원면·국제금·국내금 2열 panel | `S50160SceneMutationBuilder` → `S50160SceneDataLoader` → closed target 직접 route | `V, Vis` | `T-PANEL` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5023` / `5023` / — | 코스피·코스닥 일별/월합계 주체별 매매동향 grid | `S5023SceneMutationBuilder` → `S5023SceneDataLoader` → `LegacyGridMarketSceneRequestResolver` | `V, C` | `T-GRID` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5024` / `5024` / — | 코스피·코스닥 매매동향 막대, 중앙선과 양·음 크기/위치 | `S5024SceneMutationBuilder` → `S5024SceneDataLoader` → `LegacyGridMarketSceneRequestResolver` | `V, Vis, Pos, Scale` | `T-GRID` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5025` / `5025` / — | 승인된 수동 파일의 개인·외국인·기관 순매도 좌·우 5쌍 | `S5025SceneMutationBuilder` → `S5025SceneDataLoader`/`S5025TrustedManualFileDataSource` → `LegacyGridMarketSceneRequestResolver` | `V` | `T-GRID`, `T-MANUAL` 통과 | `FILE-P`; 외부 CP949 파일 통합 검증 완료 | `TOR-W` |
|
|
| `s5026` / `5026` / — | 두 국내 종목 주간 candle과 각 종목 시세/OHLC | `S5026SceneMutationBuilder` → `S5026SceneDataLoader` → `ComparisonAndYieldLegacyRequestResolver` | `V, Vis, C, Crop` | `T-COMP` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5029` / `5029` / — | 두 종목 candle·수익률 비교와 두 path-shape | `S5029SceneMutationBuilder` → `S5029SceneDataLoader` → `ComparisonAndYieldLegacyRequestResolver` | `V, Vis, Pos, Shape` | `T-COMP` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5032` / `8018`, `8032`, `5032` 중 선물 조건 / — | 선물을 포함한 좌·우 두 항목 plate | `S5032SceneMutationBuilder` → `S5032SceneDataLoader` → `LegacyParameterizedSceneRequestResolver` | `V, Vis, A` | `T-PARAM` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5037` / `5037` / — | 국내 종목 현재가와 매수·매도 거래원별 수량 | `S5037SceneMutationBuilder` → `S5037SceneDataLoader` → `LegacyGridMarketSceneRequestResolver` | `V, Vis` | `T-GRID` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5074` / `5074` / 5 | Oracle/MariaDB/DataManager 계열의 최대 5행 시세·수익률 목록 | `S5074SceneMutationBuilder` → `S5074SceneDataLoader` → typed paged 직접 route | `V, Vis, A` | `T-PAGED` 통과 | `DB-P` | `TOR-H` (page 1/2) |
|
|
| `s5076` / `5076` / — | 주요매출 구성, 기준일, 항목 비율과 누적 원형 각도 | `S5076SceneMutationBuilder` → `S5076SceneDataLoader` → subject 직접 route | `V, Vis, Angle` | `T-FOUND` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5077` / `5077` / 6 | Oracle/MariaDB/DataManager 계열의 최대 6행 시세·수익률 목록 | `S5077SceneMutationBuilder` → `S5077SceneDataLoader` → typed paged 직접 route | `V, Vis, A` | `T-PAGED` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5078` / `5078` / — | 미국·국내 섹터지수 값과 양·음 막대 크기 | `S5078SceneMutationBuilder` → `S5078SceneDataLoader` → `ChartLegacySceneRequestResolver` | `V, Vis, Scale` | `T-CHART` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5079` / `5079` / — | 성장성 지표 기간·값과 복수 path | `S5079SceneMutationBuilder` → `S5079SceneDataLoader` → `ChartLegacySceneRequestResolver` | `V, Vis, Path` | `T-CHART` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5080` / `5080` / — | 매출액 분기 시계열과 양·음 막대/중앙선 | `S5080SceneMutationBuilder` → `S5080SceneDataLoader` → `ChartLegacySceneRequestResolver` | `V, Vis, PosK, Scale` | `T-CHART` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5081` / `5081` / — | 영업이익 분기 시계열과 양·음 막대/중앙선 | `S5081SceneMutationBuilder` → `S5081SceneDataLoader` → subject 직접 route | `V, Vis, PosK, Scale` | `T-FOUND` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5082` / `5082` / — | 일자·개인·기관·외국인 매매동향 grid와 부호 variant | `S5082SceneMutationBuilder` → `S5082SceneDataLoader` → 직접 route | `V, Vis` | `T-5082` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5083` / `5083` / — | 개인·기관·외국인 매매 시계열, baseline과 세 path | `S5083SceneMutationBuilder` → `S5083SceneDataLoader` → `ChartLegacySceneRequestResolver` | `V, Pos, Path` | `T-CHART` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5084` / `5084` / — | 코스피·코스닥 매매 시계열, baseline과 path | `S5084SceneMutationBuilder` → `S5084SceneDataLoader` → `ChartLegacySceneRequestResolver` | `V, Pos, Path` | `T-CHART` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5085` / `5085` / — | 프로그램 매매 grid의 구분별 금액과 부호 색상 | `S5085SceneMutationBuilder` → `S5085SceneDataLoader` → `LegacyGridMarketSceneRequestResolver` | `V, C` | `T-GRID`, `T-FOUND` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5086` / `5086` / — | 국내·해외 지수/종목/업종 수익률 시계열과 path-shape | `S5086SceneMutationBuilder` → `S5086SceneDataLoader` → `ComparisonAndYieldLegacyRequestResolver` | `V, Vis, Pos, Shape` | `T-COMP` 통과 | `DB-P` | `TOR-W` |
|
|
| `s50860` / `50860` / — | 국내·해외 지수/종목/업종 line 시계열과 path-shape | `S50860SceneMutationBuilder` → `S50860SceneDataLoader` → `ComparisonAndYieldLegacyRequestResolver` | `V, Vis, C, Pos, Shape` | `T-COMP` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5087` / `5087` / — | 두 국내 종목 candle·수익률 비교와 두 line shape | `S5087SceneMutationBuilder` → `S5087SceneDataLoader` → `ComparisonAndYieldLegacyRequestResolver` | `V, Vis, Pos, Shape` | `T-COMP` 통과 | `DB-P` | `TOR-W` |
|
|
| `s5088` / `5088` / 12 | Oracle/MariaDB/DataManager 계열의 최대 12행 시세·수익률 목록 | `S5088SceneMutationBuilder` → `S5088SceneDataLoader` → typed paged 직접 route | `V, Vis, A` | `T-PAGED` 통과 | `DB-P` | `TOR-W` |
|
|
| `s6001` / `6001` / — | 해외지수와 유가·금 단일 plate, 연계 이미지·영상/방향 상태 | `S6001SceneMutationBuilder` → `S6001SceneDataLoader` → closed target 직접 route | `V, A, Vis, C` | `T-PANEL` 통과 | `DB-P` | `TOR-W` |
|
|
| `s6067` / `6067` / — | 기관 순매수 grid와 부호 색상 | `S6067SceneMutationBuilder` → `S6067SceneDataLoader` → `LegacyGridMarketSceneRequestResolver` | `V, C` | `T-GRID`, `T-FOUND` 통과 | `DB-P` | `TOR-W` |
|
|
| `s8001` / `8001`, `8002` / — | 코스피·코스닥 업종 square chart와 cube 색상 | `S8001SceneMutationBuilder` → `S8001SceneDataLoader` → `LegacyParameterizedSceneRequestResolver` | `V, C` | `T-PARAM` 통과 | `DB-P` | `TOR-W` |
|
|
| `s8003` / `8003` / — | 국내 종목 호가·시세와 매수·매도 잔량 막대 | `S8003SceneMutationBuilder` → `S8003SceneDataLoader` → `LegacyGridMarketSceneRequestResolver` | `V, Vis, C, Scale` | `T-GRID` 통과 | `DB-P` | `TOR-W` |
|
|
| `s8010` / `8035`, `8061`, `8040`, `8046`, `8051`, `8056` / — | 지수·종목·거래정지·해외 candle, 거래량, 예상지수, 이동평균 path | `S8010SceneMutationBuilder` → `S8010SceneDataLoader` → alias/market/mode 직접 route | `V, Vis, C, Pos, Crop, Path` | `T-CANDLE` 통과 | `DB-P` | `TOR-W` |
|
|
| `s8018` / `8018`, `8032`, `5032` 중 비선물 조건 / — | 국내·NXT·해외·업종 좌·우 두 항목 plate | `S8018SceneMutationBuilder` → `S8018SceneDataLoader` → `LegacyParameterizedSceneRequestResolver` | `V, Vis, A` | `T-PARAM` 통과 | `DB-P` | `TOR-W` |
|
|
| `s8067` / `8067`, `5068`, `5070`, `5072` / — | 글로벌 world-map의 지역별 현재가·등락과 방향/배경 상태 | `S8067SceneMutationBuilder` → `S8067SceneDataLoader` → 직접 route | `V, Vis, C` | `T-FOUND`, `T-PANEL` 통과 | `DB-P` | `TOR-W` |
|
|
| `s8086` / active alias 없음 / — | 유가·금 3열 원천. 원본 파일은 있으나 MainForm dispatch 없음 | `S8086SceneMutationBuilder` → `S8086DiagnosticSceneDataLoader`; 앱 runtime route 없음 | `V, C` | `T-FOUND`, `T-PANEL` 통과 | `DB-DP` | `TOR-NA` |
|
|
|
|
## 공통 호출 순서 동등성
|
|
|
|
모든 runtime scene은 Web에서 object 이름이나 K3D 메서드를 받지 않는다. Web은 closed playlist selection만 보내고, loader가 조회 결과를 명시적 DTO로 만들며, registry의 typed builder가 allowlisted mutation을 생성한다.
|
|
|
|
PREPARE의 공통 순서는 다음과 같다.
|
|
|
|
1. 활성 playlist 항목과 cut alias를 결정하고 native loader로 page DTO를 조회한다.
|
|
2. scene을 load하고 cue-level background와 fade/scene effect를 적용한다.
|
|
3. `BeginTransaction`을 호출한다.
|
|
4. builder가 생성한 mutation을 원본 순서대로 적용한다.
|
|
5. `QueryVariables`를 호출한다.
|
|
6. `EndTransaction`을 호출한다.
|
|
7. layout 10을 `Prepare`한다.
|
|
|
|
TAKE IN은 PREPARE 때의 오래된 DTO를 그대로 재생하지 않는다. 원본 `ONAirMode`와 같이 현재 playlist snapshot의 같은 entry/page를 실제 DB에서 다시 조회하고 새 scene을 `LoadScene` → transaction → `Prepare(10)`한 뒤, 그 prepare가 명확히 성공한 경우에만 `Play(10)`을 한 번 호출한다. PREPARE를 다시 누르는 원본 toggle은 `TakeOut(All)`/`StopAll`로 state를 정리한다. timeout 또는 `OutcomeUnknown`은 retry 가능한 실패로 낮추지 않는다.
|
|
|
|
공통 fade와 배경은 Web 입력이 아니라 로컬 trusted playout 설정에서만 온다. `legacySceneFadeDuration`의 원본 기본값은 6이며, `legacySceneBackgroundKind`, scene root 아래의 상대 `legacySceneBackgroundAssetPath`, video loop 설정을 `PlayoutSceneCompositionFactory`가 검증한다. `DryRun`에서도 경로 탈출, 절대 경로, 허용되지 않은 확장자, reparse point, 누락 파일을 실제 COM 전에 fail-closed preflight한다. asset 경로는 Web 상태와 preview에 노출하지 않는다.
|
|
|
|
이 순서는 `RegisteredLegacySceneCueProviderTests`, `LegacyPlayoutWorkflowTests`, Playout의 `DynamicK3dSessionTests`, `TornadoPlayoutEngineTests`에서 검증한다. 실제 COM 형식과 vendor 구현은 계속 `IPlayoutEngine` 뒤에 있다.
|
|
|
|
## PageN과 NEXT 동등성
|
|
|
|
페이지 대상은 `s5074`(5), `s5077`(6), `s5088`(12)이다. 일반 시장과 NXT 시장이 같은 계산기를 사용하며 page index는 0부터 시작한다.
|
|
|
|
- `pageCount = min(20, ceil(itemCount / pageSize))`다.
|
|
- 경계값 `0`, `1`, `size-1`, `size`, `size+1`, `20*size`, `20*size+1`을 테스트한다.
|
|
- 마지막 부분 페이지는 남은 행만 채우고 나머지 object를 clear/hide한다.
|
|
- `s5088`의 NXT 인덱스는 비교와 조회 모두 `i + pageIndex * 12`를 사용한다.
|
|
- 현재 항목에 다음 page가 있으면 operator Page NEXT는 playlist index를 유지하되 원본 `Next_Scene(0)`처럼 다음 page 데이터를 조회하고 새 scene을 `LoadScene` → transaction mutation → `QueryVariables` → `EndTransaction` → `Prepare(10)` → `Play(10)`한다. 이 경로는 `GetPlayingScene` in-place refresh가 아니다.
|
|
- 마지막 page면 다음 활성 playlist 항목으로 이동한다. 비활성 항목은 원본처럼 앞으로 건너뛰며 끝에서 wrap하지 않는다.
|
|
- 원본 timer는 TAKE IN과 playlist NEXT 뒤 반복되며 첫 `m_time` 이후 3초 주기로 계속 실행된다. 새 runtime도 반복 갱신을 유지하지만, 이전 tracked `Play`의 `OnScenePlayed` callback을 drain한 뒤에야 첫 `m_time` 또는 3초의 **전체 cooldown**을 시작한다. 이는 callback 대기와 delay가 겹쳐 operator window가 사라지는 일을 막는 의도적 안전 적응이다. 모든 operator command는 현재 epoch를 먼저 중단하고 Page NEXT 뒤에는 refresh를 재시작하지 않는다.
|
|
- 원본 `timer1_Tick`에는 mutation 전 선행 `Play(10)`과 `Prepare` 뒤 후행 `Play(10)`이 모두 있다. 마이그레이션은 불완전한 `GetPlayingScene` proxy 대신 retained on-air scene에 fresh DTO mutation을 적용하고 `BeginTransaction → mutation → QueryVariables → EndTransaction → Prepare(10) → tracked Play(10)` 한 번만 보낸다. 선행 replay를 생략한 것은 callback 추적 없이 PLAY를 중복시키지 않기 위한 명시적 안전 차이이며 Round H의 정확한 PLAY/callback 4회 예산에 반영됐다.
|
|
- refresh CTS와 공개 상태는 atomic epoch로 결합한다. `Replace`/`Stop`/조건부 update/completion이 같은 lock에서 generation을 확인하므로 취소된 이전 loop가 `active`, `NextAt`, success 또는 fault를 새 loop나 중단 상태 위에 다시 쓰지 못한다.
|
|
|
|
## WebView 동등성 및 안전 상태
|
|
|
|
- Web catalog는 35개 builder와 도달 가능한 45개 active cut alias를 모두 보존하며 `s8086`은 선택 불가 진단 항목으로 유지한다.
|
|
- 각 playlist row는 원본 active flag에 대응하는 `enabled`를 제공한다. PREPARE 성공 시 전체 playlist와 선택 index를 immutable native snapshot으로 고정한다. pending command 또는 `OutcomeUnknown`/timeout quarantine 중에도 snapshot 편집을 잠그며, 그 상태가 해제될 때까지 Web 편집값으로 NEXT 대상을 바꾸지 않는다.
|
|
- native 결과가 authoritative source이며 `currentEntryId`, `builderKey`, `pageSize`, `currentPageItemCount`, `isLastPage`, `nextKind`와 bounded mutation preview를 표시한다.
|
|
- preview는 object별 typed 값/상태를 보여주되 image, texture, video와 공통 background의 실제 asset path는 항상 `configured` 같은 비밀 없는 상태로 치환한다.
|
|
- refresh의 active/next/last-success/fault 상태를 표시한다. refresh DB·scene·COM 실패는 fault latch를 세워 TAKE OUT 외의 mutation 명령을 막고 자동 반복하지 않는다. 성공한 TAKE OUT 뒤 native refresh state가 reset되면 전용 refresh fault marker만 지우며 `OutcomeUnknown`이나 timeout quarantine은 함께 지우지 않는다.
|
|
- native 응답 상관관계가 Web 제한 시간 안에 끝나지 않으면 `WEB_TIMEOUT`을 native에 보고한다. `ParseTimeoutQuarantine`이 검증한 요청은 MainWindow의 process-lifetime latch를 먼저 세운 뒤 vendor session을 quarantine하므로 WebView reload로 해제되지 않는다. 늦은 응답이나 UI 재시도로 같은 명령을 다시 보내지 않으며 authoritative native/PGM 상태를 사람이 확인한다.
|
|
|
|
## Callback과 scene 수명
|
|
|
|
- `OnScenePlayed`가 성공한 뒤 이전 scene을 retired queue로 옮겨 안전하게 unload한다.
|
|
- `OnCutOut`은 해당 layout의 on-air 참조를, `OnStopAll`은 player의 모든 on-air 참조를 정리할 근거다.
|
|
- 이전 connection generation의 늦은 callback은 현재 state를 바꾸지 않는다.
|
|
- pending Play callback이 있으면 TAKE OUT을 제외한 PREPARE/TAKE IN/NEXT/timer refresh를 fail-closed 차단한다. 어떤 lifecycle callback이든 pending이면 Disconnect와 session recycle을 하지 않고 abandon/quarantine 및 `OutcomeUnknown`으로 보수적으로 전환한다.
|
|
- `StopAll`/`CutOut`은 SDK dispatch 전에 각 pending completion counter를 올리고 동기 호출 실패 시 되돌린다. 성공 callback은 대응 counter를 정확히 하나 줄이며, 성공한 stop/cut은 중단된 Play가 뒤늦게 `OnScenePlayed`를 보내지 않을 수 있으므로 해당 pending Play accounting을 취소한다. dispatch 뒤 cancellation/timeout은 결과 불명확으로 취급한다.
|
|
- 장기 실행 시 retired scene은 callback으로 안전성이 확인된 뒤 unload/release한다.
|
|
|
|
운영·장애 복구·승인 절차는 [`PLAYOUT_OPERATIONS.md`](PLAYOUT_OPERATIONS.md)를 따른다.
|
|
|
|
## 완료 판정과 실제 송출 범위
|
|
|
|
35개 builder, 45개 active alias, DTO/mutation, 실제 DB 55-query, 5·6·12행 PageN 경계와 마지막 페이지, Debug/Release x64 suite와 packaged `DryRun`은 완료 기준을 충족했다. Round H는 설치된 Release x64 MSIX의 WebView workflow로 승인된 `5001`과 `5074`에 대해 PREPARE → fresh TAKE IN → 자동 refresh → playlist NEXT → Page NEXT → TAKE OUT을 실제 Tornado2에서 완료했다.
|
|
|
|
이 완료 판정에는 다음 범위 제한이 있다.
|
|
|
|
1. 실제 Tornado2/PGM 화면 증거는 `5001`과 `5074` page 1/page 2뿐이다. 다른 builder의 실제 송출은 해당 scene과 자산을 묶은 새 계획·승인이 필요하다.
|
|
2. `s5025`는 승인된 trusted 외부 CP949 파일이 필수이며 파일·경로는 Git과 MSIX에 포함하지 않는다.
|
|
3. `s5006`의 background video 등 외부 asset이 필요한 scene은 승인된 asset root가 준비돼야 실제 송출할 수 있다.
|
|
4. timeout, `OutcomeUnknown`, refresh fault 또는 callback/연결 장애가 발생한 회차에서는 동일 명령을 반복하지 않고 [`PLAYOUT_OPERATIONS.md`](PLAYOUT_OPERATIONS.md)의 복구 절차를 적용한다.
|