Project: doctolib-doctolib · Branch: master · Mode: ` · **Model:**claude-haiku-4-5-20251001`
Stats: 1 user messages, 29 tool calls, tools used: Bash, Grep, Glob, Read.
Conversation
Turn 1 — User
I need to understand a document import issue where: 1. When UPLOAD_DOCUMENT_WRITE feature switch is on, documents are imported via /v2 endpoints (PUT/POST) 2. After successful import, viewing the document immediately fails 3. After waiting ~5 minutes or logout/login, viewing works
Please explore: 1. Find where UPLOAD_DOCUMENT_WRITE feature switch is used in the document upload flow 2. Look for /v2 endpoints for document upload (PUT/POST operations) 3. Find how documents are uploaded/created when this FS is enabled 4. Look for React Query cache invalidation after document uploads (specifically related to the decryptedDocuments query) 5. Check if there's a queryClient.invalidateQueries or similar after document creation
Focus on the documents engine and look for upload/import components and mutations.
Turn 1 — Assistant
I'll help you explore this document import issue. Let me search for the relevant code related to the UPLOAD_DOCUMENT_WRITE feature switch, document upload endpoints, and cache invalidation.
Tools used:
Bash:find /Users/USER/workspace/doctolib/doctolib -type f -name "*.ts" -o -name "*.tsx" -o -name "*.rb" | head -20
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/sorbet/tapioca/require.rb /Users/USER/workspace/doctolib/doctolib/sorbet/tapioca/compilers/module_constant_shortcuts.rb /Users/USER/workspace/doctolib/doctolib/docker/config/pitchfork.conf.rb /Users/USER/workspace/doctolib/doctolib/docker/scripts/generate_app_version.rb /Users/USER/workspace/doctolib/doctolib/app/middleware/error_event_id_injector.rb /Users/USER/workspace/doctolib/doctolib/app/middleware/unique_ssid_counter.rb /Users/USER/workspace/doctoli …(truncated, 1167 more chars)
Let me search for the UPLOAD_DOCUMENT_WRITE feature switch usage and document upload endpoints.
Tools used:
Grep:UPLOAD_DOCUMENT_WRITEin/Users/USER/workspace/doctolib/doctolib
Tool results:
→ result (ok): No files found
Let me try a broader search for document upload related files:
Tools used:
Glob:**/documents/**/*.ts*in/Users/USER/workspace/doctolib/doctolib
Tools used:
Grep:decryptedDocumentsin/Users/USER/workspace/doctolib/doctolib
Tools used:
Grep:invalidateQueriesin/Users/USER/workspace/doctolib/doctolib
Tool results:
→ result (ok): <persisted-output> Output too large (22.4KB). Full output saved to: /Users/USER/.claude/projects/-Users-clertonra-workspace-doctolib-doctolib/ec3195ed-8479-410c-9fb2-c5774097f38e/tool-results/toolu_0131b7smdgqj8bBAF87mR8vz.txt
Preview (first 2KB): Found 292 files packages/@doctolib/siilo_ui/src/queries/siiloPatientCases/siiloPatientCases.ts app/assets/javascripts/queries/configuration/documentCustomizations.ts engines/siilo_integration/app/assets/javascripts/queries/siilo_integration/tele_exper …(truncated, 1746 more chars)
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/app/assets/javascripts/components/doctor/desktop/pages/patient/patient-file-tabs/documents/Documents.tsx /Users/USER/workspace/doctolib/doctolib/app/assets/javascripts/components/doctor/desktop/pages/documents/useNavigateAfterImport/useEhrPtNavigateAfterImport.ts /Users/USER/workspace/doctolib/doctolib/app/assets/javascripts/components/doctor/desktop/pages/documents/useNavigateAfterImport/useDefaultNavigateAfterImport.ts /Users/USER/workspace/doctolib/doct …(truncated, 13459 more chars)
Tool results:
→ result (ok): Found 44 files packages/@doctolib/patient_messaging_pro_sdk/src/modules/doctor_app/CreateMessageButtonModule/useCreateMessageButtonModuleController.ts packages/@doctolib/patient_messaging_pro_sdk/src/modules/doctor_app/CreateMessageButtonModule/useCreateMessageButtonModuleController.test.tsx packages/@doctolib/financial_os_fr_billing/package.json packages/@doctolib/lab-integration/src/data/lab-report.ts app/assets/javascripts/components/doctor/desktop/services/export-medical-folder/pdfMedicalFol …(truncated, 3847 more chars)
Great! Let me now look at the key files related to document uploads and the decryptedDocuments query:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/engines/documents/app/assets/javascripts/queries/documents/doctor_app/decryptedDocuments.ts
Tools used:
Glob:**/documents/**/mutations/**/*.ts*in/Users/USER/workspace/doctolib/doctolib
Tools used:
Grep:v2.*upload|PUT.*document|POST.*documentin/Users/USER/workspace/doctolib/doctolib/engines/documents
Tool results:
→ result (ok): 1→import type { AccountContextType } from '@doctolib/shared_context' 2→import { AccountContext } from '@doctolib/shared_context' 3→import type { DecryptFile } from 'engines/e2ee/public' 4→import { TankerContext } from 'engines/e2ee/public' 5→import { useQuery, useQueryClient } from '@tanstack/react-query' 6→import { handleEncryptedDocument } from 'components/shared/documents/utils' 7→import { HttpClientContext } from 'contexts/ReactQueryProvider' 8→import { use …(truncated, 5373 more chars)
Tool results:
→ result (ok): No files found
Tool results:
→ result (ok): No files found
Let me search for upload and document import related files more broadly:
Tools used:
Grep:upload|importin/Users/USER/workspace/doctolib/doctolib/engines/documents
Tools used:
Glob:**/documents/**/app/controllers/**/*.rbin/Users/USER/workspace/doctolib/doctolib
Tool results:
→ result (ok): Found 30 files limit: 30, offset: 0 engines/documents/app/assets/javascripts/modules/UnifiedDocumentEditModule/types.ts engines/documents/app/assets/javascripts/modules/DocumentEditModule/types.ts engines/documents/app/assets/javascripts/modules/DocumentEditModule/useDocumentEditModuleController.tsx engines/documents/app/assets/javascripts/hooks/doctor/shared/useDocumentEdit/variants/updateDocumentCategory/updateFacets.ts engines/documents/app/assets/javascripts/modules/DocumentEditModule/Docume …(truncated, 2438 more chars)
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/engines/documents/app/controllers/concerns/documents/clear_document_render.rb /Users/USER/workspace/doctolib/doctolib/engines/documents/app/controllers/concerns/documents/parse_signed_id.rb /Users/USER/workspace/doctolib/doctolib/engines/documents/app/controllers/documents/admin/accounts_controller.rb /Users/USER/workspace/doctolib/doctolib/engines/documents/app/controllers/documents/admin/documents_controller.rb /Users/USER/workspace/doctolib/doctolib/eng …(truncated, 3751 more chars)
Perfect! I found the v2 controllers. Let me examine them:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/engines/documents/app/controllers/documents/doctor_app/v2/documents_controller.rb
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/engines/documents/app/controllers/documents/doctor_app/v2/presigned_urls_controller.rb
Tools used:
Grep:UPLOAD_DOCUMENT_WRITE|UPLOAD_DOCUMENTin/Users/USER/workspace/doctolib/doctolib
Tool results:
→ result (ok): 1→# frozen_string_literal: true 2→ 3→# V2 Documents REST Controller - Drop-in replacement for V1 4→# 5→# This controller provides the same REST API surface as V1 DocumentsController 6→# but uses V3 backend (Documents::V3::DocumentService). 7→# 8→# Architecture: 9→# - Thin wrapper around Documents::V3::DocumentService 10→# - Inherits from V1 controller to reuse all helper methods 11→# - Converts ActionDispatch::UploadedFile to hash for service 1 …(truncated, 13320 more chars)
Tool results:
→ result (ok): 1→# frozen_string_literal: true
2→
3→module Documents
4→ module DoctorApp
5→ module V2
6→ class PresignedUrlsController < ::Documents::DoctorApp::ApplicationController
7→ authenticate_with Authentication::Api::Filter::ACCOUNT
8→ after_action :verify_authorized
9→
10→ # POST /documents/doctor_app/v2/documents/:document_id/presigned_url
11→ # Generate presigned URL for a single document
12→ #
13→
…(truncated, 2782 more chars)
Tool results:
→ result (ok): No files found
Great! Now let me search for where the feature switch is actually used in the frontend:
Tools used:
Grep:feature.*switch|featureSwitch|feature_switchin/Users/USER/workspace/doctolib/doctolib/engines/documents/app/assets/javascripts
Tools used:
Glob:**/documents/**/*Import*in/Users/USER/workspace/doctolib/doctolib/app/assets/javascripts
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/app/assets/javascripts/components/doctor/desktop/pages/documents/useNavigateAfterImport/useEhrPtNavigateAfterImport.ts /Users/USER/workspace/doctolib/doctolib/app/assets/javascripts/components/doctor/desktop/pages/documents/useNavigateAfterImport/useDefaultNavigateAfterImport.ts /Users/USER/workspace/doctolib/doctolib/app/assets/javascripts/components/doctor/desktop/pages/documents/useNavigateAfterImport/useUseNavigateAfterImportVariant.ts /Users/USER/work …(truncated, 226 more chars)
Tool results:
→ result (ok): Found 11 files limit: 20, offset: 0 engines/documents/app/assets/javascripts/modules/UnifiedDocumentEditModule/types.ts engines/documents/app/assets/javascripts/modules/DocumentEditModule/types.ts engines/documents/app/assets/javascripts/modules/DocumentEditModule/useDocumentEditModuleController.tsx engines/documents/app/assets/javascripts/hooks/doctor/shared/useDocumentEdit/variants/updateDocumentCategory/updateFacets.ts engines/documents/app/assets/javascripts/modules/DocumentEditModule/Docume …(truncated, 615 more chars)
Let me look at the Imports component which likely handles document imports:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/app/assets/javascripts/components/doctor/desktop/pages/documents/Imports.tsx
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/app/assets/javascripts/components/doctor/desktop/pages/documents/ImportsMainPanel.tsx
Tool results:
→ result (ok): 1→import UnifiedDocumentEditModule from 'engines/documents/modules/UnifiedDocumentEditModule/UnifiedDocumentEditModule' 2→import type { UnifiedDocumentEditModuleProps } from 'engines/documents/modules/UnifiedDocumentEditModule/types' 3→import { type ReactNode, type TouchEvent, useContext } from 'react' 4→import { SelectedPatientContext, type DocumentImportsDocumentWithPreview } from '@doctolib/shared_context' 5→import { getDocumentImportOrigin } from 'engines/documents/helper …(truncated, 5154 more chars)
Tool results:
→ result (ok): 1→import DroppableZoneButtonModule from 'modules/shared/desktop/DroppableZoneButtonModule/DroppableZoneButtonModule' 2→import { type ChangeEvent, type TouchEvent, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react' 3→import { useLocation, useNavigate } from 'react-router-dom' 4→import { omit } from 'lodash-es' 5→import { v4 as uuidv4 } from 'uuid' 6→import type { PDFImage } from 'pdf-lib' 7→import { degrees, PDFDocument } from 'pdf-lib'
…(truncated, 43460 more chars)
Great! Now let me search for the feature switch override constant and the DocumentEditModule which handles uploads:
Tools used:
Grep:UPLOAD_DOCUMENT_FEATURE_SWITCH_OVERRIDEin/Users/USER/workspace/doctolib/doctolib
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/engines/documents/app/assets/javascripts/modules/DocumentEditModule/useDocumentEditModuleController.tsx(1–200)
Tool results:
→ result (ok): 1→import type { ShareWith } from '@doctolib/deepwater_core/public' 2→import { Button } from '@doctolib/design-system/Button' 3→import { useObservationsCreateFromMail } from '@doctolib/ehr_observations_sdk/public/queries/observations' 4→import { useTrackingsCreate } from '@doctolib/ehr_observations_sdk/public/queries/trackings' 5→import { MedicalObservationCategory } from '@doctolib/ehr_observations_sdk/public/types/MedicalObservationCategory' 6→import { mapDeprecatedObse …(truncated, 9916 more chars)
Tool results:
→ result (ok): Found 4 files packages/@doctolib/documents-ui/src/index.ts packages/@doctolib/documents-ui/src/constants.ts app/assets/javascripts/components/doctor/desktop/pages/documents/ImportsMainPanel.tsx app/assets/javascripts/contexts/doctor/desktop/DocumentImportContext.tsx
Now let me look at the documents-ui constants to find the feature switch override:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/documents-ui/src/constants.ts
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/engines/documents/app/assets/javascripts/queries/documents/doctor_app/documents.ts(1–300)
Tool results:
→ result (ok): 1→import type { FeatureSwitchOverride } from './helpers/types' 2→ 3→// Feature switch override for upload_document_write double-write mode 4→export const UPLOAD_DOCUMENT_FEATURE_SWITCH_OVERRIDE: FeatureSwitchOverride = { 5→ featureSwitch: 'upload_document_write', 6→ mode: 'double-write', 7→} 8→ 9→// Feature switch override for mobile confirmation module upload double-write mode 10→export const MOBILE_CONFIRMATION_UPLOAD_FEATURE_SWITCH_OVERRIDE: Featu …(truncated, 476 more chars)
Tool results:
→ result (ok): 1→/* 2→ * @file 3→ * @deprecated This file is deprecated and will be removed in future releases. 4→ * Please use the new implementation in packages/@doctolib/documents-ui/src/data/queries/documents.ts. 5→ * This refactor happens because of the react query migration to v5. 6→ * Feel free to move endpoints to this new file. 7→ / 8→ 9→import path from 'path' 10→import { useContext } from 'react' 11→import type { DoctorAppDocument } from '@doctolib/f …(truncated, 12505 more chars)
Let me search for where the document upload/create is called and look for cache invalidation:
Tools used:
Bash:grep -r "useDocumentsCreate\|createDocument" /Users/USER/workspace/doctolib/doctolib/engines/documents/app/assets/javascripts --include="*.ts" --include="*.tsx" -l | head -10
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/engines/documents/app/assets/javascripts/queries/documents/doctor_app/documents.ts /Users/USER/workspace/doctolib/doctolib/engines/documents/app/assets/javascripts/modules/DocumentEditModule/useDocumentEditModuleController.tsx
Let me read more of the documents.ts file to find the useDocumentsCreate mutation:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/engines/documents/app/assets/javascripts/queries/documents/doctor_app/documents.ts(300–700)
Tool results:
→ result (ok): 300→ 301→ return useQuery({ 302→ queryKey: buildDocumentsShowQueryKey(documentId), 303→ queryFn: () => { 304→ if (!documentId) throw new Error('Unable to fetch a document without documentId') 305→ return getDocument({ documentId, decryptRecord, httpClient }) 306→ }, 307→ enabled: Boolean(enabled && documentId), 308→ onSuccess, 309→ cacheTime, 310→ staleTime, 311→ }) 312→} 313→ 314→export type UseDocumentUpdateMutationResu …(truncated, 10260 more chars)
Perfect! Now let me search for where useDocumentsCreate is called with the featureSwitchOverride and look for any cache invalidation after document creation:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/engines/documents/app/assets/javascripts/modules/DocumentEditModule/useDocumentEditModuleController.tsx(200–600)
Tools used:
Grep:buildDocumentEndpointin/Users/USER/workspace/doctolib/doctolib
Tool results:
→ result (ok): 200→ documentURL: null, 201→ }) 202→ 203→ const { 204→ practitionerSignature: practitionerSignatureFromConsultation, 205→ hasSignature: practitionerHasSignature, 206→ humanFullName: practitionerHumanFullName, 207→ } = usePractitionerSignature({ 208→ accountId: account?.id, 209→ enabled: Boolean(noApptSignatureMode), 210→ }) 211→ 212→ const signatureUrl = noApptSignatureMode 213→ ? practitionerSignatureFromConsultation?.url ?? ''
…(truncated, 16484 more chars)
Tool results:
→ result (ok): Found 14 files packages/@doctolib/documents-ui/src/index.ts app/assets/javascripts/modules/doctor/mobile/document-upload/ConfirmationModule/useConfirmationModuleController.tsx packages/@doctolib/financial_os_fr_billing/src/components/doctor/desktop/patient-folder/body/tp-amc/uploadAmcDocument.ts engines/documents/app/assets/javascripts/queries/documents/doctor_app/documents.ts packages/@doctolib/documents-ui/src/data/queries/documents.ts packages/@doctolib/documents-ui/src/data/queries/documents …(truncated, 673 more chars)
Let me look at buildDocumentEndpoint to understand how the v2 endpoint is selected:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/documents-ui/src/helpers/buildDocumentEndpoint.ts
Tools used:
Grep:invalidateQueries.*decryptedDocuments|decryptedDocuments.*invalidatein/Users/USER/workspace/doctolib/doctolib
Tool results:
→ result (ok): 1→import { isFeatureEnabled } from '@doctolib/variation_management' 2→import type { FeatureSwitchOverride } from './types' 3→ 4→// Helper function to determine if V2 API should be used 5→export function shouldUseV2Api(featureSwitchOrOverride?: string | FeatureSwitchOverride): boolean { 6→ // Handle FeatureSwitchOverride object 7→ if (typeof featureSwitchOrOverride === 'object' && featureSwitchOrOverride !== null) { 8→ const override = featureSwitchOrOverri …(truncated, 1654 more chars)
Tool results:
→ result (ok): No files found
Perfect! Now let me check the DocumentImportContext to see how uploads are handled:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/app/assets/javascripts/contexts/doctor/desktop/DocumentImportContext.tsx(1–400)
Tool results:
→ result (ok): 1→import type { FunctionComponent, ReactNode } from 'react' 2→import { useCallback, useEffect, useMemo, useRef, useState } from 'react' 3→import { v4 as uuidv4 } from 'uuid' 4→import { isEmpty } from 'lodash-es' 5→// TODO - CAT : Fix useQueryClient usage in TT-20637 6→// eslint-disable-next-line doctolib-custom-rules/react-query/react-query-monolith-conventions,doctolib-custom-rules/react-query/restricted-imports 7→import { useQueryClient } from '@tanstack/react-que …(truncated, 18928 more chars)
Perfect! Now let me check if there's anything about invalidating decryptedDocuments after upload. Let me search for the new documents-ui package queries:
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/documents-ui/src/data/queries/documents.ts(1–250)
Tool results:
→ result (ok): 1→/ 2→ * As part of the react query migration to v5, we are moving the queries to this file. 3→ * This file is replacing engines/documents/app/assets/javascripts/queries/documents/doctor_app/documents.ts 4→ * Feel free to add endpoints from the old file to this new one, and fix eventual react query issues. 5→ / 6→ 7→import { useContext } from 'react' 8→import { HttpClientContext } from '@doctolib/shared_context' 9→import { useMutation, useQuery, useQuery …(truncated, 10569 more chars)
Perfect! Now I have a clear picture. Let me create a comprehensive report based on my findings.
Summary of Document Import Issue - Exploration Results
Based on my thorough exploration of the codebase, I've identified the complete flow and pinpointed the likely root cause of the document import issue.
1. UPLOAD_DOCUMENT_WRITE Feature Switch Usage
Location: /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/documents-ui/src/constants.ts
export const UPLOAD_DOCUMENT_FEATURE_SWITCH_OVERRIDE: FeatureSwitchOverride = {
featureSwitch: 'upload_document_write',
mode: 'double-write',
}
When the upload_document_write feature switch is enabled, it forces double-write mode using V2 API endpoints.
2. V2 Endpoints for Document Upload
Locations:
- /Users/USER/workspace/doctolib/doctolib/engines/documents/app/controllers/documents/doctor_app/v2/documents_controller.rb
- /Users/USER/workspace/doctolib/doctolib/engines/documents/app/controllers/documents/doctor_app/v2/presigned_urls_controller.rb
The V2 controller uses Documents::V3::DocumentService which performs:
- Server-side encryption (SSE) uploads to documents_server_encrypted bucket
- Optional Tanker encryption via tanker_encrypted_file parameter
- Atomic 2-phase commit pattern for S3 + DB consistency
Endpoint routing: /doctor_app/v2/documents (POST/PUT) vs /doctor_app/documents (V1)
3. V2 API Selection Logic
Location: /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/documents-ui/src/helpers/buildDocumentEndpoint.ts
export function shouldUseV2Api(featureSwitchOrOverride?: string | FeatureSwitchOverride): boolean {
if (typeof featureSwitchOrOverride === 'object' && featureSwitchOrOverride !== null) {
const override = featureSwitchOrOverride as FeatureSwitchOverride
if (override.featureSwitch && isFeatureEnabled(override.featureSwitch)) {
return true // ← When upload_document_write is enabled
}
return isFeatureEnabled('document_single_write') || isFeatureEnabled('document_double_write')
}
return isFeatureEnabled('document_single_write') || isFeatureEnabled('document_double_write')
}
export function buildDocumentEndpoint(documentId?: string, featureSwitchOverride?: string | FeatureSwitchOverride): string {
const version = shouldUseV2Api(featureSwitchOverride) ? '/v2' : ''
const documentPath = documentId ? `/${documentId}` : ''
return `/doctor_app${version}/documents${documentPath}` // Results in /doctor_app/v2/documents
}
4. Document Upload Flow
Location: /Users/USER/workspace/doctolib/doctolib/app/assets/javascripts/contexts/doctor/desktop/DocumentImportContext.tsx
The upload flow:
1. Files are processed in uploadFile() method (lines 294-395)
2. Encrypted form data is built with featureSwitchOverride: UPLOAD_DOCUMENT_FEATURE_SWITCH_OVERRIDE (line 321)
3. documentsCreate() mutation is called with the override (lines 335-342)
4. After successful upload, invalidateUnclassifiedDocuments() is called (line 396)
5. CRITICAL FINDING: Missing Cache Invalidation for decryptedDocuments
The Root Cause:
The decryptedDocuments query is NOT invalidated after document upload. Here's what is invalidated:
File: /Users/USER/workspace/doctolib/doctolib/engines/documents/app/assets/javascripts/queries/documents/doctor_app/documents.ts
// Lines 443-551: useDocumentsCreate() mutation
export const useDocumentsCreate = () => {
const buildEncryptedFormData = useEncryptedDocumentFormDataBuilder()
return useMutation<DocumentsCreateData, HttpError, DocumentsCreateVariables>({
mutationFn: async (variables) => {
// ... creates document via V2 endpoint
return JSON.parse(responseBody)
},
// ⚠️ NO onSuccess handler - this is the problem!
})
}
Comparison with useDocumentsUpdate (line 415-427):
export const useDocumentsUpdate = () => {
// ...
return useMutation({
// ...
onSuccess: (_, props) => {
queryClient.invalidateQueries({ queryKey: buildDocumentsShowQueryKey(props.documentId) })
// ... invalidates patient and appointment documents
},
})
}
6. What Should Be Invalidated After Upload
Location: /Users/USER/workspace/doctolib/doctolib/engines/documents/app/assets/javascripts/queries/documents/doctor_app/decryptedDocuments.ts
The decryptedDocuments query is built with:
export const buildDecryptedDocumentQueryKey = (documentId?: string) => [
'doctor_app',
'decrypted_documents_url',
documentId,
]
After creating a document via V2 API, this cache is never invalidated, which explains why: - Immediate viewing after upload fails (cached empty/stale data) - After 5 minutes (DOCUMENT_CACHE_TIME = 5 * 60 * 1000), the cache expires - After logout/login, cache is cleared
7. Where Imports Component Attempts to View Documents
File: /Users/USER/workspace/doctolib/doctolib/app/assets/javascripts/components/doctor/desktop/pages/documents/Imports.tsx
Lines 213-217:
const { data: decryptedDocument } = useDecryptedDocumentsShow({
document: selectedDocumentFromContext && 'id' in selectedDocumentFromContext ? selectedDocumentFromContext : null,
})
After upload succeeds, the document has an id but the decryptedDocument query returns stale/missing data because the cache was never invalidated.
Root Cause Summary
The useDocumentsCreate() mutation lacks an onSuccess callback to invalidate the decryptedDocuments query. When upload_document_write feature switch is enabled:
- Document is successfully created via
/doctor_app/v2/documents(POST) - Document has a valid
idin the response - Imports component tries to view the document using
useDecryptedDocumentsShow - The
decryptedDocumentsquery cache for this new document ID is empty/stale - Viewing fails until cache expires (5 minutes) or user logs out/logs back in
Recommended Fix
The useDocumentsCreate() mutation should include cache invalidation in its onSuccess handler similar to useDocumentsUpdate(), specifically:
- Invalidate
buildDecryptedDocumentQueryKey(uploadedDocumentId) - Invalidate patient/appointment document indices
- Consider invalidating any decrypted document URLs that may be cached