Skip to content

add robustness to fetching logic - #93

Merged
InfinityBowman merged 3 commits into
mainfrom
91-extract-metadata-takes-a-long-time
Dec 19, 2025
Merged

add robustness to fetching logic#93
InfinityBowman merged 3 commits into
mainfrom
91-extract-metadata-takes-a-long-time

Conversation

@InfinityBowman

@InfinityBowman InfinityBowman commented Dec 19, 2025

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Per-PDF states: extracting, success, and error with clear visuals and an inline Retry button.
    • Display extracted metadata (author, year) and allow editing titles after successful extraction.
    • Background metadata fetching with per-item loading indicators.
  • Improvements

    • Per-item loading/metadata indicators and distinct error styling/icons for failed uploads.

✏️ Tip: You can customize this high-level summary in your review settings.

@InfinityBowman InfinityBowman linked an issue Dec 19, 2025 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Dec 19, 2025

Copy link
Copy Markdown

Walkthrough

Introduces a timeout utility and refactors PDF extraction into staged, timeout-protected steps; adds per-PDF metadataLoading and error states, a retryPdfExtraction API, and UI branches for extracting/error/success with per-item loading and retry controls.

Changes

Cohort / File(s) Summary
PDF Upload UI
packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
Added per-PDF UI branches: error (VsWarning, red styling) with Retry (FiRefreshCw) that calls studies.retryPdfExtraction(pdf.id), extracting (spinner + message), and success (editable title, metadata). Shows pdf.metadataLoading indicator and conditional author/year metadata.
PDF Utilities
packages/web/src/lib/pdfUtils.js
Added withTimeout(promise, ms, operationName) export and timeout constants (PDF_INIT_TIMEOUT, PDF_EXTRACT_TIMEOUT). Wrapped PDF.js init with timeout. Split extractPdfTitle/extractPdfDoi into top-level timeout wrappers delegating to extractPdfTitleInternal/extractPdfDoiInternal, added cleanup in finally and metadata-first + fallback text extraction logic and helper utilities.
State Management & Extraction
packages/web/src/primitives/useAddStudies.js
Reworked PDF extraction to staged async steps: read file, extract title/DOI with per-step errors, set pdf.error on failures, mark pdf.metadataLoading during background DOI metadata fetch (uses withTimeout and DOI_FETCH_TIMEOUT = 10000). Added retryPdfExtraction(id) to retry failed extractions and merge/replace results. Progressive UI updates on select and background metadata updates.

Sequence Diagram

sequenceDiagram
    participant UI as User/UI
    participant Hook as useAddStudies (handler)
    participant Reader as FileReader
    participant Extractor as pdfUtils (extractors)
    participant Timeout as withTimeout
    participant DoiAPI as DOI Metadata API
    participant State as PDF State

    UI->>Hook: Select PDF
    Hook->>Reader: Read file blob
    Reader-->>Hook: file data / error

    Hook->>Timeout: wrap extractPdfTitle(file)  (PDF_EXTRACT_TIMEOUT)
    Timeout->>Extractor: run extractPdfTitleInternal
    Extractor-->>Timeout: title / error
    Timeout-->>Hook: title result

    Hook->>State: set title / set extracting state

    Hook->>Timeout: wrap extractPdfDoi(file)  (PDF_EXTRACT_TIMEOUT)
    Timeout->>Extractor: run extractPdfDoiInternal
    Extractor-->>Timeout: doi / none
    Timeout-->>Hook: doi result

    alt DOI found
      Hook->>State: set doi, set metadataLoading=true
      par Background DOI metadata fetch
        Hook->>DoiAPI: fetch metadata (withTimeout DOI_FETCH_TIMEOUT)
        DoiAPI-->>Hook: metadata / error
        Hook->>State: update metadata fields, set metadataLoading=false
      end
    else No DOI / extraction error
      Hook->>State: set error
      UI->>User: show error state + Retry button
    end

    UI->>Hook: Retry button clicked
    Hook->>Hook: retryPdfExtraction(id) -> rerun extraction flow
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

  • Pay attention to: timeout semantics and cleanup in pdfUtils (ensure pdfDoc destroyed on all paths).
  • verify useAddStudies async flow: state transitions for metadataLoading, error, duplicate-merge behavior in retry.
  • check PdfUploadSection rendering branches and event handlers wiring to the new hook API.

Possibly related PRs

Poem

🐰 Hop, nibble bytes and chase the cue,

I extract titles, DOIs — then retry too.
Timeouts guard the midnight race,
Errors blink, then find their place,
A tiny rabbit cheers: "Uploads renewed!" 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The PR title 'add robustness to fetching logic' is vague and overly generic. While the changes do add robustness (timeout utilities, error handling, retry mechanisms), the term 'fetching logic' is not specific enough and doesn't convey what is actually being made more robust. The changes involve PDF metadata extraction, UI state management, and timeout handling—details that should be reflected in the title. Consider a more specific title like 'Add timeouts and error handling to PDF metadata extraction' or 'Improve PDF extraction robustness with retry and timeout mechanisms' to better describe the actual changes.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 91-extract-metadata-takes-a-long-time

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16ae2aa and 87c620a.

📒 Files selected for processing (2)
  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx (3 hunks)
  • packages/web/src/lib/pdfUtils.js (6 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{js,jsx,ts,tsx,md,json,sql}

📄 CodeRabbit inference engine (.cursorrules)

Do not use emojis in code, comments, documentation, or commit messages

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
  • packages/web/src/lib/pdfUtils.js
packages/web/src/**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursorrules)

packages/web/src/**/*.{jsx,tsx}: For UI icons, use the solid-icons library or SVGs only, do not use emojis
Use responsive design principles for UI components
Do NOT prop-drill application state. Shared or cross-feature state must live in external stores under packages/web/src/stores/ or relative to the component file
Components should receive at most 1–5 props, and only for local configuration, not shared state
Do not destructure props in SolidJS components as it breaks reactivity. Instead, access props directly or wrap them in a function to ensure reactivity
Use createMemo for derived values in SolidJS to ensure reactivity
Use Solid's createStore for complex state or state objects for better performance and reactivity
Create reusable logic in primitives (hooks) that can be shared across components to keep components clean and focused on rendering
Components should be lean and focused. Do not implement business logic; move that into stores, utilities, or primitives
Never have a component act as a 'God component' coordinating multiple large concerns

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features
Use aliases for imports when appropriate to improve readability
Prefer using config files rather than hardcoding values
Each file should handle one coherent responsibility
Use Zod for schema and input validation

**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features
Use aliases for imports when appropriate to improve readability

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
  • packages/web/src/lib/pdfUtils.js
packages/web/src/**/*.{jsx,tsx,js,ts}

📄 CodeRabbit inference engine (.cursorrules)

Ensure browser compatibility for all frontend code, particularly for Safari

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
  • packages/web/src/lib/pdfUtils.js
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursorrules)

Keep files small, focused, and modular. Extract sub-modules into folders with index.jsx and helper components, or move complex logic into separate utility files or primitives

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
packages/web/src/components/**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursorrules)

packages/web/src/components/**/*.{jsx,tsx}: Group related components in subdirectories with an index.js barrel export
Use Zag.js for UI components and design system

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
packages/web/src/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

packages/web/src/**/*.{js,jsx,ts,tsx}: For UI icons, use the solid-icons library or SVGs only. Do not use emojis
Use responsive design principles for UI components
Ensure browser compatibility for all frontend code (Safari is usually problematic)
Move complex logic into separate utility files or primitives instead of keeping it in large component files
Use Zag.js for UI components and design system
Do NOT prop-drill application state in SolidJS components. Shared or cross-feature state must live in external stores under packages/web/src/stores/ or relative to the component file
Use createMemo to compute derived values based on props or state in SolidJS to ensure reactive updates
Use Solid's createStore for complex state or state objects in SolidJS for better performance and reactivity
Create reusable logic in primitives (hooks) that can be shared across SolidJS components to keep components clean and focused on rendering

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
  • packages/web/src/lib/pdfUtils.js
packages/web/src/components/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

packages/web/src/components/**/*.{js,jsx,ts,tsx}: Keep files small, focused, and modular. Extract sub-modules into a folder (e.g., ComponentName/ with index.jsx and helper components) if a file exceeds a high number of lines
Split large forms into section components (see add-studies/ folder pattern)
Reuse existing Zag components from packages/web/src/components/zag/* before adding new components. Check the README.md in that folder for a list of existing components
Components should receive at most 1–5 props for local configuration only, not for shared state. If more props are needed, move shared data into an external store, primitive, or Solid context
Do NOT destructure props in SolidJS components as it breaks reactivity. Access props directly from the props object or wrap them in a function to ensure they are always up-to-date
Components should be lean and focused and should not implement business logic. Move business logic into stores, utilities, or primitives

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
packages/web/src/components/**

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Group related components in subdirectories with an index.js barrel export

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
🧠 Learnings (4)
📚 Learning: 2025-12-19T01:58:03.919Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-19T01:58:03.919Z
Learning: Applies to packages/web/src/components/**/*.{js,jsx,ts,tsx} : Split large forms into section components (see `add-studies/` folder pattern)

Applied to files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
📚 Learning: 2025-12-18T22:13:00.528Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursorrules:0-0
Timestamp: 2025-12-18T22:13:00.528Z
Learning: Applies to packages/web/src/**/*.{jsx,tsx} : For UI icons, use the `solid-icons` library or SVGs only, do not use emojis

Applied to files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
📚 Learning: 2025-12-19T01:58:03.919Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-19T01:58:03.919Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : For UI icons, use the `solid-icons` library or SVGs only. Do not use emojis

Applied to files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
📚 Learning: 2025-12-18T22:13:00.529Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursorrules:0-0
Timestamp: 2025-12-18T22:13:00.529Z
Learning: Applies to packages/web/src/**/*.{jsx,tsx} : Use Solid's createStore for complex state or state objects for better performance and reactivity

Applied to files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
🧬 Code graph analysis (1)
packages/web/src/lib/pdfUtils.js (4)
packages/web/src/components/checklist-ui/ChecklistYjsWrapper.jsx (1)
  • pdfData (20-20)
packages/web/src/components/checklist-ui/compare/ReconciliationWrapper.jsx (1)
  • pdfData (44-44)
packages/workers/src/index.js (1)
  • pdfData (292-292)
packages/web/src/components/checklist-ui/pdf/PdfViewer.jsx (1)
  • pdf (29-34)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Workers Builds: corates
🔇 Additional comments (14)
packages/web/src/lib/pdfUtils.js (7)

12-14: LGTM! Timeout constants are well-defined.

The 10-second timeout values for both initialization and extraction operations provide reasonable bounds for PDF processing while being generous enough for larger files.


23-34: LGTM! Timeout wrapper is correctly implemented.

The Promise.race pattern with cleanup in finally ensures the timeout is always cleared. Note that timed-out promises continue executing in the background, but this is acceptable for read-only PDF operations.


47-51: LGTM! Initialization timeout properly applied.

The timeout wrapper around the dynamic imports ensures PDF.js initialization won't hang indefinitely.


69-71: LGTM! Clean timeout wrapper pattern.

The delegation to an internal function wrapped with timeout provides a clean separation and resolves the previous nested timeout issue.


76-142: Excellent! Past review issues have been fully addressed.

The nested timeout issue has been resolved by removing the inner withTimeout wrapper, and proper resource cleanup is now ensured with the try/finally block calling pdf.destroy(). The cleanup pattern correctly guards against null references.


216-218: LGTM! Consistent timeout wrapper pattern.

The DOI extraction follows the same clean wrapper pattern as title extraction.


223-275: LGTM! Consistent cleanup pattern applied.

The DOI extraction implements the same robust cleanup pattern with proper resource management in the finally block.

packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx (7)

9-10: LGTM! Icon imports follow project guidelines.

Using solid-icons library as required by the coding guidelines.


37-42: LGTM! Clear visual distinction for error states.

The conditional styling provides appropriate visual feedback to users when PDFs encounter errors.


44-50: LGTM! Icon color logic is correct.

The color logic now properly applies red styling to indicate errors and gray for normal states, addressing the previous review feedback.


52-67: LGTM! Clear error state with retry functionality.

The error UI provides clear feedback with appropriate icons and a user-friendly retry mechanism.


69-76: LGTM! Clear loading state indication.

The extracting state provides appropriate feedback during PDF processing.


78-97: LGTM! Clean success state with title editing.

The title editing interface is intuitive and the matched indicator provides useful feedback.


98-127: LGTM! Comprehensive metadata loading and display.

The loading indicator and metadata display provide clear feedback about the background DOI fetching process. The conditional logic correctly handles the different states.


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

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Dec 19, 2025

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
corates 87c620a Commit Preview URL Dec 19 2025, 01:58 AM

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
packages/web/src/primitives/useAddStudies.js (2)

241-264: Background DOI fetch may update state after component unmount.

The fire-and-forget pattern for DOI metadata fetching (lines 243-263) could attempt to update state after the component unmounts, potentially causing warnings or unexpected behavior in development mode.

Consider tracking the fetch with an AbortController or checking if the PDF still exists before updating state.

Defensive check before state update
       withTimeout(fetchFromDOI(doi), DOI_FETCH_TIMEOUT, 'DOI metadata fetch')
         .then(refData => {
+          // Check if PDF still exists before updating
+          const stillExists = uploadedPdfs.find(p => p.id === pdf.id);
+          if (!stillExists) return;
+          
           if (refData) {
             setUploadedPdfs(p => p.id === pdf.id, {

268-311: Fragile duplicate merging approach in retryPdfExtraction.

The current implementation calls handlePdfSelect which creates a new entry, then manually merges the duplicate back. This is complex and could have race conditions if handlePdfSelect is async and multiple retries happen simultaneously.

Consider extracting the extraction logic into a shared helper function that both handlePdfSelect and retryPdfExtraction can call directly, avoiding the duplicate creation/merging pattern.

Proposed refactor outline
// Extract core extraction logic
const extractPdfMetadata = async (pdfId, file) => {
  // Reset state
  setUploadedPdfs(p => p.id === pdfId, {
    extracting: true,
    error: null,
    // ...
  });

  // Perform extraction steps (current lines 197-264)
  // ...
};

// Use in handlePdfSelect
for (const pdf of newPdfs) {
  await extractPdfMetadata(pdf.id, pdf.file);
}

// Use in retryPdfExtraction
const retryPdfExtraction = async id => {
  const pdf = uploadedPdfs.find(p => p.id === id);
  if (!pdf?.file) return;
  await extractPdfMetadata(id, pdf.file);
};
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b5ed85 and 16ae2aa.

📒 Files selected for processing (3)
  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx (3 hunks)
  • packages/web/src/lib/pdfUtils.js (4 hunks)
  • packages/web/src/primitives/useAddStudies.js (4 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,jsx,ts,tsx,md,json,sql}

📄 CodeRabbit inference engine (.cursorrules)

Do not use emojis in code, comments, documentation, or commit messages

Files:

  • packages/web/src/lib/pdfUtils.js
  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
  • packages/web/src/primitives/useAddStudies.js
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features
Use aliases for imports when appropriate to improve readability
Prefer using config files rather than hardcoding values
Each file should handle one coherent responsibility
Use Zod for schema and input validation

**/*.{js,jsx,ts,tsx}: Prefer modern ES6+ syntax and features
Use Zod for schema and input validation

Files:

  • packages/web/src/lib/pdfUtils.js
  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
  • packages/web/src/primitives/useAddStudies.js
packages/web/src/**/*.{jsx,tsx,js,ts}

📄 CodeRabbit inference engine (.cursorrules)

Ensure browser compatibility for all frontend code, particularly for Safari

packages/web/src/**/*.{jsx,tsx,js,ts}: For UI icons, use the solid-icons library or SVGs only. Do not use emojis
Ensure browser compatibility for all frontend code with special attention to Safari
Use createMemo for derived values in SolidJS and createStore for complex state to ensure reactivity and performance

Files:

  • packages/web/src/lib/pdfUtils.js
  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
  • packages/web/src/primitives/useAddStudies.js
packages/web/src/**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursorrules)

packages/web/src/**/*.{jsx,tsx}: For UI icons, use the solid-icons library or SVGs only, do not use emojis
Use responsive design principles for UI components
Do NOT prop-drill application state. Shared or cross-feature state must live in external stores under packages/web/src/stores/ or relative to the component file
Components should receive at most 1–5 props, and only for local configuration, not shared state
Do not destructure props in SolidJS components as it breaks reactivity. Instead, access props directly or wrap them in a function to ensure reactivity
Use createMemo for derived values in SolidJS to ensure reactivity
Use Solid's createStore for complex state or state objects for better performance and reactivity
Create reusable logic in primitives (hooks) that can be shared across components to keep components clean and focused on rendering
Components should be lean and focused. Do not implement business logic; move that into stores, utilities, or primitives
Never have a component act as a 'God component' coordinating multiple large concerns

packages/web/src/**/*.{jsx,tsx}: Use responsive design principles for UI components in the web package
Use Zag.js for UI components and design system in the web package
Do not prop-drill application state—shared or cross-feature state must live in external stores under packages/web/src/stores/ or relative to the component file
Components should receive at most 1–5 props for local configuration, not shared state; move shared data into external stores, primitives, or Solid context
In SolidJS, do not destructure props as it breaks reactivity—access props directly from the props object or wrap them in a function

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursorrules)

Keep files small, focused, and modular. Extract sub-modules into folders with index.jsx and helper components, or move complex logic into separate utility files or primitives

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
packages/web/src/components/**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursorrules)

packages/web/src/components/**/*.{jsx,tsx}: Group related components in subdirectories with an index.js barrel export
Use Zag.js for UI components and design system

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
packages/web/src/components/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Group related components in subdirectories with an index.js barrel export

Files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
🧠 Learnings (3)
📚 Learning: 2025-12-18T22:13:22.395Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-18T22:13:22.395Z
Learning: Applies to packages/web/src/**/*.{jsx,tsx,js,ts} : For UI icons, use the `solid-icons` library or SVGs only. Do not use emojis

Applied to files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
📚 Learning: 2025-12-18T22:13:00.528Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursorrules:0-0
Timestamp: 2025-12-18T22:13:00.528Z
Learning: Applies to packages/web/src/**/*.{jsx,tsx} : For UI icons, use the `solid-icons` library or SVGs only, do not use emojis

Applied to files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
📚 Learning: 2025-12-18T22:13:00.529Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursorrules:0-0
Timestamp: 2025-12-18T22:13:00.529Z
Learning: Applies to packages/web/src/**/*.{jsx,tsx} : Use Solid's createStore for complex state or state objects for better performance and reactivity

Applied to files:

  • packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx
🧬 Code graph analysis (2)
packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx (7)
packages/web/src/lib/pdfUtils.js (2)
  • pdf (80-84)
  • pdf (224-228)
packages/web/src/components/project-ui/ProjectView.jsx (1)
  • studies (52-52)
packages/web/src/primitives/useProjectPdfHandlers.js (1)
  • studies (25-25)
packages/web/src/components/project-ui/ReviewerAssignment.jsx (1)
  • studies (37-37)
packages/web/src/components/project-ui/add-studies/ReferenceImportSection.jsx (1)
  • studies (20-20)
packages/web/src/components/project-ui/add-studies/DoiLookupSection.jsx (1)
  • studies (21-21)
packages/web/src/components/project-ui/add-studies/GoogleDriveSection.jsx (1)
  • studies (14-14)
packages/web/src/primitives/useAddStudies.js (2)
packages/web/src/lib/pdfUtils.js (7)
  • pdf (80-84)
  • pdf (224-228)
  • title (120-123)
  • readFileAsArrayBuffer (200-207)
  • extractPdfTitle (70-72)
  • extractPdfDoi (215-217)
  • withTimeout (24-35)
packages/web/src/lib/referenceLookup.js (1)
  • fetchFromDOI (139-170)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Workers Builds: corates
🔇 Additional comments (7)
packages/web/src/lib/pdfUtils.js (2)

24-35: LGTM - Clean timeout utility implementation.

The withTimeout function correctly uses Promise.race and cleans up the timer in finally, preventing timer leaks regardless of resolution or rejection.


248-259: _metadataMap is a private property that may break with pdfjs-dist updates.

The code accesses metadata.metadata._metadataMap to iterate over all metadata entries. While this works, it relies on internal implementation details (indicated by the underscore prefix) that could change in future versions.

The suggested getAll() method does not exist in the pdfjs-dist API. If metadata iteration is necessary for your use case, consider adding a defensive fallback or wrapping this access in a try-catch to handle potential breaking changes gracefully:

   // Check custom metadata
-  if (metadata?.metadata?._metadataMap) {
-    for (const [key, value] of metadata.metadata._metadataMap) {
+  const metadataMap = metadata?.metadata?._metadataMap;
+  if (metadataMap && typeof metadataMap[Symbol.iterator] === 'function') {
+    for (const [key, value] of metadataMap) {
packages/web/src/components/project-ui/add-studies/PdfUploadSection.jsx (2)

52-67: LGTM - Error state UI with retry functionality.

The error state properly displays the error message, shows the filename for context, and provides a retry button with appropriate styling. The optional chaining on retryPdfExtraction is good defensive coding.


69-127: LGTM - Well-structured extraction and success state UI.

The component correctly handles the three mutually exclusive states (error, extracting, success) with appropriate visual feedback. The metadata loading indicator and display are cleanly implemented with proper conditional rendering.

packages/web/src/primitives/useAddStudies.js (3)

24-25: LGTM - Timeout constant for DOI metadata fetch.

The 10-second timeout is reasonable for external API calls to CrossRef.


1046-1060: New PDF state fields (error, metadataLoading) not included in serialization.

The error and metadataLoading fields added to PDF state (lines 185-186) are not serialized in getSerializableState. While metadataLoading: false is reasonable (fetch state is lost), consider whether error should be preserved so users see extraction failures after OAuth redirects.

If errors should persist:

     const serializedPdfs = uploadedPdfs.map(pdf => ({
       id: pdf.id,
       title: pdf.title,
       extracting: pdf.extracting,
       data: cloneArrayBuffer(pdf.data),
       doi: pdf.doi,
+      error: pdf.error || null,
       metadata: pdf.metadata ? { ...pdf.metadata } : null,

1211-1218: LGTM - New handler properly exported.

The retryPdfExtraction function is correctly added to the hook's return object, making it available to consuming components.

Comment thread packages/web/src/lib/pdfUtils.js Outdated
Comment thread packages/web/src/lib/pdfUtils.js
@InfinityBowman
InfinityBowman merged commit 13215d2 into main Dec 19, 2025
3 checks passed
@InfinityBowman
InfinityBowman deleted the 91-extract-metadata-takes-a-long-time branch December 19, 2025 02:00
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.

Extract metadata takes a long time

1 participant