Repository navigation
Conversation
엔티티를 읽지 않고 본인 소유 + 휴지통 조건으로 지우는 삭제 쿼리 두 개를 추가한다. 본문 복호화에 실패하는 행도 지울 수 있어야 하기 때문이다. 지운 행이 1차 캐시에 남지 않게 실행 뒤 캐시를 비우고, 그 전에 쌓인 변경을 내보낸다.
TrashCommandService에 purge·empty를 추가한다. 영구 삭제는 지운 행이 0이면 TRASH404_1, 비우기는 지운 개수를 돌려주고 비어 있어도 성공이다.
DELETE /api/v1/trash/templates/{templateId} (TRASH200_3)와
DELETE /api/v1/trash/templates (TRASH200_4)를 추가한다.
비우기는 (user_id, deleted_at) 인덱스 → 기본 키 순서로 행을 잠그고, 복구는 기본 키를 잠근 뒤 저장할 때 같은 인덱스를 고친다. 둘이 겹치면 교착이 나서 비우기가 500이 되는 것을 동시성 테스트로 재현했다. 복구와 같이 회원 행을 먼저 잠가 같은 회원의 휴지통 쓰기를 줄 세운다. 개별 영구 삭제도 같은 순서로 맞춘다. 영구 삭제가 회원을 잠그지 않는다고 적은 복구 쪽 주석은 정리 배치만 남기도록 고친다.
oTAETAEo
marked this pull request as ready for review
November 7, 2026 06:09
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.
관련 이슈
기준 브랜치
#69(16번 복구) 위에 쌓아 시작했고, #69가 병합되어 기준이
develop으로 바뀌었습니다.develop(#63 갤러리 저장 포함)을 merge로 합쳤고, 충돌은 없었습니다. 합친 상태로./gradlew clean build통과 (테스트 981건, 실패 0).작업 내용
명세 17번
DELETE /api/v1/trash/templates/{templateId}(개별 영구 삭제)와 18번DELETE /api/v1/trash/templates(휴지통 비우기)를 구현했습니다.커밋별로 보기
TemplateRepository.deleteTrashedByIdAndUserId,deleteTrashedByUserId(@ModifyingJPQL delete, 지운 행 수 반환)TrashCommandService.purge,empty,TrashPurgeCommand,TrashPurgeResult,TrashEmptyResultTrashController에 추가,TRASH200_3·TRASH200_4,TrashPurgeResponse,TrashEmptyResponse동작
id·user_id·deleted_at is not null로 삭제TRASH200_3+templateId, 0행이면TRASH404_1(없는 ID, 다른 회원, 활성 템플릿, 이미 지운 템플릿)user_id·deleted_at is not null로 삭제TRASH200_4+deletedCount. 비어 있어도 성공(0)updated_at은 넣지 않습니다.@Modifying(flushAutomatically = true, clearAutomatically = true): 재발급 토큰 레포지토리와 같습니다.clear: 없으면 지운 행이 1차 캐시에 남아 같은 트랜잭션의findById가 그 행을 돌려줍니다 (플래그를 빼고 실패하는 것을 확인함).flush: 캐시를 비울 때 아직 내보내지 않은 변경이 사라지지 않게 합니다.templates를 참조하는 외래키는 없습니다 (ERD v0.8, 마이그레이션 확인).이슈에 없던 결정: 영구 삭제·비우기도 회원을 먼저 잠근다
MySQLTransactionRollbackException(500)이 됩니다. 동시성 테스트로 재현했습니다.idx_templates_user_deleted→ 기본 키 순서로 행을 잠급니다.lockUser를 먼저 불러 같은 회원의 휴지통 쓰기를 줄 세웠습니다. 개별 영구 삭제도 비우기와 같은 순서 문제가 있을 수 있어 함께 맞췄습니다.TemplateRepository,TrashCommandService.restore)과 테스트 주석 하나를 "정리 배치는"으로 고쳤습니다.TRASH404_1대신USER404_1입니다. 복구와 같고, 명세 1장의 개발용 토큰 설명과도 맞습니다.명세와 다른 점
없습니다. 응답 필드와 문구는 명세 17·18번 그대로입니다.
테스트
TrashPurgeControllerTest(테스트컨테이너 MySQL)no-store, 그 행만 삭제. 없는 ID·다른 회원의 활성·휴지통 템플릿·내 활성 템플릿·두 번째 삭제TRASH404_1(아무것도 지우지 않음), 숫자가 아닌templateIdCOMMON400_1, 토큰 없음COMMON401_1deletedCount일치, 활성 템플릿·다른 회원 휴지통 유지, 비어 있으면 0, 토큰 없음COMMON401_1totalCount·항목, 지운 단축어로 새 템플릿 생성TrashPurgeRepositoryTest: 조건별 지운 행 수, 깨진 본문 행, 1차 캐시 비우기, 쌓인 변경 내보내기TrashCommandServicePurgeTest(모키토): 지운 행 수에 따른 결과·TRASH404_1, 엔티티 조회 없음, 회원 잠금 → 삭제 순서TrashPurgeConcurrencyTest(실제 커밋)TRASH404_1TRASH404_1TRASH404_1/ 복구가 먼저 잡으면 영구 삭제가TRASH404_1./gradlew clean build통과 (develop합친 뒤 테스트 981건, 실패 0)변경량
develop대비 +910 / −4줄 (프로덕션 +111 / −3, 테스트 +799 / −1). 400줄 목표를 넘는 것은 이슈 완료 조건의 통합·동시성 테스트 때문입니다. 프로덕션 코드는 약 110줄입니다.정리 배치(00:10)에서 볼 것
deleted_at범위로 지우면 복구와 같은 교착이 날 수 있습니다. 행 단위로 끊어 지울지, 교착 시 재시도할지 정해야 합니다.🤖 Generated with Claude Code