@fluidframework/container-runtime 2.53.1 → 2.61.0-355054
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/.mocharc.cjs +1 -2
- package/CHANGELOG.md +4 -0
- package/api-report/{container-runtime.legacy.alpha.api.md → container-runtime.legacy.beta.api.md} +55 -55
- package/container-runtime.test-files.tar +0 -0
- package/dist/batchTracker.d.ts +1 -1
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager/blobManager.d.ts +29 -17
- package/dist/blobManager/blobManager.d.ts.map +1 -1
- package/dist/blobManager/blobManager.js +150 -135
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/blobManager/blobManagerSnapSum.d.ts +4 -4
- package/dist/blobManager/blobManagerSnapSum.d.ts.map +1 -1
- package/dist/blobManager/blobManagerSnapSum.js +30 -33
- package/dist/blobManager/blobManagerSnapSum.js.map +1 -1
- package/dist/blobManager/index.d.ts +2 -2
- package/dist/blobManager/index.d.ts.map +1 -1
- package/dist/blobManager/index.js.map +1 -1
- package/dist/channelCollection.d.ts +9 -11
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +2 -3
- package/dist/channelCollection.js.map +1 -1
- package/dist/compressionDefinitions.d.ts +3 -6
- package/dist/compressionDefinitions.d.ts.map +1 -1
- package/dist/compressionDefinitions.js +2 -4
- package/dist/compressionDefinitions.js.map +1 -1
- package/dist/connectionTelemetry.d.ts +3 -4
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerHandleContext.d.ts +2 -2
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +13 -20
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +4 -7
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +3 -3
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +8 -8
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +2 -2
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts +1 -1
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/deltaManagerProxies.d.ts +2 -3
- package/dist/deltaManagerProxies.d.ts.map +1 -1
- package/dist/deltaManagerProxies.js.map +1 -1
- package/dist/deltaScheduler.d.ts +2 -2
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/error.d.ts +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +4 -4
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +3 -3
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +10 -11
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +4 -4
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
- package/dist/gc/gcSummaryDefinitions.d.ts +1 -1
- package/dist/gc/gcSummaryDefinitions.d.ts.map +1 -1
- package/dist/gc/gcSummaryDefinitions.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +4 -4
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +6 -6
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/index.d.ts +3 -3
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js.map +1 -1
- package/dist/inboundBatchAggregator.d.ts +2 -2
- package/dist/inboundBatchAggregator.d.ts.map +1 -1
- package/dist/inboundBatchAggregator.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +2 -1
- package/dist/messageTypes.d.ts +7 -8
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js +1 -2
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +2 -2
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +1 -1
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/duplicateBatchDetector.d.ts +1 -1
- package/dist/opLifecycle/duplicateBatchDetector.d.ts.map +1 -1
- package/dist/opLifecycle/duplicateBatchDetector.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +5 -5
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts +2 -2
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +2 -2
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +3 -3
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +4 -4
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +9 -9
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +4 -4
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/opProperties.d.ts +1 -1
- package/dist/opProperties.d.ts.map +1 -1
- package/dist/opProperties.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +3 -3
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/storageServiceWithAttachBlobs.d.ts +1 -1
- package/dist/storageServiceWithAttachBlobs.d.ts.map +1 -1
- package/dist/storageServiceWithAttachBlobs.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +1 -2
- package/dist/summary/documentSchema.d.ts.map +1 -1
- package/dist/summary/documentSchema.js.map +1 -1
- package/dist/summary/index.d.ts +10 -10
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +4 -4
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +5 -5
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerNode/index.d.ts +3 -3
- package/dist/summary/summarizerNode/index.d.ts.map +1 -1
- package/dist/summary/summarizerNode/index.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +5 -6
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +3 -3
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -3
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +25 -44
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summarizerUtils.d.ts +3 -3
- package/dist/summary/summarizerUtils.d.ts.map +1 -1
- package/dist/summary/summarizerUtils.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +13 -23
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +1 -2
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/index.d.ts +2 -2
- package/dist/summary/summaryDelayLoadedModule/index.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/index.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.d.ts +1 -1
- package/dist/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts +3 -3
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summarizer.d.ts +5 -5
- package/dist/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts +3 -4
- package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.d.ts +3 -3
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryResultBuilder.d.ts +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryResultBuilder.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryResultBuilder.js.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryResultTypes.d.ts +5 -10
- package/dist/summary/summaryDelayLoadedModule/summaryResultTypes.d.ts.map +1 -1
- package/dist/summary/summaryDelayLoadedModule/summaryResultTypes.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +9 -14
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryHelpers.d.ts +1 -2
- package/dist/summary/summaryHelpers.d.ts.map +1 -1
- package/dist/summary/summaryHelpers.js +1 -2
- package/dist/summary/summaryHelpers.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +3 -3
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js.map +1 -1
- package/internal.d.ts +1 -1
- package/legacy.d.ts +1 -1
- package/lib/batchTracker.d.ts +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager/blobManager.d.ts +29 -17
- package/lib/blobManager/blobManager.d.ts.map +1 -1
- package/lib/blobManager/blobManager.js +142 -127
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/blobManager/blobManagerSnapSum.d.ts +4 -4
- package/lib/blobManager/blobManagerSnapSum.d.ts.map +1 -1
- package/lib/blobManager/blobManagerSnapSum.js +26 -29
- package/lib/blobManager/blobManagerSnapSum.js.map +1 -1
- package/lib/blobManager/index.d.ts +2 -2
- package/lib/blobManager/index.d.ts.map +1 -1
- package/lib/blobManager/index.js.map +1 -1
- package/lib/channelCollection.d.ts +9 -11
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +2 -3
- package/lib/channelCollection.js.map +1 -1
- package/lib/compressionDefinitions.d.ts +3 -6
- package/lib/compressionDefinitions.d.ts.map +1 -1
- package/lib/compressionDefinitions.js +2 -4
- package/lib/compressionDefinitions.js.map +1 -1
- package/lib/connectionTelemetry.d.ts +3 -4
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerHandleContext.d.ts +2 -2
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +13 -20
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +4 -7
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts +3 -3
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +8 -8
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts +2 -2
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/deltaManagerProxies.d.ts +2 -3
- package/lib/deltaManagerProxies.d.ts.map +1 -1
- package/lib/deltaManagerProxies.js.map +1 -1
- package/lib/deltaScheduler.d.ts +2 -2
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +1 -1
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/error.d.ts +1 -1
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +4 -4
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts +3 -3
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +10 -11
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +4 -4
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcReferenceGraphAlgorithm.d.ts +1 -1
- package/lib/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -1
- package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -1
- package/lib/gc/gcSummaryDefinitions.d.ts +1 -1
- package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -1
- package/lib/gc/gcSummaryDefinitions.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts +4 -4
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +6 -6
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/index.d.ts +3 -3
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js.map +1 -1
- package/lib/inboundBatchAggregator.d.ts +2 -2
- package/lib/inboundBatchAggregator.d.ts.map +1 -1
- package/lib/inboundBatchAggregator.js.map +1 -1
- package/lib/index.d.ts +7 -7
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +2 -1
- package/lib/messageTypes.d.ts +7 -8
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js +1 -2
- package/lib/messageTypes.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +2 -2
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +1 -1
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/duplicateBatchDetector.d.ts +1 -1
- package/lib/opLifecycle/duplicateBatchDetector.d.ts.map +1 -1
- package/lib/opLifecycle/duplicateBatchDetector.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +5 -5
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts +2 -2
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +2 -2
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +3 -3
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +4 -4
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +1 -1
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +9 -9
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +4 -4
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/opProperties.d.ts +1 -1
- package/lib/opProperties.d.ts.map +1 -1
- package/lib/opProperties.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +3 -3
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/storageServiceWithAttachBlobs.d.ts +1 -1
- package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -1
- package/lib/storageServiceWithAttachBlobs.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +1 -2
- package/lib/summary/documentSchema.d.ts.map +1 -1
- package/lib/summary/documentSchema.js.map +1 -1
- package/lib/summary/index.d.ts +10 -10
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +4 -4
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts +5 -5
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerNode/index.d.ts +3 -3
- package/lib/summary/summarizerNode/index.d.ts.map +1 -1
- package/lib/summary/summarizerNode/index.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +5 -6
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +3 -3
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -3
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +25 -44
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summarizerUtils.d.ts +3 -3
- package/lib/summary/summarizerUtils.d.ts.map +1 -1
- package/lib/summary/summarizerUtils.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +13 -23
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +1 -2
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/index.d.ts +2 -2
- package/lib/summary/summaryDelayLoadedModule/index.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/index.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.d.ts +1 -1
- package/lib/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts +3 -3
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summarizer.d.ts +5 -5
- package/lib/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts +3 -4
- package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.d.ts +3 -3
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryResultBuilder.d.ts +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryResultBuilder.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryResultBuilder.js.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryResultTypes.d.ts +5 -10
- package/lib/summary/summaryDelayLoadedModule/summaryResultTypes.d.ts.map +1 -1
- package/lib/summary/summaryDelayLoadedModule/summaryResultTypes.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +9 -14
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryHelpers.d.ts +1 -2
- package/lib/summary/summaryHelpers.d.ts.map +1 -1
- package/lib/summary/summaryHelpers.js +1 -2
- package/lib/summary/summaryHelpers.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +3 -3
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +27 -27
- package/src/batchTracker.ts +3 -3
- package/src/blobManager/blobManager.ts +165 -174
- package/src/blobManager/blobManagerSnapSum.ts +31 -53
- package/src/blobManager/index.ts +4 -4
- package/src/channelCollection.ts +28 -29
- package/src/compressionDefinitions.ts +3 -6
- package/src/connectionTelemetry.ts +8 -9
- package/src/containerHandleContext.ts +2 -2
- package/src/containerRuntime.ts +43 -50
- package/src/dataStore.ts +6 -6
- package/src/dataStoreContext.ts +33 -33
- package/src/dataStoreContexts.ts +3 -3
- package/src/dataStoreRegistry.ts +1 -1
- package/src/deltaManagerProxies.ts +3 -3
- package/src/deltaScheduler.ts +6 -3
- package/src/error.ts +1 -1
- package/src/gc/garbageCollection.ts +18 -18
- package/src/gc/gcConfigs.ts +7 -7
- package/src/gc/gcDefinitions.ts +11 -12
- package/src/gc/gcHelpers.ts +7 -7
- package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
- package/src/gc/gcSummaryDefinitions.ts +1 -1
- package/src/gc/gcSummaryStateTracker.ts +5 -5
- package/src/gc/gcTelemetry.ts +8 -8
- package/src/gc/index.ts +18 -18
- package/src/inboundBatchAggregator.ts +4 -4
- package/src/index.ts +79 -79
- package/src/messageTypes.ts +9 -10
- package/src/opLifecycle/batchManager.ts +2 -2
- package/src/opLifecycle/definitions.ts +1 -1
- package/src/opLifecycle/duplicateBatchDetector.ts +1 -1
- package/src/opLifecycle/index.ts +9 -9
- package/src/opLifecycle/opCompressor.ts +2 -2
- package/src/opLifecycle/opDecompressor.ts +3 -3
- package/src/opLifecycle/opGroupingManager.ts +6 -6
- package/src/opLifecycle/opSplitter.ts +10 -7
- package/src/opLifecycle/outbox.ts +17 -14
- package/src/opLifecycle/remoteMessageProcessor.ts +4 -4
- package/src/opProperties.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +10 -10
- package/src/storageServiceWithAttachBlobs.ts +11 -11
- package/src/summary/documentSchema.ts +1 -2
- package/src/summary/index.ts +69 -69
- package/src/summary/orderedClientElection.ts +12 -4
- package/src/summary/summarizerClientElection.ts +5 -5
- package/src/summary/summarizerNode/index.ts +3 -3
- package/src/summary/summarizerNode/summarizerNode.ts +14 -12
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +3 -3
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +3 -3
- package/src/summary/summarizerTypes.ts +25 -44
- package/src/summary/summarizerUtils.ts +3 -3
- package/src/summary/summaryCollection.ts +19 -29
- package/src/summary/summaryDelayLoadedModule/index.ts +2 -2
- package/src/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.ts +1 -1
- package/src/summary/summaryDelayLoadedModule/runningSummarizer.ts +4 -4
- package/src/summary/summaryDelayLoadedModule/summarizer.ts +8 -8
- package/src/summary/summaryDelayLoadedModule/summarizerHeuristics.ts +4 -4
- package/src/summary/summaryDelayLoadedModule/summaryGenerator.ts +3 -3
- package/src/summary/summaryDelayLoadedModule/summaryResultBuilder.ts +3 -3
- package/src/summary/summaryDelayLoadedModule/summaryResultTypes.ts +5 -10
- package/src/summary/summaryFormat.ts +9 -14
- package/src/summary/summaryHelpers.ts +1 -2
- package/src/summary/summaryManager.ts +4 -4
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
import { createEmitter } from "@fluid-internal/client-utils";
|
|
6
6
|
import { AttachState, } from "@fluidframework/container-definitions/internal";
|
|
7
7
|
import { assert, Deferred } from "@fluidframework/core-utils/internal";
|
|
8
|
-
import { canRetryOnError, runWithRetry } from "@fluidframework/driver-utils/internal";
|
|
9
8
|
import { FluidHandleBase, createResponseError, generateHandleContextPath, responseToException, } from "@fluidframework/runtime-utils/internal";
|
|
10
|
-
import { LoggingError, PerformanceEvent, UsageError, createChildMonitoringContext,
|
|
9
|
+
import { LoggingError, PerformanceEvent, UsageError, createChildMonitoringContext, } from "@fluidframework/telemetry-utils/internal";
|
|
11
10
|
import { v4 as uuid } from "uuid";
|
|
12
11
|
import { isBlobMetadata } from "../metadata.js";
|
|
13
12
|
import { getStorageIds, summarizeBlobManagerState, toRedirectTable, } from "./blobManagerSnapSum.js";
|
|
@@ -75,20 +74,20 @@ export class BlobManager {
|
|
|
75
74
|
* because we know that the server will not delete the blob corresponding to that storage ID.
|
|
76
75
|
*/
|
|
77
76
|
this.opsInFlight = new Map();
|
|
78
|
-
const { routeContext, blobManagerLoadInfo, storage, sendBlobAttachOp, blobRequested, isBlobDeleted, runtime,
|
|
77
|
+
const { routeContext, blobManagerLoadInfo, storage, sendBlobAttachOp, blobRequested, isBlobDeleted, runtime, localIdGenerator, createBlobPayloadPending, } = props;
|
|
79
78
|
this.routeContext = routeContext;
|
|
80
79
|
this.storage = storage;
|
|
81
80
|
this.blobRequested = blobRequested;
|
|
82
81
|
this.isBlobDeleted = isBlobDeleted;
|
|
83
82
|
this.runtime = runtime;
|
|
84
|
-
this.
|
|
83
|
+
this.localIdGenerator = localIdGenerator ?? uuid;
|
|
85
84
|
this.createBlobPayloadPending = createBlobPayloadPending;
|
|
86
85
|
this.mc = createChildMonitoringContext({
|
|
87
86
|
logger: this.runtime.baseLogger,
|
|
88
87
|
namespace: "BlobManager",
|
|
89
88
|
});
|
|
90
|
-
this.redirectTable = toRedirectTable(blobManagerLoadInfo, this.mc.logger
|
|
91
|
-
this.sendBlobAttachOp = (localId,
|
|
89
|
+
this.redirectTable = toRedirectTable(blobManagerLoadInfo, this.mc.logger);
|
|
90
|
+
this.sendBlobAttachOp = (localId, storageId) => {
|
|
92
91
|
const pendingEntry = this.pendingBlobs.get(localId);
|
|
93
92
|
assert(pendingEntry !== undefined, 0x725 /* Must have pending blob entry for upcoming op */);
|
|
94
93
|
if (pendingEntry?.uploadTime && pendingEntry?.minTTLInSeconds) {
|
|
@@ -114,7 +113,7 @@ export class BlobManager {
|
|
|
114
113
|
}
|
|
115
114
|
}
|
|
116
115
|
pendingEntry.opsent = true;
|
|
117
|
-
sendBlobAttachOp(localId,
|
|
116
|
+
sendBlobAttachOp(localId, storageId);
|
|
118
117
|
};
|
|
119
118
|
}
|
|
120
119
|
get allBlobsAttached() {
|
|
@@ -135,56 +134,46 @@ export class BlobManager {
|
|
|
135
134
|
uploadTime: pending?.uploadTime,
|
|
136
135
|
});
|
|
137
136
|
}
|
|
138
|
-
hasBlob(
|
|
139
|
-
return this.redirectTable.get(
|
|
137
|
+
hasBlob(localId) {
|
|
138
|
+
return this.redirectTable.get(localId) !== undefined;
|
|
140
139
|
}
|
|
141
140
|
/**
|
|
142
141
|
* Retrieve the blob with the given local blob id.
|
|
143
|
-
* @param
|
|
142
|
+
* @param localId - The local blob id. Likely coming from a handle.
|
|
144
143
|
* @param payloadPending - Whether we suspect the payload may be pending and not available yet.
|
|
145
144
|
* @returns A promise which resolves to the blob contents
|
|
146
145
|
*/
|
|
147
|
-
async getBlob(
|
|
146
|
+
async getBlob(localId, payloadPending) {
|
|
148
147
|
// Verify that the blob is not deleted, i.e., it has not been garbage collected. If it is, this will throw
|
|
149
148
|
// an error, failing the call.
|
|
150
|
-
this.verifyBlobNotDeleted(
|
|
149
|
+
this.verifyBlobNotDeleted(localId);
|
|
151
150
|
// Let runtime know that the corresponding GC node was requested.
|
|
152
151
|
// Note that this will throw if the blob is inactive or tombstoned and throwing on incorrect usage
|
|
153
152
|
// is configured.
|
|
154
|
-
this.blobRequested(
|
|
155
|
-
const pending = this.pendingBlobs.get(
|
|
153
|
+
this.blobRequested(getGCNodePathFromLocalId(localId));
|
|
154
|
+
const pending = this.pendingBlobs.get(localId);
|
|
156
155
|
if (pending) {
|
|
157
156
|
return pending.blob;
|
|
158
157
|
}
|
|
159
|
-
let storageId;
|
|
160
|
-
if (
|
|
161
|
-
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
attachedStorageId ??
|
|
179
|
-
(await new Promise((resolve) => {
|
|
180
|
-
const onProcessBlobAttach = (localId, _storageId) => {
|
|
181
|
-
if (localId === blobId) {
|
|
182
|
-
this.internalEvents.off("processedBlobAttach", onProcessBlobAttach);
|
|
183
|
-
resolve(_storageId);
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
this.internalEvents.on("processedBlobAttach", onProcessBlobAttach);
|
|
187
|
-
}));
|
|
158
|
+
let storageId = this.redirectTable.get(localId);
|
|
159
|
+
if (storageId === undefined) {
|
|
160
|
+
// Only blob handles explicitly marked with pending payload are permitted to exist without
|
|
161
|
+
// yet knowing their storage id. Otherwise they must already be associated with a storage id.
|
|
162
|
+
// Handles for detached blobs are not payload pending.
|
|
163
|
+
assert(payloadPending, 0x11f /* "requesting unknown blobs" */);
|
|
164
|
+
// If we didn't find it in the redirectTable and it's payloadPending, assume the attach op is coming
|
|
165
|
+
// eventually and wait. We do this even if the local client doesn't have the blob payloadPending flag
|
|
166
|
+
// enabled, in case a remote client does have it enabled. This wait may be infinite if the uploading
|
|
167
|
+
// client failed the upload and doesn't exist anymore.
|
|
168
|
+
storageId = await new Promise((resolve) => {
|
|
169
|
+
const onProcessBlobAttach = (_localId, _storageId) => {
|
|
170
|
+
if (_localId === localId) {
|
|
171
|
+
this.internalEvents.off("processedBlobAttach", onProcessBlobAttach);
|
|
172
|
+
resolve(_storageId);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
this.internalEvents.on("processedBlobAttach", onProcessBlobAttach);
|
|
176
|
+
});
|
|
188
177
|
}
|
|
189
178
|
return PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "AttachmentReadBlob", id: storageId }, async (event) => {
|
|
190
179
|
return this.storage.readBlob(storageId).catch((error) => {
|
|
@@ -208,15 +197,17 @@ export class BlobManager {
|
|
|
208
197
|
this.deletePendingBlobMaybe(localId);
|
|
209
198
|
}
|
|
210
199
|
: undefined;
|
|
211
|
-
return new BlobHandle(
|
|
200
|
+
return new BlobHandle(getGCNodePathFromLocalId(localId), this.routeContext, async () => this.getBlob(localId, false), false, // payloadPending
|
|
212
201
|
callback);
|
|
213
202
|
}
|
|
214
203
|
async createBlobDetached(blob) {
|
|
204
|
+
const localId = this.localIdGenerator();
|
|
215
205
|
// Blobs created while the container is detached are stored in IDetachedBlobStorage.
|
|
216
|
-
// The 'IContainerStorageService.createBlob()' call below will respond with a
|
|
217
|
-
|
|
218
|
-
this.
|
|
219
|
-
|
|
206
|
+
// The 'IContainerStorageService.createBlob()' call below will respond with a pseudo storage ID.
|
|
207
|
+
// That pseudo storage ID will be replaced with the real storage ID at attach time.
|
|
208
|
+
const { id: detachedStorageId } = await this.storage.createBlob(blob);
|
|
209
|
+
this.setRedirection(localId, detachedStorageId);
|
|
210
|
+
return this.getBlobHandle(localId);
|
|
220
211
|
}
|
|
221
212
|
async createBlob(blob, signal) {
|
|
222
213
|
if (this.runtime.attachState === AttachState.Detached) {
|
|
@@ -238,7 +229,7 @@ export class BlobManager {
|
|
|
238
229
|
}
|
|
239
230
|
// Create a local ID for the blob. After uploading it to storage and before returning it, a local ID to
|
|
240
231
|
// storage ID mapping is created.
|
|
241
|
-
const localId = this.
|
|
232
|
+
const localId = this.localIdGenerator();
|
|
242
233
|
const pendingEntry = {
|
|
243
234
|
blob,
|
|
244
235
|
handleP: new Deferred(),
|
|
@@ -260,8 +251,8 @@ export class BlobManager {
|
|
|
260
251
|
});
|
|
261
252
|
}
|
|
262
253
|
createBlobWithPayloadPending(blob) {
|
|
263
|
-
const localId = this.
|
|
264
|
-
const blobHandle = new BlobHandle(
|
|
254
|
+
const localId = this.localIdGenerator();
|
|
255
|
+
const blobHandle = new BlobHandle(getGCNodePathFromLocalId(localId), this.routeContext, async () => blob, true, // payloadPending
|
|
265
256
|
() => {
|
|
266
257
|
const pendingEntry = {
|
|
267
258
|
blob,
|
|
@@ -289,36 +280,49 @@ export class BlobManager {
|
|
|
289
280
|
this.internalEvents.on("uploadFailed", onUploadFailed);
|
|
290
281
|
return blobHandle;
|
|
291
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Upload a blob to the storage service.
|
|
285
|
+
* @returns A promise that resolves when the upload is complete and a blob attach op has been sent (but not ack'd).
|
|
286
|
+
*
|
|
287
|
+
* @privateRemarks This method must not reject, as there is no error handling for it in current tracking.
|
|
288
|
+
*/
|
|
292
289
|
async uploadBlob(localId, blob) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
assert(!!entry, 0x387 /* Must have pending blob entry for blob which failed to upload */);
|
|
300
|
-
if (entry.opsent && !canRetryOnError(error)) {
|
|
301
|
-
throw wrapError(error, () => new LoggingError(`uploadBlob error`, { canRetry: true }));
|
|
302
|
-
}
|
|
303
|
-
throw error;
|
|
304
|
-
}
|
|
305
|
-
}, "createBlob", this.mc.logger, {
|
|
306
|
-
cancel: this.pendingBlobs.get(localId)?.abortSignal,
|
|
307
|
-
}).then((response) => this.onUploadResolve(localId, response), (error) => {
|
|
290
|
+
let response;
|
|
291
|
+
try {
|
|
292
|
+
response = await this.storage.createBlob(blob);
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
const entry = this.pendingBlobs.get(localId);
|
|
308
296
|
this.mc.logger.sendTelemetryEvent({
|
|
309
297
|
eventName: "UploadBlobReject",
|
|
310
298
|
// TODO: better typing
|
|
311
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
312
|
-
error,
|
|
299
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
|
|
300
|
+
error: error,
|
|
301
|
+
message: entry === undefined ? "Missing pendingBlob" : undefined,
|
|
313
302
|
localId,
|
|
314
303
|
});
|
|
315
|
-
//
|
|
316
|
-
//
|
|
317
|
-
//
|
|
318
|
-
|
|
319
|
-
|
|
304
|
+
// We probably should assert the pendingBlobs entry here, but we don't currently have any error handling
|
|
305
|
+
// for the uploadP - a promise rejection would be unhandled anyway. For now we can detect this with the
|
|
306
|
+
// message on the UploadBlobReject telemetry.
|
|
307
|
+
if (entry !== undefined) {
|
|
308
|
+
entry.handleP.reject(error);
|
|
309
|
+
this.deletePendingBlob(localId);
|
|
310
|
+
}
|
|
320
311
|
this.internalEvents.emit("uploadFailed", localId, error);
|
|
321
|
-
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
try {
|
|
315
|
+
this.onUploadResolve(localId, response);
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
this.mc.logger.sendTelemetryEvent({
|
|
319
|
+
eventName: "OnUploadResolveError",
|
|
320
|
+
// TODO: better typing
|
|
321
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
|
|
322
|
+
error: error,
|
|
323
|
+
localId,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
322
326
|
}
|
|
323
327
|
/**
|
|
324
328
|
* Set up a mapping in the redirect table from fromId to toId. Also, notify the runtime that a reference is added
|
|
@@ -363,7 +367,7 @@ export class BlobManager {
|
|
|
363
367
|
if (!entry.opsent) {
|
|
364
368
|
this.sendBlobAttachOp(localId, response.id);
|
|
365
369
|
}
|
|
366
|
-
const storageIds = getStorageIds(this.redirectTable
|
|
370
|
+
const storageIds = getStorageIds(this.redirectTable);
|
|
367
371
|
if (storageIds.has(response.id)) {
|
|
368
372
|
// The blob is de-duped. Set up a local ID to storage ID mapping and return the blob. Since this is
|
|
369
373
|
// an existing blob, we don't have to wait for the op to be ack'd since this step has already
|
|
@@ -396,7 +400,7 @@ export class BlobManager {
|
|
|
396
400
|
*/
|
|
397
401
|
reSubmit(metadata) {
|
|
398
402
|
assert(isBlobMetadata(metadata), 0xc01 /* Expected blob metadata for a BlobAttach op */);
|
|
399
|
-
const { localId, blobId } = metadata;
|
|
403
|
+
const { localId, blobId: storageId } = metadata;
|
|
400
404
|
// Any blob that we're actively trying to advance to attached state must have a
|
|
401
405
|
// pendingBlobs entry. Decline to resubmit for anything else.
|
|
402
406
|
// For example, we might be asked to resubmit stashed ops for blobs that never had
|
|
@@ -404,22 +408,22 @@ export class BlobManager {
|
|
|
404
408
|
// try to attach them since they won't be accessible to the customer and would just
|
|
405
409
|
// be considered garbage immediately.
|
|
406
410
|
if (this.pendingBlobs.has(localId)) {
|
|
407
|
-
this.sendBlobAttachOp(localId,
|
|
411
|
+
this.sendBlobAttachOp(localId, storageId);
|
|
408
412
|
}
|
|
409
413
|
}
|
|
410
414
|
processBlobAttachMessage(message, local) {
|
|
411
415
|
assert(isBlobMetadata(message.metadata), 0xc02 /* Expected blob metadata for a BlobAttach op */);
|
|
412
|
-
const { localId, blobId } = message.metadata;
|
|
416
|
+
const { localId, blobId: storageId } = message.metadata;
|
|
413
417
|
const pendingEntry = this.pendingBlobs.get(localId);
|
|
414
418
|
if (pendingEntry?.abortSignal?.aborted) {
|
|
415
419
|
this.deletePendingBlob(localId);
|
|
416
420
|
return;
|
|
417
421
|
}
|
|
418
|
-
this.setRedirection(localId,
|
|
422
|
+
this.setRedirection(localId, storageId);
|
|
419
423
|
// set identity (id -> id) entry
|
|
420
|
-
this.setRedirection(
|
|
424
|
+
this.setRedirection(storageId, storageId);
|
|
421
425
|
if (local) {
|
|
422
|
-
const waitingBlobs = this.opsInFlight.get(
|
|
426
|
+
const waitingBlobs = this.opsInFlight.get(storageId);
|
|
423
427
|
if (waitingBlobs !== undefined) {
|
|
424
428
|
// For each op corresponding to this storage ID that we are waiting for, resolve the pending blob.
|
|
425
429
|
// This is safe because the server will keep the blob alive and the op containing the local ID to
|
|
@@ -427,14 +431,14 @@ export class BlobManager {
|
|
|
427
431
|
for (const pendingLocalId of waitingBlobs) {
|
|
428
432
|
const entry = this.pendingBlobs.get(pendingLocalId);
|
|
429
433
|
assert(entry !== undefined, 0x38f /* local online BlobAttach op with no pending blob entry */);
|
|
430
|
-
this.setRedirection(pendingLocalId,
|
|
434
|
+
this.setRedirection(pendingLocalId, storageId);
|
|
431
435
|
entry.acked = true;
|
|
432
436
|
const blobHandle = this.getBlobHandle(pendingLocalId);
|
|
433
437
|
blobHandle.notifyShared();
|
|
434
438
|
entry.handleP.resolve(blobHandle);
|
|
435
439
|
this.deletePendingBlobMaybe(pendingLocalId);
|
|
436
440
|
}
|
|
437
|
-
this.opsInFlight.delete(
|
|
441
|
+
this.opsInFlight.delete(storageId);
|
|
438
442
|
}
|
|
439
443
|
const localEntry = this.pendingBlobs.get(localId);
|
|
440
444
|
if (localEntry) {
|
|
@@ -445,10 +449,10 @@ export class BlobManager {
|
|
|
445
449
|
this.deletePendingBlobMaybe(localId);
|
|
446
450
|
}
|
|
447
451
|
}
|
|
448
|
-
this.internalEvents.emit("processedBlobAttach", localId,
|
|
452
|
+
this.internalEvents.emit("processedBlobAttach", localId, storageId);
|
|
449
453
|
}
|
|
450
454
|
summarize(telemetryContext) {
|
|
451
|
-
return summarizeBlobManagerState(this.redirectTable
|
|
455
|
+
return summarizeBlobManagerState(this.redirectTable);
|
|
452
456
|
}
|
|
453
457
|
/**
|
|
454
458
|
* Generates data used for garbage collection. Each blob uploaded represents a node in the GC graph as it can be
|
|
@@ -459,13 +463,12 @@ export class BlobManager {
|
|
|
459
463
|
getGCData(fullGC = false) {
|
|
460
464
|
const gcData = { gcNodes: {} };
|
|
461
465
|
for (const [localId, storageId] of this.redirectTable) {
|
|
462
|
-
|
|
463
|
-
//
|
|
464
|
-
// id entries have the same key and value, ignore them.
|
|
465
|
-
// The outbound routes are empty because a blob node cannot reference other nodes. It can only be referenced
|
|
466
|
-
// by adding its handle to a referenced DDS.
|
|
466
|
+
// Don't report the identity mappings to GC - these exist to service old handles that referenced the storage
|
|
467
|
+
// IDs directly. We'll implicitly clean them up if all of their localId references get GC'd first.
|
|
467
468
|
if (localId !== storageId) {
|
|
468
|
-
|
|
469
|
+
// The outbound routes are empty because a blob node cannot reference other nodes. It can only be referenced
|
|
470
|
+
// by adding its handle to a referenced DDS.
|
|
471
|
+
gcData.gcNodes[getGCNodePathFromLocalId(localId)] = [];
|
|
469
472
|
}
|
|
470
473
|
}
|
|
471
474
|
return gcData;
|
|
@@ -484,55 +487,53 @@ export class BlobManager {
|
|
|
484
487
|
* Delete blobs with the given routes from the redirect table.
|
|
485
488
|
*
|
|
486
489
|
* @remarks
|
|
487
|
-
* The routes are GC nodes paths of format -`/<blobManagerBasePath>/<
|
|
490
|
+
* The routes are GC nodes paths of format -`/<blobManagerBasePath>/<localId>`.
|
|
488
491
|
* Deleting the blobs involves 2 steps:
|
|
489
492
|
*
|
|
490
493
|
* 1. The redirect table entry for the local ids are deleted.
|
|
491
494
|
*
|
|
492
|
-
* 2. If the storage ids corresponding to the deleted local ids are not
|
|
493
|
-
*
|
|
495
|
+
* 2. If the storage ids corresponding to the deleted local ids are not referenced by any further local ids, the
|
|
496
|
+
* identity mappings in the redirect table are deleted as well.
|
|
494
497
|
*
|
|
495
498
|
* Note that this does not delete the blobs from storage service immediately. Deleting the blobs from redirect table
|
|
496
|
-
* will
|
|
499
|
+
* will ensure we don't create an attachment blob for them at the next summary. The service would then delete them
|
|
500
|
+
* some time in the future.
|
|
497
501
|
*/
|
|
498
502
|
deleteBlobsFromRedirectTable(blobRoutes) {
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
}
|
|
502
|
-
// This tracks the storage ids of local ids that are deleted. After the local ids have been deleted, if any of
|
|
503
|
-
// these storage ids are unused, they will be deleted as well.
|
|
503
|
+
// maybeUnusedStorageIds is used to compute the set of storage IDs that *used to have a local ID*, but that
|
|
504
|
+
// local ID is being deleted.
|
|
504
505
|
const maybeUnusedStorageIds = new Set();
|
|
505
506
|
for (const route of blobRoutes) {
|
|
506
|
-
const
|
|
507
|
+
const localId = getLocalIdFromGCNodePath(route);
|
|
507
508
|
// If the blob hasn't already been deleted, log an error because this should never happen.
|
|
508
509
|
// If the blob has already been deleted, log a telemetry event. This can happen because multiple GC
|
|
509
510
|
// sweep ops can contain the same data store. It would be interesting to track how often this happens.
|
|
510
511
|
const alreadyDeleted = this.isBlobDeleted(route);
|
|
511
|
-
|
|
512
|
+
const storageId = this.redirectTable.get(localId);
|
|
513
|
+
if (storageId === undefined) {
|
|
512
514
|
this.mc.logger.sendTelemetryEvent({
|
|
513
515
|
eventName: "DeletedAttachmentBlobNotFound",
|
|
514
516
|
category: alreadyDeleted ? "generic" : "error",
|
|
515
|
-
blobId,
|
|
517
|
+
blobId: localId,
|
|
516
518
|
details: { alreadyDeleted },
|
|
517
519
|
});
|
|
518
520
|
continue;
|
|
519
521
|
}
|
|
520
|
-
const storageId = this.redirectTable.get(blobId);
|
|
521
|
-
assert(!!storageId, 0x5bb /* Must be attached to run GC */);
|
|
522
522
|
maybeUnusedStorageIds.add(storageId);
|
|
523
|
-
this.redirectTable.delete(
|
|
523
|
+
this.redirectTable.delete(localId);
|
|
524
524
|
}
|
|
525
|
-
//
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
assert(!!storageId, 0x5bc /* Must be attached to run GC */);
|
|
529
|
-
// For every storage id, the redirect table has a id -> id entry. These do not make the storage id in-use.
|
|
530
|
-
if (maybeUnusedStorageIds.has(storageId) && localId !== storageId) {
|
|
525
|
+
// Remove any storage IDs that still have local IDs referring to them (excluding the identity mapping).
|
|
526
|
+
for (const [localId, storageId] of this.redirectTable) {
|
|
527
|
+
if (localId !== storageId) {
|
|
531
528
|
maybeUnusedStorageIds.delete(storageId);
|
|
532
529
|
}
|
|
533
530
|
}
|
|
534
|
-
//
|
|
535
|
-
// This way they'll be absent from the next summary, and the service
|
|
531
|
+
// Now delete any identity mappings (storage ID -> storage ID) from the redirect table that used to be
|
|
532
|
+
// referenced by a distinct local ID. This way they'll be absent from the next summary, and the service
|
|
533
|
+
// is free to delete them from storage.
|
|
534
|
+
// WARNING: This can potentially delete identity mappings that are still referenced, if storage deduping
|
|
535
|
+
// has let us add a local ID -> storage ID mapping that is later deleted. AB#47337 tracks this issue
|
|
536
|
+
// and possible solutions.
|
|
536
537
|
for (const storageId of maybeUnusedStorageIds) {
|
|
537
538
|
this.redirectTable.delete(storageId);
|
|
538
539
|
}
|
|
@@ -541,11 +542,11 @@ export class BlobManager {
|
|
|
541
542
|
* Verifies that the blob with given id is not deleted, i.e., it has not been garbage collected. If the blob is GC'd,
|
|
542
543
|
* log an error and throw if necessary.
|
|
543
544
|
*/
|
|
544
|
-
verifyBlobNotDeleted(
|
|
545
|
-
if (!this.isBlobDeleted(
|
|
545
|
+
verifyBlobNotDeleted(localId) {
|
|
546
|
+
if (!this.isBlobDeleted(getGCNodePathFromLocalId(localId))) {
|
|
546
547
|
return;
|
|
547
548
|
}
|
|
548
|
-
const request = { url:
|
|
549
|
+
const request = { url: localId };
|
|
549
550
|
const error = responseToException(createResponseError(404, `Blob was deleted`, request), request);
|
|
550
551
|
// Only log deleted events. Tombstone events are logged by garbage collector.
|
|
551
552
|
this.mc.logger.sendErrorEvent({
|
|
@@ -554,14 +555,28 @@ export class BlobManager {
|
|
|
554
555
|
}, error);
|
|
555
556
|
throw error;
|
|
556
557
|
}
|
|
557
|
-
|
|
558
|
+
/**
|
|
559
|
+
* Called in detached state just prior to attaching, this will update the redirect table by
|
|
560
|
+
* converting the pseudo storage IDs into real storage IDs using the provided detachedStorageTable.
|
|
561
|
+
* The provided table must have exactly the same set of pseudo storage IDs as are found in the redirect table.
|
|
562
|
+
* @param detachedStorageTable - A map of pseudo storage IDs to real storage IDs.
|
|
563
|
+
*/
|
|
564
|
+
patchRedirectTable(detachedStorageTable) {
|
|
558
565
|
assert(this.runtime.attachState === AttachState.Detached, 0x252 /* "redirect table can only be set in detached container" */);
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
566
|
+
// The values of the redirect table are the pseudo storage IDs, which are the keys of the
|
|
567
|
+
// detachedStorageTable. We expect to have a many:1 mapping from local IDs to pseudo
|
|
568
|
+
// storage IDs (many in the case that the storage dedupes the blob).
|
|
569
|
+
assert(new Set(this.redirectTable.values()).size === detachedStorageTable.size, 0x391 /* Redirect table size must match BlobManager's local ID count */);
|
|
570
|
+
// Taking a snapshot of the redirect table entries before iterating, because
|
|
571
|
+
// we will be adding identity mappings to the the redirect table as we iterate
|
|
572
|
+
// and we don't want to include those in the iteration.
|
|
573
|
+
const redirectTableEntries = [...this.redirectTable.entries()];
|
|
574
|
+
for (const [localId, detachedStorageId] of redirectTableEntries) {
|
|
575
|
+
const newStorageId = detachedStorageTable.get(detachedStorageId);
|
|
576
|
+
assert(newStorageId !== undefined, "Couldn't find a matching storage ID");
|
|
577
|
+
this.setRedirection(localId, newStorageId);
|
|
563
578
|
// set identity (id -> id) entry
|
|
564
|
-
this.setRedirection(
|
|
579
|
+
this.setRedirection(newStorageId, newStorageId);
|
|
565
580
|
}
|
|
566
581
|
}
|
|
567
582
|
/**
|
|
@@ -593,15 +608,15 @@ export class BlobManager {
|
|
|
593
608
|
}
|
|
594
609
|
}
|
|
595
610
|
/**
|
|
596
|
-
* For a
|
|
611
|
+
* For a localId, returns its path in GC's graph. The node path is of the format `/<blobManagerBasePath>/<localId>`.
|
|
597
612
|
* This path must match the path of the blob handle returned by the createBlob API because blobs are marked
|
|
598
613
|
* referenced by storing these handles in a referenced DDS.
|
|
599
614
|
*/
|
|
600
|
-
const
|
|
615
|
+
const getGCNodePathFromLocalId = (localId) => `/${blobManagerBasePath}/${localId}`;
|
|
601
616
|
/**
|
|
602
|
-
* For a given GC node path, return the
|
|
617
|
+
* For a given GC node path, return the localId. The node path is of the format `/<basePath>/<localId>`.
|
|
603
618
|
*/
|
|
604
|
-
const
|
|
619
|
+
const getLocalIdFromGCNodePath = (nodePath) => {
|
|
605
620
|
const pathParts = nodePath.split("/");
|
|
606
621
|
assert(areBlobPathParts(pathParts), 0x5bd /* Invalid blob node path */);
|
|
607
622
|
return pathParts[2];
|