Skip to content

[feat] 스케줄러·셰드락 공통 설정 · 휴지통 정리 배치 (00:10) #81

Open

Description

@chjpooh2002

관련 명세

  • CLAUDE.md 배치 (셰드락 필수): 매일 00:10 휴지통 30일 지난 템플릿 영구 삭제
  • docs/erd.md 5장 배치 작업, 인덱스 idx_templates_deleted_at (deleted_at)
  • 보관 기간: TrashRetention (휴지통 목록의 purgeAt과 같은 기간을 쓴다)

작업 내용

1. 스케줄러·셰드락 공통 설정 (global)

  • 스케줄 활성화와 셰드락 설정을 global/config에 둔다
  • 셰드락 의존성 추가: 서버가 여러 대가 되어도 같은 배치가 한 번만 돌게 하기 위해서다 (CLAUDE.md 배치 규칙)
  • 셰드락 잠금 테이블은 플라이웨이 새 마이그레이션 파일로 추가한다
  • 04:00 재발급 토큰 정리 배치도 이 설정을 그대로 쓸 수 있게 한다

2. 휴지통 정리 배치 (template)

  • 매일 00:10(KST), 휴지통으로 옮긴 지 30일 지난 템플릿을 영구 삭제한다
  • 현재 시각은 Clock 빈에서 얻는다
  • 엔티티를 읽지 않고 삭제 쿼리로 지운다 (#70과 같은 이유: 본문 복호화에 실패하는 행도 지울 수 있어야 한다)

설계 시 반드시 볼 것: 복구와의 교착 (#78에서 재현)

#78에서 휴지통 비우기와 복구가 동시에 실행되면 교착이 나서 한쪽이 500이 되는 것을 동시성 테스트로 재현했다.

  • 비우기는 (user_id, deleted_at) 인덱스 → 기본 키 순서로 행을 잠근다
  • 복구는 기본 키를 잠근 뒤, 저장할 때 같은 인덱스를 고친다
  • #78은 영구 삭제·비우기도 lockUser를 먼저 불러 같은 회원의 휴지통 쓰기를 줄 세워 해결했다

정리 배치는 여러 회원의 행을 deleted_at 범위로 지우므로, 회원을 잠그지 않으면 같은 교착이 날 수 있다. 아래 중 하나 이상으로 정하고 근거를 PR에 남긴다.

  • 대상 회원별로 lockUser → 삭제 (잠금 순서를 복구와 맞춤)
  • 일정 개수씩 나눠 삭제 (한 번에 잡는 잠금 범위·시간 축소)
  • 교착이 나면 재시도

함께 고칠 주석

#78은 "정리 배치는 회원을 잠그지 않는다"는 전제로 주석을 남겼다. 배치 설계가 정해지면 아래를 실제 동작에 맞게 고친다.

  • TemplateRepository.findTrashedByIdAndUserIdForUpdate 주석: "회원을 잠그지 않는 정리 배치가 먼저 지우고 있으면…"
  • TrashCommandService.restore 주석: "정리 배치는 회원을 잠그지 않아…"

완료 조건

  • 스케줄러·셰드락 설정, 잠금 테이블 마이그레이션
  • 같은 배치가 동시에 두 번 실행되지 않음
  • 30일 경계: 딱 30일 지난 행은 삭제, 덜 지난 행은 유지
  • 활성 템플릿은 삭제하지 않음
  • 복호화가 실패하는 행도 삭제
  • 동시성: 배치와 복구가 겹쳐도 500 없이 끝나고, 결과가 둘 중 하나의 성공과 일치
  • 위 두 주석 수정
  • ./gradlew build 통과

참고

Activity

  1. self-assigned this
    on Nov 9, 2026
  2. added
    template내 템플릿·휴지통
    aiAI 톤 교정
    global공통 응답·예외·보안 설정
    on Nov 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

aiAI 톤 교정feature기능 개발global공통 응답·예외·보안 설정template내 템플릿·휴지통

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions