@fluidframework/odsp-driver 2.0.0-dev-rc.1.0.0.232845 → 2.0.0-dev-rc.2.0.0.246488
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +18 -3
- package/{.mocharc.js → .mocharc.cjs} +1 -1
- package/CHANGELOG.md +44 -0
- package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
- package/api-extractor-lint.json +1 -1
- package/api-extractor.json +1 -1
- package/api-report/odsp-driver.api.md +11 -12
- package/dist/ReadBufferUtils.d.ts.map +1 -1
- package/dist/ReadBufferUtils.js.map +1 -1
- package/dist/WriteBufferUtils.d.ts +1 -1
- package/dist/WriteBufferUtils.d.ts.map +1 -1
- package/dist/WriteBufferUtils.js +12 -12
- package/dist/WriteBufferUtils.js.map +1 -1
- package/dist/checkUrl.d.ts.map +1 -1
- package/dist/checkUrl.js +5 -3
- package/dist/checkUrl.js.map +1 -1
- package/dist/compactSnapshotParser.d.ts.map +1 -1
- package/dist/compactSnapshotParser.js +87 -69
- package/dist/compactSnapshotParser.js.map +1 -1
- package/dist/compactSnapshotWriter.d.ts.map +1 -1
- package/dist/compactSnapshotWriter.js +25 -19
- package/dist/compactSnapshotWriter.js.map +1 -1
- package/dist/contracts.d.ts +10 -4
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/createFile.d.ts +3 -3
- package/dist/createFile.d.ts.map +1 -1
- package/dist/createFile.js +30 -27
- package/dist/createFile.js.map +1 -1
- package/dist/createNewContainerOnExistingFile.d.ts +2 -2
- package/dist/createNewContainerOnExistingFile.d.ts.map +1 -1
- package/dist/createNewContainerOnExistingFile.js +14 -14
- package/dist/createNewContainerOnExistingFile.js.map +1 -1
- package/dist/createNewModule.d.ts +2 -2
- package/dist/createNewModule.d.ts.map +1 -1
- package/dist/createNewModule.js +4 -4
- package/dist/createNewModule.js.map +1 -1
- package/dist/createNewUtils.d.ts +2 -2
- package/dist/createNewUtils.d.ts.map +1 -1
- package/dist/createNewUtils.js +12 -8
- package/dist/createNewUtils.js.map +1 -1
- package/dist/createOdspCreateContainerRequest.d.ts.map +1 -1
- package/dist/createOdspCreateContainerRequest.js +6 -2
- package/dist/createOdspCreateContainerRequest.js.map +1 -1
- package/dist/createOdspUrl.d.ts +1 -1
- package/dist/createOdspUrl.d.ts.map +1 -1
- package/dist/createOdspUrl.js.map +1 -1
- package/dist/epochTracker.d.ts +10 -9
- package/dist/epochTracker.d.ts.map +1 -1
- package/dist/epochTracker.js +66 -43
- package/dist/epochTracker.js.map +1 -1
- package/dist/fetchSnapshot.d.ts +11 -8
- package/dist/fetchSnapshot.d.ts.map +1 -1
- package/dist/fetchSnapshot.js +79 -58
- package/dist/fetchSnapshot.js.map +1 -1
- package/dist/getFileLink.d.ts.map +1 -1
- package/dist/getFileLink.js +24 -17
- package/dist/getFileLink.js.map +1 -1
- package/dist/getQueryString.d.ts.map +1 -1
- package/dist/getQueryString.js +6 -0
- package/dist/getQueryString.js.map +1 -1
- package/dist/index.d.ts +19 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -44
- package/dist/index.js.map +1 -1
- package/dist/localOdspDriver/localOdspDocumentService.d.ts +1 -1
- package/dist/localOdspDriver/localOdspDocumentService.d.ts.map +1 -1
- package/dist/localOdspDriver/localOdspDocumentService.js +5 -5
- package/dist/localOdspDriver/localOdspDocumentService.js.map +1 -1
- package/dist/localOdspDriver/localOdspDocumentServiceFactory.d.ts +8 -6
- package/dist/localOdspDriver/localOdspDocumentServiceFactory.d.ts.map +1 -1
- package/dist/localOdspDriver/localOdspDocumentServiceFactory.js +10 -9
- package/dist/localOdspDriver/localOdspDocumentServiceFactory.js.map +1 -1
- package/dist/localOdspDriver/localOdspDocumentStorageManager.d.ts +1 -1
- package/dist/localOdspDriver/localOdspDocumentStorageManager.d.ts.map +1 -1
- package/dist/localOdspDriver/localOdspDocumentStorageManager.js +6 -6
- package/dist/localOdspDriver/localOdspDocumentStorageManager.js.map +1 -1
- package/dist/odsp-driver-alpha.d.ts +27 -12
- package/dist/odsp-driver-beta.d.ts +1 -2
- package/dist/odsp-driver-public.d.ts +1 -2
- package/dist/odsp-driver-untrimmed.d.ts +29 -12
- package/dist/odspCache.d.ts +3 -3
- package/dist/odspCache.d.ts.map +1 -1
- package/dist/odspCache.js +3 -4
- package/dist/odspCache.js.map +1 -1
- package/dist/odspDelayLoadedDeltaStream.d.ts +7 -5
- package/dist/odspDelayLoadedDeltaStream.d.ts.map +1 -1
- package/dist/odspDelayLoadedDeltaStream.js +41 -28
- package/dist/odspDelayLoadedDeltaStream.js.map +1 -1
- package/dist/odspDeltaStorageService.d.ts +7 -7
- package/dist/odspDeltaStorageService.d.ts.map +1 -1
- package/dist/odspDeltaStorageService.js +5 -5
- package/dist/odspDeltaStorageService.js.map +1 -1
- package/dist/odspDocumentDeltaConnection.d.ts +1 -1
- package/dist/odspDocumentDeltaConnection.d.ts.map +1 -1
- package/dist/odspDocumentDeltaConnection.js +41 -23
- package/dist/odspDocumentDeltaConnection.js.map +1 -1
- package/dist/odspDocumentService.d.ts +6 -4
- package/dist/odspDocumentService.d.ts.map +1 -1
- package/dist/odspDocumentService.js +19 -16
- package/dist/odspDocumentService.js.map +1 -1
- package/dist/odspDocumentServiceFactory.d.ts +6 -1
- package/dist/odspDocumentServiceFactory.d.ts.map +1 -1
- package/dist/odspDocumentServiceFactory.js +9 -4
- package/dist/odspDocumentServiceFactory.js.map +1 -1
- package/dist/odspDocumentServiceFactoryCore.d.ts +4 -4
- package/dist/odspDocumentServiceFactoryCore.d.ts.map +1 -1
- package/dist/odspDocumentServiceFactoryCore.js +26 -22
- package/dist/odspDocumentServiceFactoryCore.js.map +1 -1
- package/dist/odspDocumentServiceFactoryWithCodeSplit.d.ts +1 -1
- package/dist/odspDocumentServiceFactoryWithCodeSplit.d.ts.map +1 -1
- package/dist/odspDocumentServiceFactoryWithCodeSplit.js +2 -2
- package/dist/odspDocumentServiceFactoryWithCodeSplit.js.map +1 -1
- package/dist/odspDocumentStorageManager.d.ts +15 -9
- package/dist/odspDocumentStorageManager.d.ts.map +1 -1
- package/dist/odspDocumentStorageManager.js +219 -181
- package/dist/odspDocumentStorageManager.js.map +1 -1
- package/dist/odspDocumentStorageServiceBase.d.ts +2 -4
- package/dist/odspDocumentStorageServiceBase.d.ts.map +1 -1
- package/dist/odspDocumentStorageServiceBase.js +32 -29
- package/dist/odspDocumentStorageServiceBase.js.map +1 -1
- package/dist/odspDriverUrlResolver.d.ts +5 -1
- package/dist/odspDriverUrlResolver.d.ts.map +1 -1
- package/dist/odspDriverUrlResolver.js +27 -24
- package/dist/odspDriverUrlResolver.js.map +1 -1
- package/dist/odspDriverUrlResolverForShareLink.d.ts +17 -6
- package/dist/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
- package/dist/odspDriverUrlResolverForShareLink.js +49 -39
- package/dist/odspDriverUrlResolverForShareLink.js.map +1 -1
- package/dist/odspError.d.ts +1 -1
- package/dist/odspError.d.ts.map +1 -1
- package/dist/odspError.js +5 -5
- package/dist/odspError.js.map +1 -1
- package/dist/odspFluidFileLink.d.ts +1 -1
- package/dist/odspFluidFileLink.d.ts.map +1 -1
- package/dist/odspFluidFileLink.js +2 -2
- package/dist/odspFluidFileLink.js.map +1 -1
- package/dist/odspLocationRedirection.js +2 -2
- package/dist/odspLocationRedirection.js.map +1 -1
- package/dist/odspPublicUtils.d.ts +3 -0
- package/dist/odspPublicUtils.d.ts.map +1 -1
- package/dist/odspPublicUtils.js +3 -0
- package/dist/odspPublicUtils.js.map +1 -1
- package/dist/odspSnapshotParser.d.ts +1 -1
- package/dist/odspSnapshotParser.d.ts.map +1 -1
- package/dist/odspSnapshotParser.js +3 -2
- package/dist/odspSnapshotParser.js.map +1 -1
- package/dist/odspSummaryUploadManager.d.ts +1 -1
- package/dist/odspSummaryUploadManager.d.ts.map +1 -1
- package/dist/odspSummaryUploadManager.js +9 -6
- package/dist/odspSummaryUploadManager.js.map +1 -1
- package/dist/odspUrlHelper.d.ts.map +1 -1
- package/dist/odspUrlHelper.js +1 -2
- package/dist/odspUrlHelper.js.map +1 -1
- package/dist/odspUtils.d.ts +19 -7
- package/dist/odspUtils.d.ts.map +1 -1
- package/dist/odspUtils.js +61 -31
- package/dist/odspUtils.js.map +1 -1
- package/dist/opsCaching.d.ts +1 -1
- package/dist/opsCaching.d.ts.map +1 -1
- package/dist/opsCaching.js +2 -1
- package/dist/opsCaching.js.map +1 -1
- package/dist/package.json +3 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/prefetchLatestSnapshot.d.ts +2 -2
- package/dist/prefetchLatestSnapshot.d.ts.map +1 -1
- package/dist/prefetchLatestSnapshot.js +17 -12
- package/dist/prefetchLatestSnapshot.js.map +1 -1
- package/dist/retryErrorsStorageAdapter.d.ts +0 -1
- package/dist/retryErrorsStorageAdapter.d.ts.map +1 -1
- package/dist/retryErrorsStorageAdapter.js +2 -5
- package/dist/retryErrorsStorageAdapter.js.map +1 -1
- package/dist/retryUtils.d.ts.map +1 -1
- package/dist/retryUtils.js +6 -2
- package/dist/retryUtils.js.map +1 -1
- package/dist/socketModule.d.ts.map +1 -1
- package/dist/socketModule.js +2 -0
- package/dist/socketModule.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/vroom.d.ts +2 -2
- package/dist/vroom.d.ts.map +1 -1
- package/dist/vroom.js +5 -5
- package/dist/vroom.js.map +1 -1
- package/dist/zipItDataRepresentationUtils.d.ts +1 -1
- package/dist/zipItDataRepresentationUtils.d.ts.map +1 -1
- package/dist/zipItDataRepresentationUtils.js +15 -11
- package/dist/zipItDataRepresentationUtils.js.map +1 -1
- package/lib/{ReadBufferUtils.d.mts → ReadBufferUtils.d.ts} +1 -1
- package/lib/ReadBufferUtils.d.ts.map +1 -0
- package/lib/{ReadBufferUtils.mjs → ReadBufferUtils.js} +1 -1
- package/lib/ReadBufferUtils.js.map +1 -0
- package/lib/{WriteBufferUtils.d.mts → WriteBufferUtils.d.ts} +2 -2
- package/lib/WriteBufferUtils.d.ts.map +1 -0
- package/lib/{WriteBufferUtils.mjs → WriteBufferUtils.js} +2 -2
- package/lib/WriteBufferUtils.js.map +1 -0
- package/lib/{checkUrl.d.mts → checkUrl.d.ts} +1 -1
- package/lib/checkUrl.d.ts.map +1 -0
- package/lib/{checkUrl.mjs → checkUrl.js} +5 -3
- package/lib/checkUrl.js.map +1 -0
- package/lib/{compactSnapshotParser.d.mts → compactSnapshotParser.d.ts} +1 -1
- package/lib/compactSnapshotParser.d.ts.map +1 -0
- package/lib/{compactSnapshotParser.mjs → compactSnapshotParser.js} +61 -43
- package/lib/compactSnapshotParser.js.map +1 -0
- package/lib/{compactSnapshotWriter.d.mts → compactSnapshotWriter.d.ts} +1 -1
- package/lib/compactSnapshotWriter.d.ts.map +1 -0
- package/lib/{compactSnapshotWriter.mjs → compactSnapshotWriter.js} +13 -7
- package/lib/compactSnapshotWriter.js.map +1 -0
- package/lib/{constants.d.mts → constants.d.ts} +1 -1
- package/lib/constants.d.ts.map +1 -0
- package/lib/{constants.mjs → constants.js} +1 -1
- package/lib/constants.js.map +1 -0
- package/lib/{contracts.d.mts → contracts.d.ts} +11 -5
- package/lib/contracts.d.ts.map +1 -0
- package/lib/{contracts.mjs → contracts.js} +1 -1
- package/lib/contracts.js.map +1 -0
- package/lib/{contractsPublic.d.mts → contractsPublic.d.ts} +1 -1
- package/lib/contractsPublic.d.ts.map +1 -0
- package/lib/{contractsPublic.mjs → contractsPublic.js} +1 -1
- package/lib/contractsPublic.js.map +1 -0
- package/lib/{createFile.d.mts → createFile.d.ts} +4 -4
- package/lib/createFile.d.ts.map +1 -0
- package/lib/{createFile.mjs → createFile.js} +15 -12
- package/lib/createFile.js.map +1 -0
- package/lib/{createNewContainerOnExistingFile.d.mts → createNewContainerOnExistingFile.d.ts} +3 -3
- package/lib/createNewContainerOnExistingFile.d.ts.map +1 -0
- package/lib/{createNewContainerOnExistingFile.mjs → createNewContainerOnExistingFile.js} +7 -7
- package/lib/createNewContainerOnExistingFile.js.map +1 -0
- package/lib/{createNewModule.mjs → createNewModule.d.ts} +3 -3
- package/lib/createNewModule.d.ts.map +1 -0
- package/lib/{createNewModule.d.mts → createNewModule.js} +3 -3
- package/lib/createNewModule.js.map +1 -0
- package/lib/{createNewUtils.d.mts → createNewUtils.d.ts} +3 -3
- package/lib/createNewUtils.d.ts.map +1 -0
- package/lib/{createNewUtils.mjs → createNewUtils.js} +9 -5
- package/lib/createNewUtils.js.map +1 -0
- package/lib/{createOdspCreateContainerRequest.d.mts → createOdspCreateContainerRequest.d.ts} +5 -1
- package/lib/createOdspCreateContainerRequest.d.ts.map +1 -0
- package/lib/{createOdspCreateContainerRequest.mjs → createOdspCreateContainerRequest.js} +6 -2
- package/lib/createOdspCreateContainerRequest.js.map +1 -0
- package/lib/{createOdspUrl.d.mts → createOdspUrl.d.ts} +2 -2
- package/lib/createOdspUrl.d.ts.map +1 -0
- package/lib/{createOdspUrl.mjs → createOdspUrl.js} +1 -1
- package/lib/createOdspUrl.js.map +1 -0
- package/lib/{epochTracker.d.mts → epochTracker.d.ts} +11 -10
- package/lib/epochTracker.d.ts.map +1 -0
- package/lib/{epochTracker.mjs → epochTracker.js} +56 -33
- package/lib/epochTracker.js.map +1 -0
- package/lib/{fetch.d.mts → fetch.d.ts} +1 -1
- package/lib/fetch.d.ts.map +1 -0
- package/lib/{fetch.mjs → fetch.js} +1 -1
- package/lib/fetch.js.map +1 -0
- package/lib/{fetchSnapshot.d.mts → fetchSnapshot.d.ts} +12 -9
- package/lib/fetchSnapshot.d.ts.map +1 -0
- package/lib/{fetchSnapshot.mjs → fetchSnapshot.js} +61 -40
- package/lib/fetchSnapshot.js.map +1 -0
- package/lib/{getFileLink.d.mts → getFileLink.d.ts} +1 -1
- package/lib/getFileLink.d.ts.map +1 -0
- package/lib/{getFileLink.mjs → getFileLink.js} +14 -7
- package/lib/getFileLink.js.map +1 -0
- package/lib/{getQueryString.d.mts → getQueryString.d.ts} +5 -1
- package/lib/getQueryString.d.ts.map +1 -0
- package/lib/{getQueryString.mjs → getQueryString.js} +7 -1
- package/lib/getQueryString.js.map +1 -0
- package/lib/{getUrlAndHeadersWithAuth.d.mts → getUrlAndHeadersWithAuth.d.ts} +1 -1
- package/lib/getUrlAndHeadersWithAuth.d.ts.map +1 -0
- package/lib/{getUrlAndHeadersWithAuth.mjs → getUrlAndHeadersWithAuth.js} +1 -1
- package/lib/getUrlAndHeadersWithAuth.js.map +1 -0
- package/lib/{index.d.mts → index.d.ts} +20 -20
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +29 -0
- package/lib/index.js.map +1 -0
- package/lib/localOdspDriver/{localOdspDeltaStorageService.d.mts → localOdspDeltaStorageService.d.ts} +1 -1
- package/lib/localOdspDriver/localOdspDeltaStorageService.d.ts.map +1 -0
- package/lib/localOdspDriver/{localOdspDeltaStorageService.mjs → localOdspDeltaStorageService.js} +1 -1
- package/lib/localOdspDriver/localOdspDeltaStorageService.js.map +1 -0
- package/lib/localOdspDriver/{localOdspDocumentService.d.mts → localOdspDocumentService.d.ts} +2 -2
- package/lib/localOdspDriver/localOdspDocumentService.d.ts.map +1 -0
- package/lib/localOdspDriver/{localOdspDocumentService.mjs → localOdspDocumentService.js} +4 -4
- package/lib/localOdspDriver/localOdspDocumentService.js.map +1 -0
- package/lib/localOdspDriver/{localOdspDocumentServiceFactory.d.mts → localOdspDocumentServiceFactory.d.ts} +9 -7
- package/lib/localOdspDriver/localOdspDocumentServiceFactory.d.ts.map +1 -0
- package/lib/localOdspDriver/{localOdspDocumentServiceFactory.mjs → localOdspDocumentServiceFactory.js} +9 -8
- package/lib/localOdspDriver/localOdspDocumentServiceFactory.js.map +1 -0
- package/lib/localOdspDriver/{localOdspDocumentStorageManager.d.mts → localOdspDocumentStorageManager.d.ts} +2 -2
- package/lib/localOdspDriver/localOdspDocumentStorageManager.d.ts.map +1 -0
- package/lib/localOdspDriver/{localOdspDocumentStorageManager.mjs → localOdspDocumentStorageManager.js} +4 -4
- package/lib/localOdspDriver/localOdspDocumentStorageManager.js.map +1 -0
- package/lib/{odsp-driver-alpha.d.mts → odsp-driver-alpha.d.ts} +27 -12
- package/lib/{odsp-driver-public.d.mts → odsp-driver-beta.d.ts} +1 -2
- package/lib/{odsp-driver-beta.d.mts → odsp-driver-public.d.ts} +1 -2
- package/lib/{odsp-driver-untrimmed.d.mts → odsp-driver-untrimmed.d.ts} +29 -12
- package/lib/{odspCache.d.mts → odspCache.d.ts} +8 -4
- package/lib/odspCache.d.ts.map +1 -0
- package/lib/{odspCache.mjs → odspCache.js} +6 -3
- package/lib/odspCache.js.map +1 -0
- package/lib/{odspDelayLoadedDeltaStream.d.mts → odspDelayLoadedDeltaStream.d.ts} +8 -6
- package/lib/odspDelayLoadedDeltaStream.d.ts.map +1 -0
- package/lib/{odspDelayLoadedDeltaStream.mjs → odspDelayLoadedDeltaStream.js} +33 -20
- package/lib/odspDelayLoadedDeltaStream.js.map +1 -0
- package/lib/{odspDeltaStorageService.d.mts → odspDeltaStorageService.d.ts} +8 -8
- package/lib/odspDeltaStorageService.d.ts.map +1 -0
- package/lib/{odspDeltaStorageService.mjs → odspDeltaStorageService.js} +5 -5
- package/lib/odspDeltaStorageService.js.map +1 -0
- package/lib/{odspDocumentDeltaConnection.d.mts → odspDocumentDeltaConnection.d.ts} +2 -2
- package/lib/odspDocumentDeltaConnection.d.ts.map +1 -0
- package/lib/{odspDocumentDeltaConnection.mjs → odspDocumentDeltaConnection.js} +34 -16
- package/lib/odspDocumentDeltaConnection.js.map +1 -0
- package/lib/{odspDocumentService.d.mts → odspDocumentService.d.ts} +7 -5
- package/lib/odspDocumentService.d.ts.map +1 -0
- package/lib/{odspDocumentService.mjs → odspDocumentService.js} +16 -11
- package/lib/odspDocumentService.js.map +1 -0
- package/lib/{odspDocumentServiceFactory.d.mts → odspDocumentServiceFactory.d.ts} +7 -2
- package/lib/odspDocumentServiceFactory.d.ts.map +1 -0
- package/lib/{odspDocumentServiceFactory.mjs → odspDocumentServiceFactory.js} +9 -3
- package/lib/odspDocumentServiceFactory.js.map +1 -0
- package/lib/{odspDocumentServiceFactoryCore.d.mts → odspDocumentServiceFactoryCore.d.ts} +5 -5
- package/lib/odspDocumentServiceFactoryCore.d.ts.map +1 -0
- package/lib/{odspDocumentServiceFactoryCore.mjs → odspDocumentServiceFactoryCore.js} +23 -17
- package/lib/odspDocumentServiceFactoryCore.js.map +1 -0
- package/lib/{odspDocumentServiceFactoryWithCodeSplit.d.mts → odspDocumentServiceFactoryWithCodeSplit.d.ts} +2 -2
- package/lib/odspDocumentServiceFactoryWithCodeSplit.d.ts.map +1 -0
- package/lib/{odspDocumentServiceFactoryWithCodeSplit.mjs → odspDocumentServiceFactoryWithCodeSplit.js} +2 -2
- package/lib/odspDocumentServiceFactoryWithCodeSplit.js.map +1 -0
- package/lib/{odspDocumentStorageManager.d.mts → odspDocumentStorageManager.d.ts} +16 -10
- package/lib/odspDocumentStorageManager.d.ts.map +1 -0
- package/lib/{odspDocumentStorageManager.mjs → odspDocumentStorageManager.js} +207 -167
- package/lib/odspDocumentStorageManager.js.map +1 -0
- package/lib/{odspDocumentStorageServiceBase.d.mts → odspDocumentStorageServiceBase.d.ts} +3 -5
- package/lib/odspDocumentStorageServiceBase.d.ts.map +1 -0
- package/lib/{odspDocumentStorageServiceBase.mjs → odspDocumentStorageServiceBase.js} +32 -29
- package/lib/odspDocumentStorageServiceBase.js.map +1 -0
- package/lib/{odspDriverUrlResolver.d.mts → odspDriverUrlResolver.d.ts} +6 -2
- package/lib/odspDriverUrlResolver.d.ts.map +1 -0
- package/lib/{odspDriverUrlResolver.mjs → odspDriverUrlResolver.js} +24 -17
- package/lib/odspDriverUrlResolver.js.map +1 -0
- package/lib/{odspDriverUrlResolverForShareLink.d.mts → odspDriverUrlResolverForShareLink.d.ts} +18 -7
- package/lib/odspDriverUrlResolverForShareLink.d.ts.map +1 -0
- package/lib/{odspDriverUrlResolverForShareLink.mjs → odspDriverUrlResolverForShareLink.js} +41 -27
- package/lib/odspDriverUrlResolverForShareLink.js.map +1 -0
- package/lib/{odspError.d.mts → odspError.d.ts} +2 -2
- package/lib/odspError.d.ts.map +1 -0
- package/lib/{odspError.mjs → odspError.js} +4 -4
- package/lib/odspError.js.map +1 -0
- package/lib/{odspFluidFileLink.d.mts → odspFluidFileLink.d.ts} +2 -2
- package/lib/odspFluidFileLink.d.ts.map +1 -0
- package/lib/{odspFluidFileLink.mjs → odspFluidFileLink.js} +2 -2
- package/lib/odspFluidFileLink.js.map +1 -0
- package/lib/{odspLocationRedirection.d.mts → odspLocationRedirection.d.ts} +1 -1
- package/lib/odspLocationRedirection.d.ts.map +1 -0
- package/lib/{odspLocationRedirection.mjs → odspLocationRedirection.js} +2 -2
- package/lib/odspLocationRedirection.js.map +1 -0
- package/lib/{odspPublicUtils.d.mts → odspPublicUtils.d.ts} +4 -1
- package/lib/odspPublicUtils.d.ts.map +1 -0
- package/lib/{odspPublicUtils.mjs → odspPublicUtils.js} +4 -1
- package/lib/odspPublicUtils.js.map +1 -0
- package/lib/{odspSnapshotParser.d.mts → odspSnapshotParser.d.ts} +2 -2
- package/lib/odspSnapshotParser.d.ts.map +1 -0
- package/lib/{odspSnapshotParser.mjs → odspSnapshotParser.js} +4 -3
- package/lib/odspSnapshotParser.js.map +1 -0
- package/lib/{odspSummaryUploadManager.d.mts → odspSummaryUploadManager.d.ts} +2 -2
- package/lib/odspSummaryUploadManager.d.ts.map +1 -0
- package/lib/{odspSummaryUploadManager.mjs → odspSummaryUploadManager.js} +8 -5
- package/lib/odspSummaryUploadManager.js.map +1 -0
- package/lib/{odspUrlHelper.d.mts → odspUrlHelper.d.ts} +1 -1
- package/lib/odspUrlHelper.d.ts.map +1 -0
- package/lib/{odspUrlHelper.mjs → odspUrlHelper.js} +2 -3
- package/lib/odspUrlHelper.js.map +1 -0
- package/lib/{odspUtils.d.mts → odspUtils.d.ts} +20 -8
- package/lib/odspUtils.d.ts.map +1 -0
- package/lib/{odspUtils.mjs → odspUtils.js} +45 -17
- package/lib/odspUtils.js.map +1 -0
- package/lib/{opsCaching.d.mts → opsCaching.d.ts} +2 -2
- package/lib/opsCaching.d.ts.map +1 -0
- package/lib/{opsCaching.mjs → opsCaching.js} +3 -2
- package/lib/opsCaching.js.map +1 -0
- package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
- package/lib/packageVersion.d.ts.map +1 -0
- package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
- package/lib/packageVersion.js.map +1 -0
- package/lib/{prefetchLatestSnapshot.d.mts → prefetchLatestSnapshot.d.ts} +3 -3
- package/lib/prefetchLatestSnapshot.d.ts.map +1 -0
- package/lib/{prefetchLatestSnapshot.mjs → prefetchLatestSnapshot.js} +16 -11
- package/lib/prefetchLatestSnapshot.js.map +1 -0
- package/lib/{retryErrorsStorageAdapter.d.mts → retryErrorsStorageAdapter.d.ts} +1 -2
- package/lib/retryErrorsStorageAdapter.d.ts.map +1 -0
- package/lib/{retryErrorsStorageAdapter.mjs → retryErrorsStorageAdapter.js} +2 -5
- package/lib/retryErrorsStorageAdapter.js.map +1 -0
- package/lib/{retryUtils.d.mts → retryUtils.d.ts} +1 -1
- package/lib/retryUtils.d.ts.map +1 -0
- package/lib/{retryUtils.mjs → retryUtils.js} +6 -2
- package/lib/retryUtils.js.map +1 -0
- package/lib/{socketModule.d.mts → socketModule.d.ts} +1 -1
- package/lib/socketModule.d.ts.map +1 -0
- package/lib/{socketModule.mjs → socketModule.js} +3 -1
- package/lib/socketModule.js.map +1 -0
- package/lib/test/buildOdspShareLinkReqParams.spec.js +25 -0
- package/lib/test/buildOdspShareLinkReqParams.spec.js.map +1 -0
- package/lib/test/createNewUtilsTests.spec.js +221 -0
- package/lib/test/createNewUtilsTests.spec.js.map +1 -0
- package/lib/test/deltaStorageService.spec.js +176 -0
- package/lib/test/deltaStorageService.spec.js.map +1 -0
- package/lib/test/epochTests.spec.js +340 -0
- package/lib/test/epochTests.spec.js.map +1 -0
- package/lib/test/epochTestsWithRedemption.spec.js +119 -0
- package/lib/test/epochTestsWithRedemption.spec.js.map +1 -0
- package/lib/test/fetchSnapshot.spec.js +412 -0
- package/lib/test/fetchSnapshot.spec.js.map +1 -0
- package/lib/test/getFileLink.spec.js +62 -0
- package/lib/test/getFileLink.spec.js.map +1 -0
- package/lib/test/getUrlAndHeadersWithAuth.spec.js +66 -0
- package/lib/test/getUrlAndHeadersWithAuth.spec.js.map +1 -0
- package/lib/test/getVersions.spec.js +284 -0
- package/lib/test/getVersions.spec.js.map +1 -0
- package/lib/test/joinSessionCacheTests.spec.js +53 -0
- package/lib/test/joinSessionCacheTests.spec.js.map +1 -0
- package/lib/test/joinSessionPeriodicCall.spec.js +158 -0
- package/lib/test/joinSessionPeriodicCall.spec.js.map +1 -0
- package/lib/test/jsonSnapshotFormatTests.spec.js +107 -0
- package/lib/test/jsonSnapshotFormatTests.spec.js.map +1 -0
- package/lib/test/localOdspDriver.spec.js +177 -0
- package/lib/test/localOdspDriver.spec.js.map +1 -0
- package/lib/test/mockFetch.js +61 -0
- package/lib/test/mockFetch.js.map +1 -0
- package/lib/test/odspCreateContainer.spec.js +116 -0
- package/lib/test/odspCreateContainer.spec.js.map +1 -0
- package/lib/test/odspDriverResolverTest.spec.js +289 -0
- package/lib/test/odspDriverResolverTest.spec.js.map +1 -0
- package/lib/test/odspDriverUrlResolverForShareLink.spec.js +287 -0
- package/lib/test/odspDriverUrlResolverForShareLink.spec.js.map +1 -0
- package/lib/test/odspError.spec.js +299 -0
- package/lib/test/odspError.spec.js.map +1 -0
- package/lib/test/opsCaching.spec.js +357 -0
- package/lib/test/opsCaching.spec.js.map +1 -0
- package/lib/test/prefetchSnapshotTests.spec.js +420 -0
- package/lib/test/prefetchSnapshotTests.spec.js.map +1 -0
- package/lib/test/snapshotFormatTests.spec.js +218 -0
- package/lib/test/snapshotFormatTests.spec.js.map +1 -0
- package/lib/test/socketTests/deltaConnectionUpdateTests.spec.js +152 -0
- package/lib/test/socketTests/deltaConnectionUpdateTests.spec.js.map +1 -0
- package/lib/test/socketTests/socketMock.js +109 -0
- package/lib/test/socketTests/socketMock.js.map +1 -0
- package/lib/test/socketTests/socketTests.spec.js +256 -0
- package/lib/test/socketTests/socketTests.spec.js.map +1 -0
- package/lib/test/tokenFetch.spec.js +39 -0
- package/lib/test/tokenFetch.spec.js.map +1 -0
- package/lib/test/types/validateOdspDriverPrevious.generated.js +96 -0
- package/lib/test/types/validateOdspDriverPrevious.generated.js.map +1 -0
- package/lib/test/zipItDataRepresentationTests.spec.js +207 -0
- package/lib/test/zipItDataRepresentationTests.spec.js.map +1 -0
- package/lib/{vroom.d.mts → vroom.d.ts} +3 -3
- package/lib/vroom.d.ts.map +1 -0
- package/lib/{vroom.mjs → vroom.js} +4 -4
- package/lib/vroom.js.map +1 -0
- package/lib/{zipItDataRepresentationUtils.d.mts → zipItDataRepresentationUtils.d.ts} +2 -2
- package/lib/zipItDataRepresentationUtils.d.ts.map +1 -0
- package/lib/{zipItDataRepresentationUtils.mjs → zipItDataRepresentationUtils.js} +17 -9
- package/lib/zipItDataRepresentationUtils.js.map +1 -0
- package/package.json +90 -31
- package/src/ReadBufferUtils.ts +7 -7
- package/src/WriteBufferUtils.ts +13 -9
- package/src/checkUrl.ts +4 -2
- package/src/compactSnapshotParser.ts +87 -52
- package/src/compactSnapshotWriter.ts +19 -12
- package/src/contracts.ts +16 -4
- package/src/createFile.ts +16 -13
- package/src/createNewContainerOnExistingFile.ts +8 -8
- package/src/createNewModule.ts +2 -2
- package/src/createNewUtils.ts +19 -9
- package/src/createOdspCreateContainerRequest.ts +2 -1
- package/src/createOdspUrl.ts +1 -1
- package/src/epochTracker.ts +90 -55
- package/src/fetchSnapshot.ts +104 -47
- package/src/getFileLink.ts +21 -13
- package/src/getQueryString.ts +3 -0
- package/src/index.ts +27 -19
- package/src/localOdspDriver/localOdspDocumentService.ts +3 -3
- package/src/localOdspDriver/localOdspDocumentServiceFactory.ts +12 -11
- package/src/localOdspDriver/localOdspDocumentStorageManager.ts +5 -5
- package/src/odspCache.ts +13 -9
- package/src/odspDelayLoadedDeltaStream.ts +54 -33
- package/src/odspDeltaStorageService.ts +17 -16
- package/src/odspDocumentDeltaConnection.ts +52 -34
- package/src/odspDocumentService.ts +23 -20
- package/src/odspDocumentServiceFactory.ts +7 -2
- package/src/odspDocumentServiceFactoryCore.ts +25 -18
- package/src/odspDocumentServiceFactoryWithCodeSplit.ts +1 -1
- package/src/odspDocumentStorageManager.ts +276 -216
- package/src/odspDocumentStorageServiceBase.ts +45 -43
- package/src/odspDriverUrlResolver.ts +39 -24
- package/src/odspDriverUrlResolverForShareLink.ts +51 -31
- package/src/odspError.ts +4 -4
- package/src/odspFluidFileLink.ts +3 -3
- package/src/odspLocationRedirection.ts +1 -1
- package/src/odspPublicUtils.ts +3 -0
- package/src/odspSnapshotParser.ts +4 -3
- package/src/odspSummaryUploadManager.ts +21 -9
- package/src/odspUrlHelper.ts +2 -3
- package/src/odspUtils.ts +73 -30
- package/src/opsCaching.ts +13 -12
- package/src/packageVersion.ts +1 -1
- package/src/prefetchLatestSnapshot.ts +24 -15
- package/src/retryErrorsStorageAdapter.ts +4 -8
- package/src/retryUtils.ts +6 -2
- package/src/socketModule.ts +2 -0
- package/src/vroom.ts +6 -6
- package/src/zipItDataRepresentationUtils.ts +63 -35
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.json +2 -5
- package/lib/ReadBufferUtils.d.mts.map +0 -1
- package/lib/ReadBufferUtils.mjs.map +0 -1
- package/lib/WriteBufferUtils.d.mts.map +0 -1
- package/lib/WriteBufferUtils.mjs.map +0 -1
- package/lib/checkUrl.d.mts.map +0 -1
- package/lib/checkUrl.mjs.map +0 -1
- package/lib/compactSnapshotParser.d.mts.map +0 -1
- package/lib/compactSnapshotParser.mjs.map +0 -1
- package/lib/compactSnapshotWriter.d.mts.map +0 -1
- package/lib/compactSnapshotWriter.mjs.map +0 -1
- package/lib/constants.d.mts.map +0 -1
- package/lib/constants.mjs.map +0 -1
- package/lib/contracts.d.mts.map +0 -1
- package/lib/contracts.mjs.map +0 -1
- package/lib/contractsPublic.d.mts.map +0 -1
- package/lib/contractsPublic.mjs.map +0 -1
- package/lib/createFile.d.mts.map +0 -1
- package/lib/createFile.mjs.map +0 -1
- package/lib/createNewContainerOnExistingFile.d.mts.map +0 -1
- package/lib/createNewContainerOnExistingFile.mjs.map +0 -1
- package/lib/createNewModule.d.mts.map +0 -1
- package/lib/createNewModule.mjs.map +0 -1
- package/lib/createNewUtils.d.mts.map +0 -1
- package/lib/createNewUtils.mjs.map +0 -1
- package/lib/createOdspCreateContainerRequest.d.mts.map +0 -1
- package/lib/createOdspCreateContainerRequest.mjs.map +0 -1
- package/lib/createOdspUrl.d.mts.map +0 -1
- package/lib/createOdspUrl.mjs.map +0 -1
- package/lib/epochTracker.d.mts.map +0 -1
- package/lib/epochTracker.mjs.map +0 -1
- package/lib/fetch.d.mts.map +0 -1
- package/lib/fetch.mjs.map +0 -1
- package/lib/fetchSnapshot.d.mts.map +0 -1
- package/lib/fetchSnapshot.mjs.map +0 -1
- package/lib/getFileLink.d.mts.map +0 -1
- package/lib/getFileLink.mjs.map +0 -1
- package/lib/getQueryString.d.mts.map +0 -1
- package/lib/getQueryString.mjs.map +0 -1
- package/lib/getUrlAndHeadersWithAuth.d.mts.map +0 -1
- package/lib/getUrlAndHeadersWithAuth.mjs.map +0 -1
- package/lib/index.d.mts.map +0 -1
- package/lib/index.mjs +0 -22
- package/lib/index.mjs.map +0 -1
- package/lib/localOdspDriver/localOdspDeltaStorageService.d.mts.map +0 -1
- package/lib/localOdspDriver/localOdspDeltaStorageService.mjs.map +0 -1
- package/lib/localOdspDriver/localOdspDocumentService.d.mts.map +0 -1
- package/lib/localOdspDriver/localOdspDocumentService.mjs.map +0 -1
- package/lib/localOdspDriver/localOdspDocumentServiceFactory.d.mts.map +0 -1
- package/lib/localOdspDriver/localOdspDocumentServiceFactory.mjs.map +0 -1
- package/lib/localOdspDriver/localOdspDocumentStorageManager.d.mts.map +0 -1
- package/lib/localOdspDriver/localOdspDocumentStorageManager.mjs.map +0 -1
- package/lib/odspCache.d.mts.map +0 -1
- package/lib/odspCache.mjs.map +0 -1
- package/lib/odspDelayLoadedDeltaStream.d.mts.map +0 -1
- package/lib/odspDelayLoadedDeltaStream.mjs.map +0 -1
- package/lib/odspDeltaStorageService.d.mts.map +0 -1
- package/lib/odspDeltaStorageService.mjs.map +0 -1
- package/lib/odspDocumentDeltaConnection.d.mts.map +0 -1
- package/lib/odspDocumentDeltaConnection.mjs.map +0 -1
- package/lib/odspDocumentService.d.mts.map +0 -1
- package/lib/odspDocumentService.mjs.map +0 -1
- package/lib/odspDocumentServiceFactory.d.mts.map +0 -1
- package/lib/odspDocumentServiceFactory.mjs.map +0 -1
- package/lib/odspDocumentServiceFactoryCore.d.mts.map +0 -1
- package/lib/odspDocumentServiceFactoryCore.mjs.map +0 -1
- package/lib/odspDocumentServiceFactoryWithCodeSplit.d.mts.map +0 -1
- package/lib/odspDocumentServiceFactoryWithCodeSplit.mjs.map +0 -1
- package/lib/odspDocumentStorageManager.d.mts.map +0 -1
- package/lib/odspDocumentStorageManager.mjs.map +0 -1
- package/lib/odspDocumentStorageServiceBase.d.mts.map +0 -1
- package/lib/odspDocumentStorageServiceBase.mjs.map +0 -1
- package/lib/odspDriverUrlResolver.d.mts.map +0 -1
- package/lib/odspDriverUrlResolver.mjs.map +0 -1
- package/lib/odspDriverUrlResolverForShareLink.d.mts.map +0 -1
- package/lib/odspDriverUrlResolverForShareLink.mjs.map +0 -1
- package/lib/odspError.d.mts.map +0 -1
- package/lib/odspError.mjs.map +0 -1
- package/lib/odspFluidFileLink.d.mts.map +0 -1
- package/lib/odspFluidFileLink.mjs.map +0 -1
- package/lib/odspLocationRedirection.d.mts.map +0 -1
- package/lib/odspLocationRedirection.mjs.map +0 -1
- package/lib/odspPublicUtils.d.mts.map +0 -1
- package/lib/odspPublicUtils.mjs.map +0 -1
- package/lib/odspSnapshotParser.d.mts.map +0 -1
- package/lib/odspSnapshotParser.mjs.map +0 -1
- package/lib/odspSummaryUploadManager.d.mts.map +0 -1
- package/lib/odspSummaryUploadManager.mjs.map +0 -1
- package/lib/odspUrlHelper.d.mts.map +0 -1
- package/lib/odspUrlHelper.mjs.map +0 -1
- package/lib/odspUtils.d.mts.map +0 -1
- package/lib/odspUtils.mjs.map +0 -1
- package/lib/opsCaching.d.mts.map +0 -1
- package/lib/opsCaching.mjs.map +0 -1
- package/lib/packageVersion.d.mts.map +0 -1
- package/lib/packageVersion.mjs.map +0 -1
- package/lib/prefetchLatestSnapshot.d.mts.map +0 -1
- package/lib/prefetchLatestSnapshot.mjs.map +0 -1
- package/lib/retryErrorsStorageAdapter.d.mts.map +0 -1
- package/lib/retryErrorsStorageAdapter.mjs.map +0 -1
- package/lib/retryUtils.d.mts.map +0 -1
- package/lib/retryUtils.mjs.map +0 -1
- package/lib/socketModule.d.mts.map +0 -1
- package/lib/socketModule.mjs.map +0 -1
- package/lib/vroom.d.mts.map +0 -1
- package/lib/vroom.mjs.map +0 -1
- package/lib/zipItDataRepresentationUtils.d.mts.map +0 -1
- package/lib/zipItDataRepresentationUtils.mjs.map +0 -1
|
@@ -10,11 +10,11 @@ import { promiseRaceWithWinner } from "@fluidframework/driver-base";
|
|
|
10
10
|
import { FetchSource, } from "@fluidframework/driver-definitions";
|
|
11
11
|
import { RateLimiter, NonRetryableError } from "@fluidframework/driver-utils";
|
|
12
12
|
import { OdspErrorTypes, getKeyForCacheEntry, } from "@fluidframework/odsp-driver-definitions";
|
|
13
|
-
import { downloadSnapshot, evalBlobsAndTrees, fetchSnapshot, fetchSnapshotWithRedeem, } from "./fetchSnapshot.
|
|
14
|
-
import { getUrlAndHeadersWithAuth } from "./getUrlAndHeadersWithAuth.
|
|
15
|
-
import { createCacheSnapshotKey, getWithRetryForTokenRefresh, isInstanceOfISnapshot, } from "./odspUtils.
|
|
16
|
-
import { pkgVersion as driverVersion } from "./packageVersion.
|
|
17
|
-
import { OdspDocumentStorageServiceBase } from "./odspDocumentStorageServiceBase.
|
|
13
|
+
import { downloadSnapshot, evalBlobsAndTrees, fetchSnapshot, fetchSnapshotWithRedeem, } from "./fetchSnapshot.js";
|
|
14
|
+
import { getUrlAndHeadersWithAuth } from "./getUrlAndHeadersWithAuth.js";
|
|
15
|
+
import { createCacheSnapshotKey, getWithRetryForTokenRefresh, isInstanceOfISnapshot, isSnapshotFetchForLoadingGroup, useLegacyFlowWithoutGroupsForSnapshotFetch, } from "./odspUtils.js";
|
|
16
|
+
import { pkgVersion as driverVersion } from "./packageVersion.js";
|
|
17
|
+
import { OdspDocumentStorageServiceBase } from "./odspDocumentStorageServiceBase.js";
|
|
18
18
|
export const defaultSummarizerCacheExpiryTimeout = 60 * 1000; // 60 seconds.
|
|
19
19
|
export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
20
20
|
constructor(odspResolvedUrl, getStorageToken, logger, fetchFullSnapshot, cache, hostPolicy, epochTracker, flushCallback, relayServiceTenantAndSessionId, snapshotFormatFetchType) {
|
|
@@ -30,7 +30,7 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
30
30
|
this.relayServiceTenantAndSessionId = relayServiceTenantAndSessionId;
|
|
31
31
|
this.snapshotFormatFetchType = snapshotFormatFetchType;
|
|
32
32
|
this.odspSummaryModuleLoaded = false;
|
|
33
|
-
this.
|
|
33
|
+
this.firstSnapshotFetchCall = true;
|
|
34
34
|
// Driver specified limits for snapshot size and time.
|
|
35
35
|
/**
|
|
36
36
|
* NOTE: While commit cfff6e3 added restrictions to prevent large payloads, snapshot failures will continue to
|
|
@@ -84,7 +84,7 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
84
84
|
eventName: "readDataBlob",
|
|
85
85
|
blobId,
|
|
86
86
|
evicted,
|
|
87
|
-
headers: Object.keys(headers).length
|
|
87
|
+
headers: Object.keys(headers).length > 0 ? true : undefined,
|
|
88
88
|
waitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,
|
|
89
89
|
}, async (event) => {
|
|
90
90
|
const res = await this.epochTracker.fetchArray(url, { headers }, "blob");
|
|
@@ -111,14 +111,185 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
111
111
|
}
|
|
112
112
|
async getSnapshotTree(version, scenarioName) {
|
|
113
113
|
if (!this.snapshotUrl) {
|
|
114
|
+
// eslint-disable-next-line unicorn/no-null
|
|
114
115
|
return null;
|
|
115
116
|
}
|
|
116
117
|
return super.getSnapshotTree(version, scenarioName);
|
|
117
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Fetches and returns the snapshot. If no loadingGroupIds or empty loadingGroupIds is provided, then snapshot for all
|
|
121
|
+
* ungrouped data will be provided.
|
|
122
|
+
* @param snapshotFetchOptions - fetch options for snapshot.
|
|
123
|
+
*/
|
|
118
124
|
async getSnapshot(snapshotFetchOptions) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
125
|
+
// Don't consult cache if request is not for a particular loading group.
|
|
126
|
+
const { snapshot } = await this.fetchSnapshot({
|
|
127
|
+
...snapshotFetchOptions,
|
|
128
|
+
fetchSource: isSnapshotFetchForLoadingGroup(snapshotFetchOptions?.loadingGroupIds)
|
|
129
|
+
? FetchSource.noCache
|
|
130
|
+
: snapshotFetchOptions?.fetchSource,
|
|
131
|
+
loadingGroupIds: snapshotFetchOptions?.loadingGroupIds ?? [],
|
|
132
|
+
});
|
|
133
|
+
return {
|
|
134
|
+
...snapshot,
|
|
135
|
+
snapshotTree: this.combineProtocolAndAppSnapshotTree(snapshot.snapshotTree),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
async fetchSnapshot(snapshotFetchOptions) {
|
|
139
|
+
const hostSnapshotOptions = this.hostPolicy.snapshotOptions;
|
|
140
|
+
const odspSnapshotCacheValue = await PerformanceEvent.timedExecAsync(this.logger, {
|
|
141
|
+
eventName: isSnapshotFetchForLoadingGroup(snapshotFetchOptions.loadingGroupIds)
|
|
142
|
+
? "ObtainSnapshotForGroup"
|
|
143
|
+
: "ObtainSnapshot",
|
|
144
|
+
fetchSource: snapshotFetchOptions?.fetchSource,
|
|
145
|
+
}, async (event) => {
|
|
146
|
+
const props = {};
|
|
147
|
+
let cacheLookupTimeInSerialFetch = 0;
|
|
148
|
+
let retrievedSnapshot;
|
|
149
|
+
let method;
|
|
150
|
+
let prefetchWaitStartTime = performance.now();
|
|
151
|
+
if (snapshotFetchOptions.fetchSource === FetchSource.noCache) {
|
|
152
|
+
retrievedSnapshot = await this.fetchSnapshotFromNetwork(hostSnapshotOptions, snapshotFetchOptions.loadingGroupIds, snapshotFetchOptions.scenarioName);
|
|
153
|
+
method = "networkOnly";
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// Here's the logic to grab the persistent cache snapshot implemented by the host
|
|
157
|
+
// Epoch tracker is responsible for communicating with the persistent cache, handling epochs and cache versions
|
|
158
|
+
const cachedSnapshotP = this.epochTracker
|
|
159
|
+
.get(createCacheSnapshotKey(this.odspResolvedUrl))
|
|
160
|
+
.then(async (
|
|
161
|
+
// eslint-disable-next-line import/no-deprecated
|
|
162
|
+
snapshotCachedEntry) => {
|
|
163
|
+
if (snapshotCachedEntry !== undefined) {
|
|
164
|
+
// If the cached entry does not contain the entry time, then assign it a default of 30 days old.
|
|
165
|
+
const age = Date.now() -
|
|
166
|
+
(snapshotCachedEntry.cacheEntryTime ??
|
|
167
|
+
Date.now() - 30 * 24 * 60 * 60 * 1000);
|
|
168
|
+
// In order to decrease the number of times we have to execute a snapshot refresh,
|
|
169
|
+
// if this is the summarizer and we have a cache entry but it is past the defaultSummarizerCacheExpiryTimeout,
|
|
170
|
+
// force the network retrieval instead as there might be a more recent snapshot available.
|
|
171
|
+
// See: https://github.com/microsoft/FluidFramework/issues/8995 for additional information.
|
|
172
|
+
if (this.hostPolicy.summarizerClient) {
|
|
173
|
+
if (age > defaultSummarizerCacheExpiryTimeout) {
|
|
174
|
+
props.cacheSummarizerExpired = true;
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
props.cacheSummarizerExpired = false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Record the cache age
|
|
182
|
+
props.cacheEntryAge = age;
|
|
183
|
+
// Snapshot from cache could be in older format, so transform that before returning.
|
|
184
|
+
if (isInstanceOfISnapshot(snapshotCachedEntry)) {
|
|
185
|
+
return snapshotCachedEntry;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
const snapshot = {
|
|
189
|
+
snapshotTree: snapshotCachedEntry.snapshotTree,
|
|
190
|
+
blobContents: snapshotCachedEntry.blobs,
|
|
191
|
+
ops: snapshotCachedEntry.ops,
|
|
192
|
+
latestSequenceNumber: snapshotCachedEntry.latestSequenceNumber,
|
|
193
|
+
sequenceNumber: snapshotCachedEntry.sequenceNumber,
|
|
194
|
+
snapshotFormatV: 1,
|
|
195
|
+
};
|
|
196
|
+
return snapshot;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
// Based on the concurrentSnapshotFetch policy:
|
|
201
|
+
// Either retrieve both the network and cache snapshots concurrently and pick the first to return,
|
|
202
|
+
// or grab the cache value and then the network value if the cache value returns undefined.
|
|
203
|
+
// For summarizer which could call this during refreshing of summary parent, always use the cache
|
|
204
|
+
// first. Also for other clients, if it is not critical path which is determined by firstSnapshotFetchCall,
|
|
205
|
+
// then also check the cache first.
|
|
206
|
+
if (this.firstSnapshotFetchCall &&
|
|
207
|
+
this.hostPolicy.concurrentSnapshotFetch &&
|
|
208
|
+
!this.hostPolicy.summarizerClient) {
|
|
209
|
+
const networkSnapshotP = this.fetchSnapshotFromNetwork(hostSnapshotOptions, snapshotFetchOptions.loadingGroupIds, snapshotFetchOptions.scenarioName);
|
|
210
|
+
// Ensure that failures on both paths are ignored initially.
|
|
211
|
+
// I.e. if cache fails for some reason, we will proceed with network result.
|
|
212
|
+
// And vice versa - if (for example) client is offline and network request fails first, we
|
|
213
|
+
// do want to attempt to succeed with cached data!
|
|
214
|
+
const promiseRaceWinner = await promiseRaceWithWinner([
|
|
215
|
+
cachedSnapshotP.catch(() => undefined),
|
|
216
|
+
networkSnapshotP.catch(() => undefined),
|
|
217
|
+
]);
|
|
218
|
+
retrievedSnapshot = promiseRaceWinner.value;
|
|
219
|
+
method = promiseRaceWinner.index === 0 ? "cache" : "network";
|
|
220
|
+
if (retrievedSnapshot === undefined) {
|
|
221
|
+
// if network failed -> wait for cache ( then return network failure)
|
|
222
|
+
// If cache returned empty or failed -> wait for network (success of failure)
|
|
223
|
+
try {
|
|
224
|
+
if (promiseRaceWinner.index === 1) {
|
|
225
|
+
retrievedSnapshot = await cachedSnapshotP;
|
|
226
|
+
method = "cache";
|
|
227
|
+
}
|
|
228
|
+
if (retrievedSnapshot === undefined) {
|
|
229
|
+
retrievedSnapshot = await networkSnapshotP;
|
|
230
|
+
method = "network";
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
// The call stacks of any errors thrown by cached snapshot or network snapshot aren't very useful:
|
|
235
|
+
// they get truncated at this stack frame due to the promise race and how v8 tracks async stack traces--
|
|
236
|
+
// see https://v8.dev/docs/stack-trace-api#async-stack-traces and the "zero-cost async stack traces" document
|
|
237
|
+
// linked there. https://v8.dev/blog/fast-async#await-under-the-hood may also be helpful for context on internals.
|
|
238
|
+
// Regenerating the stack at this level provides more information for logged errors.
|
|
239
|
+
// Once FF uses an ES2021 target, we could convert the above promise race to use `Promise.any` + AggregateError and
|
|
240
|
+
// get similar quality stacks with less hand-crafted code.
|
|
241
|
+
const innerStack = error.stack;
|
|
242
|
+
const normalizedError = normalizeError(error);
|
|
243
|
+
normalizedError.addTelemetryProperties({ innerStack });
|
|
244
|
+
const newStack = `<<STACK TRUNCATED: see innerStack property>> \n${generateStack()}`;
|
|
245
|
+
overwriteStack(normalizedError, newStack);
|
|
246
|
+
throw normalizedError;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
// Note: There's a race condition here - another caller may come past the undefined check
|
|
252
|
+
// while the first caller is awaiting later async code in this block.
|
|
253
|
+
const startTime = performance.now();
|
|
254
|
+
retrievedSnapshot = await cachedSnapshotP;
|
|
255
|
+
cacheLookupTimeInSerialFetch = performance.now() - startTime;
|
|
256
|
+
method = retrievedSnapshot === undefined ? "network" : "cache";
|
|
257
|
+
if (retrievedSnapshot === undefined) {
|
|
258
|
+
prefetchWaitStartTime = performance.now();
|
|
259
|
+
retrievedSnapshot = await this.fetchSnapshotFromNetwork(hostSnapshotOptions, snapshotFetchOptions.loadingGroupIds, snapshotFetchOptions.scenarioName);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (method === "network") {
|
|
264
|
+
props.cacheEntryAge = undefined;
|
|
265
|
+
}
|
|
266
|
+
if (this.firstSnapshotFetchCall) {
|
|
267
|
+
this._isFirstSnapshotFromNetwork = method === "cache" ? false : true;
|
|
268
|
+
}
|
|
269
|
+
const prefetchStartTime = retrievedSnapshot.prefetchStartTime;
|
|
270
|
+
event.end({
|
|
271
|
+
...props,
|
|
272
|
+
method,
|
|
273
|
+
fetchSnapshotForInitialLoad: this.firstSnapshotFetchCall,
|
|
274
|
+
useLegacyFlowWithoutGroups: useLegacyFlowWithoutGroupsForSnapshotFetch(snapshotFetchOptions.loadingGroupIds),
|
|
275
|
+
avoidPrefetchSnapshotCache: this.hostPolicy.avoidPrefetchSnapshotCache,
|
|
276
|
+
...evalBlobsAndTrees(retrievedSnapshot),
|
|
277
|
+
cacheLookupTimeInSerialFetch,
|
|
278
|
+
prefetchSavedDuration: prefetchStartTime !== undefined && method !== "cache"
|
|
279
|
+
? prefetchWaitStartTime - prefetchStartTime
|
|
280
|
+
: undefined,
|
|
281
|
+
});
|
|
282
|
+
return retrievedSnapshot;
|
|
283
|
+
});
|
|
284
|
+
const stTime = performance.now();
|
|
285
|
+
// Don't override ops which were fetched during initial load, since we could still need them.
|
|
286
|
+
const id = this.initializeFromSnapshot(odspSnapshotCacheValue, this.firstSnapshotFetchCall, snapshotFetchOptions?.cacheSnapshot ?? this.firstSnapshotFetchCall);
|
|
287
|
+
this.logger.sendTelemetryEvent({
|
|
288
|
+
eventName: "SnapshotInitializeTime",
|
|
289
|
+
duration: performance.now() - stTime,
|
|
290
|
+
}, undefined, LogLevel.verbose);
|
|
291
|
+
this.firstSnapshotFetchCall = false;
|
|
292
|
+
return { snapshot: odspSnapshotCacheValue, id };
|
|
122
293
|
}
|
|
123
294
|
async getVersions(
|
|
124
295
|
// eslint-disable-next-line @rushstack/no-new-null
|
|
@@ -142,150 +313,12 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
142
313
|
}
|
|
143
314
|
// If count is one, we can use the trees/latest API, which returns the latest version and trees in a single request for better performance
|
|
144
315
|
if (count === 1 && (blobid === null || blobid === this.documentId)) {
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
let method;
|
|
151
|
-
let prefetchWaitStartTime = performance.now();
|
|
152
|
-
if (fetchSource === FetchSource.noCache) {
|
|
153
|
-
retrievedSnapshot = await this.fetchSnapshot(hostSnapshotOptions, scenarioName);
|
|
154
|
-
method = "networkOnly";
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
// Here's the logic to grab the persistent cache snapshot implemented by the host
|
|
158
|
-
// Epoch tracker is responsible for communicating with the persistent cache, handling epochs and cache versions
|
|
159
|
-
const cachedSnapshotP = this.epochTracker
|
|
160
|
-
.get(createCacheSnapshotKey(this.odspResolvedUrl))
|
|
161
|
-
.then(async (snapshotCachedEntry) => {
|
|
162
|
-
if (snapshotCachedEntry !== undefined) {
|
|
163
|
-
// If the cached entry does not contain the entry time, then assign it a default of 30 days old.
|
|
164
|
-
const age = Date.now() -
|
|
165
|
-
(snapshotCachedEntry.cacheEntryTime ??
|
|
166
|
-
Date.now() - 30 * 24 * 60 * 60 * 1000);
|
|
167
|
-
// In order to decrease the number of times we have to execute a snapshot refresh,
|
|
168
|
-
// if this is the summarizer and we have a cache entry but it is past the defaultSummarizerCacheExpiryTimeout,
|
|
169
|
-
// force the network retrieval instead as there might be a more recent snapshot available.
|
|
170
|
-
// See: https://github.com/microsoft/FluidFramework/issues/8995 for additional information.
|
|
171
|
-
if (this.hostPolicy.summarizerClient) {
|
|
172
|
-
if (age > defaultSummarizerCacheExpiryTimeout) {
|
|
173
|
-
props.cacheSummarizerExpired = true;
|
|
174
|
-
return undefined;
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
props.cacheSummarizerExpired = false;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
// Record the cache age
|
|
181
|
-
props.cacheEntryAge = age;
|
|
182
|
-
// Snapshot from cache could be in older format, so transform that before returning.
|
|
183
|
-
if (isInstanceOfISnapshot(snapshotCachedEntry)) {
|
|
184
|
-
return snapshotCachedEntry;
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
const snapshot = {
|
|
188
|
-
snapshotTree: snapshotCachedEntry.snapshotTree,
|
|
189
|
-
blobContents: snapshotCachedEntry.blobs,
|
|
190
|
-
ops: snapshotCachedEntry.ops,
|
|
191
|
-
latestSequenceNumber: snapshotCachedEntry.latestSequenceNumber,
|
|
192
|
-
sequenceNumber: snapshotCachedEntry.sequenceNumber,
|
|
193
|
-
snapshotFormatV: 1,
|
|
194
|
-
};
|
|
195
|
-
return snapshot;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
// Based on the concurrentSnapshotFetch policy:
|
|
200
|
-
// Either retrieve both the network and cache snapshots concurrently and pick the first to return,
|
|
201
|
-
// or grab the cache value and then the network value if the cache value returns undefined.
|
|
202
|
-
// For summarizer which could call this during refreshing of summary parent, always use the cache
|
|
203
|
-
// first. Also for other clients, if it is not critical path which is determined by firstVersionCall,
|
|
204
|
-
// then also check the cache first.
|
|
205
|
-
if (this.firstVersionCall &&
|
|
206
|
-
this.hostPolicy.concurrentSnapshotFetch &&
|
|
207
|
-
!this.hostPolicy.summarizerClient) {
|
|
208
|
-
const networkSnapshotP = this.fetchSnapshot(hostSnapshotOptions, scenarioName);
|
|
209
|
-
// Ensure that failures on both paths are ignored initially.
|
|
210
|
-
// I.e. if cache fails for some reason, we will proceed with network result.
|
|
211
|
-
// And vice versa - if (for example) client is offline and network request fails first, we
|
|
212
|
-
// do want to attempt to succeed with cached data!
|
|
213
|
-
const promiseRaceWinner = await promiseRaceWithWinner([
|
|
214
|
-
cachedSnapshotP.catch(() => undefined),
|
|
215
|
-
networkSnapshotP.catch(() => undefined),
|
|
216
|
-
]);
|
|
217
|
-
retrievedSnapshot = promiseRaceWinner.value;
|
|
218
|
-
method = promiseRaceWinner.index === 0 ? "cache" : "network";
|
|
219
|
-
if (retrievedSnapshot === undefined) {
|
|
220
|
-
// if network failed -> wait for cache ( then return network failure)
|
|
221
|
-
// If cache returned empty or failed -> wait for network (success of failure)
|
|
222
|
-
try {
|
|
223
|
-
if (promiseRaceWinner.index === 1) {
|
|
224
|
-
retrievedSnapshot = await cachedSnapshotP;
|
|
225
|
-
method = "cache";
|
|
226
|
-
}
|
|
227
|
-
if (retrievedSnapshot === undefined) {
|
|
228
|
-
retrievedSnapshot = await networkSnapshotP;
|
|
229
|
-
method = "network";
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
catch (err) {
|
|
233
|
-
// The call stacks of any errors thrown by cached snapshot or network snapshot aren't very useful:
|
|
234
|
-
// they get truncated at this stack frame due to the promise race and how v8 tracks async stack traces--
|
|
235
|
-
// see https://v8.dev/docs/stack-trace-api#async-stack-traces and the "zero-cost async stack traces" document
|
|
236
|
-
// linked there. https://v8.dev/blog/fast-async#await-under-the-hood may also be helpful for context on internals.
|
|
237
|
-
// Regenerating the stack at this level provides more information for logged errors.
|
|
238
|
-
// Once FF uses an ES2021 target, we could convert the above promise race to use `Promise.any` + AggregateError and
|
|
239
|
-
// get similar quality stacks with less hand-crafted code.
|
|
240
|
-
const innerStack = err.stack;
|
|
241
|
-
const normalizedError = normalizeError(err);
|
|
242
|
-
normalizedError.addTelemetryProperties({ innerStack });
|
|
243
|
-
const newStack = `<<STACK TRUNCATED: see innerStack property>> \n${generateStack()}`;
|
|
244
|
-
overwriteStack(normalizedError, newStack);
|
|
245
|
-
throw normalizedError;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
// Note: There's a race condition here - another caller may come past the undefined check
|
|
251
|
-
// while the first caller is awaiting later async code in this block.
|
|
252
|
-
const startTime = performance.now();
|
|
253
|
-
retrievedSnapshot = await cachedSnapshotP;
|
|
254
|
-
cacheLookupTimeInSerialFetch = performance.now() - startTime;
|
|
255
|
-
method = retrievedSnapshot !== undefined ? "cache" : "network";
|
|
256
|
-
if (retrievedSnapshot === undefined) {
|
|
257
|
-
prefetchWaitStartTime = performance.now();
|
|
258
|
-
retrievedSnapshot = await this.fetchSnapshot(hostSnapshotOptions, scenarioName);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
if (method === "network") {
|
|
263
|
-
props.cacheEntryAge = undefined;
|
|
264
|
-
}
|
|
265
|
-
if (this.firstVersionCall) {
|
|
266
|
-
this._isFirstSnapshotFromNetwork = method === "cache" ? false : true;
|
|
267
|
-
}
|
|
268
|
-
const prefetchStartTime = retrievedSnapshot.prefetchStartTime;
|
|
269
|
-
event.end({
|
|
270
|
-
...props,
|
|
271
|
-
method,
|
|
272
|
-
avoidPrefetchSnapshotCache: this.hostPolicy.avoidPrefetchSnapshotCache,
|
|
273
|
-
...evalBlobsAndTrees(retrievedSnapshot),
|
|
274
|
-
cacheLookupTimeInSerialFetch,
|
|
275
|
-
prefetchSavedDuration: prefetchStartTime !== undefined && method !== "cache"
|
|
276
|
-
? prefetchWaitStartTime - prefetchStartTime
|
|
277
|
-
: undefined,
|
|
278
|
-
});
|
|
279
|
-
return retrievedSnapshot;
|
|
316
|
+
const { id } = await this.fetchSnapshot({
|
|
317
|
+
cacheSnapshot: true,
|
|
318
|
+
scenarioName,
|
|
319
|
+
versionId: blobid ?? undefined,
|
|
320
|
+
fetchSource,
|
|
280
321
|
});
|
|
281
|
-
const stTime = performance.now();
|
|
282
|
-
// Don't override ops which were fetched during initial load, since we could still need them.
|
|
283
|
-
const id = this.initializeFromSnapshot(odspSnapshotCacheValue, this.firstVersionCall);
|
|
284
|
-
this.logger.sendTelemetryEvent({
|
|
285
|
-
eventName: "SnapshotInitializeTime",
|
|
286
|
-
duration: performance.now() - stTime,
|
|
287
|
-
}, undefined, LogLevel.verbose);
|
|
288
|
-
this.firstVersionCall = false;
|
|
289
322
|
return id ? [{ id, treeId: undefined }] : [];
|
|
290
323
|
}
|
|
291
324
|
return getWithRetryForTokenRefresh(async (options) => {
|
|
@@ -294,7 +327,7 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
294
327
|
// Fetch the latest snapshot versions for the document
|
|
295
328
|
const response = await PerformanceEvent.timedExecAsync(this.logger, {
|
|
296
329
|
eventName: "getVersions",
|
|
297
|
-
headers: Object.keys(headers).length
|
|
330
|
+
headers: Object.keys(headers).length > 0 ? true : undefined,
|
|
298
331
|
}, async () => this.epochTracker.fetchAndParseAsJSON(url, { headers }, "versions", undefined, scenarioName));
|
|
299
332
|
const versionsResponse = response.content;
|
|
300
333
|
if (!versionsResponse) {
|
|
@@ -311,22 +344,24 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
311
344
|
});
|
|
312
345
|
});
|
|
313
346
|
}
|
|
314
|
-
async
|
|
315
|
-
return this.
|
|
347
|
+
async fetchSnapshotFromNetwork(hostSnapshotOptions, loadingGroupIds, scenarioName) {
|
|
348
|
+
return this.fetchSnapshotFromNetworkCore(hostSnapshotOptions, loadingGroupIds, scenarioName).catch((error) => {
|
|
316
349
|
// Issue #5895:
|
|
317
350
|
// If we are offline, this error is retryable. But that means that RetriableDocumentStorageService
|
|
318
351
|
// will run in circles calling getSnapshotTree, which would result in OdspDocumentStorageService class
|
|
319
352
|
// going getVersions / individual blob download path. This path is very slow, and will not work with
|
|
320
353
|
// delay-loaded data stores and ODSP storage deleting old snapshots and blobs.
|
|
321
354
|
if (typeof error === "object" && error !== null) {
|
|
355
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
322
356
|
error.canRetry = false;
|
|
323
357
|
}
|
|
324
358
|
throw error;
|
|
325
359
|
});
|
|
326
360
|
}
|
|
327
|
-
async
|
|
328
|
-
// Don't look into cache, if the host specifically tells us so.
|
|
329
|
-
|
|
361
|
+
async fetchSnapshotFromNetworkCore(hostSnapshotOptions, loadingGroupIds, scenarioName) {
|
|
362
|
+
// Don't look into cache, if the host specifically tells us so. Also, if request is
|
|
363
|
+
// for initial snapshot, don't consult the prefetch cache.
|
|
364
|
+
if (!this.hostPolicy.avoidPrefetchSnapshotCache && this.firstSnapshotFetchCall) {
|
|
330
365
|
const prefetchCacheKey = getKeyForCacheEntry(createCacheSnapshotKey(this.odspResolvedUrl));
|
|
331
366
|
const result = await this.cache.snapshotPrefetchResultCache
|
|
332
367
|
?.get(prefetchCacheKey)
|
|
@@ -337,11 +372,11 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
337
372
|
await this.epochTracker.validateEpoch(response.fluidEpoch, "treesLatest");
|
|
338
373
|
return response;
|
|
339
374
|
})
|
|
340
|
-
.catch(async (
|
|
375
|
+
.catch(async (error) => {
|
|
341
376
|
this.logger.sendTelemetryEvent({
|
|
342
377
|
eventName: "PrefetchSnapshotError",
|
|
343
378
|
concurrentSnapshotFetch: this.hostPolicy.concurrentSnapshotFetch,
|
|
344
|
-
},
|
|
379
|
+
}, error);
|
|
345
380
|
return undefined;
|
|
346
381
|
});
|
|
347
382
|
// If the prefetch call, is successful, then return the contents otherwise as backup for now, just
|
|
@@ -362,8 +397,8 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
362
397
|
snapshotOptions.mds = undefined;
|
|
363
398
|
snapshotOptions.timeout = undefined;
|
|
364
399
|
}
|
|
365
|
-
const snapshotDownloader = async (finalOdspResolvedUrl, storageToken, options, controller) => {
|
|
366
|
-
return downloadSnapshot(finalOdspResolvedUrl, storageToken,
|
|
400
|
+
const snapshotDownloader = async (finalOdspResolvedUrl, storageToken, loadingGroupId, options, controller) => {
|
|
401
|
+
return downloadSnapshot(finalOdspResolvedUrl, storageToken, loadingGroupId, options, this.snapshotFormatFetchType, controller, this.epochTracker, scenarioName);
|
|
367
402
|
};
|
|
368
403
|
const putInCache = async (valueWithEpoch) => {
|
|
369
404
|
return this.cache.persistedCache.put(createCacheSnapshotKey(this.odspResolvedUrl),
|
|
@@ -372,10 +407,12 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
372
407
|
};
|
|
373
408
|
const removeEntries = async () => this.cache.persistedCache.removeEntries();
|
|
374
409
|
try {
|
|
375
|
-
const odspSnapshot = await fetchSnapshotWithRedeem(this.odspResolvedUrl, this.getStorageToken, snapshotOptions, !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader, this.logger, snapshotDownloader, putInCache, removeEntries, this.hostPolicy.enableRedeemFallback);
|
|
410
|
+
const odspSnapshot = await fetchSnapshotWithRedeem(this.odspResolvedUrl, this.getStorageToken, snapshotOptions, !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader, this.logger, snapshotDownloader, putInCache, removeEntries, loadingGroupIds, this.hostPolicy.enableRedeemFallback);
|
|
376
411
|
return odspSnapshot;
|
|
412
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
377
413
|
}
|
|
378
414
|
catch (error) {
|
|
415
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
379
416
|
const errorType = error.errorType;
|
|
380
417
|
// If the snapshot size is too big and the host specified the size limitation(specified in hostSnapshotOptions), then don't try to fetch the snapshot again.
|
|
381
418
|
if (errorType === OdspErrorTypes.snapshotTooBig &&
|
|
@@ -389,6 +426,7 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
389
426
|
snapshotOptions.blobs) {
|
|
390
427
|
this.logger.sendErrorEvent({
|
|
391
428
|
eventName: "TreeLatest_SecondCall",
|
|
429
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
392
430
|
errorType,
|
|
393
431
|
});
|
|
394
432
|
const snapshotOptionsWithoutBlobs = {
|
|
@@ -397,7 +435,7 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
397
435
|
mds: undefined,
|
|
398
436
|
timeout: undefined,
|
|
399
437
|
};
|
|
400
|
-
const odspSnapshot = await fetchSnapshotWithRedeem(this.odspResolvedUrl, this.getStorageToken, snapshotOptionsWithoutBlobs, !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader, this.logger, snapshotDownloader, putInCache, removeEntries, this.hostPolicy.enableRedeemFallback);
|
|
438
|
+
const odspSnapshot = await fetchSnapshotWithRedeem(this.odspResolvedUrl, this.getStorageToken, snapshotOptionsWithoutBlobs, !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader, this.logger, snapshotDownloader, putInCache, removeEntries, loadingGroupIds, this.hostPolicy.enableRedeemFallback);
|
|
401
439
|
return odspSnapshot;
|
|
402
440
|
}
|
|
403
441
|
throw error;
|
|
@@ -454,7 +492,9 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
454
492
|
}
|
|
455
493
|
async getDelayLoadedSummaryManager() {
|
|
456
494
|
assert(this.odspSummaryModuleLoaded === false, 0x56f /* Should be loaded only once */);
|
|
457
|
-
const module = await import(
|
|
495
|
+
const module = await import(
|
|
496
|
+
/* webpackChunkName: "summaryModule" */ "./odspSummaryUploadManager.js")
|
|
497
|
+
.then((m) => {
|
|
458
498
|
this.logger.sendTelemetryEvent({ eventName: "SummaryModuleLoaded" });
|
|
459
499
|
return m;
|
|
460
500
|
})
|
|
@@ -502,4 +542,4 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
|
|
|
502
542
|
});
|
|
503
543
|
}
|
|
504
544
|
}
|
|
505
|
-
//# sourceMappingURL=odspDocumentStorageManager.
|
|
545
|
+
//# sourceMappingURL=odspDocumentStorageManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"odspDocumentStorageManager.js","sourceRoot":"","sources":["../src/odspDocumentStorageManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tgenerateStack,\n\tITelemetryLoggerExt,\n\tloggerToMonitoringContext,\n\tnormalizeError,\n\toverwriteStack,\n\tPerformanceEvent,\n} from \"@fluidframework/telemetry-utils\";\nimport { performance } from \"@fluid-internal/client-utils\";\nimport { assert, delay } from \"@fluidframework/core-utils\";\nimport { LogLevel } from \"@fluidframework/core-interfaces\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport { promiseRaceWithWinner } from \"@fluidframework/driver-base\";\nimport {\n\tISummaryContext,\n\tFetchSource,\n\tISnapshot,\n\tISnapshotFetchOptions,\n} from \"@fluidframework/driver-definitions\";\nimport { RateLimiter, NonRetryableError } from \"@fluidframework/driver-utils\";\nimport {\n\tIOdspResolvedUrl,\n\tISnapshotOptions,\n\tOdspErrorTypes,\n\tInstrumentedStorageTokenFetcher,\n\tgetKeyForCacheEntry,\n} from \"@fluidframework/odsp-driver-definitions\";\nimport {\n\tIDocumentStorageGetVersionsResponse,\n\tHostStoragePolicyInternal,\n\tIVersionedValueWithEpoch,\n\t// eslint-disable-next-line import/no-deprecated\n\tISnapshotCachedEntry,\n\tISnapshotCachedEntry2,\n} from \"./contracts.js\";\nimport {\n\tdownloadSnapshot,\n\tevalBlobsAndTrees,\n\tfetchSnapshot,\n\tfetchSnapshotWithRedeem,\n\tISnapshotRequestAndResponseOptions,\n\tSnapshotFormatSupportType,\n} from \"./fetchSnapshot.js\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth.js\";\nimport { IOdspCache, IPrefetchSnapshotContents } from \"./odspCache.js\";\nimport {\n\tcreateCacheSnapshotKey,\n\tgetWithRetryForTokenRefresh,\n\tIOdspResponse,\n\tisInstanceOfISnapshot,\n\tisSnapshotFetchForLoadingGroup,\n\tuseLegacyFlowWithoutGroupsForSnapshotFetch,\n} from \"./odspUtils.js\";\nimport { EpochTracker } from \"./epochTracker.js\";\nimport type { OdspSummaryUploadManager } from \"./odspSummaryUploadManager.js\";\nimport { FlushResult } from \"./odspDocumentDeltaConnection.js\";\nimport { pkgVersion as driverVersion } from \"./packageVersion.js\";\nimport { OdspDocumentStorageServiceBase } from \"./odspDocumentStorageServiceBase.js\";\n\nexport const defaultSummarizerCacheExpiryTimeout: number = 60 * 1000; // 60 seconds.\n\ninterface GetVersionsTelemetryProps {\n\tcacheEntryAge?: number;\n\tcacheSummarizerExpired?: boolean;\n}\n\nexport class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {\n\tprivate odspSummaryModuleLoaded: boolean = false;\n\tprivate summaryModuleP: Promise<OdspSummaryUploadManager> | undefined;\n\tprivate odspSummaryUploadManager: OdspSummaryUploadManager | undefined;\n\n\tprivate firstSnapshotFetchCall = true;\n\tprivate _isFirstSnapshotFromNetwork: boolean | undefined;\n\tprivate readonly documentId: string;\n\tprivate readonly snapshotUrl: string | undefined;\n\tprivate readonly attachmentPOSTUrl: string | undefined;\n\tprivate readonly attachmentGETUrl: string | undefined;\n\t// Driver specified limits for snapshot size and time.\n\t/**\n\t * NOTE: While commit cfff6e3 added restrictions to prevent large payloads, snapshot failures will continue to\n\t * happen until blob request throttling is implemented. Until then, as a temporary fix we set arbitrarily large\n\t * snapshot size and timeout limits so that such failures are unlikely to occur.\n\t */\n\tprivate readonly maxSnapshotSizeLimit = 500000000; // 500 MB\n\tprivate readonly maxSnapshotFetchTimeout = 120000; // 2 min\n\n\t// limits the amount of parallel \"attachment\" blob uploads\n\tprivate readonly createBlobRateLimiter = new RateLimiter(1);\n\n\tconstructor(\n\t\tprivate readonly odspResolvedUrl: IOdspResolvedUrl,\n\t\tprivate readonly getStorageToken: InstrumentedStorageTokenFetcher,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t\tprivate readonly fetchFullSnapshot: boolean,\n\t\tprivate readonly cache: IOdspCache,\n\t\tprivate readonly hostPolicy: HostStoragePolicyInternal,\n\t\tprivate readonly epochTracker: EpochTracker,\n\t\tprivate readonly flushCallback: () => Promise<FlushResult>,\n\t\tprivate readonly relayServiceTenantAndSessionId: () => string | undefined,\n\t\tprivate readonly snapshotFormatFetchType?: SnapshotFormatSupportType,\n\t) {\n\t\tsuper(loggerToMonitoringContext(logger).config);\n\n\t\tthis.documentId = this.odspResolvedUrl.hashedDocumentId;\n\t\tthis.snapshotUrl = this.odspResolvedUrl.endpoints.snapshotStorageUrl;\n\t\tthis.attachmentPOSTUrl = this.odspResolvedUrl.endpoints.attachmentPOSTStorageUrl;\n\t\tthis.attachmentGETUrl = this.odspResolvedUrl.endpoints.attachmentGETStorageUrl;\n\t}\n\n\tpublic get isFirstSnapshotFromNetwork(): boolean | undefined {\n\t\treturn this._isFirstSnapshotFromNetwork;\n\t}\n\n\tpublic async createBlob(file: ArrayBufferLike): Promise<api.ICreateBlobResponse> {\n\t\tthis.checkAttachmentPOSTUrl();\n\n\t\tconst response = await getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"CreateBlob\");\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\t`${this.attachmentPOSTUrl}/content`,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\t\t\theaders[\"Content-Type\"] = \"application/octet-stream\";\n\n\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"createBlob\",\n\t\t\t\t\tsize: file.byteLength,\n\t\t\t\t\twaitQueueLength: this.createBlobRateLimiter.waitQueueLength,\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tconst res = await this.createBlobRateLimiter.schedule(async () =>\n\t\t\t\t\t\tthis.epochTracker.fetchAndParseAsJSON<api.ICreateBlobResponse>(\n\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbody: file,\n\t\t\t\t\t\t\t\theaders,\n\t\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"createBlob\",\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\tblobId: res.content.id,\n\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t});\n\t\t\t\t\treturn res;\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\n\t\treturn response.content;\n\t}\n\n\tprotected async fetchBlobFromStorage(blobId: string, evicted: boolean): Promise<ArrayBuffer> {\n\t\tthis.checkAttachmentGETUrl();\n\n\t\tconst blob = await getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"GetBlob\");\n\t\t\tconst unAuthedUrl = `${this.attachmentGETUrl}/${encodeURIComponent(blobId)}/content`;\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\tunAuthedUrl,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\n\t\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"readDataBlob\",\n\t\t\t\t\tblobId,\n\t\t\t\t\tevicted,\n\t\t\t\t\theaders: Object.keys(headers).length > 0 ? true : undefined,\n\t\t\t\t\twaitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n\t\t\t\t},\n\t\t\t\tasync (event) => {\n\t\t\t\t\tconst res = await this.epochTracker.fetchArray(url, { headers }, \"blob\");\n\t\t\t\t\tevent.end({\n\t\t\t\t\t\twaitQueueLength: this.epochTracker.rateLimiter.waitQueueLength,\n\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t\tattempts: options.refresh ? 2 : 1,\n\t\t\t\t\t});\n\t\t\t\t\tconst cacheControl = res.headers.get(\"cache-control\");\n\t\t\t\t\tif (\n\t\t\t\t\t\tcacheControl === undefined ||\n\t\t\t\t\t\t!(cacheControl.includes(\"private\") || cacheControl.includes(\"public\"))\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\t\teventName: \"NonCacheableBlob\",\n\t\t\t\t\t\t\tcacheControl,\n\t\t\t\t\t\t\tblobId,\n\t\t\t\t\t\t\t...res.propsToLog,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn res.content;\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t\tthis.blobCache.setBlob(blobId, blob);\n\t\treturn blob;\n\t}\n\n\tpublic async getSnapshotTree(\n\t\tversion?: api.IVersion,\n\t\tscenarioName?: string,\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t): Promise<api.ISnapshotTree | null> {\n\t\tif (!this.snapshotUrl) {\n\t\t\t// eslint-disable-next-line unicorn/no-null\n\t\t\treturn null;\n\t\t}\n\t\treturn super.getSnapshotTree(version, scenarioName);\n\t}\n\n\t/**\n\t * Fetches and returns the snapshot. If no loadingGroupIds or empty loadingGroupIds is provided, then snapshot for all\n\t * ungrouped data will be provided.\n\t * @param snapshotFetchOptions - fetch options for snapshot.\n\t */\n\tpublic async getSnapshot(snapshotFetchOptions?: ISnapshotFetchOptions): Promise<ISnapshot> {\n\t\t// Don't consult cache if request is not for a particular loading group.\n\t\tconst { snapshot } = await this.fetchSnapshot({\n\t\t\t...snapshotFetchOptions,\n\t\t\tfetchSource: isSnapshotFetchForLoadingGroup(snapshotFetchOptions?.loadingGroupIds)\n\t\t\t\t? FetchSource.noCache\n\t\t\t\t: snapshotFetchOptions?.fetchSource,\n\t\t\tloadingGroupIds: snapshotFetchOptions?.loadingGroupIds ?? [],\n\t\t});\n\n\t\treturn {\n\t\t\t...snapshot,\n\t\t\tsnapshotTree: this.combineProtocolAndAppSnapshotTree(snapshot.snapshotTree),\n\t\t};\n\t}\n\n\tprivate async fetchSnapshot(\n\t\tsnapshotFetchOptions: ISnapshotFetchOptions,\n\t): Promise<{ snapshot: ISnapshot; id: string | undefined }> {\n\t\tconst hostSnapshotOptions = this.hostPolicy.snapshotOptions;\n\t\tconst odspSnapshotCacheValue: ISnapshot = await PerformanceEvent.timedExecAsync(\n\t\t\tthis.logger,\n\t\t\t{\n\t\t\t\teventName: isSnapshotFetchForLoadingGroup(snapshotFetchOptions.loadingGroupIds)\n\t\t\t\t\t? \"ObtainSnapshotForGroup\"\n\t\t\t\t\t: \"ObtainSnapshot\",\n\t\t\t\tfetchSource: snapshotFetchOptions?.fetchSource,\n\t\t\t},\n\t\t\tasync (event: PerformanceEvent) => {\n\t\t\t\tconst props: GetVersionsTelemetryProps = {};\n\t\t\t\tlet cacheLookupTimeInSerialFetch = 0;\n\t\t\t\tlet retrievedSnapshot: ISnapshot | IPrefetchSnapshotContents | undefined;\n\n\t\t\t\tlet method: string;\n\t\t\t\tlet prefetchWaitStartTime: number = performance.now();\n\t\t\t\tif (snapshotFetchOptions.fetchSource === FetchSource.noCache) {\n\t\t\t\t\tretrievedSnapshot = await this.fetchSnapshotFromNetwork(\n\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\tsnapshotFetchOptions.loadingGroupIds,\n\t\t\t\t\t\tsnapshotFetchOptions.scenarioName,\n\t\t\t\t\t);\n\t\t\t\t\tmethod = \"networkOnly\";\n\t\t\t\t} else {\n\t\t\t\t\t// Here's the logic to grab the persistent cache snapshot implemented by the host\n\t\t\t\t\t// Epoch tracker is responsible for communicating with the persistent cache, handling epochs and cache versions\n\t\t\t\t\tconst cachedSnapshotP: Promise<ISnapshot | undefined> = this.epochTracker\n\t\t\t\t\t\t.get(createCacheSnapshotKey(this.odspResolvedUrl))\n\t\t\t\t\t\t.then(\n\t\t\t\t\t\t\tasync (\n\t\t\t\t\t\t\t\t// eslint-disable-next-line import/no-deprecated\n\t\t\t\t\t\t\t\tsnapshotCachedEntry: ISnapshotCachedEntry | ISnapshotCachedEntry2,\n\t\t\t\t\t\t\t) => {\n\t\t\t\t\t\t\t\tif (snapshotCachedEntry !== undefined) {\n\t\t\t\t\t\t\t\t\t// If the cached entry does not contain the entry time, then assign it a default of 30 days old.\n\t\t\t\t\t\t\t\t\tconst age =\n\t\t\t\t\t\t\t\t\t\tDate.now() -\n\t\t\t\t\t\t\t\t\t\t(snapshotCachedEntry.cacheEntryTime ??\n\t\t\t\t\t\t\t\t\t\t\tDate.now() - 30 * 24 * 60 * 60 * 1000);\n\n\t\t\t\t\t\t\t\t\t// In order to decrease the number of times we have to execute a snapshot refresh,\n\t\t\t\t\t\t\t\t\t// if this is the summarizer and we have a cache entry but it is past the defaultSummarizerCacheExpiryTimeout,\n\t\t\t\t\t\t\t\t\t// force the network retrieval instead as there might be a more recent snapshot available.\n\t\t\t\t\t\t\t\t\t// See: https://github.com/microsoft/FluidFramework/issues/8995 for additional information.\n\t\t\t\t\t\t\t\t\tif (this.hostPolicy.summarizerClient) {\n\t\t\t\t\t\t\t\t\t\tif (age > defaultSummarizerCacheExpiryTimeout) {\n\t\t\t\t\t\t\t\t\t\t\tprops.cacheSummarizerExpired = true;\n\t\t\t\t\t\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tprops.cacheSummarizerExpired = false;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Record the cache age\n\t\t\t\t\t\t\t\t\tprops.cacheEntryAge = age;\n\t\t\t\t\t\t\t\t\t// Snapshot from cache could be in older format, so transform that before returning.\n\t\t\t\t\t\t\t\t\tif (isInstanceOfISnapshot(snapshotCachedEntry)) {\n\t\t\t\t\t\t\t\t\t\treturn snapshotCachedEntry;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tconst snapshot: ISnapshot = {\n\t\t\t\t\t\t\t\t\t\t\tsnapshotTree: snapshotCachedEntry.snapshotTree,\n\t\t\t\t\t\t\t\t\t\t\tblobContents: snapshotCachedEntry.blobs,\n\t\t\t\t\t\t\t\t\t\t\tops: snapshotCachedEntry.ops,\n\t\t\t\t\t\t\t\t\t\t\tlatestSequenceNumber:\n\t\t\t\t\t\t\t\t\t\t\t\tsnapshotCachedEntry.latestSequenceNumber,\n\t\t\t\t\t\t\t\t\t\t\tsequenceNumber: snapshotCachedEntry.sequenceNumber,\n\t\t\t\t\t\t\t\t\t\t\tsnapshotFormatV: 1,\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\treturn snapshot;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t// Based on the concurrentSnapshotFetch policy:\n\t\t\t\t\t// Either retrieve both the network and cache snapshots concurrently and pick the first to return,\n\t\t\t\t\t// or grab the cache value and then the network value if the cache value returns undefined.\n\t\t\t\t\t// For summarizer which could call this during refreshing of summary parent, always use the cache\n\t\t\t\t\t// first. Also for other clients, if it is not critical path which is determined by firstSnapshotFetchCall,\n\t\t\t\t\t// then also check the cache first.\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis.firstSnapshotFetchCall &&\n\t\t\t\t\t\tthis.hostPolicy.concurrentSnapshotFetch &&\n\t\t\t\t\t\t!this.hostPolicy.summarizerClient\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst networkSnapshotP = this.fetchSnapshotFromNetwork(\n\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\tsnapshotFetchOptions.loadingGroupIds,\n\t\t\t\t\t\t\tsnapshotFetchOptions.scenarioName,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// Ensure that failures on both paths are ignored initially.\n\t\t\t\t\t\t// I.e. if cache fails for some reason, we will proceed with network result.\n\t\t\t\t\t\t// And vice versa - if (for example) client is offline and network request fails first, we\n\t\t\t\t\t\t// do want to attempt to succeed with cached data!\n\t\t\t\t\t\tconst promiseRaceWinner = await promiseRaceWithWinner([\n\t\t\t\t\t\t\tcachedSnapshotP.catch(() => undefined),\n\t\t\t\t\t\t\tnetworkSnapshotP.catch(() => undefined),\n\t\t\t\t\t\t]);\n\t\t\t\t\t\tretrievedSnapshot = promiseRaceWinner.value;\n\t\t\t\t\t\tmethod = promiseRaceWinner.index === 0 ? \"cache\" : \"network\";\n\n\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t// if network failed -> wait for cache ( then return network failure)\n\t\t\t\t\t\t\t// If cache returned empty or failed -> wait for network (success of failure)\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (promiseRaceWinner.index === 1) {\n\t\t\t\t\t\t\t\t\tretrievedSnapshot = await cachedSnapshotP;\n\t\t\t\t\t\t\t\t\tmethod = \"cache\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\t\t\tretrievedSnapshot = await networkSnapshotP;\n\t\t\t\t\t\t\t\t\tmethod = \"network\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\t\t\t// The call stacks of any errors thrown by cached snapshot or network snapshot aren't very useful:\n\t\t\t\t\t\t\t\t// they get truncated at this stack frame due to the promise race and how v8 tracks async stack traces--\n\t\t\t\t\t\t\t\t// see https://v8.dev/docs/stack-trace-api#async-stack-traces and the \"zero-cost async stack traces\" document\n\t\t\t\t\t\t\t\t// linked there. https://v8.dev/blog/fast-async#await-under-the-hood may also be helpful for context on internals.\n\t\t\t\t\t\t\t\t// Regenerating the stack at this level provides more information for logged errors.\n\t\t\t\t\t\t\t\t// Once FF uses an ES2021 target, we could convert the above promise race to use `Promise.any` + AggregateError and\n\t\t\t\t\t\t\t\t// get similar quality stacks with less hand-crafted code.\n\t\t\t\t\t\t\t\tconst innerStack = (error as Error).stack;\n\t\t\t\t\t\t\t\tconst normalizedError = normalizeError(error);\n\t\t\t\t\t\t\t\tnormalizedError.addTelemetryProperties({ innerStack });\n\n\t\t\t\t\t\t\t\tconst newStack = `<<STACK TRUNCATED: see innerStack property>> \\n${generateStack()}`;\n\t\t\t\t\t\t\t\toverwriteStack(normalizedError, newStack);\n\n\t\t\t\t\t\t\t\tthrow normalizedError;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Note: There's a race condition here - another caller may come past the undefined check\n\t\t\t\t\t\t// while the first caller is awaiting later async code in this block.\n\t\t\t\t\t\tconst startTime = performance.now();\n\t\t\t\t\t\tretrievedSnapshot = await cachedSnapshotP;\n\t\t\t\t\t\tcacheLookupTimeInSerialFetch = performance.now() - startTime;\n\t\t\t\t\t\tmethod = retrievedSnapshot === undefined ? \"network\" : \"cache\";\n\n\t\t\t\t\t\tif (retrievedSnapshot === undefined) {\n\t\t\t\t\t\t\tprefetchWaitStartTime = performance.now();\n\t\t\t\t\t\t\tretrievedSnapshot = await this.fetchSnapshotFromNetwork(\n\t\t\t\t\t\t\t\thostSnapshotOptions,\n\t\t\t\t\t\t\t\tsnapshotFetchOptions.loadingGroupIds,\n\t\t\t\t\t\t\t\tsnapshotFetchOptions.scenarioName,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (method === \"network\") {\n\t\t\t\t\tprops.cacheEntryAge = undefined;\n\t\t\t\t}\n\t\t\t\tif (this.firstSnapshotFetchCall) {\n\t\t\t\t\tthis._isFirstSnapshotFromNetwork = method === \"cache\" ? false : true;\n\t\t\t\t}\n\t\t\t\tconst prefetchStartTime: number | undefined = (\n\t\t\t\t\tretrievedSnapshot as IPrefetchSnapshotContents\n\t\t\t\t).prefetchStartTime;\n\t\t\t\tevent.end({\n\t\t\t\t\t...props,\n\t\t\t\t\tmethod,\n\t\t\t\t\tfetchSnapshotForInitialLoad: this.firstSnapshotFetchCall,\n\t\t\t\t\tuseLegacyFlowWithoutGroups: useLegacyFlowWithoutGroupsForSnapshotFetch(\n\t\t\t\t\t\tsnapshotFetchOptions.loadingGroupIds,\n\t\t\t\t\t),\n\t\t\t\t\tavoidPrefetchSnapshotCache: this.hostPolicy.avoidPrefetchSnapshotCache,\n\t\t\t\t\t...evalBlobsAndTrees(retrievedSnapshot),\n\t\t\t\t\tcacheLookupTimeInSerialFetch,\n\t\t\t\t\tprefetchSavedDuration:\n\t\t\t\t\t\tprefetchStartTime !== undefined && method !== \"cache\"\n\t\t\t\t\t\t\t? prefetchWaitStartTime - prefetchStartTime\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t});\n\t\t\t\treturn retrievedSnapshot;\n\t\t\t},\n\t\t);\n\n\t\tconst stTime = performance.now();\n\t\t// Don't override ops which were fetched during initial load, since we could still need them.\n\t\tconst id = this.initializeFromSnapshot(\n\t\t\todspSnapshotCacheValue,\n\t\t\tthis.firstSnapshotFetchCall,\n\t\t\tsnapshotFetchOptions?.cacheSnapshot ?? this.firstSnapshotFetchCall,\n\t\t);\n\t\tthis.logger.sendTelemetryEvent(\n\t\t\t{\n\t\t\t\teventName: \"SnapshotInitializeTime\",\n\t\t\t\tduration: performance.now() - stTime,\n\t\t\t},\n\t\t\tundefined,\n\t\t\tLogLevel.verbose,\n\t\t);\n\t\tthis.firstSnapshotFetchCall = false;\n\n\t\treturn { snapshot: odspSnapshotCacheValue, id };\n\t}\n\n\tpublic async getVersions(\n\t\t// eslint-disable-next-line @rushstack/no-new-null\n\t\tblobid: string | null,\n\t\tcount: number,\n\t\tscenarioName?: string,\n\t\tfetchSource?: FetchSource,\n\t): Promise<api.IVersion[]> {\n\t\t// Regular load workflow uses blobId === documentID to indicate \"latest\".\n\t\tif (blobid !== this.documentId && blobid) {\n\t\t\t// FluidFetch & FluidDebugger tools use empty sting to query for versions\n\t\t\t// In such case we need to make a call against SPO to give full picture to the tool.\n\t\t\t// Otherwise, each commit calls getVersions but odsp doesn't have a history for each commit\n\t\t\t// return the blobid as is\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: blobid,\n\t\t\t\t\ttreeId: undefined!,\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\t// Can't really make a call if we do not have URL\n\t\tif (!this.snapshotUrl) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// If count is one, we can use the trees/latest API, which returns the latest version and trees in a single request for better performance\n\t\tif (count === 1 && (blobid === null || blobid === this.documentId)) {\n\t\t\tconst { id } = await this.fetchSnapshot({\n\t\t\t\tcacheSnapshot: true,\n\t\t\t\tscenarioName,\n\t\t\t\tversionId: blobid ?? undefined,\n\t\t\t\tfetchSource,\n\t\t\t});\n\t\t\treturn id ? [{ id, treeId: undefined! }] : [];\n\t\t}\n\n\t\treturn getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"GetVersions\");\n\t\t\tconst { url, headers } = getUrlAndHeadersWithAuth(\n\t\t\t\t`${this.snapshotUrl}/versions?top=${count}`,\n\t\t\t\tstorageToken,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t);\n\n\t\t\t// Fetch the latest snapshot versions for the document\n\t\t\tconst response = await PerformanceEvent.timedExecAsync(\n\t\t\t\tthis.logger,\n\t\t\t\t{\n\t\t\t\t\teventName: \"getVersions\",\n\t\t\t\t\theaders: Object.keys(headers).length > 0 ? true : undefined,\n\t\t\t\t},\n\t\t\t\tasync () =>\n\t\t\t\t\tthis.epochTracker.fetchAndParseAsJSON<IDocumentStorageGetVersionsResponse>(\n\t\t\t\t\t\turl,\n\t\t\t\t\t\t{ headers },\n\t\t\t\t\t\t\"versions\",\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tscenarioName,\n\t\t\t\t\t),\n\t\t\t);\n\t\t\tconst versionsResponse = response.content;\n\t\t\tif (!versionsResponse) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\"No response from /versions endpoint\",\n\t\t\t\t\tOdspErrorTypes.genericNetworkError,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!Array.isArray(versionsResponse.value)) {\n\t\t\t\tthrow new NonRetryableError(\n\t\t\t\t\t\"Incorrect response from /versions endpoint, expected an array\",\n\t\t\t\t\tOdspErrorTypes.genericNetworkError,\n\t\t\t\t\t{ driverVersion },\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn versionsResponse.value.map((version) => {\n\t\t\t\treturn {\n\t\t\t\t\tid: version.id,\n\t\t\t\t\ttreeId: undefined!,\n\t\t\t\t};\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async fetchSnapshotFromNetwork(\n\t\thostSnapshotOptions: ISnapshotOptions | undefined,\n\t\tloadingGroupIds: string[] | undefined,\n\t\tscenarioName?: string,\n\t): Promise<ISnapshot | IPrefetchSnapshotContents> {\n\t\treturn this.fetchSnapshotFromNetworkCore(\n\t\t\thostSnapshotOptions,\n\t\t\tloadingGroupIds,\n\t\t\tscenarioName,\n\t\t).catch((error) => {\n\t\t\t// Issue #5895:\n\t\t\t// If we are offline, this error is retryable. But that means that RetriableDocumentStorageService\n\t\t\t// will run in circles calling getSnapshotTree, which would result in OdspDocumentStorageService class\n\t\t\t// going getVersions / individual blob download path. This path is very slow, and will not work with\n\t\t\t// delay-loaded data stores and ODSP storage deleting old snapshots and blobs.\n\t\t\tif (typeof error === \"object\" && error !== null) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\t\terror.canRetry = false;\n\t\t\t}\n\t\t\tthrow error;\n\t\t});\n\t}\n\n\tprivate async fetchSnapshotFromNetworkCore(\n\t\thostSnapshotOptions: ISnapshotOptions | undefined,\n\t\tloadingGroupIds: string[] | undefined,\n\t\tscenarioName?: string,\n\t): Promise<ISnapshot | IPrefetchSnapshotContents> {\n\t\t// Don't look into cache, if the host specifically tells us so. Also, if request is\n\t\t// for initial snapshot, don't consult the prefetch cache.\n\t\tif (!this.hostPolicy.avoidPrefetchSnapshotCache && this.firstSnapshotFetchCall) {\n\t\t\tconst prefetchCacheKey = getKeyForCacheEntry(\n\t\t\t\tcreateCacheSnapshotKey(this.odspResolvedUrl),\n\t\t\t);\n\t\t\tconst result = await this.cache.snapshotPrefetchResultCache\n\t\t\t\t?.get(prefetchCacheKey)\n\t\t\t\t?.then(async (response) => {\n\t\t\t\t\t// Remove it from cache once used.\n\t\t\t\t\tthis.cache.snapshotPrefetchResultCache.remove(prefetchCacheKey);\n\t\t\t\t\t// Validate the epoch from the prefetched snapshot result.\n\t\t\t\t\tawait this.epochTracker.validateEpoch(response.fluidEpoch, \"treesLatest\");\n\t\t\t\t\treturn response;\n\t\t\t\t})\n\t\t\t\t.catch(async (error) => {\n\t\t\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\teventName: \"PrefetchSnapshotError\",\n\t\t\t\t\t\t\tconcurrentSnapshotFetch: this.hostPolicy.concurrentSnapshotFetch,\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror,\n\t\t\t\t\t);\n\t\t\t\t\treturn undefined;\n\t\t\t\t});\n\t\t\t// If the prefetch call, is successful, then return the contents otherwise as backup for now, just\n\t\t\t// proceed with the old snapshot fetch flow.\n\t\t\tif (result !== undefined) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t\tconst snapshotOptions: ISnapshotOptions = {\n\t\t\tmds: this.maxSnapshotSizeLimit,\n\t\t\t...hostSnapshotOptions,\n\t\t\ttimeout: hostSnapshotOptions?.timeout\n\t\t\t\t? Math.min(hostSnapshotOptions.timeout, this.maxSnapshotFetchTimeout)\n\t\t\t\t: this.maxSnapshotFetchTimeout,\n\t\t};\n\n\t\t// No limit on size of snapshot or time to fetch, as otherwise we fail all clients to summarize\n\t\tif (this.hostPolicy.summarizerClient) {\n\t\t\tsnapshotOptions.mds = undefined;\n\t\t\tsnapshotOptions.timeout = undefined;\n\t\t}\n\n\t\tconst snapshotDownloader = async (\n\t\t\tfinalOdspResolvedUrl: IOdspResolvedUrl,\n\t\t\tstorageToken: string,\n\t\t\tloadingGroupId: string[] | undefined,\n\t\t\toptions: ISnapshotOptions | undefined,\n\t\t\tcontroller?: AbortController,\n\t\t): Promise<ISnapshotRequestAndResponseOptions> => {\n\t\t\treturn downloadSnapshot(\n\t\t\t\tfinalOdspResolvedUrl,\n\t\t\t\tstorageToken,\n\t\t\t\tloadingGroupId,\n\t\t\t\toptions,\n\t\t\t\tthis.snapshotFormatFetchType,\n\t\t\t\tcontroller,\n\t\t\t\tthis.epochTracker,\n\t\t\t\tscenarioName,\n\t\t\t);\n\t\t};\n\t\tconst putInCache = async (valueWithEpoch: IVersionedValueWithEpoch): Promise<void> => {\n\t\t\treturn this.cache.persistedCache.put(\n\t\t\t\tcreateCacheSnapshotKey(this.odspResolvedUrl),\n\t\t\t\t// Epoch tracker will add the epoch and version to the value here. So just send value to cache.\n\t\t\t\tvalueWithEpoch.value,\n\t\t\t);\n\t\t};\n\t\tconst removeEntries = async (): Promise<void> => this.cache.persistedCache.removeEntries();\n\t\ttry {\n\t\t\tconst odspSnapshot = await fetchSnapshotWithRedeem(\n\t\t\t\tthis.odspResolvedUrl,\n\t\t\t\tthis.getStorageToken,\n\t\t\t\tsnapshotOptions,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\tthis.logger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t\tputInCache,\n\t\t\t\tremoveEntries,\n\t\t\t\tloadingGroupIds,\n\t\t\t\tthis.hostPolicy.enableRedeemFallback,\n\t\t\t);\n\t\t\treturn odspSnapshot;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t} catch (error: any) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n\t\t\tconst errorType = error.errorType;\n\t\t\t// If the snapshot size is too big and the host specified the size limitation(specified in hostSnapshotOptions), then don't try to fetch the snapshot again.\n\t\t\tif (\n\t\t\t\terrorType === OdspErrorTypes.snapshotTooBig &&\n\t\t\t\thostSnapshotOptions?.mds !== undefined &&\n\t\t\t\tthis.hostPolicy.summarizerClient !== true\n\t\t\t) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\t// If the first snapshot request was with blobs and we either timed out or the size was too big, then try to fetch without blobs.\n\t\t\tif (\n\t\t\t\t(errorType === OdspErrorTypes.snapshotTooBig ||\n\t\t\t\t\terrorType === OdspErrorTypes.fetchTimeout) &&\n\t\t\t\tsnapshotOptions.blobs\n\t\t\t) {\n\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\teventName: \"TreeLatest_SecondCall\",\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\terrorType,\n\t\t\t\t});\n\t\t\t\tconst snapshotOptionsWithoutBlobs: ISnapshotOptions = {\n\t\t\t\t\t...snapshotOptions,\n\t\t\t\t\tblobs: 0,\n\t\t\t\t\tmds: undefined,\n\t\t\t\t\ttimeout: undefined,\n\t\t\t\t};\n\t\t\t\tconst odspSnapshot = await fetchSnapshotWithRedeem(\n\t\t\t\t\tthis.odspResolvedUrl,\n\t\t\t\t\tthis.getStorageToken,\n\t\t\t\t\tsnapshotOptionsWithoutBlobs,\n\t\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tsnapshotDownloader,\n\t\t\t\t\tputInCache,\n\t\t\t\t\tremoveEntries,\n\t\t\t\t\tloadingGroupIds,\n\t\t\t\t\tthis.hostPolicy.enableRedeemFallback,\n\t\t\t\t);\n\t\t\t\treturn odspSnapshot;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async uploadSummaryWithContext(\n\t\tsummary: api.ISummaryTree,\n\t\tcontext: ISummaryContext,\n\t): Promise<string> {\n\t\tthis.checkSnapshotUrl();\n\n\t\t// Set the module promise right away, so as to not call it twice.\n\t\tif (this.summaryModuleP === undefined) {\n\t\t\tthis.summaryModuleP = this.getDelayLoadedSummaryManager();\n\t\t}\n\n\t\t// Enable flushing only if we have single commit summary and this is not the initial summary for an empty file\n\t\tif (\".protocol\" in summary.tree && context.ackHandle !== undefined) {\n\t\t\tlet retry = 1;\n\t\t\tfor (;;) {\n\t\t\t\tconst result = await this.flushCallback();\n\t\t\t\tconst seq = result.lastPersistedSequenceNumber;\n\t\t\t\tif (seq !== undefined && seq >= context.referenceSequenceNumber) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (retry > 3) {\n\t\t\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\t\t\teventName: \"FlushFailure\",\n\t\t\t\t\t\t...result,\n\t\t\t\t\t\tretry,\n\t\t\t\t\t\treferenceSequenceNumber: context.referenceSequenceNumber,\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\t\teventName: \"FlushExtraCall\",\n\t\t\t\t\t...result,\n\t\t\t\t\tretry,\n\t\t\t\t\treferenceSequenceNumber: context.referenceSequenceNumber,\n\t\t\t\t});\n\n\t\t\t\tretry++;\n\t\t\t\tawait delay(1000 * (result.retryAfter ?? 1));\n\t\t\t}\n\t\t}\n\n\t\tif (!this.odspSummaryUploadManager) {\n\t\t\tthis.odspSummaryUploadManager = await this.summaryModuleP\n\t\t\t\t.then(async (m) => {\n\t\t\t\t\tthis.odspSummaryModuleLoaded = true;\n\t\t\t\t\treturn m;\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tthis.odspSummaryModuleLoaded = false;\n\t\t\t\t\tthrow error;\n\t\t\t\t});\n\t\t}\n\n\t\tassert(\n\t\t\tthis.odspSummaryUploadManager !== undefined,\n\t\t\t0x56e /* summary upload manager should have been initialized */,\n\t\t);\n\t\tconst id = await this.odspSummaryUploadManager.writeSummaryTree(summary, context);\n\t\treturn id;\n\t}\n\n\tprivate async getDelayLoadedSummaryManager(): Promise<OdspSummaryUploadManager> {\n\t\tassert(this.odspSummaryModuleLoaded === false, 0x56f /* Should be loaded only once */);\n\t\tconst module = await import(\n\t\t\t/* webpackChunkName: \"summaryModule\" */ \"./odspSummaryUploadManager.js\"\n\t\t)\n\t\t\t.then((m) => {\n\t\t\t\tthis.logger.sendTelemetryEvent({ eventName: \"SummaryModuleLoaded\" });\n\t\t\t\treturn m;\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.logger.sendErrorEvent({ eventName: \"SummaryModuleLoadFailed\" }, error);\n\t\t\t\tthrow error;\n\t\t\t});\n\t\tthis.odspSummaryUploadManager = new module.OdspSummaryUploadManager(\n\t\t\tthis.odspResolvedUrl.endpoints.snapshotStorageUrl,\n\t\t\tthis.getStorageToken,\n\t\t\tthis.logger,\n\t\t\tthis.epochTracker,\n\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\tthis.relayServiceTenantAndSessionId,\n\t\t);\n\t\treturn this.odspSummaryUploadManager;\n\t}\n\n\tprivate checkSnapshotUrl(): void {\n\t\tif (!this.snapshotUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no snapshot url was available\",\n\t\t\t\tOdspErrorTypes.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate checkAttachmentPOSTUrl(): void {\n\t\tif (!this.attachmentPOSTUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no attachment POST url was available\",\n\t\t\t\tOdspErrorTypes.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate checkAttachmentGETUrl(): void {\n\t\tif (!this.attachmentGETUrl) {\n\t\t\tthrow new NonRetryableError(\n\t\t\t\t\"Method failed because no attachment GET url was available\",\n\t\t\t\tOdspErrorTypes.genericError,\n\t\t\t\t{ driverVersion },\n\t\t\t);\n\t\t}\n\t}\n\n\tprotected async fetchTreeFromSnapshot(\n\t\tid: string,\n\t\tscenarioName?: string,\n\t): Promise<api.ISnapshotTree | undefined> {\n\t\treturn getWithRetryForTokenRefresh(async (options) => {\n\t\t\tconst storageToken = await this.getStorageToken(options, \"ReadCommit\");\n\t\t\tconst snapshotDownloader = async (\n\t\t\t\turl: string,\n\t\t\t\tfetchOptions: RequestInit,\n\t\t\t\t// eslint-disable-next-line unicorn/consistent-function-scoping\n\t\t\t): Promise<IOdspResponse<unknown>> => {\n\t\t\t\treturn this.epochTracker.fetchAndParseAsJSON(\n\t\t\t\t\turl,\n\t\t\t\t\tfetchOptions,\n\t\t\t\t\t\"snapshotTree\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tscenarioName,\n\t\t\t\t);\n\t\t\t};\n\t\t\tconst snapshot = await fetchSnapshot(\n\t\t\t\tthis.snapshotUrl!,\n\t\t\t\tstorageToken,\n\t\t\t\tid,\n\t\t\t\tthis.fetchFullSnapshot,\n\t\t\t\t!!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,\n\t\t\t\tthis.logger,\n\t\t\t\tsnapshotDownloader,\n\t\t\t);\n\t\t\tlet treeId = \"\";\n\t\t\tif (snapshot.snapshotTree) {\n\t\t\t\tassert(\n\t\t\t\t\tsnapshot.snapshotTree.id !== undefined,\n\t\t\t\t\t0x222 /* \"Root tree should contain the id!!\" */,\n\t\t\t\t);\n\t\t\t\ttreeId = snapshot.snapshotTree.id;\n\t\t\t\tthis.setRootTree(treeId, snapshot.snapshotTree);\n\t\t\t}\n\t\t\tif (snapshot.blobContents) {\n\t\t\t\tthis.initBlobsCache(snapshot.blobContents);\n\t\t\t}\n\t\t\t// If the version id doesn't match with the id of the tree, then use the id of first tree which in that case\n\t\t\t// will be the actual id of tree to be fetched.\n\t\t\treturn this.commitCache.get(id) ?? this.commitCache.get(treeId);\n\t\t});\n\t}\n}\n"]}
|