feat: 플레이 감사 월별 수집과 원자적 배치 저장 연결
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
# 플레이 감사 구현 기록과 수집 inventory
|
||||
|
||||
[확정 설계](play-audit.md)의 P1~P6를 구현하는 작업 기록이다. 전체 기능은 진행 중이며,
|
||||
아래 순수 projection은 아직 runtime 수집·DB·API·화면에 연결되지 않았다.
|
||||
월별 projection과 runtime 수집·DB transaction 연결을 구현했다. API·화면은 아직 미구현이다.
|
||||
Push 요청 이후 `feat/play-audit` 전용 worktree에서 계속 구현하며 전체 완료 후 main 통합·push한다.
|
||||
|
||||
## 현재 구현
|
||||
|
||||
@@ -21,20 +22,42 @@ triggerState, credential과 전체 world는 복사하지 않는다.
|
||||
국가 전후값·적용 세율·보정액은 이후 원장 구현에서 보존해야 하며 이 projection만으로
|
||||
R1을 완료했다고 판단하지 않는다.
|
||||
|
||||
## 월별 저장 구현
|
||||
|
||||
`playAudit/collection.ts`가 `beforeMonthChanged`에 이전 월 표본을 queue한다.
|
||||
`incomeHandler`에서 이미 계산한 수입·급여를 관측하여 작은 국가별 월합계를
|
||||
world meta에 함께 저장한다. 월중 재시작에도 집계가 유지되며, 수집 도입 월은
|
||||
불완전으로 표시하고 다음 월부터 완전 수집한다. 기수 identity가 없는 설치에서는
|
||||
profile명으로 대체하지 않는다. 해당 구간의 API coverage 안내는 아직 구현해야 한다.
|
||||
|
||||
`InMemoryTurnWorld`의 capture/restore/peek/acknowledge에 pending 표본을 포함하고
|
||||
`databaseHooks.persistChanges`에서 gameplay와 같은 transaction으로 저장한다.
|
||||
`unificationHandler`는 월말과 구분되는 FINAL 표본을 queue한다.
|
||||
`PlayAuditMonth/Nation/City/General` 네 테이블에 명시적 projection을 보존한다.
|
||||
국가·도시별 장수 검색 index를 두고 child insert를 200행씩 분할한다. 표본 ID와
|
||||
payload hash가 같은 재시도는 중복 저장하지 않고, 내용이 다르면 transaction을 실패시킨다.
|
||||
200은 초기 batch 설정이며 payload bytes/WAL/heap 실측을 통한 최종 선정은 남아 있다.
|
||||
|
||||
새 migration은 기존 행을 backfill하지 않는다. 전용 PostgreSQL에서 빈 설치 전체 적용,
|
||||
기존 49 migration 이후 새 migration 증분 적용, 두 번째 deploy no-op을 검증했다.
|
||||
업무 데이터와 감사 표본의 transaction rollback, 재시도/충돌, 월 경계의 전월 세율과
|
||||
world meta reload도 확인했다. 이전 기수 차단/정리, 최종 표본 전체 종료 경로,
|
||||
정산 전후값의 별도 사건 원장은 아직 남아 있다.
|
||||
|
||||
## 수집 지점과 쓰기 재검토
|
||||
|
||||
기준 Core commit은 `5ac961dfd17738dc4c39e6401f975296f39403a5`이다.
|
||||
SQL/bytes는 아직 실측하지 않았으며 아래는 현재 소스에서 확인한 연결 지점과 구현 경계다.
|
||||
|
||||
| 자료 | 실제 source / 관측할 값 | 구현·비용 결정 | 남은 검증 |
|
||||
| ------------------- | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- |
|
||||
| 월별 장수·도시·국가 | `turn/yearbookHandler.ts`의 `beforeMonthChanged`; `playAudit/snapshot.ts`의 필드 allowlist | 메모리 한 순회, 추가 SELECT 없이 수집. 상세는 도시/국가/장수로 페이지 조회 가능한 행에 batch 저장하며 큰 월 JSON 전체를 목록 조회하지 않음 | 월 pending/rollback 연결, migration, DB reload, 종료 부분 표본 |
|
||||
| 세율 적용 수입·급여 | `turn/incomeHandler.ts`의 `applyIncome`, `incomeValue`, `current`, `next`, `ratio`, 장수별 `pay`; `turn/nationTaxRate.ts` | 이미 계산한 수치만 관측. 국가 수입과 실제 급여 합계 분리, 과거 metadata 재누적 금지. 정산 원장을 월집계 입력으로 재사용 | 정수화·최저 자원 보정, 원장/집계 원자 저장, 도입 월 coverage |
|
||||
| 월별 내구성 | `turn/inMemoryWorld.ts`의 capture/restore, peek/acknowledge와 pending yearbook; `turn/databaseHooks.ts`의 `persistChanges` | 별도 audit pending을 같은 transaction과 savepoint에 포함. 기존 연감의 장기보존 테이블에 상세 감사를 넣지 않음 | 실패·중복·재시작, bounded 삭제 |
|
||||
| 기수 identity | `scenario/scenarioSeeder.ts`의 `install.serverId`, `GameHistory` 충돌 검사 | profile명으로 대체하지 않음. 외부 install 입력을 만드는 지점과 RESET 전체 경로를 추가 추적한 뒤 수집 활성화 | 신규 identity 생성, 재시도, 기존 설치에 identity 누락 시 처리 |
|
||||
| 외교 | game-api `router/diplomacy/index.ts`, engine 월간 외교 처리 | 불변 문서는 참조, 갱신되는 내용만 당시 버전 저장. 현재 상태 월복사만으로 사건을 대신하지 않음 | 모든 API/engine mutation별 inventory |
|
||||
| NPC 정책 | `turn/worldCommandHandler.ts` → `turn/npcPolicyMutation.ts` | CAS 성공하고 실제 값이 달라진 경우에만 불변 버전. 무변경/거부는 적용 버전에서 제외 | 초기 버전, actor/직책, 국방 mutation inventory |
|
||||
| 권한 | Gateway `adminCapabilities.ts`, `adminAuth.ts`; game-api `trpc.ts` 인증·제재 middleware | scoped 감사 권한과 공통 계정 추가 권한 분리. `getMyGeneral` 요구 없이 서버에서 검사 | catalog/token/flush/HTTP matrix 전체 연결 |
|
||||
| 자료 | 실제 source / 관측할 값 | 구현·비용 결정 | 남은 검증 |
|
||||
| ------------------- | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------- |
|
||||
| 월별 장수·도시·국가 | `turn/yearbookHandler.ts`의 `beforeMonthChanged`; `playAudit/snapshot.ts`의 필드 allowlist | 메모리 한 순회, 추가 SELECT 없이 수집. 상세는 도시/국가/장수로 페이지 조회 가능한 행에 batch 저장하며 큰 월 JSON 전체를 목록 조회하지 않음 | 단위/DB 연결 확인; 전체 종료 경로·coverage·비용 gate는 남음 |
|
||||
| 세율 적용 수입·급여 | `turn/incomeHandler.ts`의 `applyIncome`, `incomeValue`, `current`, `next`, `ratio`, 장수별 `pay`; `turn/nationTaxRate.ts` | 이미 계산한 수치만 관측. 국가 수입과 실제 급여 합계 분리, 과거 metadata 재누적 금지. 정산 원장을 월집계 입력으로 재사용 | 정수화·최저 자원 보정, 원장/집계 원자 저장, 도입 월 coverage |
|
||||
| 월별 내구성 | `turn/inMemoryWorld.ts`의 capture/restore, peek/acknowledge와 pending yearbook; `turn/databaseHooks.ts`의 `persistChanges` | 별도 audit pending을 같은 transaction과 savepoint에 포함. 기존 연감의 장기보존 테이블에 상세 감사를 넣지 않음 | 실패·중복·재시작, bounded 삭제 |
|
||||
| 기수 identity | `scenario/scenarioSeeder.ts`의 `install.serverId`, `GameHistory` 충돌 검사 | profile명으로 대체하지 않음. 외부 install 입력을 만드는 지점과 RESET 전체 경로를 추가 추적한 뒤 수집 활성화 | 신규 identity 생성, 재시도, 기존 설치에 identity 누락 시 처리 |
|
||||
| 외교 | game-api `router/diplomacy/index.ts`, engine 월간 외교 처리 | 불변 문서는 참조, 갱신되는 내용만 당시 버전 저장. 현재 상태 월복사만으로 사건을 대신하지 않음 | 모든 API/engine mutation별 inventory |
|
||||
| NPC 정책 | `turn/worldCommandHandler.ts` → `turn/npcPolicyMutation.ts` | CAS 성공하고 실제 값이 달라진 경우에만 불변 버전. 무변경/거부는 적용 버전에서 제외 | 초기 버전, actor/직책, 국방 mutation inventory |
|
||||
| 권한 | Gateway `adminCapabilities.ts`, `adminAuth.ts`; game-api `trpc.ts` 인증·제재 middleware | scoped 감사 권한과 공통 계정 추가 권한 분리. `getMyGeneral` 요구 없이 서버에서 검사 | catalog/token/flush/HTTP matrix 전체 연결 |
|
||||
|
||||
월간 실행은 이전 월 snapshot → 달 변경 → 새달 `onMonthChanged` 순서다.
|
||||
1월 금/7월 쌀 정산은 새로 진입한 월의 흐름으로 누적하고 그 월 마감에 집계한다.
|
||||
@@ -48,6 +71,10 @@ SQL/bytes는 아직 실측하지 않았으며 아래는 현재 소스에서 확
|
||||
- 수입: `monthlySemiAnnualPersistence.integration.test.ts`, `monthlyWarIncomePersistence.integration.test.ts`.
|
||||
- 원자성: `inputEventAtomicity.test.ts`, `readModelChangeJournalPersistence.integration.test.ts`.
|
||||
|
||||
현재 순수 fixture는 분모, 0/null, 소수 수입, 미수집, 외국 주둔, 과거 값의 독립성,
|
||||
순수 fixture는 분모, 0/null, 소수 수입, 미수집, 외국 주둔, 과거 값의 독립성,
|
||||
민감 meta 제외와 단일 순회를 검증한다. PostgreSQL SQL count/WAL/실행계획,
|
||||
권한 HTTP, CHE/HWE Chromium과 전체 source inventory는 아직 남아 있다.
|
||||
|
||||
월 저장 검증: `playAuditCollection.test.ts`, `playAuditPersistence.integration.test.ts`와
|
||||
확장한 `monthlyBoundaryPrePersistence.integration.test.ts`. 정확한 명령·결과는
|
||||
상위 보고서 `2026-09-16-플레이-감사-월별-저장.md`에 기록한다.
|
||||
|
||||
Reference in New Issue
Block a user