카드 표시값을 포인터 대신 만든 사람 기준으로 계산하고 위시에 item_id 를 되살린다 (1단계) - #1054
Merged
Conversation
- 위시 포인터(snapshot_id) 한 칸이 "내가 만든 값" 과 "내가 기다리는 작업" 두 역할을 겸해, 새로고침이 포인터를 옮기는 순간 내 수기값이 계산에서 빠지고(실패 시 빈 카드·옛 기계값) INCOMPLETE 는 옛 READY 에 밀렸다. 화면값 계산에 필요한 사실은 "이 버전을 누가 만들었나" 인데 행에 없어 포인터로 간접 표현하던 것이 원인이다 - item_snapshots.created_by 를 두고 등록·새로고침·공유 합류·토너먼트 링크 등록 네 지점에서 요청자를 기록한다. MANUAL 행은 editedBy 가 곧 created_by 다. 백필은 MANUAL 은 edited_by 복사, 서버 행은 그 행을 가리키는 가장 오래된 위시(없으면 출전)의 주인으로 추정 - 병합·합류가 겹친 드문 행만 틀릴 수 있고 다음 버전부터 정확해진다 - 표시 규칙을 도메인 ItemVersions.displayFor(viewer) 한 곳에 박았다: 내가 시킨 진행 중 > 내 맥락의 값(READY·INCOMPLETE) vs 공유 기계 READY 중 최신 > 값이 없으면 상품의 최신 사실. FAILED 는 후보가 아니라 새로고침 실패 뒤 카드가 새로고침 전과 같고, 남의 진행 중·남의 수기·남의 미완은 내 카드에 보이지 않는다. ItemDisplayService 는 버전을 끌어와 카드 주인별로 위임만 한다 - 위시에 item_id 를 되살려(nullable, 백필, dual write) 위시가 아이템만 참조하는 후속 단계의 바닥을 깐다. 읽기는 아직 snapshot_id 경로다 - 옛 컨테이너가 item_id 를 안 쓰는 배포 창을 견디기 위해 NOT NULL·읽기 전환·snapshot_id 제거는 다음 단계로 나눈다 - 가격 이력 테스트의 표시값 기대를 새 규칙으로 바꿨다(내 수기가 LLM READY 보다 새로우면 포인터와 무관하게 내 수기). 표시 규칙 분기는 ItemVersionsTest(단위)가 망라하고 WishDisplayIntegrationTest 는 HTTP 경계에서 불변식 세 건(남의 진행 중·수기값 유지·내 INCOMPLETE)을 고정한다 Claude-Session: https://claude.ai/code/session_01HnKAcdnoziL8hdVr9xinFb
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Team Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Discord 스레드 연동용 메타데이터입니다. discord-pr-bot 워크플로가 자동 생성하며, 수정·삭제하면 PR 과 Discord 알림 연동이 끊깁니다. |
- 코드 리뷰 반영. 진행 중을 "만든 사람" 기준으로 보이면 위시 새로고침이 같은 사람의 토너먼트 카드를 가로채 시작을 막고, 남의 파싱에 합류한 사람에겐 진행 중이 안 보였다. 카드의 참조(위시 snapshot_id·출전 pin)를 "기다리는 행" 으로 의미 확정하고, 그 행이 진행 중일 때만 진행 중을 보인다. 새로고침은 이전 값이 있는 카드에서만 시작됨을 진입 조건 전수로 확인했다 - 값 없는 fallback 을 기다리던 행의 결과 우선으로 바꿨다. 남이 뒤에 남긴 FAILED 가 합류자의 INCOMPLETE 를 지우고 409 로 복구까지 막던 구멍이고, 마지막 fallback 이 남의 수기까지 새던 것도 막았다(정책 A: 수기는 쓴 사람만 본다) - 공유 값 판정을 출처만으로(수기 아닌 READY) 바꿨다. 같은 PR 의 추정 백필이 도입 전 행에도 만든 사람을 채우므로 만든 사람으로 가르면 옛 값만 갖던 카드가 빈다. == null 비교도 이 수정으로 사라졌다 - 정체성 병합이 위시의 item_id 를 안 따라가던 구멍을 ItemMerged 이벤트 + BEFORE_COMMIT 리스너로 같은 트랜잭션에서 옮기게 했다. item 도메인이 위시를 모르는 단방향 의존을 유지한다 - 호출처가 사라진 findLatestMachineReadyByItemIds 3층을 지웠다. 옛 정책을 말하던 주석도 함께 사라진다 Claude-Session: https://claude.ai/code/session_01HnKAcdnoziL8hdVr9xinFb
m-a-king
added a commit
that referenced
this pull request
Sep 7, 2026
…정한다 (2단계) - 1단계(#1054)가 깐 wishes.item_id 를 배포 창의 NULL 재백필 뒤 NOT NULL 로 올리고, 목록·단건·수기 base·메모·새로고침·출전 소유 체크·메모 조회가 위시의 item_id 로 상품에 간다. 스냅샷 theta join 세 개가 사라진다 - Wish.snapshotId 를 waitingSnapshotId / waitFor 로 바꿔 "보는 값" 이 아니라 "기다리는 행" 임을 코드가 말하게 했다. 컬럼명(snapshot_id)은 rename 이 3단계 배포를 요구해 그대로 둔다 - 표시값 질의를 DisplayCard(itemId, owner, waitingOn) 로 바꿨다. 위시는 포인터 행을 따로 읽지 않고 카드 셋으로 묻고, 출전은 pin 에서 상품을 읽는 waitingOn 팩토리로 같은 모양을 쓴다. 결과는 입력 순서의 리스트라 pin 이 겹치는 카드도 안전하다 - 해소 통지(#1028) 수신자를 "미완성 버전을 가리키던 사람" 에서 "화면값이 실패·미완이었다가 이 버전으로 채워지는 카드의 주인" 으로 바꿨다. 카드 표시값 규칙(ItemVersions) 그대로 이 버전을 뺀 표시값과 넣은 표시값을 비교하므로 알림과 화면이 어긋날 수 없다. 상태 필터 쿼리 두 개는 상품의 카드 전부를 읽는 조회로 대체 - editedByMe 를 created_by 로 읽는다. edited_by 제거는 3단계 - raw SQL 로 위시를 넣던 테스트 두 곳에 item_id 를 채웠다(NOT NULL 회귀) Claude-Session: https://claude.ai/code/session_01HnKAcdnoziL8hdVr9xinFb
This was referenced Sep 7, 2026
m-a-king
added a commit
that referenced
this pull request
Sep 8, 2026
) * refactor: 위시 읽기를 item_id 로 옮기고 참조를 "기다리는 행" 으로 확정하며 해소 통지를 표시값 규칙으로 판정한다 (2단계) - 1단계(#1054)가 깐 wishes.item_id 를 배포 창의 NULL 재백필 뒤 NOT NULL 로 올리고, 목록·단건·수기 base·메모·새로고침·출전 소유 체크·메모 조회가 위시의 item_id 로 상품에 간다. 스냅샷 theta join 세 개가 사라진다 - Wish.snapshotId 를 waitingSnapshotId / waitFor 로 바꿔 "보는 값" 이 아니라 "기다리는 행" 임을 코드가 말하게 했다. 컬럼명(snapshot_id)은 rename 이 3단계 배포를 요구해 그대로 둔다 - 표시값 질의를 DisplayCard(itemId, owner, waitingOn) 로 바꿨다. 위시는 포인터 행을 따로 읽지 않고 카드 셋으로 묻고, 출전은 pin 에서 상품을 읽는 waitingOn 팩토리로 같은 모양을 쓴다. 결과는 입력 순서의 리스트라 pin 이 겹치는 카드도 안전하다 - 해소 통지(#1028) 수신자를 "미완성 버전을 가리키던 사람" 에서 "화면값이 실패·미완이었다가 이 버전으로 채워지는 카드의 주인" 으로 바꿨다. 카드 표시값 규칙(ItemVersions) 그대로 이 버전을 뺀 표시값과 넣은 표시값을 비교하므로 알림과 화면이 어긋날 수 없다. 상태 필터 쿼리 두 개는 상품의 카드 전부를 읽는 조회로 대체 - editedByMe 를 created_by 로 읽는다. edited_by 제거는 3단계 - raw SQL 로 위시를 넣던 테스트 두 곳에 item_id 를 채웠다(NOT NULL 회귀) Claude-Session: https://claude.ai/code/session_01HnKAcdnoziL8hdVr9xinFb * refactor: 해소 통지 판정을 도메인(ItemVersions.recovers)으로 옮기고 리뷰 지적을 반영한다 - 코드 리뷰 반영. 해소 통지 판정이 서비스 안 지역 함수로 남아 있던 것을 ItemVersions.recovers 로 옮기고, 판정 기준을 "그 버전을 뺀 집합" 이 아니라 "그 버전이 생기던 순간의 접두 상태" 로 바꿨다. 성공 버전이 둘 쌓인 채 앞 버전 이벤트를 처리하면 집합 비교는 앞 버전을 뒤 버전이 가려 아무 알림도 안 나갔다. 그 버전 뒤에 기다리기 시작한 카드도 제외한다. 단위 9건 추가 - 적재도 표시값과 같은 경로를 탄다(ItemDisplayService.versionsContaining). 상품은 이벤트의 itemId 가 아니라 버전 행에서 되짚어, 정체성 병합이 파싱 완료와 겹쳐 버전이 이긴 상품으로 옮겨져도 예외·유실 없이 판정한다. 알림 해석기가 스냅샷 저장소를 직접 쓰지 않게 돼 동결 목록에서 뺐다 - 후보를 상태로 SQL 선필터하지 않는다. 내 INCOMPLETE 가 기다리는 행(READY)보다 새로우면 규칙 2 로 카드가 미완성이 되므로 기다리는 행의 상태만 보는 필터는 그 카드를 놓친다. 출전은 파생을 타는 대기실(PENDING)만 후보다 - 시작된 토너먼트는 pin 을 박제해 읽어 채워질 카드가 없다. 두 케이스를 통합 테스트로 고정 - 표시값 배치 결과를 카드 키 맵으로 바꿔 호출부가 순서에 기대지 않게 했다. 출전 판정 맵은 위시의 상품을 키로 만들고 키 커버리지로 검사한다 - 메모만 수정하는 경로의 표시값 이중 파생, displayedSnapshotsOf 의 도달 불가 fallback, 한 줄 위임 displayOf, 죽은 projection data class 2개를 제거했다. TournamentItemCardView 는 라우팅 뷰를 상속한다 - 수기 팩토리 인자를 createdBy 로 바꿔 쓰는 곳을 하나로 모았다(edited_by 는 같은 값을 함께 적고 3단계에서 제거). editedByMe 는 도메인 술어(isManual·isOwnedBy)로 판정한다 - 메트릭 SQL 의 위시-스냅샷 조인을 wishes.item_id 직접 참조로 바꾸고 옛 주석을 고쳤다. CLAUDE.md 도메인 용어의 "wish 는 활성 버전을 가리킨다" 를 현재 모델로 고쳤다 Claude-Session: https://claude.ai/code/session_01HnKAcdnoziL8hdVr9xinFb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Situation
snapshot_id) 한 칸이 "내가 만든 값의 위치" 와 "내가 기다리는 작업" 두 역할을 겸한다. 새로고침이 포인터를 진행 중 버전으로 옮기는 순간 내 수기값은 계산에서 빠지고, 새로고침이 실패하면 빈 카드 또는 옛 기계값이 남았다. 내 새로고침이 INCOMPLETE 로 끝나도 옛 READY 가 이겨 "일부만 빈 상태" 가 보이지 않았다.Task
Action
스키마 (additive)
item_snapshots.created_by추가edited_by복사, 서버 행은 그 행을 가리키는 가장 오래된 위시(없으면 출전)의 주인으로 추정 백필wishes.item_id추가 (nullable)snapshot_id조인으로 전량 백필 + 인덱스. 새 위시는 dual write표시 규칙을 도메인으로
ItemVersions.displayFor(viewer, waitingOn)가 한 상품의 버전들, 카드 주인, 카드가 기다리는 행으로 보일 버전을 고른다.ItemDisplayService는 버전을 끌어와 카드별로 위임만 한다.snapshot_id·출전 pin)는 "보는 값" 이 아니라 "기다리는 행" 이다. 본인의 등록·새로고침·합류로만 움직이므로, 진행 중 표시는 그 행을 기다리는 카드에만 나타난다.병합 추종
item_id가 진 상품(soft delete)에 남는 구멍이 생긴다. item 도메인이ItemMerged를 병합 트랜잭션 안에서 발행하고, 위시가 BEFORE_COMMIT 리스너로 같은 커밋에서item_id를 옮긴다. item 은 위시를 모르는 단방향 의존을 유지한다.요청자 기록
ItemSnapshot.pending(itemId, requestedBy)로 시킨 사람을 적는다. 공유 합류 경로는resolveAttachment에 요청자를 넘긴다.검토 후 채택하지 않은 안
snapshot_id만 쓰는 배포 창에서 NOT NULL·DROP 이 깨진다Result
ItemVersionsTest(단위 17건)가 망라하고,WishDisplayIntegrationTest는 HTTP 경계에서 불변식 세 건(남의 진행 중 안 보임·수기값 유지·내 INCOMPLETE)을 고정한다. 병합 추종은 정체성 기록 통합 테스트가 위시item_id이동으로 고정한다.findLatestMachineReadyByItemIds3층을 지웠다. 상품별 버전 전체 조회의 상한은 이슈 후속 최적화로 남긴다.item_id로 전환하고 알림 수신자를 "그 행을 기다리는 카드 주인" 기준으로 바꾼다.snapshot_id는 제거하지 않고 "기다리는 행" 으로 의미와 이름을 바꾼다. 3단계에서edited_by를 제거한다.연관 이슈