Skip to content

[FEAT] 문서 생성·수정·삭제 시 참조 관계 동기화 - #205

Merged
sun007021 merged 4 commits into
developfrom
feat/204
Aug 31, 2026
Merged

sun007021 merged 4 commits into
developfrom
feat/204

Conversation

@poketopa

@poketopa poketopa commented Aug 30, 2026

Copy link
Copy Markdown
Member

관련 이슈

Closes #204

변경 배경

그래프 조회 시 본문을 반복 분석하지 않도록, 크루 문서가 변경되는 시점에 참조 관계를 저장한다.

변경 내용

  • 유효한 내부 문서 링크만 추려 참조 추가·삭제 동기화
  • 문서 생성·수정·삭제와 참조 변경을 하나의 트랜잭션으로 처리
  • 동일 문서 동시 수정 시 비관적 잠금으로 본문과 참조 정합성 보장
  • 생명주기, 롤백, 동시성 테스트 추가

검증

  • 테스트 통과
    • Java 17 전체 테스트 130개 통과
    • failures 0, errors 0, skipped 0
  • 변경 동작 확인
    • 생성·수정·삭제 후 본문과 참조 일치 확인
    • 동기화 실패 시 문서·히스토리·참조 롤백 확인
    • 동일 문서 동시 수정 후 최종 본문과 참조 일치 확인
    • git diff --check 통과

영향 및 참고사항

  • 크루 문서 쓰기 시 document_reference 테이블도 함께 변경된다.
  • 기존 문서의 참조 데이터 적재는 별도 backfill 작업 범위다.

Summary by CodeRabbit

  • 새로운 기능

    • 문서 생성·수정·삭제 시 문서 간 링크가 자동으로 동기화됩니다.
    • 유효하지 않은 링크, 자기 자신을 가리키는 링크, 중복 링크가 자동으로 제외됩니다.
    • 문서 변경 중 오류가 발생하면 내용과 관련 링크가 함께 이전 상태로 복원됩니다.
  • 버그 수정

    • 동시에 문서를 수정할 때 문서 링크가 잘못 저장되는 문제를 방지했습니다.

@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e6f9dc0a-af06-4813-aec6-54c40d090b37

📥 Commits

Reviewing files that changed from the base of the PR and between c0bd336 and bc25e64.

📒 Files selected for processing (8)
  • src/main/java/com/wooteco/wiki/admin/service/CrewDocumentService.java
  • src/main/java/com/wooteco/wiki/document/repository/CrewDocumentRepository.java
  • src/main/java/com/wooteco/wiki/graph/dto/DocumentReferenceSyncResult.java
  • src/main/java/com/wooteco/wiki/graph/service/DocumentReferenceSyncService.java
  • src/test/java/com/wooteco/wiki/document/service/CrewDocumentReferenceConcurrencyTest.java
  • src/test/java/com/wooteco/wiki/document/service/CrewDocumentReferenceLifecycleTest.java
  • src/test/java/com/wooteco/wiki/document/service/CrewDocumentReferenceTransactionTest.java
  • src/test/java/com/wooteco/wiki/graph/service/DocumentReferenceSyncServiceTest.java

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

크루 문서의 생성, 수정, 삭제 시 본문 링크와 DocumentReference를 동기화합니다. 자기 참조, 중복 링크, 존재하지 않는 문서는 제외합니다. 참조 변경 실패 시 문서와 이력을 롤백하며, 동시 수정에는 비관적 쓰기 잠금을 사용합니다.

Changes

문서 참조 동기화

Layer / File(s) Summary
참조 동기화 서비스
src/main/java/com/wooteco/wiki/graph/dto/DocumentReferenceSyncResult.java, src/main/java/com/wooteco/wiki/graph/service/DocumentReferenceSyncService.java
문서 본문에서 대상 UUID를 추출합니다. 자기 참조, 중복 링크, 존재하지 않는 대상을 제외합니다. 기존 참조를 삭제하고 새 참조를 저장합니다.
문서 생명주기와 잠금 연동
src/main/java/com/wooteco/wiki/admin/service/CrewDocumentService.java, src/main/java/com/wooteco/wiki/document/repository/CrewDocumentRepository.java
문서 생성과 수정 후 참조를 동기화합니다. 문서 삭제 시 소스 및 대상 기준 참조를 제거합니다. 수정과 삭제 조회에 PESSIMISTIC_WRITE 잠금을 적용합니다.
참조 동기화 검증
src/test/java/com/wooteco/wiki/graph/service/DocumentReferenceSyncServiceTest.java, src/test/java/com/wooteco/wiki/document/service/CrewDocumentReferenceLifecycleTest.java, src/test/java/com/wooteco/wiki/document/service/CrewDocumentReferenceTransactionTest.java, src/test/java/com/wooteco/wiki/document/service/CrewDocumentReferenceConcurrencyTest.java
유효 링크 필터링, 생성·수정·삭제, 동기화 변경, 트랜잭션 롤백, 동일 문서의 동시 수정을 검증합니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to bc25e

The change synchronizes document references with document creation, updates, and deletion within the same transaction. No actionable merge-blocking risk remains based on the supplied validation and current PR evidence.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant CrewDocumentService
  participant CrewDocumentRepository
  participant DocumentReferenceSyncService
  participant DocumentReferenceRepository

  Client->>CrewDocumentService: 문서 생성 또는 수정 요청
  CrewDocumentService->>CrewDocumentRepository: 문서 저장 또는 잠금 조회
  CrewDocumentService->>DocumentReferenceSyncService: synchronize(CrewDocument)
  DocumentReferenceSyncService->>DocumentReferenceRepository: 기존 참조 조회
  DocumentReferenceSyncService->>DocumentReferenceRepository: 참조 추가 및 제거
  DocumentReferenceSyncService-->>CrewDocumentService: DocumentReferenceSyncResult
  CrewDocumentService-->>Client: 처리 결과
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 44 functions across 8 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 문서 생성·수정·삭제 시 참조 관계를 동기화하는 핵심 변경을 정확하고 간결하게 설명합니다.
Description check ✅ Passed 관련 이슈, 변경 배경, 변경 내용, 검증 결과, 영향 사항을 모두 작성했습니다. 테스트 결과와 별도 backfill 범위도 명시했습니다.
Linked Issues check ✅ Passed PR은 직접 연결된 이슈 [#204]의 요구사항을 충족합니다. 유효 링크 필터링, 참조 추가·삭제, 삭제 시 정리, 트랜잭션 처리, 비관적 잠금, 롤백 및 관련 테스트를 구현했습니다.
Out of Scope Changes check ✅ Passed 변경 사항은 [#204]의 문서 참조 동기화와 정합성 보장 범위에 포함됩니다. 서비스, 저장소, 결과 DTO, 동기화 로직 및 관련 통합 테스트만 추가·수정했습니다.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/204

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sun007021

Copy link
Copy Markdown
Member

@coderabbitai 리뷰해줘

@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '=== Changed files ==='
git diff --name-status HEAD^ HEAD

printf '%s\n' '=== Full PR diff ==='
git diff --find-renames --find-copies --unified=80 HEAD^ HEAD

printf '%s\n' '=== Changed Java file outlines ==='
git diff --name-only HEAD^ HEAD -- 'src/main/java/**/*.java' |
  while IFS= read -r file; do
    printf '\n--- %s ---\n' "$file"
    ast-grep outline "$file" --items all || true
  done

printf '%s\n' '=== Related reference types, repositories, and link extraction usages ==='
rg -n -C 5 \
  -e '\b(class|record|interface)\s+DocumentReference\b' \
  -e '\binterface\s+DocumentReferenceRepository\b' \
  -e '\bDocumentReference\b' \
  -e 'extract.*(Uuid|UUID)|parse.*(Uuid|UUID)|document.*link|internal.*link' \
  src/main/java src/test/java || true

Length of output: 102636


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for name in \
  CrewDocumentService.java \
  CrewDocumentRepository.java \
  DocumentReferenceSyncService.java \
  DocumentReferenceSyncResult.java \
  DocumentReference.java \
  DocumentReferenceRepository.java
do
  fd -a -t f --glob "$name" src || true
done | sort -u | while IFS= read -r file; do
  printf '\n===== %s =====\n' "$file"
  cat -n "$file"
done

printf '\n===== Transaction annotations and reference repository calls =====\n'
rg -n -C 8 \
  -e '`@Transactional`' \
  -e '\b(synchronize|deleteAllByDocument|findByUuidForUpdate)\s*\(' \
  -e '\b(documentReferenceRepository|crewDocumentRepository)\.[A-Za-z0-9_]+\s*\(' \
  src/main/java/com/wooteco/wiki || true

printf '\n===== Schema constraints for document_reference =====\n'
rg -n -C 5 -i \
  -e 'document_reference' \
  -e 'unique.*(source|target|document)' \
  src/main/resources src/test/resources || true

Length of output: 71728


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="Crew-Wiki/backend"
pr="205"

printf '%s\n' '=== Pull request metadata ==='
gh pr view "$pr" --repo "$repo" --json number,title,baseRefName,baseRefOid,headRefName,headRefOid,changedFiles,additions,deletions,mergeable,state

printf '%s\n' '=== Pull request files ==='
gh api "repos/$repo/pulls/$pr/files?per_page=100" \
  --jq '.[] | {filename,status,additions,deletions,patch}' || true

printf '%s\n' '=== Local HEAD and merge-base ==='
git rev-parse HEAD
git status --short
git branch --show-current

Length of output: 41871


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '=== Link extractor and graph reference construction ==='
for name in CrewDocumentReferenceExtractor.java CrewGraphQueryService.java CrewGraphQueryRepository.java; do
  fd -a -t f --glob "$name" src/main/java | while IFS= read -r file; do
    printf '\n===== %s =====\n' "$file"
    cat -n "$file"
  done
done

printf '%s\n' '=== Document persistence and deletion mappings ==='
for name in DocumentRepository.java Document.java CrewDocument.java History.java HistoryRepository.java; do
  fd -a -t f --glob "$name" src/main/java | while IFS= read -r file; do
    printf '\n===== %s =====\n' "$file"
    cat -n "$file"
  done
done

printf '%s\n' '=== Previous delete method and database migration declarations ==='
git show c0bd336f16a2584e7542a9f30fecaf1b5b68d6c1:src/main/java/com/wooteco/wiki/document/repository/DocumentRepository.java || true
rg -n -C 8 -i \
  -e 'create table.*(history|document_reference|document)' \
  -e 'alter table.*(history|document_reference|document)' \
  -e 'fk_.*(history|document_reference)' \
  src/main/resources || true

printf '%s\n' '=== Extractor tests ==='
fd -a -t f --glob 'CrewDocumentReferenceExtractorTest.java' src/test |
  while IFS= read -r file; do
    cat -n "$file"
  done

Length of output: 39409


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '=== Organization document write and delete paths ==='
fd -a -t f --glob 'OrganizationDocumentService.java' --glob '*OrganizationDocument*Controller.java' src/main/java |
  while IFS= read -r file; do
    printf '\n===== %s =====\n' "$file"
    cat -n "$file"
  done

printf '%s\n' '=== All document deletion calls and document-reference cleanup calls ==='
rg -n -C 6 \
  -e '\.(delete|deleteByUuid|deleteAllBy)[A-Za-z0-9_]*\s*\(' \
  -e '\bdeleteAllByDocument\s*\(' \
  -e '\bDocumentReference\.of\s*\(' \
  src/main/java

printf '%s\n' '=== Foreign-key behavior in generated schema or migrations ==='
fd -a -t f src/main/resources |
  while IFS= read -r file; do
    case "$file" in
      *.sql|*.yaml|*.yml|*.properties)
        printf '\n===== %s =====\n' "$file"
        rg -n -C 4 -i 'document_reference|foreign.?key|on delete' "$file" || true
        ;;
    esac
  done

Length of output: 23381


@sun007021 리뷰를 완료했습니다.

차단 수준의 문제는 확인하지 못했습니다.

확인한 항목은 다음과 같습니다.

  • 생성, 수정, 삭제가 참조 동기화와 같은 트랜잭션에서 처리됩니다.
  • 수정과 삭제는 PESSIMISTIC_WRITE 잠금으로 동일 문서의 동시 변경을 직렬화합니다.
  • 동기화는 중복 링크, 자기 참조, 존재하지 않는 문서를 제외합니다.
  • 삭제는 문서가 source 또는 target인 참조를 모두 제거합니다.
  • document_reference의 source-target 고유 제약이 중복 저장을 방지합니다.
  • 생성, 수정, 삭제, 롤백, 동시 수정 테스트가 추가되었습니다.

실행 환경 제한으로 테스트는 직접 실행하지 못했습니다.

[approve]

You are interacting with an AI system.

@sun007021
sun007021 merged commit 3daad38 into develop Aug 31, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants