Skip to content

fix: 문서 교체 시 진행 중인 figure 스캔을 실제로 중단 - #36

Merged
onetwothr1 merged 1 commit into
devfrom
fix/34-abort-figure-scan-on-document-swap
Jul 28, 2026
Merged

fix: 문서 교체 시 진행 중인 figure 스캔을 실제로 중단#36
onetwothr1 merged 1 commit into
devfrom
fix/34-abort-figure-scan-on-document-swap

Conversation

@onetwothr1

@onetwothr1 onetwothr1 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

FiguresTab.setDocument()#scanGeneration을 올려 이전 스캔의 결과만 버렸고, #scan()이 엔진에 opts.signal을 넘기지 않아 작업은 끝까지 돌았다. 문서를 빠르게 갈아타면 스캔이 중첩돼 크롭 세트가 두 벌 상주한다 — 통합 규약(docs/fig-extract-integration.md §취소)이 명시적으로 요구하는 호스트 측 배선이 빠져 있었다.

엔진은 v2.5.0부터 opts.signal을 지원하고 v2.5.1부터 진행 중 렌더도 RenderTask.cancel()로 끊는다. ExtractOptions.signal도 이미 선언돼 있었다. 호스트만 배선하면 되는 문제였다.

Closes #34

Changes

  • setDocument()가 이전 AbortController를 abort한다. abort는 여기에만 둔다 — 문서 교체만이 진행 중인 스캔을 무효화하는 사건이고, 재시도(ensureScanned)는 종료 상태 'error'에서만 진입하므로 그때는 취소할 스캔이 없다.
  • ensureScanned()가 스캔마다 새 컨트롤러를 만들고 #scan()signal을 전달한다.
  • 취소를 정상 흐름으로 처리한다. 기존 catch는 generation 불일치로 에러 UI가 가려지는 구조였는데, 그에 의존하지 않고 signal.aborted를 명시적으로 본다. 안 그러면 문서를 바꿀 때마다 "figure 스캔에 실패했어요"가 번쩍인다. 엔진이 던지는 이름(AbortError·RenderingCancelledException…)에 기대지 않는다.
  • 성공/실패 경로를 대칭으로 만들었다. generation을 올리지 않는 abort 지점(dispose·패널 닫기 등)이 나중에 생겨도, 취소된 스캔의 결과가 후임 문서 탭에 그려지지 않는다.
  • 조기 반환을 try 안으로 옮겨 #scanAbort 정리가 항상 finally를 거치게 했다 (현재 도달 불가하지만 새 불변식을 가드 하나에만 의존시키지 않는다).

Test plan

  • npm run typecheck 통과 · vitest run 29/29 (기존 27 + 신규 2) · npm run build 통과
  • 신규 테스트가 동어반복이 아님을 확인: src/viewer/panel/tab-figures.ts만 stash하고 돌려 두 테스트가 정확히 실패하는 것을 봤다.
  • 첫 테스트는 엔진과 같은 형태(new DOMException('figure 추출이 취소됨', 'AbortError'))로 거절하며, ① signal.aborted가 실제로 true가 되는지 ② 취소가 에러 UI·console.error를 남기지 않는지 ③ 새 문서 스캔이 정상 렌더되는지를 본다.
  • 수동 QA 완료
  1. Margin 뷰어에서 figure 개수가 많은 논문 A를 엽니다.
  2. 사이드 패널의 그림·표 탭을 엽니다. "figure 스캔 중…" 또는 진행 메시지가 보여야 합니다.
  3. 스캔이 끝나기 전에(카드가 아직 안 뜬 상태) 같은 뷰어 창에 논문 B를 드래그&드롭.

기대 결과

  • "figure 스캔에 실패했어요" + [다시 시도]가 뜨지 않는다 ← 이게 핵심 확인점입니다. 취소를 에러로 처리하면 여기서 번쩍입니다.
  • 논문 B의 figure 카드가 정상 렌더된다.
  • DevTools 콘솔에 figure 스캔 실패 로그가 남지 않는다.
  • 논문 A의 카드가 뒤늦게 섞여 들어오지 않는다.

알아 둘 것

  • 취소는 협조적이라 중첩이 0이 되는 건 아니다. 엔진은 페이지 경계 checkAborted()와 진행 중 렌더에서만 멈추므로, 문서 교체 후에도 나가는 스캔이 약 1페이지 분량을 더 들고 있을 수 있다. "스캔 두 개가 끝까지" 대비 이득이 목적이다.
  • 리뷰 중 더 큰 압력원을 발견해 별건으로 올렸다 (fix: 문서를 교체해도 이전 PDFDocumentProxy를 destroy하지 않아 세션 내내 상주한다 #35): PdfHost.#setDocument가 이전 PDFDocumentProxydestroy()하지 않아 세션 내내 상주한다. 문서를 열수록 단조 증가하므로 이 PR보다 영향이 크다.

Checklist

  • PR 제목이 Conventional Commits 형식 (feat: …, fix: … — squash 커밋 메시지가 됨)
  • npm run typecheck · npm test 통과
  • AI-assisted (에이전트가 작성/보조한 PR이면 체크)

🤖 Generated with Claude Code

setDocument()은 #scanGeneration만 올려 이전 스캔의 결과를 버렸을 뿐, #scan()이
opts.signal을 넘기지 않아 작업은 끝까지 돌았다. 통합 규약 §취소가 요구하는
호스트 측 배선이 빠져 있었다.

- setDocument에서 이전 컨트롤러 abort (여기에만 둔다 — 문서 교체만이 진행 중인
  스캔을 무효화하는 사건이고, 재시도는 종료 상태 'error'에서만 진입한다)
- ensureScanned가 스캔마다 새 AbortController를 만들고 #scan이 signal 전달
- 취소는 정상 흐름이므로 에러 UI를 띄우지 않는다. 엔진이 던지는 이름
  (AbortError·RenderingCancelledException…)에 기대지 않고 signal.aborted만 본다
- 성공/실패 경로를 대칭으로: generation을 올리지 않는 abort 지점이 나중에 생겨도
  취소된 스캔 결과가 후임 문서 탭에 그려지지 않는다
- 조기 반환을 try 안으로 옮겨 #scanAbort 정리가 finally를 항상 거치게 한다

Closes #34

typecheck 0 · vitest 29/29 · build 0. 신규 테스트 2건은 src 수정을 되돌리면
실패함을 확인했다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@onetwothr1
onetwothr1 requested a review from enu3379 as a code owner July 28, 2026 06:19
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@onetwothr1, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 24 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 551f2285-eacf-4657-ad32-e74774518de3

📥 Commits

Reviewing files that changed from the base of the PR and between 2e4d0d7 and 2291d23.

📒 Files selected for processing (3)
  • docs/fig-extract-integration.md
  • src/viewer/panel/tab-figures.ts
  • test/tab-figures.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/34-abort-figure-scan-on-document-swap

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.

@onetwothr1
onetwothr1 merged commit 8bbc8ab into dev Jul 28, 2026
3 checks passed
@onetwothr1
onetwothr1 deleted the fix/34-abort-figure-scan-on-document-swap branch July 28, 2026 06:45
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.

fix: 문서 교체 시 이전 figure 스캔이 중단되지 않아 스캔이 중첩된다

1 participant