실측 PR 상태 및 이벤트 모델
한국어 번역본
이 문서는 원문(영어)의 한국어 번역이다. 정본은 원문이며, 계약·게이트 판단이 갈리면 원문을 따른다. 원문: docs/data/measured-pr-state-events.md
도메인 경계
실측(measured) PR은 사용자가 직접 만든 사실(fact)의 프로젝션이다. 추정치가 아니며, 그 자체가 권위 있는 입력 행도 아니다.
권위 있는 사실은 다음과 같다.
- 완료된
main및top종목 세트. - 날짜가 있는 과거 1RM 입력.
- 정확한 날짜를 알 수 없는, 날짜 없는 과거 1RM 입력.
추정 1RM(e1RM)은 별도의 계산, 이력, API 필드, UI 개념으로 남는다. 실측 PR이 비어 있을 때 e1RM 값으로 절대 채워서는 안 된다.
정확 반복수 정책
무게-반복수 종목의 경우, 실측 PR의 차원(dimension)은 정확한 반복수 1부터 20까지다. 한 세트는 자신의 반복수 차원만 갱신한다. 예를 들어 100 kg x 10은 10회 후보이며, 3RM, 5RM, 8RM 후보가 아니다.
주어진 사용자, 종목, 반복수, 관측일에 대해 프로젝션은 결정적으로 정해진 최고 부하 후보 하나를 유지한다. 새 이벤트는 그 후보가 이전의 모든 후보보다 엄격하게 클 때만 존재한다. 동점은 최초 달성 날짜를 옮기지 않으며 이벤트를 만들지 않는다.
1~20 범위를 벗어난 세트와 부하가 0인 맨몸 반복 기록은 훈련 사실로는 남지만, 이 실측 부하 PR 프로젝션에는 들어가지 않는다. 그런 종목 측정 타입은 자체적인 기록 정의를 필요로 한다.
프로젝션 계층
user_exercise_pr_events에는 실제 러닝 맥시멈(running-maximum) 전이만 담긴다. 하나의 이벤트에는 이전 값과 새 값, 델타, 정확한 반복수, 유효 날짜, 소스 종류, 소스 식별자가 포함된다.
user_exercise_pr_states에는 (user_id, exercise_id, target_reps)당 최대 한 개의 현재 행이 담긴다. 이 행은 현재 값을 확정한 이벤트를 가리킨다. 상태는 상한이 걸린(bounded) 읽기 프로젝션이며, 감사 로그가 아니다.
두 테이블 모두 서비스가 쓰고, 상한이 걸린 화면 RPC를 통해 사용자가 읽을 수 있다. 두 테이블은 canonical 사실로부터 재구축 가능해야 한다.
날짜 없는 온보딩 기준선
날짜를 알 수 없는 온보딩 1RM은, 나중에 더 오래된 날짜로 임포트되는 사실을 포함해, 관측된 모든 세션과 임포트된 WodUp 사실보다 앞에 정렬된다. 여기에 지어낸 날짜를 부여하지 않는다.
모든 원본 과거 입력은 독립적으로 편집 가능한 소스 사실로 남는다. 한 종목에 날짜 없는 사실이 둘 이상 존재하면, 결정적으로 정해진 최고값 하나가 프로젝션에서 유효한 기준선이 된다. 프로젝터는 나머지 소스 사실을 삭제하거나 덮어쓰지 않는다.
유효 기준선은 target_reps = 1의 러닝 맥시멈을 시딩한다. 이 값은 날짜 없는 출발점으로 표시될 수 있고, 첫 번째 날짜 있는 개선의 previous_value를 제공할 수 있다. 그러나 날짜 있는 PR, 최근 PR, 연간 PR, 알림을 보낼 만한 성취로는 계산되지 않는다.
이후 사용자가 날짜를 제공하면 그 소스 사실은 날짜 있는 사실이 되고, 영향을 받은 종목 타임라인이 리플레이된다.
리플레이와 정정
최근 세트를 덧붙이는 것은 최적화할 수 있지만, 정확성은 리플레이로 정의된다. 삽입, 수정, 삭제, 날짜 이동, 종목 이동은 가장 이른 이전/새 날짜와 모든 이전/새 종목을 dirty로 표시한다. 기존의 사용자별 어드바이저리 락(advisory lock) 아래에서, 워커는 영향을 받은 이벤트 스트림을 결정적인 시간순으로 재구축하고 같은 트랜잭션에서 현재 상태를 교체한다.
이 리플레이는 이벤트를 추가하거나, 이벤트를 제거하거나, 달성 날짜를 옮기거나, 과거 정정 이후 현재 상태를 낮출 수 있다. 그것은 예상된 동작이다. 이벤트 테이블은 현재 지원되는 역사적 진실이지, 불변(immutable) 변경 감사 기록이 아니다. 변경 감사가 필요하다면, 그것은 별도의 append-only 감사 로그에 속한다.
프로젝션 세대(generation)와 PR 전광판 스냅샷은 원자적으로 발행된다. 리더(reader)는 어떤 상태 세대를 다른 이벤트 세대나 전광판 세대와 절대 조합해서는 안 된다.
읽기 모델 한계
- Home과 PR 전광판은 실측 1RM 상태와 상한이 걸린 최근 이벤트 피드를 반환한다.
- 선택된 종목 상세는 현재 20개 NRM 상태 행을 모두 반환할 수 있다.
- 이벤트 이력은 keyset 페이지네이션을 사용한다.
- 전광판은 카탈로그의 모든 종목에 대해 20개 NRM 행을 반환해서는 안 된다.
- 훈련 이력과 e1RM 이력은 별도의 지연 프래그먼트로 남는다.
PR 개수는 기준선이 아닌 전이 이벤트의 개수다. previous PR은 이전 전이 값을 의미하며, 두 번째로 큰 임의의 수행 기록을 의미하지 않는다.
컷오버 정책
이것은 출시 전 파괴적(breaking) 컷오버다. 활성 데이터베이스 빌더, 화면 RPC, TypeScript 계약, 매퍼는 상태/이벤트 프로젝션을 직접 읽는다. 이중 쓰기 기간은 없으며, 레거시 후보 행이나 e1RM으로의 실측값 폴백도 없다. 기존 소스 사실은 새 읽기 계약이 발행되기 전 마이그레이션 중에 리플레이된다.