feat: migrate legacy playout workflow and scenes
This commit is contained in:
261
docs/PLAYOUT_OPERATIONS.md
Normal file
261
docs/PLAYOUT_OPERATIONS.md
Normal file
@@ -0,0 +1,261 @@
|
||||
# MBN_STOCK_WEBVIEW 송출 운영·검증 절차
|
||||
|
||||
이 문서는 마이그레이션된 WebView → `IPlayoutEngine` → K3D/Tornado2 경로를 검증할 때의 승인, 실행, 감시, 장애 복구와 rollback 기준이다. 기존 [`PLAYOUT.md`](PLAYOUT.md)의 K3D 설치·해시 핀·격리 진단 규칙을 대체하지 않고, 35개 scene과 PageN 동등성 검증에 필요한 운영 절차를 추가한다.
|
||||
|
||||
## 현재 상태
|
||||
|
||||
| 항목 | 상태 |
|
||||
|---|---|
|
||||
| 기본 모드 | `DryRun`; COM 객체와 `KTAPConnect`를 만들지 않음 |
|
||||
| 자동 테스트 | 최신 전체 재검증에서 Core Debug/Release x64 각각 779/779, Playout 각각 355/355, Infrastructure 각각 64/64, Web safety 11/11 통과; 이후 테스트 추가 시 개수보다 실패 0건을 기준으로 재확인 |
|
||||
| Visual Studio 2026 | Debug/Release x64 빌드 성공 |
|
||||
| trusted Release x64 MSIX | 생성·서명 검증·x64 설치·package context 실행 성공. 실제 DB DryRun에서 5001 timer refresh, 5074 playlist/Page NEXT와 1~20페이지 마지막 경계, TAKE OUT 정리를 확인 |
|
||||
| 실제 데이터 전체 scene smoke | 34개 도달 가능 builder 통과: 33개 DB + `s5025` trusted 외부 CP949 파일. `s8086` diagnostic 포함 Oracle/MariaDB query 55건 통과 |
|
||||
| `s5025` trusted 수동 파일 | 외부 CP949 source 통합 검증 통과; 실제 파일/환경은 계속 Git 밖에서 회차별 preflight |
|
||||
| `s5006` `Video\큐브배경.vrv` | 현재 승인 Cuts root에서 누락 |
|
||||
| 이번 마이그레이션 WebView workflow의 실제 Tornado2 검증 | **미승인·미실행** |
|
||||
|
||||
과거 고정 `5001 → 5006` runner의 실제 PGM 기록은 연결과 기본 K3D 명령 표면의 증거다. 현재 WebView playlist, fresh TAKE IN, Page NEXT, timer refresh, callback/unload의 동등성 완료 증거는 아니다. 이번 WebView runtime의 실제 Tornado2 Network Monitoring/PGM 회차는 여전히 승인되지 않았고 실행하지 않았다.
|
||||
|
||||
## 절대 안전 규칙
|
||||
|
||||
1. 앱의 기본값은 항상 `DryRun`으로 유지한다.
|
||||
2. `DryRun`, `--probe`, `--dry-run`, `--test-plan`은 `KTAPConnect`를 호출하지 않는다. 이때 Tornado2 Network Monitoring에 기록이 없는 것이 정상이다.
|
||||
3. 실제 출력은 승인된 테스트 scene, 지정된 PGM, 지정된 회차에서만 허용한다.
|
||||
4. Connect/PREPARE를 시작하기 전에 회차 범위 승인이 있어야 한다. **현재 PGM에 TAKE IN을 보내기 직전에는 같은 회차의 별도 명시적 승인을 다시 받아야 한다.**
|
||||
5. 승인에 없는 NEXT, Page NEXT, TAKE OUT 이외 명령 또는 다른 scene으로 범위를 넓히지 않는다.
|
||||
6. timeout, `OutcomeUnknown`, `WEB_TIMEOUT`, refresh fault, 응답/화면 불일치, 대상 프로세스 변경, callback 누락 상태에서는 같은 명령을 자동 또는 수동으로 반복하지 않는다.
|
||||
7. 실제 검증 회차에는 `reconnectEnabled=false`, `maximumReconnectAttempts=0`을 사용한다. 재접속은 새 회차와 새 승인으로만 수행한다.
|
||||
8. 안전 게이트, x64 vendor hash pin, scene allowlist, process/window/port ownership 검사를 완화하지 않는다.
|
||||
9. Web 입력으로 object 이름, 파일 경로, K3D method, 임의 SQL을 받지 않는다.
|
||||
10. 실제 on-air일 수 있는 scene을 수동으로 unload하거나 COM RCW를 강제 release하지 않는다.
|
||||
11. pending Play callback이 있으면 TAKE OUT 이외의 PREPARE/TAKE IN/NEXT/timer refresh를 실행하지 않는다. lifecycle callback이 남아 있으면 Disconnect하지 않는다.
|
||||
|
||||
## Git 밖에서 준비할 항목
|
||||
|
||||
다음 항목은 로컬 운영 설정 또는 승인된 외부 자산이다. Git, MSIX, 로그 첨부, 테스트 fixture에 복사하지 않는다.
|
||||
|
||||
- 원본 test Cuts root: `C:\Users\MD\source\repos\MBN_STOCK_N\MBN_STOCK_N\bin\Debug\Cuts`
|
||||
- 실제 `.t2s`, image, texture, video와 기타 scene 자산
|
||||
- `s5006`의 상대 자산 `Video\큐브배경.vrv`; 현재 위 Cuts root에는 없으므로 제공 전 실제 PREPARE 금지
|
||||
- `s5025` trusted CP949 수동 파일 디렉터리와 환경 변수 `MBN_STOCK_S5025_MANUAL_DATA_DIRECTORY`
|
||||
- Oracle/MariaDB host, SID/service, database, user, password와 운영 query selector
|
||||
- K3D/Tornado vendor DLL, Interop, license와 설치 경로
|
||||
- `MBN_STOCK_K3D_NATIVE_SHA256`, `MBN_STOCK_K3D_INTEROP_SHA256` 승인 값과 승인 근거
|
||||
- MSIX 서명 인증서, 개인 키, 암호와 배포용 secrets
|
||||
- 실제 Tornado host/port, output channel, PGM 창 정보와 운영 설정
|
||||
- Network Monitoring/PGM screenshot·영상·manifest 등 실제 방송 증거
|
||||
|
||||
Cuts root는 이번 작업에서 읽기 전용으로 취급한다. [`Test-LegacyCutCoverage.ps1`](../scripts/Test-LegacyCutCoverage.ps1)은 45개 active alias의 cut 존재 여부만 검사하며 자산을 복사하거나 수정하지 않는다.
|
||||
|
||||
## 승인 게이트
|
||||
|
||||
### Gate A: 회차 범위 승인
|
||||
|
||||
Connect 또는 실제 PREPARE 전에 다음 내용을 운영 기록에 남긴다.
|
||||
|
||||
```text
|
||||
[MBN_STOCK_WEBVIEW Tornado 검증 회차]
|
||||
회차 ID:
|
||||
예정 시각/최대 종료 시각:
|
||||
대상 Tornado2/PGM 식별값:
|
||||
승인된 test cut alias:
|
||||
승인된 selector와 시작 page:
|
||||
허용 동작과 횟수: CONNECT, PREPARE, TAKE IN, NEXT/Page NEXT, timer refresh 관찰, TAKE OUT, DISCONNECT
|
||||
Network Monitoring/PGM 관찰 담당자:
|
||||
비상 TAKE OUT 담당자:
|
||||
```
|
||||
|
||||
대상, cut, selector, page, 횟수 중 하나라도 바뀌면 같은 회차 승인을 재사용하지 않는다.
|
||||
|
||||
### Gate B: TAKE IN 직전 승인
|
||||
|
||||
PREPARE 결과와 Network Monitoring 상태를 운영자가 확인한 후, TAKE IN 직전에 다음과 같이 명시적인 승인을 받아야 한다.
|
||||
|
||||
```text
|
||||
회차 <ID>의 준비된 cut <alias>, page <N>을 현재 PGM에 TAKE IN 1회 실행하는 것을 승인한다.
|
||||
```
|
||||
|
||||
이 문구가 없거나 회차 ID/cut/page가 다르면 TAKE IN을 실행하지 않는다. 이전 대화의 일반적 동의, 과거 회차 승인, DryRun 성공은 Gate B를 충족하지 않는다.
|
||||
|
||||
## 실제 연결 전 offline preflight
|
||||
|
||||
아래 단계는 Tornado에 명령을 보내지 않는다.
|
||||
|
||||
1. 원본 기준선과 cut alias를 확인한다.
|
||||
|
||||
```powershell
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\Test-LegacySceneBaseline.ps1
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\Test-LegacyCutCoverage.ps1 `
|
||||
-CutRoot "C:\Users\MD\source\repos\MBN_STOCK_N\MBN_STOCK_N\bin\Debug\Cuts"
|
||||
```
|
||||
|
||||
2. Debug/Release x64 테스트와 Web bridge 검사를 실행한다.
|
||||
|
||||
```powershell
|
||||
dotnet test .\tests\MBN_STOCK_WEBVIEW.Core.Tests\MBN_STOCK_WEBVIEW.Core.Tests.csproj -c Debug -p:Platform=x64
|
||||
dotnet test .\tests\MBN_STOCK_WEBVIEW.Core.Tests\MBN_STOCK_WEBVIEW.Core.Tests.csproj -c Release -p:Platform=x64
|
||||
dotnet test .\tests\MBN_STOCK_WEBVIEW.Playout.Tests\MBN_STOCK_WEBVIEW.Playout.Tests.csproj -c Debug -p:Platform=x64
|
||||
dotnet test .\tests\MBN_STOCK_WEBVIEW.Playout.Tests\MBN_STOCK_WEBVIEW.Playout.Tests.csproj -c Release -p:Platform=x64
|
||||
dotnet test .\tests\MBN_STOCK_WEBVIEW.Infrastructure.Tests\MBN_STOCK_WEBVIEW.Infrastructure.Tests.csproj -c Debug -p:Platform=x64
|
||||
dotnet test .\tests\MBN_STOCK_WEBVIEW.Infrastructure.Tests\MBN_STOCK_WEBVIEW.Infrastructure.Tests.csproj -c Release -p:Platform=x64
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\Test-WebPlayout.ps1
|
||||
```
|
||||
|
||||
3. 실제 DB smoke는 read-only query만 사용하는 별도 단계로 실행한다. DB 오류가 있으면 Tornado 단계로 넘어가지 않는다.
|
||||
|
||||
```powershell
|
||||
dotnet run --project .\tools\MBN_STOCK_WEBVIEW.DbSmoke\MBN_STOCK_WEBVIEW.DbSmoke.csproj -c Release --no-restore
|
||||
```
|
||||
|
||||
4. 설치된 trusted Release x64 MSIX가 package context에서 실행되는지 확인한다. `bin` 또는 loose EXE를 실제 검증에 사용하지 않는다.
|
||||
5. K3D Registry64, AMD64 PE, TypeLib/Interop metadata, 두 SHA-256 pin, license를 확인한다. DLL을 repo 또는 앱 폴더로 복사해 우회하지 않는다.
|
||||
6. 정확히 하나의 승인 대상 Tornado2 프로세스, PGM 창, Network Server TCP port와 LISTEN 소유권을 확인한다. 매뉴얼 예시 port를 추정해 사용하지 않는다.
|
||||
7. `s5025`를 선택했다면 trusted 외부 디렉터리와 파일 preflight가 성공해야 한다. `s5006`를 선택했다면 `Video\큐브배경.vrv`가 승인 asset root 안에 있어야 한다.
|
||||
8. 실제 COM을 사용하는 Test/Live playlist의 모든 cut이 로컬 폐쇄형 allowlist 안에 있고 selector가 closed enum/lookup 규칙을 통과하는지 DryRun에서 확인한다. allowlist가 비어 있으면 실제 모드 초기화 자체를 거부해야 한다.
|
||||
9. 로컬 playout 설정의 `legacySceneFadeDuration` 기본값 6과 `legacySceneBackgroundKind`를 확인한다. 공통 background를 쓸 때 `legacySceneBackgroundAssetPath`는 `sceneDirectory` 아래의 승인된 상대 경로여야 한다. `PlayoutSceneCompositionFactory`의 DryRun preflight가 파일 존재, 허용 확장자, root 탈출, 절대 경로와 reparse point를 모두 거부하는지 확인한다. Web에는 이 asset 경로를 보내지 않는다.
|
||||
10. Web DryRun에서 45개 active alias, row별 `enabled`, PREPARE 뒤 snapshot freeze, current entry/builder/page size/current rows/last-page/preview와 refresh 상태를 확인한다. pending command와 `OutcomeUnknown`/timeout quarantine에서도 playlist 편집이 잠겨야 한다. preview에 image/texture/video 경로가 나타나면 실제 회차를 중단한다.
|
||||
|
||||
하나라도 실패하면 회차를 시작하지 않는다. 설정을 수정한 뒤 처음부터 새 preflight 결과를 만든다.
|
||||
|
||||
## 정상 실행 순서와 관찰점
|
||||
|
||||
### 1. Connect
|
||||
|
||||
- Gate A와 모든 preflight를 다시 확인한다.
|
||||
- Connect는 한 번만 보낸다.
|
||||
- `OnHello`와 Network Monitoring의 request/response를 함께 확인한다.
|
||||
- Connect 결과가 accepted이지만 `OnHello` 또는 monitor 왕복이 확인되지 않으면 준비 완료로 간주하지 않는다.
|
||||
|
||||
### 2. PREPARE
|
||||
|
||||
PREPARE는 다음 native 순서를 수행해야 한다.
|
||||
|
||||
1. 현재 활성 playlist 항목과 page 0을 native loader가 조회한다.
|
||||
2. scene load, trusted common background와 기본 fade 6 또는 승인된 로컬 fade/scene effect를 적용한다.
|
||||
3. `BeginTransaction` → allowlisted mutation → `QueryVariables` → `EndTransaction`을 실행한다.
|
||||
4. layout 10을 `Prepare`한다.
|
||||
|
||||
관찰자는 Network Monitoring의 load/prepare 관련 왕복이 한 번씩인지, 앱이 `Prepared`와 정확한 cue/page를 표시하는지 확인한다. PGM에 의도하지 않은 on-air 변화가 있으면 즉시 회차를 중단하고 장애 절차를 따른다.
|
||||
|
||||
### 3. TAKE IN
|
||||
|
||||
- Gate B를 받은 뒤 한 번만 실행한다.
|
||||
- PREPARE 때의 DTO를 재사용하지 않고 frozen entry/page를 실제 DB에서 새로 조회하는지 확인한다.
|
||||
- fresh scene의 `LoadScene` → transaction → `Prepare(10)`이 명확히 성공한 뒤 `Play(10)`이 한 번 실행되는지와 `OnScenePlayed`를 확인한다.
|
||||
- PGM에서 원본과 비교할 object 이름별 값, 표시 상태, 색, 위치/크기, crop, path, image/texture/video, fade를 기록한다.
|
||||
- Network Monitoring의 두 번째 load/prepare와 PLAY request/response, PGM 화면 시각을 같은 증거 묶음에 보존한다.
|
||||
|
||||
### 4. NEXT
|
||||
|
||||
앱이 반환한 `nextKind`가 기준이다. Web에서 임의로 page/playlist 유형을 정하지 않는다.
|
||||
|
||||
- `PageNext`: playlist index를 유지하고 원본 `Next_Scene(0)`처럼 다음 page의 fresh 데이터를 조회한 뒤 새 scene을 `LoadScene` → transaction mutation → `QueryVariables` → `EndTransaction` → `Prepare(10)` → `Play(10)`한다. 이 경로에서 `GetPlayingScene` in-place 갱신을 기대하지 않는다.
|
||||
- `PlaylistNext`: 현재 page가 마지막일 때 다음 활성 playlist 항목을 load/prepare/play한다. 비활성 항목은 앞으로 건너뛰고 끝에서 wrap하지 않는다.
|
||||
- 각 NEXT는 Gate A에 승인된 유형과 횟수 안에서만 한 번씩 실행한다.
|
||||
- `pageIndex`, `pageCount`, `itemCount`, 마지막 부분 page의 빈 object clear/hide와 PGM 화면을 함께 확인한다.
|
||||
- 모든 operator command는 timer를 먼저 멈춘다. TAKE IN/playlist NEXT 뒤에는 원본 `m_time`으로 첫 timer가 시작되지만 Page NEXT 성공 뒤에는 timer가 정지 상태로 남아야 한다.
|
||||
|
||||
### 5. Timer refresh
|
||||
|
||||
- 승인 범위에 포함된 경우에만 자동 refresh를 관찰한다. 첫 실행은 해당 cut의 원본 `m_time` 뒤, 이후 성공한 실행은 3초 간격이어야 한다.
|
||||
- 각 tick은 current entry/page의 fresh DB DTO를 사용하며 K3D 호출은 원본처럼 `Play(10)` → `GetPlayingScene(10)` → transaction mutation → `QueryVariables` → `EndTransaction` → `Prepare(10)` → `Play(10)` 순서다.
|
||||
- timer refresh는 scene-level background와 fade effect를 다시 적용하지 않는다.
|
||||
- 앱의 `refreshActive`, `refreshNextAt`, `refreshLastSuccessAt`, fault code/message와 PGM 데이터를 함께 기록한다.
|
||||
- refresh가 실패하거나 timeout/unknown이면 fault latch가 켜지고 반복이 즉시 끝나야 한다. TAKE OUT 이외의 명령을 시도하지 않는다.
|
||||
- 명확히 성공한 TAKE OUT 뒤 native refresh state가 reset되면 전용 refresh fault marker만 사라져야 한다. `OutcomeUnknown`, `WEB_TIMEOUT` 또는 native quarantine 표시는 함께 reset되면 안 된다.
|
||||
|
||||
### 6. TAKE OUT과 Disconnect
|
||||
|
||||
- 승인된 TAKE OUT 한 번으로 `TakeOut(All)`/`StopAll`을 실행한다.
|
||||
- `OnCutOut` 또는 `OnStopAll`, 앱 state clear와 PGM의 검은 화면 또는 승인된 종료 상태를 확인한다.
|
||||
- pending callback과 retired scene 정리가 끝난 뒤에만 Disconnect한다.
|
||||
- Network Monitoring에서 stop 계열 왕복과 BYE/disconnect를 확인한다.
|
||||
|
||||
## Network Monitoring과 PGM 증거 체크리스트
|
||||
|
||||
vendor monitor의 실제 명령 표기는 버전에 따라 다를 수 있으므로 추정 문자열로 성공을 만들지 않는다. raw 화면과 시각을 보존하고 다음 의미 단위로 대조한다.
|
||||
|
||||
| 단계 | Network Monitoring | PGM/앱 |
|
||||
|---|---|---|
|
||||
| Connect | HELLO 또는 대응 connect request/response 한 쌍 | 앱 Connected, 대상 process generation 일치 |
|
||||
| PREPARE | scene load, mutation transaction, prepare의 중복 없는 왕복 | Prepared cue/page/row 수 일치, 의도하지 않은 on-air 없음 |
|
||||
| TAKE IN | fresh DB 결과의 두 번째 load/prepare 뒤 PLAY request/response | `OnScenePlayed`, 실제 object 값과 시각 상태 일치 |
|
||||
| Page NEXT | 같은 alias의 새 scene load/transaction/prepare/play 왕복 | playlist index 유지, page만 +1, 빈 slot clear/hide, refresh timer 정지 |
|
||||
| Playlist NEXT | 다음 cut load/prepare/play 왕복 | 다음 활성 항목과 page 0 표시 |
|
||||
| Timer refresh | PLAY, `GetPlayingScene` update transaction, prepare, PLAY의 중복 없는 왕복 | 첫 `m_time` 뒤 실행, 이후 3초, 같은 entry/page의 fresh 값, refresh 상태 정상 |
|
||||
| TAKE OUT | STOP/STOPALL 대응 왕복 | `OnCutOut`/`OnStopAll`, 승인된 종료 화면 |
|
||||
| Disconnect | BYE 또는 대응 disconnect 왕복 | callback pending 0, 연결 해제 |
|
||||
|
||||
회차 증거에는 다음을 포함한다.
|
||||
|
||||
- 회차 ID, package version, Git commit, 실행 시각과 timezone
|
||||
- cut alias, closed selector, page index/count, DB 조회 식별값; password와 connection string 제외
|
||||
- 각 앱 명령의 결과 code와 `OutcomeUnknown` 여부
|
||||
- 같은 시각의 Network Monitoring과 PGM 화면
|
||||
- PREPARE/TAKE IN/NEXT/timer refresh/TAKE OUT 전후 screenshot 또는 연속 capture
|
||||
- callback 순서, retired/unloaded scene 수, disconnect 결과
|
||||
- Web의 frozen entry/builder/page size/current rows/last-page/preview와 refresh status; asset path는 제외
|
||||
- 운영자 최종 판정과 불일치 목록
|
||||
|
||||
증거는 Git 제외 로컬 경로 또는 승인된 증거 저장소에 보관한다. 캡처에 host, port, 계정, license 정보가 보이면 외부 전달 전에 별도 보안 절차로 처리하며 원본 증거를 repo에 넣지 않는다.
|
||||
|
||||
## 장애 판정과 반복 금지
|
||||
|
||||
| 상황 | 즉시 조치 | 재시도 조건 |
|
||||
|---|---|---|
|
||||
| DB/selector/asset preflight 실패, COM 호출 전 명시적 `Rejected` | 회차 중단, DryRun으로 복귀, 원인 기록 | offline 수정과 전체 preflight 후 새 회차 승인 |
|
||||
| Connect timeout 또는 `OnHello`/monitor 불일치 | 결과를 불명확으로 격리, Connect 반복 금지 | 운영자가 세션과 process/port 상태를 확인한 뒤 새 회차 승인 |
|
||||
| PREPARE/TAKE IN/NEXT/refresh/TAKE OUT timeout | `OutcomeUnknown`으로 취급, 같은 명령과 반대 명령 자동 실행 금지 | PGM/monitor/콜백을 사람이 확인하고 출력 안전을 복구한 뒤 새 회차 승인 |
|
||||
| `WEB_TIMEOUT` | strict timeout-quarantine message를 native에 전달. MainWindow가 process-lifetime latch를 먼저 세우고 vendor session을 quarantine; 늦은 응답, UI 재시도와 WebView reload로 해제 금지 | native status와 PGM을 사람이 대조하고 process를 새로 시작한 뒤 새 승인 |
|
||||
| refresh DB/scene/COM fault | refresh loop 중단, fault latch 유지, TAKE OUT 외 명령 금지 | 정상 TAKE OUT과 실제 화면 확인 후 offline 원인 수정, 새 회차 승인 |
|
||||
| 명령 성공 응답과 PGM 화면 불일치 | 앱 state를 신뢰하지 말고 회차 중단 | PGM 운영자가 실제 상태를 판정하고 새 회차 승인 |
|
||||
| callback 누락/지연 | scene을 unload하거나 disconnect 강제하지 않음 | callback 도착 또는 운영자의 수동 안전 판정 후 새 회차 |
|
||||
| Tornado process generation, 창, LISTEN 소유권 변경 | 모든 자동 동작 중지, 대상 격리 | 새 process를 처음부터 검증하고 새 승인 |
|
||||
| 연결 장애/Disconnect timeout | 자동 reconnect 금지, 연결·출력 상태를 불명확으로 기록 | 운영자가 Tornado 세션을 확인한 뒤 새 회차 |
|
||||
|
||||
`OutcomeUnknown`은 단순 실패 code가 아니라 실제 출력 결과를 모른다는 latch다. Cancelled, Rejected, `WEB_TIMEOUT` 또는 UI 오류로 낮추지 않는다. timeout quarantine은 native process-lifetime latch이므로 WebView reload나 오류 창으로 해제되지 않는다. refresh fault marker는 성공한 TAKE OUT 뒤 native reset에만 맞춰 제거할 수 있지만 unknown/quarantine latch에는 영향을 주지 않는다. process를 재시작해 표시를 지우는 행위도 실제 출력 복구가 아니다.
|
||||
|
||||
## Rollback과 unload
|
||||
|
||||
### 명확히 출력 전 실패한 경우
|
||||
|
||||
COM 명령 전 validation에서 명시적으로 거부됐고 Network Monitoring/PGM에 변화가 없음을 확인한 경우에만 offline 수정으로 돌아간다. 수정 후에는 기존 회차를 이어가지 않고 새 회차로 시작한다.
|
||||
|
||||
### 출력이 명확히 active이고 엔진이 정상인 경우
|
||||
|
||||
Gate A에 포함된 TAKE OUT을 한 번 실행한다. 성공 callback과 PGM 종료 화면을 확인한 뒤 Disconnect한다. 같은 TAKE OUT을 확인용으로 반복하지 않는다.
|
||||
|
||||
### 결과가 불명확한 경우
|
||||
|
||||
1. 앱에서 추가 PREPARE, TAKE IN, NEXT, timer refresh, TAKE OUT, Disconnect를 자동으로 보내지 않는다.
|
||||
2. 현재 앱 status, 마지막 명령, Network Monitoring, PGM을 캡처한다.
|
||||
3. 방송 운영자가 Tornado 본 프로그램/PGM에서 실제 출력과 세션을 판정한다.
|
||||
4. 필요한 수동 정리는 방송 운영 권한과 현장 절차로 수행한다. Codex나 앱이 임의 명령을 추정하지 않는다.
|
||||
5. 안전한 black/approved fallback과 세션 종료가 사람에게 확인된 뒤 앱을 종료한다.
|
||||
6. 장애 원인과 조치가 확정될 때까지 새 검증을 승인하지 않는다.
|
||||
|
||||
### Scene 수명 규칙
|
||||
|
||||
- `OnScenePlayed`가 새 scene의 재생을 확정하면 이전 scene만 retired queue로 이동한다.
|
||||
- `OnCutOut`은 해당 layout, `OnStopAll`은 전체 player의 on-air 참조를 정리할 근거다.
|
||||
- pending Play callback이 있으면 TAKE OUT 이외의 명령을 fail-closed 차단한다. pending `OnScenePlayed`/`OnCutOut`/`OnStopAll`이 있으면 Disconnect와 unload를 시도하지 않는다.
|
||||
- `CutOut`/`StopAll` pending counter는 SDK dispatch 직전에 증가하고 동기 호출 실패 시 감소한다. 성공 callback은 대응 counter를 하나 감소시키고 중단된 Play의 pending accounting을 취소한다. dispatch 뒤 cancellation/timeout이면 counter 상태를 성공으로 추정하지 않는다.
|
||||
- 이전 connection generation에서 늦게 온 callback은 현재 generation의 state나 scene을 정리하는 근거로 쓰지 않는다.
|
||||
- 장기 실행 중 retired scene은 callback으로 안전성이 확인된 뒤 STA queue 안에서 `Unload`와 release를 수행한다.
|
||||
- 강제 GC, 임의 RCW release, 현재 on-air scene unload를 rollback으로 사용하지 않는다.
|
||||
|
||||
## 완료 판정
|
||||
|
||||
실제 검증 회차는 다음을 모두 만족할 때만 성공이다.
|
||||
|
||||
1. Gate A와 Gate B가 같은 회차에 기록돼 있다.
|
||||
2. 허용된 test cut과 selector만 사용했다.
|
||||
3. PREPARE → fresh DB TAKE IN → 승인된 Page NEXT/playlist NEXT → 원본 간격 timer refresh → TAKE OUT 순서가 중복 없이 완료됐다.
|
||||
4. 모든 결과가 명확한 성공이며 `OutcomeUnknown=false`다.
|
||||
5. Network Monitoring request/response와 PGM 화면이 같은 시각 증거로 남아 있다.
|
||||
6. 원본과 object 값, 표시, 색, 위치/크기, crop, path, asset, fade, page와 refresh 상태가 일치한다. Web preview에는 실제 asset path가 없다.
|
||||
7. callback과 unload 순서가 정상이고 Disconnect가 성공했다.
|
||||
8. DB password, vendor DLL/license, 인증서/private key, 실제 cut/asset, 운영 설정이 Git 변경에 포함되지 않았다.
|
||||
|
||||
검증 후 결과를 [`SCENE_EQUIVALENCE.md`](SCENE_EQUIVALENCE.md)의 해당 행에 기록한다. 일부 scene 성공이나 과거 runner 성공으로 나머지 행을 일괄 완료 처리하지 않는다.
|
||||
Reference in New Issue
Block a user