@fluidframework/container-runtime 2.0.0-rc.2.0.2 → 2.0.0-rc.3.0.0
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/CHANGELOG.md +23 -0
- package/api-report/container-runtime.api.md +471 -52
- package/dist/batchTracker.d.ts +1 -1
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +4 -4
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +33 -30
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +82 -107
- package/dist/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +27 -22
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +155 -165
- package/dist/channelCollection.js.map +1 -1
- package/dist/connectionTelemetry.d.ts +3 -3
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +17 -17
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +2 -2
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +42 -39
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +425 -292
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +8 -8
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +58 -19
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +169 -114
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +1 -0
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +12 -11
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts +5 -1
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +4 -4
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/deltaScheduler.d.ts +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +6 -6
- 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 +4 -4
- package/dist/error.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +3 -2
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +23 -23
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +2 -2
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +4 -5
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +4 -5
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +5 -1
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +21 -12
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +2 -2
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +11 -11
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +2 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +11 -9
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +6 -6
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +1 -1
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +2 -1
- package/dist/gc/index.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +91 -0
- package/dist/messageTypes.d.ts +11 -5
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js +4 -0
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +2 -20
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +3 -3
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +3 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +5 -6
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +15 -4
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +62 -63
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +2 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +14 -16
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +12 -4
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +63 -53
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +2 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +30 -29
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +8 -0
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +36 -32
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +1 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +18 -18
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/public.d.ts +12 -0
- package/dist/scheduleManager.d.ts +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +28 -24
- package/dist/scheduleManager.js.map +1 -1
- package/dist/storageServiceWithAttachBlobs.d.ts +2 -2
- package/dist/storageServiceWithAttachBlobs.d.ts.map +1 -1
- package/dist/storageServiceWithAttachBlobs.js +2 -2
- package/dist/storageServiceWithAttachBlobs.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +209 -0
- package/dist/summary/documentSchema.d.ts.map +1 -0
- package/dist/summary/documentSchema.js +390 -0
- package/dist/summary/documentSchema.js.map +1 -0
- package/dist/summary/index.d.ts +2 -1
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js +4 -1
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +2 -2
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +12 -7
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js +3 -3
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +3 -3
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +16 -16
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +3 -2
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +13 -13
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +2 -2
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.d.ts +1 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js +2 -2
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +3 -2
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +28 -28
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js +3 -3
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +2 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +14 -14
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +5 -3
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +2 -2
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +7 -7
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +6 -17
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js +8 -8
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +4 -3
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +17 -17
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +15 -14
- package/dist/summary/summaryManager.js.map +1 -1
- package/internal.d.ts +11 -0
- package/legacy.d.ts +11 -0
- package/lib/batchTracker.d.ts +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -2
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +33 -30
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +48 -73
- package/lib/blobManager.js.map +1 -1
- package/lib/channelCollection.d.ts +27 -22
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +96 -106
- package/lib/channelCollection.js.map +1 -1
- package/lib/connectionTelemetry.d.ts +3 -3
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +3 -3
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +1 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +42 -39
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +276 -141
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +3 -3
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +58 -19
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +107 -52
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts +1 -0
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +3 -2
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts +5 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +1 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -1
- package/lib/deltaManagerSummarizerProxy.js.map +1 -1
- package/lib/deltaScheduler.d.ts +1 -1
- 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 +2 -2
- package/lib/error.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +3 -2
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +8 -8
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts +2 -2
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +4 -5
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +4 -5
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +5 -1
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +10 -2
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts +2 -2
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +2 -2
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +2 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +4 -2
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js +2 -2
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/lib/gc/index.d.ts +1 -1
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +1 -1
- package/lib/gc/index.js.map +1 -1
- package/lib/index.d.ts +5 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +5 -2
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +91 -0
- package/lib/messageTypes.d.ts +11 -5
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js +4 -0
- package/lib/messageTypes.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +2 -20
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +3 -3
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js +2 -2
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +2 -3
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +15 -4
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +61 -62
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +2 -1
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +9 -12
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +12 -4
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +47 -38
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +2 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +19 -18
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +8 -0
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +36 -32
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +1 -1
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +2 -2
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/public.d.ts +12 -0
- package/lib/scheduleManager.d.ts +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +7 -3
- package/lib/scheduleManager.js.map +1 -1
- package/lib/storageServiceWithAttachBlobs.d.ts +2 -2
- package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -1
- package/lib/storageServiceWithAttachBlobs.js +1 -1
- package/lib/storageServiceWithAttachBlobs.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +209 -0
- package/lib/summary/documentSchema.d.ts.map +1 -0
- package/lib/summary/documentSchema.js +386 -0
- package/lib/summary/documentSchema.js.map +1 -0
- package/lib/summary/index.d.ts +2 -1
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js +1 -0
- package/lib/summary/index.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +2 -2
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +7 -2
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts +1 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +3 -3
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +3 -3
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +3 -2
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +3 -3
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts +2 -2
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.d.ts +1 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summary/summarizerHeuristics.js +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +3 -2
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +5 -5
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +2 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +2 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +3 -3
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +5 -3
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +2 -2
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +1 -1
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +6 -17
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js +3 -3
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +4 -3
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +4 -4
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +9 -8
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +57 -65
- package/src/batchTracker.ts +4 -3
- package/src/blobManager.ts +100 -77
- package/src/channelCollection.ts +180 -165
- package/src/connectionTelemetry.ts +12 -12
- package/src/containerHandleContext.ts +3 -2
- package/src/containerRuntime.ts +481 -277
- package/src/dataStore.ts +9 -4
- package/src/dataStoreContext.ts +195 -93
- package/src/dataStoreContexts.ts +5 -2
- package/src/dataStoreRegistry.ts +3 -2
- package/src/deltaManagerSummarizerProxy.ts +1 -1
- package/src/deltaScheduler.ts +2 -1
- package/src/error.ts +2 -2
- package/src/gc/garbageCollection.ts +21 -20
- package/src/gc/gcConfigs.ts +15 -18
- package/src/gc/gcDefinitions.ts +6 -8
- package/src/gc/gcHelpers.ts +22 -5
- package/src/gc/gcSummaryStateTracker.ts +7 -5
- package/src/gc/gcTelemetry.ts +13 -7
- package/src/gc/gcUnreferencedStateTracker.ts +3 -2
- package/src/gc/index.ts +1 -0
- package/src/index.ts +22 -1
- package/src/messageTypes.ts +20 -6
- package/src/opLifecycle/README.md +89 -0
- package/src/opLifecycle/batchManager.ts +1 -0
- package/src/opLifecycle/definitions.ts +3 -21
- package/src/opLifecycle/index.ts +3 -9
- package/src/opLifecycle/opCompressor.ts +6 -5
- package/src/opLifecycle/opDecompressor.ts +90 -100
- package/src/opLifecycle/opGroupingManager.ts +12 -14
- package/src/opLifecycle/opSplitter.ts +76 -48
- package/src/opLifecycle/outbox.ts +30 -38
- package/src/opLifecycle/remoteMessageProcessor.ts +43 -55
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +6 -6
- package/src/scheduleManager.ts +10 -8
- package/src/storageServiceWithAttachBlobs.ts +2 -2
- package/src/summary/documentSchema.ts +631 -0
- package/src/summary/index.ts +10 -1
- package/src/summary/orderedClientElection.ts +7 -7
- package/src/summary/runWhileConnectedCoordinator.ts +3 -2
- package/src/summary/runningSummarizer.ts +22 -20
- package/src/summary/summarizer.ts +17 -15
- package/src/summary/summarizerClientElection.ts +3 -2
- package/src/summary/summarizerHeuristics.ts +4 -2
- package/src/summary/summarizerNode/summarizerNode.ts +20 -18
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +3 -2
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +16 -8
- package/src/summary/summarizerTypes.ts +7 -3
- package/src/summary/summaryCollection.ts +3 -3
- package/src/summary/summaryFormat.ts +14 -26
- package/src/summary/summaryGenerator.ts +12 -15
- package/src/summary/summaryManager.ts +16 -13
- package/api-extractor-cjs.json +0 -8
- package/dist/container-runtime-alpha.d.ts +0 -1753
- package/dist/container-runtime-beta.d.ts +0 -268
- package/dist/container-runtime-public.d.ts +0 -268
- package/dist/container-runtime-untrimmed.d.ts +0 -1893
- package/lib/container-runtime-alpha.d.ts +0 -1753
- package/lib/container-runtime-beta.d.ts +0 -268
- package/lib/container-runtime-public.d.ts +0 -268
- package/lib/container-runtime-untrimmed.d.ts +0 -1893
- package/lib/test/batchTracker.spec.js +0 -88
- package/lib/test/batchTracker.spec.js.map +0 -1
- package/lib/test/blobManager.spec.js +0 -835
- package/lib/test/blobManager.spec.js.map +0 -1
- package/lib/test/channelCollection.spec.js +0 -141
- package/lib/test/channelCollection.spec.js.map +0 -1
- package/lib/test/containerRuntime.spec.js +0 -1748
- package/lib/test/containerRuntime.spec.js.map +0 -1
- package/lib/test/dataStoreContext.spec.js +0 -801
- package/lib/test/dataStoreContext.spec.js.map +0 -1
- package/lib/test/dataStoreCreation.spec.js +0 -312
- package/lib/test/dataStoreCreation.spec.js.map +0 -1
- package/lib/test/dataStoreRegistry.spec.js +0 -26
- package/lib/test/dataStoreRegistry.spec.js.map +0 -1
- package/lib/test/fuzz/fuzzUtils.js +0 -66
- package/lib/test/fuzz/fuzzUtils.js.map +0 -1
- package/lib/test/fuzz/summarizer.fuzz.spec.js +0 -31
- package/lib/test/fuzz/summarizer.fuzz.spec.js.map +0 -1
- package/lib/test/fuzz/summarizerFuzzMocks.js +0 -162
- package/lib/test/fuzz/summarizerFuzzMocks.js.map +0 -1
- package/lib/test/fuzz/summarizerFuzzSuite.js +0 -106
- package/lib/test/fuzz/summarizerFuzzSuite.js.map +0 -1
- package/lib/test/gc/garbageCollection.spec.js +0 -1465
- package/lib/test/gc/garbageCollection.spec.js.map +0 -1
- package/lib/test/gc/gcConfigs.spec.js +0 -690
- package/lib/test/gc/gcConfigs.spec.js.map +0 -1
- package/lib/test/gc/gcHelpers.spec.js +0 -110
- package/lib/test/gc/gcHelpers.spec.js.map +0 -1
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js +0 -68
- package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js.map +0 -1
- package/lib/test/gc/gcStats.spec.js +0 -391
- package/lib/test/gc/gcStats.spec.js.map +0 -1
- package/lib/test/gc/gcSummaryStateTracker.spec.js +0 -228
- package/lib/test/gc/gcSummaryStateTracker.spec.js.map +0 -1
- package/lib/test/gc/gcTelemetry.spec.js +0 -530
- package/lib/test/gc/gcTelemetry.spec.js.map +0 -1
- package/lib/test/gc/gcUnitTestHelpers.js +0 -29
- package/lib/test/gc/gcUnitTestHelpers.js.map +0 -1
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js +0 -192
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js.map +0 -1
- package/lib/test/getPendingBlobs.spec.js +0 -193
- package/lib/test/getPendingBlobs.spec.js.map +0 -1
- package/lib/test/hardwareStats.spec.js +0 -93
- package/lib/test/hardwareStats.spec.js.map +0 -1
- package/lib/test/index.js +0 -6
- package/lib/test/index.js.map +0 -1
- package/lib/test/opLifecycle/OpGroupingManager.spec.js +0 -225
- package/lib/test/opLifecycle/OpGroupingManager.spec.js.map +0 -1
- package/lib/test/opLifecycle/batchManager.spec.js +0 -189
- package/lib/test/opLifecycle/batchManager.spec.js.map +0 -1
- package/lib/test/opLifecycle/opCompressor.spec.js +0 -74
- package/lib/test/opLifecycle/opCompressor.spec.js.map +0 -1
- package/lib/test/opLifecycle/opDecompressor.spec.js +0 -218
- package/lib/test/opLifecycle/opDecompressor.spec.js.map +0 -1
- package/lib/test/opLifecycle/opSplitter.spec.js +0 -272
- package/lib/test/opLifecycle/opSplitter.spec.js.map +0 -1
- package/lib/test/opLifecycle/outbox.spec.js +0 -675
- package/lib/test/opLifecycle/outbox.spec.js.map +0 -1
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js +0 -196
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js.map +0 -1
- package/lib/test/pendingStateManager.spec.js +0 -329
- package/lib/test/pendingStateManager.spec.js.map +0 -1
- package/lib/test/scheduleManager.spec.js +0 -270
- package/lib/test/scheduleManager.spec.js.map +0 -1
- package/lib/test/summarizerNode.spec.js +0 -326
- package/lib/test/summarizerNode.spec.js.map +0 -1
- package/lib/test/summarizerNodeWithGc.spec.js +0 -318
- package/lib/test/summarizerNodeWithGc.spec.js.map +0 -1
- package/lib/test/summary/orderedClientElection.spec.js +0 -535
- package/lib/test/summary/orderedClientElection.spec.js.map +0 -1
- package/lib/test/summary/runningSummarizer.spec.js +0 -1349
- package/lib/test/summary/runningSummarizer.spec.js.map +0 -1
- package/lib/test/summary/summarizer.spec.js +0 -29
- package/lib/test/summary/summarizer.spec.js.map +0 -1
- package/lib/test/summary/summarizerClientElection.spec.js +0 -436
- package/lib/test/summary/summarizerClientElection.spec.js.map +0 -1
- package/lib/test/summary/summarizerHeuristics.spec.js +0 -289
- package/lib/test/summary/summarizerHeuristics.spec.js.map +0 -1
- package/lib/test/summary/summaryCollection.spec.js +0 -200
- package/lib/test/summary/summaryCollection.spec.js.map +0 -1
- package/lib/test/summary/summaryManager.spec.js +0 -430
- package/lib/test/summary/summaryManager.spec.js.map +0 -1
- package/lib/test/summary/testQuorumClients.js +0 -34
- package/lib/test/summary/testQuorumClients.js.map +0 -1
- package/lib/test/throttler.spec.js +0 -175
- package/lib/test/throttler.spec.js.map +0 -1
- package/lib/test/types/validateContainerRuntimePrevious.generated.js +0 -180
- package/lib/test/types/validateContainerRuntimePrevious.generated.js.map +0 -1
- /package/{dist → lib}/tsdoc-metadata.json +0 -0
|
@@ -1,835 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import { strict as assert } from "assert";
|
|
6
|
-
import { v4 as uuid } from "uuid";
|
|
7
|
-
import { Deferred } from "@fluidframework/core-utils";
|
|
8
|
-
import { bufferToString, gitHashFile, IsoBuffer, TypedEventEmitter, } from "@fluid-internal/client-utils";
|
|
9
|
-
import { AttachState } from "@fluidframework/container-definitions";
|
|
10
|
-
import { SummaryType, } from "@fluidframework/protocol-definitions";
|
|
11
|
-
import { mixinMonitoringContext, createChildLogger, LoggingError, } from "@fluidframework/telemetry-utils";
|
|
12
|
-
import { BlobManager } from "../blobManager.js";
|
|
13
|
-
const MIN_TTL = 24 * 60 * 60; // same as ODSP
|
|
14
|
-
class BaseMockBlobStorage {
|
|
15
|
-
constructor() {
|
|
16
|
-
this.blobs = new Map();
|
|
17
|
-
}
|
|
18
|
-
async readBlob(id) {
|
|
19
|
-
const blob = this.blobs.get(id);
|
|
20
|
-
assert(!!blob);
|
|
21
|
-
return blob;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
class DedupeStorage extends BaseMockBlobStorage {
|
|
25
|
-
constructor() {
|
|
26
|
-
super(...arguments);
|
|
27
|
-
this.minTTL = MIN_TTL;
|
|
28
|
-
}
|
|
29
|
-
async createBlob(blob) {
|
|
30
|
-
const s = bufferToString(blob, "base64");
|
|
31
|
-
const id = await gitHashFile(IsoBuffer.from(s, "base64"));
|
|
32
|
-
this.blobs.set(id, blob);
|
|
33
|
-
return { id, minTTLInSeconds: this.minTTL };
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
class NonDedupeStorage extends BaseMockBlobStorage {
|
|
37
|
-
async createBlob(blob) {
|
|
38
|
-
const id = this.blobs.size.toString();
|
|
39
|
-
this.blobs.set(id, blob);
|
|
40
|
-
return { id, minTTLInSeconds: MIN_TTL };
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
export class MockRuntime extends TypedEventEmitter {
|
|
44
|
-
constructor(mc, snapshot = {}, attached = false, stashed = [[], {}]) {
|
|
45
|
-
super();
|
|
46
|
-
this.mc = mc;
|
|
47
|
-
this.clientDetails = { capabilities: { interactive: true } };
|
|
48
|
-
this.processing = false;
|
|
49
|
-
this.unprocessedBlobs = new Set();
|
|
50
|
-
this.connected = false;
|
|
51
|
-
this.closed = false;
|
|
52
|
-
this.attachedStorage = new DedupeStorage();
|
|
53
|
-
this.detachedStorage = new NonDedupeStorage();
|
|
54
|
-
this.logger = this.mc.logger;
|
|
55
|
-
this.ops = [];
|
|
56
|
-
this.processBlobsP = new Deferred();
|
|
57
|
-
this.blobPs = [];
|
|
58
|
-
this.handlePs = [];
|
|
59
|
-
this.deletedBlobs = [];
|
|
60
|
-
this.attachState = attached ? AttachState.Attached : AttachState.Detached;
|
|
61
|
-
this.ops = stashed[0];
|
|
62
|
-
this.blobManager = new BlobManager(undefined, // routeContext
|
|
63
|
-
snapshot, () => this.getStorage(), (localId, blobId) => this.sendBlobAttachOp(localId, blobId), () => undefined, (blobPath) => this.isBlobDeleted(blobPath), this, stashed[1], () => (this.closed = true));
|
|
64
|
-
}
|
|
65
|
-
get storage() {
|
|
66
|
-
return (this.attachState === AttachState.Detached
|
|
67
|
-
? this.detachedStorage
|
|
68
|
-
: this.attachedStorage);
|
|
69
|
-
}
|
|
70
|
-
getStorage() {
|
|
71
|
-
return {
|
|
72
|
-
createBlob: async (blob) => {
|
|
73
|
-
if (this.processing) {
|
|
74
|
-
return this.storage.createBlob(blob);
|
|
75
|
-
}
|
|
76
|
-
const P = this.processBlobsP.promise.then(async () => {
|
|
77
|
-
if (!this.connected && this.attachState === AttachState.Attached) {
|
|
78
|
-
this.unprocessedBlobs.delete(blob);
|
|
79
|
-
throw new Error("fake error due to having no connection to storage service");
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
this.unprocessedBlobs.delete(blob);
|
|
83
|
-
return this.storage.createBlob(blob);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
this.unprocessedBlobs.add(blob);
|
|
87
|
-
this.emit("blob");
|
|
88
|
-
this.blobPs.push(P);
|
|
89
|
-
return P;
|
|
90
|
-
},
|
|
91
|
-
readBlob: async (id) => this.storage.readBlob(id),
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
sendBlobAttachOp(localId, blobId) {
|
|
95
|
-
this.ops.push({ metadata: { localId, blobId } });
|
|
96
|
-
}
|
|
97
|
-
async createBlob(blob, signal) {
|
|
98
|
-
const P = this.blobManager.createBlob(blob, signal);
|
|
99
|
-
this.handlePs.push(P);
|
|
100
|
-
return P;
|
|
101
|
-
}
|
|
102
|
-
async getBlob(blobHandle) {
|
|
103
|
-
const pathParts = blobHandle.absolutePath.split("/");
|
|
104
|
-
const blobId = pathParts[2];
|
|
105
|
-
return this.blobManager.getBlob(blobId);
|
|
106
|
-
}
|
|
107
|
-
async getPendingLocalState() {
|
|
108
|
-
const pendingBlobs = await this.blobManager.attachAndGetPendingBlobs();
|
|
109
|
-
return [[...this.ops], pendingBlobs];
|
|
110
|
-
}
|
|
111
|
-
processOps() {
|
|
112
|
-
assert(this.connected || this.ops.length === 0);
|
|
113
|
-
this.ops.forEach((op) => this.blobManager.processBlobAttachOp(op, true));
|
|
114
|
-
this.ops = [];
|
|
115
|
-
}
|
|
116
|
-
async processBlobs(resolve, canRetry = false, retryAfterSeconds) {
|
|
117
|
-
const blobPs = this.blobPs;
|
|
118
|
-
this.blobPs = [];
|
|
119
|
-
if (resolve) {
|
|
120
|
-
this.processBlobsP.resolve();
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
this.processBlobsP.reject(new LoggingError("fake driver error", { canRetry, retryAfterSeconds }));
|
|
124
|
-
}
|
|
125
|
-
this.processBlobsP = new Deferred();
|
|
126
|
-
await Promise.allSettled(blobPs).catch(() => { });
|
|
127
|
-
}
|
|
128
|
-
async processHandles() {
|
|
129
|
-
const handlePs = this.handlePs;
|
|
130
|
-
this.handlePs = [];
|
|
131
|
-
const handles = await Promise.all(handlePs);
|
|
132
|
-
handles.forEach((handle) => handle.attachGraph());
|
|
133
|
-
}
|
|
134
|
-
async processAll() {
|
|
135
|
-
while (this.blobPs.length + this.handlePs.length + this.ops.length > 0) {
|
|
136
|
-
const p1 = this.processBlobs(true);
|
|
137
|
-
const p2 = this.processHandles();
|
|
138
|
-
this.processOps();
|
|
139
|
-
await Promise.race([p1, p2]);
|
|
140
|
-
this.processOps();
|
|
141
|
-
await Promise.all([p1, p2]);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
async attach() {
|
|
145
|
-
if (this.detachedStorage.blobs.size > 0) {
|
|
146
|
-
const table = new Map();
|
|
147
|
-
for (const [detachedId, blob] of this.detachedStorage.blobs) {
|
|
148
|
-
const { id } = await this.attachedStorage.createBlob(blob);
|
|
149
|
-
table.set(detachedId, id);
|
|
150
|
-
}
|
|
151
|
-
this.detachedStorage.blobs.clear();
|
|
152
|
-
this.blobManager.setRedirectTable(table);
|
|
153
|
-
}
|
|
154
|
-
const summary = validateSummary(this);
|
|
155
|
-
this.attachState = AttachState.Attached;
|
|
156
|
-
this.emit("attached");
|
|
157
|
-
return summary;
|
|
158
|
-
}
|
|
159
|
-
async connect(delay = 0, processStashedWithRetry) {
|
|
160
|
-
assert(!this.connected);
|
|
161
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
162
|
-
this.connected = true;
|
|
163
|
-
this.emit("connected", "client ID");
|
|
164
|
-
await this.processStashed(processStashedWithRetry);
|
|
165
|
-
const ops = this.ops;
|
|
166
|
-
this.ops = [];
|
|
167
|
-
ops.forEach((op) => this.blobManager.reSubmit(op.metadata));
|
|
168
|
-
}
|
|
169
|
-
async processStashed(processStashedWithRetry) {
|
|
170
|
-
const uploadP = this.blobManager.processStashedChanges();
|
|
171
|
-
this.processing = true;
|
|
172
|
-
if (processStashedWithRetry) {
|
|
173
|
-
await this.processBlobs(false, false, 0);
|
|
174
|
-
// wait till next retry
|
|
175
|
-
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
176
|
-
// try again successfully
|
|
177
|
-
await this.processBlobs(true);
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
await this.processBlobs(true);
|
|
181
|
-
}
|
|
182
|
-
await uploadP;
|
|
183
|
-
this.processing = false;
|
|
184
|
-
}
|
|
185
|
-
disconnect() {
|
|
186
|
-
assert(this.connected);
|
|
187
|
-
this.connected = false;
|
|
188
|
-
this.emit("disconnected");
|
|
189
|
-
}
|
|
190
|
-
async remoteUpload(blob) {
|
|
191
|
-
const response = await this.storage.createBlob(blob);
|
|
192
|
-
const op = { metadata: { localId: uuid(), blobId: response.id } };
|
|
193
|
-
this.blobManager.processBlobAttachOp(op, false);
|
|
194
|
-
return op;
|
|
195
|
-
}
|
|
196
|
-
deleteBlob(blobHandle) {
|
|
197
|
-
this.deletedBlobs.push(blobHandle.absolutePath);
|
|
198
|
-
}
|
|
199
|
-
isBlobDeleted(blobPath) {
|
|
200
|
-
return this.deletedBlobs.includes(blobPath);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
export const validateSummary = (runtime) => {
|
|
204
|
-
const summary = runtime.blobManager.summarize();
|
|
205
|
-
const ids = [];
|
|
206
|
-
let redirectTable;
|
|
207
|
-
for (const [key, attachment] of Object.entries(summary.summary.tree)) {
|
|
208
|
-
if (attachment.type === SummaryType.Attachment) {
|
|
209
|
-
ids.push(attachment.id);
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
assert.strictEqual(key, BlobManager.redirectTableBlobName);
|
|
213
|
-
assert(attachment.type === SummaryType.Blob);
|
|
214
|
-
assert(typeof attachment.content === "string");
|
|
215
|
-
redirectTable = new Map(JSON.parse(attachment.content));
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
return { ids, redirectTable };
|
|
219
|
-
};
|
|
220
|
-
describe("BlobManager", () => {
|
|
221
|
-
const handlePs = [];
|
|
222
|
-
let runtime;
|
|
223
|
-
let createBlob;
|
|
224
|
-
let waitForBlob;
|
|
225
|
-
let mc;
|
|
226
|
-
let injectedSettings = {};
|
|
227
|
-
beforeEach(() => {
|
|
228
|
-
const configProvider = (settings) => ({
|
|
229
|
-
getRawConfig: (name) => settings[name],
|
|
230
|
-
});
|
|
231
|
-
mc = mixinMonitoringContext(createChildLogger(), configProvider(injectedSettings));
|
|
232
|
-
runtime = new MockRuntime(mc);
|
|
233
|
-
handlePs.length = 0;
|
|
234
|
-
// ensures this blob will be processed next time runtime.processBlobs() is called
|
|
235
|
-
waitForBlob = async (blob) => {
|
|
236
|
-
if (!runtime.unprocessedBlobs.has(blob)) {
|
|
237
|
-
await new Promise((resolve) => runtime.on("blob", () => {
|
|
238
|
-
if (!runtime.unprocessedBlobs.has(blob)) {
|
|
239
|
-
resolve();
|
|
240
|
-
}
|
|
241
|
-
}));
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
// create blob and await the handle after the test
|
|
245
|
-
createBlob = async (blob, signal) => {
|
|
246
|
-
const handleP = runtime.createBlob(blob, signal);
|
|
247
|
-
handlePs.push(handleP);
|
|
248
|
-
await waitForBlob(blob);
|
|
249
|
-
};
|
|
250
|
-
const onNoPendingBlobs = () => {
|
|
251
|
-
assert(runtime.blobManager.pendingBlobs.size === 0);
|
|
252
|
-
};
|
|
253
|
-
runtime.blobManager.on("noPendingBlobs", () => onNoPendingBlobs());
|
|
254
|
-
});
|
|
255
|
-
afterEach(async () => {
|
|
256
|
-
assert(runtime.blobManager.pendingBlobs.size === 0);
|
|
257
|
-
injectedSettings = {};
|
|
258
|
-
});
|
|
259
|
-
it("empty snapshot", () => {
|
|
260
|
-
const summaryData = validateSummary(runtime);
|
|
261
|
-
assert.strictEqual(summaryData.ids.length, 0);
|
|
262
|
-
assert.strictEqual(summaryData.redirectTable, undefined);
|
|
263
|
-
});
|
|
264
|
-
it("non empty snapshot", async () => {
|
|
265
|
-
await runtime.attach();
|
|
266
|
-
await runtime.connect();
|
|
267
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
268
|
-
await runtime.processAll();
|
|
269
|
-
const summaryData = validateSummary(runtime);
|
|
270
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
271
|
-
assert.strictEqual(summaryData.redirectTable.size, 1);
|
|
272
|
-
});
|
|
273
|
-
it("hasPendingBlobs", async () => {
|
|
274
|
-
await runtime.attach();
|
|
275
|
-
await runtime.connect();
|
|
276
|
-
assert.strictEqual(runtime.blobManager.hasPendingBlobs, false);
|
|
277
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
278
|
-
await createBlob(IsoBuffer.from("blob2", "utf8"));
|
|
279
|
-
assert.strictEqual(runtime.blobManager.hasPendingBlobs, true);
|
|
280
|
-
await runtime.processAll();
|
|
281
|
-
assert.strictEqual(runtime.blobManager.hasPendingBlobs, false);
|
|
282
|
-
const summaryData = validateSummary(runtime);
|
|
283
|
-
assert.strictEqual(summaryData.ids.length, 2);
|
|
284
|
-
assert.strictEqual(summaryData.redirectTable.size, 2);
|
|
285
|
-
});
|
|
286
|
-
it("NoPendingBlobs count", async () => {
|
|
287
|
-
await runtime.attach();
|
|
288
|
-
await runtime.connect();
|
|
289
|
-
let count = 0;
|
|
290
|
-
runtime.blobManager.on("noPendingBlobs", () => count++);
|
|
291
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
292
|
-
await runtime.processAll();
|
|
293
|
-
assert.strictEqual(count, 1);
|
|
294
|
-
await createBlob(IsoBuffer.from("blob2", "utf8"));
|
|
295
|
-
await createBlob(IsoBuffer.from("blob3", "utf8"));
|
|
296
|
-
await runtime.processAll();
|
|
297
|
-
assert.strictEqual(count, 2);
|
|
298
|
-
const summaryData = validateSummary(runtime);
|
|
299
|
-
assert.strictEqual(summaryData.ids.length, 3);
|
|
300
|
-
assert.strictEqual(summaryData.redirectTable.size, 3);
|
|
301
|
-
});
|
|
302
|
-
it("detached snapshot", async () => {
|
|
303
|
-
assert.strictEqual(runtime.blobManager.hasPendingBlobs, false);
|
|
304
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
305
|
-
await runtime.processAll();
|
|
306
|
-
assert.strictEqual(runtime.blobManager.hasPendingBlobs, true);
|
|
307
|
-
const summaryData = validateSummary(runtime);
|
|
308
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
309
|
-
assert.strictEqual(summaryData.redirectTable, undefined);
|
|
310
|
-
});
|
|
311
|
-
it("detached->attached snapshot", async () => {
|
|
312
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
313
|
-
await runtime.processAll();
|
|
314
|
-
assert.strictEqual(runtime.blobManager.hasPendingBlobs, true);
|
|
315
|
-
await runtime.attach();
|
|
316
|
-
assert.strictEqual(runtime.blobManager.hasPendingBlobs, false);
|
|
317
|
-
const summaryData = validateSummary(runtime);
|
|
318
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
319
|
-
assert.strictEqual(summaryData.redirectTable.size, 1);
|
|
320
|
-
});
|
|
321
|
-
it("uploads while disconnected", async () => {
|
|
322
|
-
await runtime.attach();
|
|
323
|
-
const handleP = runtime.createBlob(IsoBuffer.from("blob", "utf8"));
|
|
324
|
-
await runtime.connect();
|
|
325
|
-
await runtime.processAll();
|
|
326
|
-
await assert.doesNotReject(handleP);
|
|
327
|
-
const summaryData = validateSummary(runtime);
|
|
328
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
329
|
-
assert.strictEqual(summaryData.redirectTable.size, 1);
|
|
330
|
-
});
|
|
331
|
-
it("close container if blob expired", async () => {
|
|
332
|
-
await runtime.attach();
|
|
333
|
-
await runtime.connect();
|
|
334
|
-
runtime.attachedStorage.minTTL = 0.001; // force expired TTL being less than connection time (50ms)
|
|
335
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
336
|
-
await runtime.processBlobs(true);
|
|
337
|
-
runtime.disconnect();
|
|
338
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
339
|
-
await runtime.connect();
|
|
340
|
-
assert.strictEqual(runtime.closed, true);
|
|
341
|
-
await runtime.processAll();
|
|
342
|
-
});
|
|
343
|
-
it("completes after disconnection while upload pending", async () => {
|
|
344
|
-
await runtime.attach();
|
|
345
|
-
await runtime.connect();
|
|
346
|
-
const handleP = runtime.createBlob(IsoBuffer.from("blob", "utf8"));
|
|
347
|
-
runtime.disconnect();
|
|
348
|
-
await runtime.connect(10); // adding some delay to reconnection
|
|
349
|
-
await runtime.processAll();
|
|
350
|
-
await assert.doesNotReject(handleP);
|
|
351
|
-
const summaryData = validateSummary(runtime);
|
|
352
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
353
|
-
assert.strictEqual(summaryData.redirectTable.size, 1);
|
|
354
|
-
});
|
|
355
|
-
it("upload fails gracefully", async () => {
|
|
356
|
-
await runtime.attach();
|
|
357
|
-
await runtime.connect();
|
|
358
|
-
const handleP = runtime.createBlob(IsoBuffer.from("blob", "utf8"));
|
|
359
|
-
await runtime.processBlobs(false);
|
|
360
|
-
runtime.processOps();
|
|
361
|
-
try {
|
|
362
|
-
await handleP;
|
|
363
|
-
assert.fail("should fail");
|
|
364
|
-
}
|
|
365
|
-
catch (error) {
|
|
366
|
-
assert.strictEqual(error.message, "fake driver error");
|
|
367
|
-
}
|
|
368
|
-
await assert.rejects(handleP);
|
|
369
|
-
const summaryData = validateSummary(runtime);
|
|
370
|
-
assert.strictEqual(summaryData.ids.length, 0);
|
|
371
|
-
assert.strictEqual(summaryData.redirectTable, undefined);
|
|
372
|
-
});
|
|
373
|
-
it.skip("upload fails and retries for retriable errors", async () => {
|
|
374
|
-
// Needs to use some sort of fake timer or write test in a different way as it is waiting
|
|
375
|
-
// for actual time which is causing timeouts.
|
|
376
|
-
await runtime.attach();
|
|
377
|
-
await runtime.connect();
|
|
378
|
-
const handleP = runtime.createBlob(IsoBuffer.from("blob", "utf8"));
|
|
379
|
-
await runtime.processBlobs(false, true, 0);
|
|
380
|
-
// wait till next retry
|
|
381
|
-
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
382
|
-
// try again successfully
|
|
383
|
-
await runtime.processBlobs(true);
|
|
384
|
-
runtime.processOps();
|
|
385
|
-
await runtime.processHandles();
|
|
386
|
-
assert(handleP);
|
|
387
|
-
const summaryData = validateSummary(runtime);
|
|
388
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
389
|
-
assert.strictEqual(summaryData.redirectTable.size, 1);
|
|
390
|
-
});
|
|
391
|
-
it("completes after disconnection while op in flight", async () => {
|
|
392
|
-
await runtime.attach();
|
|
393
|
-
await runtime.connect();
|
|
394
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
395
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
396
|
-
await runtime.processBlobs(true);
|
|
397
|
-
runtime.disconnect();
|
|
398
|
-
await runtime.connect();
|
|
399
|
-
await runtime.processAll();
|
|
400
|
-
const summaryData = validateSummary(runtime);
|
|
401
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
402
|
-
assert.strictEqual(summaryData.redirectTable.size, 2);
|
|
403
|
-
});
|
|
404
|
-
it("multiple disconnect/connects", async () => {
|
|
405
|
-
await runtime.attach();
|
|
406
|
-
await runtime.connect();
|
|
407
|
-
const blob = IsoBuffer.from("blob", "utf8");
|
|
408
|
-
const handleP = runtime.createBlob(blob);
|
|
409
|
-
runtime.disconnect();
|
|
410
|
-
await runtime.connect(10);
|
|
411
|
-
const blob2 = IsoBuffer.from("blob2", "utf8");
|
|
412
|
-
const handleP2 = runtime.createBlob(blob2);
|
|
413
|
-
runtime.disconnect();
|
|
414
|
-
await runtime.connect(10);
|
|
415
|
-
await runtime.processAll();
|
|
416
|
-
await assert.doesNotReject(handleP);
|
|
417
|
-
await assert.doesNotReject(handleP2);
|
|
418
|
-
const summaryData = validateSummary(runtime);
|
|
419
|
-
assert.strictEqual(summaryData.ids.length, 2);
|
|
420
|
-
assert.strictEqual(summaryData.redirectTable.size, 2);
|
|
421
|
-
});
|
|
422
|
-
it("handles deduped IDs", async () => {
|
|
423
|
-
await runtime.attach();
|
|
424
|
-
await runtime.connect();
|
|
425
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
426
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
427
|
-
runtime.disconnect();
|
|
428
|
-
await runtime.connect();
|
|
429
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
430
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
431
|
-
await runtime.processBlobs(true);
|
|
432
|
-
runtime.disconnect();
|
|
433
|
-
await runtime.connect();
|
|
434
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
435
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
436
|
-
await runtime.processAll();
|
|
437
|
-
const summaryData = validateSummary(runtime);
|
|
438
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
439
|
-
assert.strictEqual(summaryData.redirectTable.size, 6);
|
|
440
|
-
});
|
|
441
|
-
it("handles deduped IDs in detached", async () => {
|
|
442
|
-
runtime.detachedStorage = new DedupeStorage();
|
|
443
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
444
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
445
|
-
await runtime.processAll();
|
|
446
|
-
const summaryData = validateSummary(runtime);
|
|
447
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
448
|
-
assert.strictEqual(summaryData.redirectTable, undefined);
|
|
449
|
-
});
|
|
450
|
-
it("handles deduped IDs in detached->attached", async () => {
|
|
451
|
-
runtime.detachedStorage = new DedupeStorage();
|
|
452
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
453
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
454
|
-
await runtime.processAll();
|
|
455
|
-
await runtime.attach();
|
|
456
|
-
await runtime.connect();
|
|
457
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
458
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
459
|
-
runtime.disconnect();
|
|
460
|
-
await runtime.connect();
|
|
461
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
462
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
463
|
-
await runtime.processAll();
|
|
464
|
-
const summaryData = validateSummary(runtime);
|
|
465
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
466
|
-
assert.strictEqual(summaryData.redirectTable.size, 4);
|
|
467
|
-
});
|
|
468
|
-
it("can load from summary", async () => {
|
|
469
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
470
|
-
await runtime.processAll();
|
|
471
|
-
await runtime.attach();
|
|
472
|
-
const handle = runtime.createBlob(IsoBuffer.from("blob", "utf8"));
|
|
473
|
-
await runtime.connect();
|
|
474
|
-
await runtime.processAll();
|
|
475
|
-
await assert.doesNotReject(handle);
|
|
476
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
477
|
-
await runtime.processAll();
|
|
478
|
-
const summaryData = validateSummary(runtime);
|
|
479
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
480
|
-
assert.strictEqual(summaryData.redirectTable.size, 3);
|
|
481
|
-
const runtime2 = new MockRuntime(mc, summaryData, true);
|
|
482
|
-
const summaryData2 = validateSummary(runtime2);
|
|
483
|
-
assert.strictEqual(summaryData2.ids.length, 1);
|
|
484
|
-
assert.strictEqual(summaryData2.redirectTable.size, 3);
|
|
485
|
-
});
|
|
486
|
-
it("handles duplicate remote upload", async () => {
|
|
487
|
-
await runtime.attach();
|
|
488
|
-
await runtime.connect();
|
|
489
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
490
|
-
await runtime.remoteUpload(IsoBuffer.from("blob", "utf8"));
|
|
491
|
-
await runtime.processAll();
|
|
492
|
-
const summaryData = validateSummary(runtime);
|
|
493
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
494
|
-
assert.strictEqual(summaryData.redirectTable.size, 2);
|
|
495
|
-
});
|
|
496
|
-
it("handles duplicate remote upload between upload and op", async () => {
|
|
497
|
-
await runtime.attach();
|
|
498
|
-
await runtime.connect();
|
|
499
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
500
|
-
await runtime.processBlobs(true);
|
|
501
|
-
await runtime.remoteUpload(IsoBuffer.from("blob", "utf8"));
|
|
502
|
-
await runtime.processAll();
|
|
503
|
-
const summaryData = validateSummary(runtime);
|
|
504
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
505
|
-
assert.strictEqual(summaryData.redirectTable.size, 2);
|
|
506
|
-
});
|
|
507
|
-
it("handles duplicate remote upload with local ID", async () => {
|
|
508
|
-
await runtime.attach();
|
|
509
|
-
await createBlob(IsoBuffer.from("blob", "utf8"));
|
|
510
|
-
await runtime.connect();
|
|
511
|
-
await runtime.processBlobs(true);
|
|
512
|
-
await runtime.remoteUpload(IsoBuffer.from("blob", "utf8"));
|
|
513
|
-
await runtime.processAll();
|
|
514
|
-
const summaryData = validateSummary(runtime);
|
|
515
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
516
|
-
assert.strictEqual(summaryData.redirectTable.size, 2);
|
|
517
|
-
});
|
|
518
|
-
it("includes blob IDs in summary while attaching", async () => {
|
|
519
|
-
await createBlob(IsoBuffer.from("blob1", "utf8"));
|
|
520
|
-
await createBlob(IsoBuffer.from("blob2", "utf8"));
|
|
521
|
-
await createBlob(IsoBuffer.from("blob3", "utf8"));
|
|
522
|
-
await runtime.processAll();
|
|
523
|
-
// While attaching with blobs, Container takes a summary while still in "Detached"
|
|
524
|
-
// state. BlobManager should know to include the list of attached blob
|
|
525
|
-
// IDs since this summary will be used to create the document
|
|
526
|
-
const summaryData = await runtime.attach();
|
|
527
|
-
assert.strictEqual(summaryData?.ids.length, 3);
|
|
528
|
-
assert.strictEqual(summaryData?.redirectTable.size, 3);
|
|
529
|
-
});
|
|
530
|
-
it("all blobs attached", async () => {
|
|
531
|
-
await runtime.attach();
|
|
532
|
-
await runtime.connect();
|
|
533
|
-
assert.strictEqual(runtime.blobManager.allBlobsAttached, true);
|
|
534
|
-
await createBlob(IsoBuffer.from("blob1", "utf8"));
|
|
535
|
-
assert.strictEqual(runtime.blobManager.allBlobsAttached, false);
|
|
536
|
-
await runtime.processBlobs(true);
|
|
537
|
-
assert.strictEqual(runtime.blobManager.allBlobsAttached, false);
|
|
538
|
-
await runtime.processAll();
|
|
539
|
-
assert.strictEqual(runtime.blobManager.allBlobsAttached, true);
|
|
540
|
-
await createBlob(IsoBuffer.from("blob1", "utf8"));
|
|
541
|
-
await createBlob(IsoBuffer.from("blob2", "utf8"));
|
|
542
|
-
await createBlob(IsoBuffer.from("blob3", "utf8"));
|
|
543
|
-
assert.strictEqual(runtime.blobManager.allBlobsAttached, false);
|
|
544
|
-
await runtime.processAll();
|
|
545
|
-
assert.strictEqual(runtime.blobManager.allBlobsAttached, true);
|
|
546
|
-
});
|
|
547
|
-
describe("Abort Signal", () => {
|
|
548
|
-
it("abort before upload", async () => {
|
|
549
|
-
await runtime.attach();
|
|
550
|
-
await runtime.connect();
|
|
551
|
-
const ac = new AbortController();
|
|
552
|
-
ac.abort("abort test");
|
|
553
|
-
try {
|
|
554
|
-
const blob = IsoBuffer.from("blob", "utf8");
|
|
555
|
-
await runtime.createBlob(blob, ac.signal);
|
|
556
|
-
assert.fail("Should not succeed");
|
|
557
|
-
}
|
|
558
|
-
catch (error) {
|
|
559
|
-
assert.strictEqual(error.status, undefined);
|
|
560
|
-
assert.strictEqual(error.uploadTime, undefined);
|
|
561
|
-
assert.strictEqual(error.acked, undefined);
|
|
562
|
-
assert.strictEqual(error.message, "uploadBlob aborted");
|
|
563
|
-
}
|
|
564
|
-
const summaryData = validateSummary(runtime);
|
|
565
|
-
assert.strictEqual(summaryData.ids.length, 0);
|
|
566
|
-
assert.strictEqual(summaryData.redirectTable, undefined);
|
|
567
|
-
});
|
|
568
|
-
it("abort while upload", async () => {
|
|
569
|
-
await runtime.attach();
|
|
570
|
-
await runtime.connect();
|
|
571
|
-
const ac = new AbortController();
|
|
572
|
-
const blob = IsoBuffer.from("blob", "utf8");
|
|
573
|
-
const handleP = runtime.createBlob(blob, ac.signal);
|
|
574
|
-
ac.abort("abort test");
|
|
575
|
-
assert.strictEqual(runtime.unprocessedBlobs.size, 1);
|
|
576
|
-
await runtime.processBlobs(true);
|
|
577
|
-
try {
|
|
578
|
-
await handleP;
|
|
579
|
-
assert.fail("Should not succeed");
|
|
580
|
-
}
|
|
581
|
-
catch (error) {
|
|
582
|
-
assert.strictEqual(error.uploadTime, undefined);
|
|
583
|
-
assert.strictEqual(error.acked, false);
|
|
584
|
-
assert.strictEqual(error.message, "uploadBlob aborted");
|
|
585
|
-
}
|
|
586
|
-
assert(handleP);
|
|
587
|
-
await assert.rejects(handleP);
|
|
588
|
-
const summaryData = validateSummary(runtime);
|
|
589
|
-
assert.strictEqual(summaryData.ids.length, 0);
|
|
590
|
-
assert.strictEqual(summaryData.redirectTable, undefined);
|
|
591
|
-
});
|
|
592
|
-
it("abort while failed upload", async () => {
|
|
593
|
-
await runtime.attach();
|
|
594
|
-
await runtime.connect();
|
|
595
|
-
const ac = new AbortController();
|
|
596
|
-
const blob = IsoBuffer.from("blob", "utf8");
|
|
597
|
-
const handleP = runtime.createBlob(blob, ac.signal);
|
|
598
|
-
const handleP2 = runtime.createBlob(IsoBuffer.from("blob2", "utf8"));
|
|
599
|
-
ac.abort("abort test");
|
|
600
|
-
assert.strictEqual(runtime.unprocessedBlobs.size, 2);
|
|
601
|
-
await runtime.processBlobs(false);
|
|
602
|
-
try {
|
|
603
|
-
await handleP;
|
|
604
|
-
assert.fail("Should not succeed");
|
|
605
|
-
}
|
|
606
|
-
catch (error) {
|
|
607
|
-
assert.strictEqual(error.message, "uploadBlob aborted");
|
|
608
|
-
}
|
|
609
|
-
try {
|
|
610
|
-
await handleP2;
|
|
611
|
-
assert.fail("Should not succeed");
|
|
612
|
-
}
|
|
613
|
-
catch (error) {
|
|
614
|
-
assert.strictEqual(error.message, "fake driver error");
|
|
615
|
-
}
|
|
616
|
-
await assert.rejects(handleP);
|
|
617
|
-
await assert.rejects(handleP2);
|
|
618
|
-
const summaryData = validateSummary(runtime);
|
|
619
|
-
assert.strictEqual(summaryData.ids.length, 0);
|
|
620
|
-
assert.strictEqual(summaryData.redirectTable, undefined);
|
|
621
|
-
});
|
|
622
|
-
it("abort while disconnected", async () => {
|
|
623
|
-
await runtime.attach();
|
|
624
|
-
await runtime.connect();
|
|
625
|
-
const ac = new AbortController();
|
|
626
|
-
const blob = IsoBuffer.from("blob", "utf8");
|
|
627
|
-
const handleP = runtime.createBlob(blob, ac.signal);
|
|
628
|
-
runtime.disconnect();
|
|
629
|
-
ac.abort();
|
|
630
|
-
await runtime.processBlobs(true);
|
|
631
|
-
try {
|
|
632
|
-
await handleP;
|
|
633
|
-
assert.fail("Should not succeed");
|
|
634
|
-
}
|
|
635
|
-
catch (error) {
|
|
636
|
-
assert.strictEqual(error.message, "uploadBlob aborted");
|
|
637
|
-
}
|
|
638
|
-
await assert.rejects(handleP);
|
|
639
|
-
const summaryData = validateSummary(runtime);
|
|
640
|
-
assert.strictEqual(summaryData.ids.length, 0);
|
|
641
|
-
assert.strictEqual(summaryData.redirectTable, undefined);
|
|
642
|
-
});
|
|
643
|
-
it("abort after blob suceeds", async () => {
|
|
644
|
-
await runtime.attach();
|
|
645
|
-
await runtime.connect();
|
|
646
|
-
const ac = new AbortController();
|
|
647
|
-
let handleP;
|
|
648
|
-
try {
|
|
649
|
-
const blob = IsoBuffer.from("blob", "utf8");
|
|
650
|
-
handleP = runtime.createBlob(blob, ac.signal);
|
|
651
|
-
await runtime.processAll();
|
|
652
|
-
ac.abort();
|
|
653
|
-
}
|
|
654
|
-
catch (error) {
|
|
655
|
-
assert.fail("abort after processing should not throw");
|
|
656
|
-
}
|
|
657
|
-
assert(handleP);
|
|
658
|
-
await assert.doesNotReject(handleP);
|
|
659
|
-
const summaryData = validateSummary(runtime);
|
|
660
|
-
assert.strictEqual(summaryData.ids.length, 1);
|
|
661
|
-
assert.strictEqual(summaryData.redirectTable.size, 1);
|
|
662
|
-
});
|
|
663
|
-
it("abort while waiting for op", async () => {
|
|
664
|
-
await runtime.attach();
|
|
665
|
-
await runtime.connect();
|
|
666
|
-
const ac = new AbortController();
|
|
667
|
-
const blob = IsoBuffer.from("blob", "utf8");
|
|
668
|
-
const handleP = runtime.createBlob(blob, ac.signal);
|
|
669
|
-
const p1 = runtime.processBlobs(true);
|
|
670
|
-
const p2 = runtime.processHandles();
|
|
671
|
-
// finish upload
|
|
672
|
-
await Promise.race([p1, p2]);
|
|
673
|
-
ac.abort();
|
|
674
|
-
runtime.processOps();
|
|
675
|
-
try {
|
|
676
|
-
// finish op
|
|
677
|
-
await handleP;
|
|
678
|
-
assert.fail("Should not succeed");
|
|
679
|
-
}
|
|
680
|
-
catch (error) {
|
|
681
|
-
assert.strictEqual(error.message, "uploadBlob aborted");
|
|
682
|
-
assert.ok(error.uploadTime);
|
|
683
|
-
assert.strictEqual(error.acked, false);
|
|
684
|
-
}
|
|
685
|
-
await assert.rejects(handleP);
|
|
686
|
-
const summaryData = validateSummary(runtime);
|
|
687
|
-
assert.strictEqual(summaryData.ids.length, 0);
|
|
688
|
-
assert.strictEqual(summaryData.redirectTable, undefined);
|
|
689
|
-
});
|
|
690
|
-
it("resubmit on aborted pending op", async () => {
|
|
691
|
-
await runtime.attach();
|
|
692
|
-
await runtime.connect();
|
|
693
|
-
const ac = new AbortController();
|
|
694
|
-
let handleP;
|
|
695
|
-
try {
|
|
696
|
-
handleP = runtime.createBlob(IsoBuffer.from("blob", "utf8"), ac.signal);
|
|
697
|
-
const p1 = runtime.processBlobs(true);
|
|
698
|
-
const p2 = runtime.processHandles();
|
|
699
|
-
// finish upload
|
|
700
|
-
await Promise.race([p1, p2]);
|
|
701
|
-
runtime.disconnect();
|
|
702
|
-
ac.abort();
|
|
703
|
-
await handleP;
|
|
704
|
-
assert.fail("Should not succeed");
|
|
705
|
-
}
|
|
706
|
-
catch (error) {
|
|
707
|
-
assert.strictEqual(error.message, "uploadBlob aborted");
|
|
708
|
-
assert.ok(error.uploadTime);
|
|
709
|
-
assert.strictEqual(error.acked, false);
|
|
710
|
-
}
|
|
711
|
-
await runtime.connect();
|
|
712
|
-
runtime.processOps();
|
|
713
|
-
await assert.rejects(handleP);
|
|
714
|
-
const summaryData = validateSummary(runtime);
|
|
715
|
-
assert.strictEqual(summaryData.ids.length, 0);
|
|
716
|
-
assert.strictEqual(summaryData.redirectTable, undefined);
|
|
717
|
-
});
|
|
718
|
-
});
|
|
719
|
-
describe("Garbage Collection", () => {
|
|
720
|
-
let redirectTable;
|
|
721
|
-
/** Creates a blob with the given content and returns its local and storage id. */
|
|
722
|
-
async function createBlobAndGetIds(content) {
|
|
723
|
-
// For a given blob's GC node id, returns the blob id.
|
|
724
|
-
const getBlobIdFromGCNodeId = (gcNodeId) => {
|
|
725
|
-
const pathParts = gcNodeId.split("/");
|
|
726
|
-
assert(pathParts.length === 3 && pathParts[1] === BlobManager.basePath, "Invalid blob node path");
|
|
727
|
-
return pathParts[2];
|
|
728
|
-
};
|
|
729
|
-
// For a given blob's id, returns the GC node id.
|
|
730
|
-
const getGCNodeIdFromBlobId = (blobId) => {
|
|
731
|
-
return `/${BlobManager.basePath}/${blobId}`;
|
|
732
|
-
};
|
|
733
|
-
const blobContents = IsoBuffer.from(content, "utf8");
|
|
734
|
-
const handleP = runtime.createBlob(blobContents);
|
|
735
|
-
await runtime.processAll();
|
|
736
|
-
const blobHandle = await handleP;
|
|
737
|
-
const localId = getBlobIdFromGCNodeId(blobHandle.absolutePath);
|
|
738
|
-
assert(redirectTable.has(localId), "blob not found in redirect table");
|
|
739
|
-
const storageId = redirectTable.get(localId);
|
|
740
|
-
assert(storageId !== undefined, "storage id not found in redirect table");
|
|
741
|
-
return {
|
|
742
|
-
localId,
|
|
743
|
-
localGCNodeId: getGCNodeIdFromBlobId(localId),
|
|
744
|
-
storageId,
|
|
745
|
-
storageGCNodeId: getGCNodeIdFromBlobId(storageId),
|
|
746
|
-
};
|
|
747
|
-
}
|
|
748
|
-
beforeEach(() => {
|
|
749
|
-
redirectTable = runtime.blobManager.redirectTable;
|
|
750
|
-
});
|
|
751
|
-
it("fetching deleted blob fails", async () => {
|
|
752
|
-
await runtime.attach();
|
|
753
|
-
await runtime.connect();
|
|
754
|
-
const blob1Contents = IsoBuffer.from("blob1", "utf8");
|
|
755
|
-
const blob2Contents = IsoBuffer.from("blob2", "utf8");
|
|
756
|
-
const handle1P = runtime.createBlob(blob1Contents);
|
|
757
|
-
const handle2P = runtime.createBlob(blob2Contents);
|
|
758
|
-
await runtime.processAll();
|
|
759
|
-
const blob1Handle = await handle1P;
|
|
760
|
-
const blob2Handle = await handle2P;
|
|
761
|
-
// Validate that the blobs can be retrieved.
|
|
762
|
-
assert.strictEqual(await runtime.getBlob(blob1Handle), blob1Contents);
|
|
763
|
-
assert.strictEqual(await runtime.getBlob(blob2Handle), blob2Contents);
|
|
764
|
-
// Delete blob1. Retrieving it should result in an error.
|
|
765
|
-
runtime.deleteBlob(blob1Handle);
|
|
766
|
-
await assert.rejects(async () => runtime.getBlob(blob1Handle), (error) => {
|
|
767
|
-
const blob1Id = blob1Handle.absolutePath.split("/")[2];
|
|
768
|
-
const correctErrorType = error.code === 404;
|
|
769
|
-
const correctErrorMessage = error.message === `Blob was deleted: ${blob1Id}`;
|
|
770
|
-
return correctErrorType && correctErrorMessage;
|
|
771
|
-
}, "Deleted blob2 fetch should have failed");
|
|
772
|
-
// Delete blob2. Retrieving it should result in an error.
|
|
773
|
-
runtime.deleteBlob(blob2Handle);
|
|
774
|
-
await assert.rejects(async () => runtime.getBlob(blob2Handle), (error) => {
|
|
775
|
-
const blob2Id = blob2Handle.absolutePath.split("/")[2];
|
|
776
|
-
const correctErrorType = error.code === 404;
|
|
777
|
-
const correctErrorMessage = error.message === `Blob was deleted: ${blob2Id}`;
|
|
778
|
-
return correctErrorType && correctErrorMessage;
|
|
779
|
-
}, "Deleted blob2 fetch should have failed");
|
|
780
|
-
});
|
|
781
|
-
// Support for this config has been removed.
|
|
782
|
-
const legacyKey_disableAttachmentBlobSweep = "Fluid.GarbageCollection.DisableAttachmentBlobSweep";
|
|
783
|
-
[true, undefined].forEach((disableAttachmentBlobsSweep) => it(`deletes unused blobs regardless of DisableAttachmentBlobsSweep setting [DisableAttachmentBlobsSweep=${disableAttachmentBlobsSweep}]`, async () => {
|
|
784
|
-
injectedSettings[legacyKey_disableAttachmentBlobSweep] =
|
|
785
|
-
disableAttachmentBlobsSweep;
|
|
786
|
-
await runtime.attach();
|
|
787
|
-
await runtime.connect();
|
|
788
|
-
const blob1 = await createBlobAndGetIds("blob1");
|
|
789
|
-
const blob2 = await createBlobAndGetIds("blob2");
|
|
790
|
-
// Delete blob1's local id. The local id and the storage id should both be deleted from the redirect table
|
|
791
|
-
// since the blob only had one reference.
|
|
792
|
-
runtime.blobManager.deleteSweepReadyNodes([blob1.localGCNodeId]);
|
|
793
|
-
assert(!redirectTable.has(blob1.localId));
|
|
794
|
-
assert(!redirectTable.has(blob1.storageId));
|
|
795
|
-
// Delete blob2's local id. The local id and the storage id should both be deleted from the redirect table
|
|
796
|
-
// since the blob only had one reference.
|
|
797
|
-
runtime.blobManager.deleteSweepReadyNodes([blob2.localGCNodeId]);
|
|
798
|
-
assert(!redirectTable.has(blob2.localId));
|
|
799
|
-
assert(!redirectTable.has(blob2.storageId));
|
|
800
|
-
}));
|
|
801
|
-
it("deletes unused de-duped blobs", async () => {
|
|
802
|
-
await runtime.attach();
|
|
803
|
-
await runtime.connect();
|
|
804
|
-
// Create 2 blobs with the same content. They should get de-duped.
|
|
805
|
-
const blob1 = await createBlobAndGetIds("blob1");
|
|
806
|
-
const blob1Duplicate = await createBlobAndGetIds("blob1");
|
|
807
|
-
assert(blob1.storageId === blob1Duplicate.storageId, "blob1 not de-duped");
|
|
808
|
-
// Create another 2 blobs with the same content. They should get de-duped.
|
|
809
|
-
const blob2 = await createBlobAndGetIds("blob2");
|
|
810
|
-
const blob2Duplicate = await createBlobAndGetIds("blob2");
|
|
811
|
-
assert(blob2.storageId === blob2Duplicate.storageId, "blob2 not de-duped");
|
|
812
|
-
// Delete blob1's local id. The local id should both be deleted from the redirect table but the storage id
|
|
813
|
-
// should not because the blob has another referenced from the de-duped blob.
|
|
814
|
-
runtime.blobManager.deleteSweepReadyNodes([blob1.localGCNodeId]);
|
|
815
|
-
assert(!redirectTable.has(blob1.localId), "blob1 localId should have been deleted");
|
|
816
|
-
assert(redirectTable.has(blob1.storageId), "blob1 storageId should not have been deleted");
|
|
817
|
-
// Delete blob1's de-duped local id. The local id and the storage id should both be deleted from the redirect table
|
|
818
|
-
// since all the references for the blob are now deleted.
|
|
819
|
-
runtime.blobManager.deleteSweepReadyNodes([blob1Duplicate.localGCNodeId]);
|
|
820
|
-
assert(!redirectTable.has(blob1Duplicate.localId), "blob1Duplicate localId should have been deleted");
|
|
821
|
-
assert(!redirectTable.has(blob1.storageId), "blob1 storageId should have been deleted");
|
|
822
|
-
// Delete blob2's local id. The local id should both be deleted from the redirect table but the storage id
|
|
823
|
-
// should not because the blob has another referenced from the de-duped blob.
|
|
824
|
-
runtime.blobManager.deleteSweepReadyNodes([blob2.localGCNodeId]);
|
|
825
|
-
assert(!redirectTable.has(blob2.localId), "blob2 localId should have been deleted");
|
|
826
|
-
assert(redirectTable.has(blob2.storageId), "blob2 storageId should not have been deleted");
|
|
827
|
-
// Delete blob2's de-duped local id. The local id and the storage id should both be deleted from the redirect table
|
|
828
|
-
// since all the references for the blob are now deleted.
|
|
829
|
-
runtime.blobManager.deleteSweepReadyNodes([blob2Duplicate.localGCNodeId]);
|
|
830
|
-
assert(!redirectTable.has(blob2Duplicate.localId), "blob2Duplicate localId should have been deleted");
|
|
831
|
-
assert(!redirectTable.has(blob2.storageId), "blob2 storageId should have been deleted");
|
|
832
|
-
});
|
|
833
|
-
});
|
|
834
|
-
});
|
|
835
|
-
//# sourceMappingURL=blobManager.spec.js.map
|