@fluidframework/container-runtime 2.0.0-dev.3.1.0.125672 → 2.0.0-dev.4.1.0.148229
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/dist/blobManager.d.ts +24 -11
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +112 -55
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +60 -75
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +295 -256
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +39 -13
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +112 -49
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +28 -4
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +107 -41
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts +19 -0
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -0
- package/dist/deltaManagerSummarizerProxy.js +40 -0
- package/dist/deltaManagerSummarizerProxy.js.map +1 -0
- package/dist/gc/garbageCollection.d.ts +204 -0
- package/dist/gc/garbageCollection.d.ts.map +1 -0
- package/dist/{garbageCollection.js → gc/garbageCollection.js} +190 -554
- package/dist/gc/garbageCollection.js.map +1 -0
- package/dist/gc/gcConfigs.d.ts +22 -0
- package/dist/gc/gcConfigs.d.ts.map +1 -0
- package/dist/gc/gcConfigs.js +143 -0
- package/dist/gc/gcConfigs.js.map +1 -0
- package/dist/gc/gcDefinitions.d.ts +320 -0
- package/dist/gc/gcDefinitions.d.ts.map +1 -0
- package/dist/gc/gcDefinitions.js +81 -0
- package/dist/gc/gcDefinitions.js.map +1 -0
- package/dist/gc/gcHelpers.d.ts +86 -0
- package/dist/gc/gcHelpers.d.ts.map +1 -0
- package/dist/gc/gcHelpers.js +268 -0
- package/dist/gc/gcHelpers.js.map +1 -0
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts +16 -0
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -0
- package/dist/gc/gcReferenceGraphAlgorithm.js +49 -0
- package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -0
- package/dist/gc/gcSummaryDefinitions.d.ts +52 -0
- package/dist/gc/gcSummaryDefinitions.d.ts.map +1 -0
- package/dist/gc/gcSummaryDefinitions.js +7 -0
- package/dist/gc/gcSummaryDefinitions.js.map +1 -0
- package/dist/gc/gcSummaryStateTracker.d.ts +93 -0
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -0
- package/dist/gc/gcSummaryStateTracker.js +239 -0
- package/dist/gc/gcSummaryStateTracker.js.map +1 -0
- package/dist/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
- package/dist/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +2 -2
- package/dist/gc/gcSweepReadyUsageDetection.js.map +1 -0
- package/dist/gc/gcUnreferencedStateTracker.d.ts +34 -0
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
- package/dist/gc/gcUnreferencedStateTracker.js +94 -0
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -0
- package/dist/gc/index.d.ts +13 -0
- package/dist/gc/index.d.ts.map +1 -0
- package/dist/gc/index.js +50 -0
- package/dist/gc/index.js.map +1 -0
- package/dist/index.d.ts +3 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -9
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +11 -13
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +26 -38
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +4 -0
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +1 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +2 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +25 -10
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +4 -0
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +42 -4
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +15 -3
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +35 -10
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +19 -3
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +88 -49
- package/dist/opLifecycle/outbox.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 +3 -3
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +20 -21
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/storageServiceWithAttachBlobs.d.ts +17 -0
- package/dist/storageServiceWithAttachBlobs.d.ts.map +1 -0
- package/dist/storageServiceWithAttachBlobs.js +32 -0
- package/dist/storageServiceWithAttachBlobs.js.map +1 -0
- package/dist/summary/index.d.ts +17 -0
- package/dist/summary/index.d.ts.map +1 -0
- package/dist/summary/index.js +46 -0
- package/dist/summary/index.js.map +1 -0
- package/dist/summary/orderedClientElection.d.ts.map +1 -0
- package/dist/summary/orderedClientElection.js.map +1 -0
- package/dist/{runWhileConnectedCoordinator.d.ts → summary/runWhileConnectedCoordinator.d.ts} +3 -2
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/dist/{runWhileConnectedCoordinator.js → summary/runWhileConnectedCoordinator.js} +5 -4
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -0
- package/{lib → dist/summary}/runningSummarizer.d.ts +19 -18
- package/dist/summary/runningSummarizer.d.ts.map +1 -0
- package/dist/{runningSummarizer.js → summary/runningSummarizer.js} +158 -56
- package/dist/summary/runningSummarizer.js.map +1 -0
- package/dist/{summarizer.d.ts → summary/summarizer.d.ts} +4 -9
- package/dist/summary/summarizer.d.ts.map +1 -0
- package/dist/{summarizer.js → summary/summarizer.js} +9 -74
- package/dist/summary/summarizer.js.map +1 -0
- package/dist/summary/summarizerClientElection.d.ts.map +1 -0
- package/dist/summary/summarizerClientElection.js.map +1 -0
- package/{lib → dist/summary}/summarizerHeuristics.d.ts +1 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -0
- package/dist/{summarizerHeuristics.js → summary/summarizerHeuristics.js} +3 -3
- package/dist/summary/summarizerHeuristics.js.map +1 -0
- package/dist/summary/summarizerNode/index.d.ts +8 -0
- package/dist/summary/summarizerNode/index.d.ts.map +1 -0
- package/dist/summary/summarizerNode/index.js +12 -0
- package/dist/summary/summarizerNode/index.js.map +1 -0
- package/dist/summary/summarizerNode/summarizerNode.d.ts +149 -0
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -0
- package/dist/summary/summarizerNode/summarizerNode.js +531 -0
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -0
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +125 -0
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -0
- package/dist/summary/summarizerNode/summarizerNodeUtils.js +132 -0
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -0
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +22 -0
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -0
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +423 -0
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -0
- package/{lib → dist/summary}/summarizerTypes.d.ts +7 -17
- package/dist/summary/summarizerTypes.d.ts.map +1 -0
- package/dist/{summarizerTypes.js → summary/summarizerTypes.js} +0 -5
- package/dist/summary/summarizerTypes.js.map +1 -0
- package/dist/summary/summaryCollection.d.ts.map +1 -0
- package/dist/summary/summaryCollection.js.map +1 -0
- package/{lib → dist/summary}/summaryFormat.d.ts +3 -21
- package/dist/summary/summaryFormat.d.ts.map +1 -0
- package/dist/{summaryFormat.js → summary/summaryFormat.js} +1 -10
- package/dist/summary/summaryFormat.js.map +1 -0
- package/dist/summary/summaryGenerator.d.ts.map +1 -0
- package/dist/{summaryGenerator.js → summary/summaryGenerator.js} +4 -4
- package/dist/summary/summaryGenerator.js.map +1 -0
- package/dist/{summaryManager.d.ts → summary/summaryManager.d.ts} +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -0
- package/dist/summary/summaryManager.js.map +1 -0
- package/lib/blobManager.d.ts +24 -11
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +109 -52
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +60 -75
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +267 -228
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +39 -13
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +101 -38
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +28 -4
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +100 -34
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts +19 -0
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -0
- package/lib/deltaManagerSummarizerProxy.js +36 -0
- package/lib/deltaManagerSummarizerProxy.js.map +1 -0
- package/lib/gc/garbageCollection.d.ts +204 -0
- package/lib/gc/garbageCollection.d.ts.map +1 -0
- package/lib/{garbageCollection.js → gc/garbageCollection.js} +172 -535
- package/lib/gc/garbageCollection.js.map +1 -0
- package/lib/gc/gcConfigs.d.ts +22 -0
- package/lib/gc/gcConfigs.d.ts.map +1 -0
- package/lib/gc/gcConfigs.js +139 -0
- package/lib/gc/gcConfigs.js.map +1 -0
- package/lib/gc/gcDefinitions.d.ts +320 -0
- package/lib/gc/gcDefinitions.d.ts.map +1 -0
- package/lib/gc/gcDefinitions.js +78 -0
- package/lib/gc/gcDefinitions.js.map +1 -0
- package/lib/gc/gcHelpers.d.ts +86 -0
- package/lib/gc/gcHelpers.d.ts.map +1 -0
- package/lib/gc/gcHelpers.js +254 -0
- package/lib/gc/gcHelpers.js.map +1 -0
- package/lib/gc/gcReferenceGraphAlgorithm.d.ts +16 -0
- package/lib/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -0
- package/lib/gc/gcReferenceGraphAlgorithm.js +45 -0
- package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -0
- package/lib/gc/gcSummaryDefinitions.d.ts +52 -0
- package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -0
- package/lib/gc/gcSummaryDefinitions.js +6 -0
- package/lib/gc/gcSummaryDefinitions.js.map +1 -0
- package/lib/gc/gcSummaryStateTracker.d.ts +93 -0
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -0
- package/lib/gc/gcSummaryStateTracker.js +235 -0
- package/lib/gc/gcSummaryStateTracker.js.map +1 -0
- package/lib/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
- package/lib/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +1 -1
- package/lib/gc/gcSweepReadyUsageDetection.js.map +1 -0
- package/lib/gc/gcUnreferencedStateTracker.d.ts +34 -0
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
- package/lib/gc/gcUnreferencedStateTracker.js +90 -0
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -0
- package/lib/gc/index.d.ts +13 -0
- package/lib/gc/index.d.ts.map +1 -0
- package/lib/gc/index.js +12 -0
- package/lib/gc/index.js.map +1 -0
- package/lib/index.d.ts +3 -7
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -4
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +11 -13
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +24 -37
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +4 -0
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +1 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +26 -11
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +4 -0
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +42 -4
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +15 -3
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +35 -10
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +19 -3
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +90 -51
- package/lib/opLifecycle/outbox.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 +3 -3
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +20 -21
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/storageServiceWithAttachBlobs.d.ts +17 -0
- package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -0
- package/lib/storageServiceWithAttachBlobs.js +28 -0
- package/lib/storageServiceWithAttachBlobs.js.map +1 -0
- package/lib/summary/index.d.ts +17 -0
- package/lib/summary/index.d.ts.map +1 -0
- package/lib/summary/index.js +15 -0
- package/lib/summary/index.js.map +1 -0
- package/lib/summary/orderedClientElection.d.ts.map +1 -0
- package/lib/summary/orderedClientElection.js.map +1 -0
- package/lib/{runWhileConnectedCoordinator.d.ts → summary/runWhileConnectedCoordinator.d.ts} +3 -2
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/lib/{runWhileConnectedCoordinator.js → summary/runWhileConnectedCoordinator.js} +5 -4
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -0
- package/{dist → lib/summary}/runningSummarizer.d.ts +19 -18
- package/lib/summary/runningSummarizer.d.ts.map +1 -0
- package/lib/{runningSummarizer.js → summary/runningSummarizer.js} +159 -57
- package/lib/summary/runningSummarizer.js.map +1 -0
- package/lib/{summarizer.d.ts → summary/summarizer.d.ts} +4 -9
- package/lib/summary/summarizer.d.ts.map +1 -0
- package/lib/{summarizer.js → summary/summarizer.js} +11 -76
- package/lib/summary/summarizer.js.map +1 -0
- package/lib/summary/summarizerClientElection.d.ts.map +1 -0
- package/lib/summary/summarizerClientElection.js.map +1 -0
- package/{dist → lib/summary}/summarizerHeuristics.d.ts +1 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
- package/lib/{summarizerHeuristics.js → summary/summarizerHeuristics.js} +3 -3
- package/lib/summary/summarizerHeuristics.js.map +1 -0
- package/lib/summary/summarizerNode/index.d.ts +8 -0
- package/lib/summary/summarizerNode/index.d.ts.map +1 -0
- package/lib/summary/summarizerNode/index.js +7 -0
- package/lib/summary/summarizerNode/index.js.map +1 -0
- package/lib/summary/summarizerNode/summarizerNode.d.ts +149 -0
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -0
- package/lib/summary/summarizerNode/summarizerNode.js +526 -0
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -0
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +125 -0
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -0
- package/lib/summary/summarizerNode/summarizerNodeUtils.js +125 -0
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -0
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +22 -0
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -0
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +419 -0
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -0
- package/{dist → lib/summary}/summarizerTypes.d.ts +7 -17
- package/lib/summary/summarizerTypes.d.ts.map +1 -0
- package/lib/summary/summarizerTypes.js +6 -0
- package/{dist → lib/summary}/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts.map +1 -0
- package/lib/summary/summaryCollection.js.map +1 -0
- package/{dist → lib/summary}/summaryFormat.d.ts +3 -21
- package/lib/summary/summaryFormat.d.ts.map +1 -0
- package/lib/{summaryFormat.js → summary/summaryFormat.js} +0 -8
- package/lib/summary/summaryFormat.js.map +1 -0
- package/lib/summary/summaryGenerator.d.ts.map +1 -0
- package/lib/{summaryGenerator.js → summary/summaryGenerator.js} +4 -4
- package/lib/summary/summaryGenerator.js.map +1 -0
- package/lib/{summaryManager.d.ts → summary/summaryManager.d.ts} +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -0
- package/lib/summary/summaryManager.js.map +1 -0
- package/package.json +63 -60
- package/src/blobManager.ts +132 -69
- package/src/containerRuntime.ts +421 -382
- package/src/dataStoreContext.ts +140 -49
- package/src/dataStores.ts +139 -41
- package/src/deltaManagerSummarizerProxy.ts +46 -0
- package/{garbageCollection.md → src/gc/garbageCollection.md} +2 -2
- package/src/{garbageCollection.ts → gc/garbageCollection.ts} +245 -890
- package/src/gc/gcConfigs.ts +193 -0
- package/src/gc/gcDefinitions.ts +387 -0
- package/src/gc/gcHelpers.ts +332 -0
- package/src/gc/gcReferenceGraphAlgorithm.ts +52 -0
- package/src/gc/gcSummaryDefinitions.ts +54 -0
- package/src/gc/gcSummaryStateTracker.ts +329 -0
- package/src/{gcSweepReadyUsageDetection.ts → gc/gcSweepReadyUsageDetection.ts} +1 -1
- package/src/gc/gcUnreferencedStateTracker.ts +114 -0
- package/src/gc/index.ts +65 -0
- package/src/index.ts +10 -22
- package/src/opLifecycle/README.md +157 -0
- package/src/opLifecycle/batchManager.ts +26 -55
- package/src/opLifecycle/definitions.ts +4 -0
- package/src/opLifecycle/index.ts +1 -1
- package/src/opLifecycle/opCompressor.ts +32 -12
- package/src/opLifecycle/opDecompressor.ts +49 -5
- package/src/opLifecycle/opSplitter.ts +55 -12
- package/src/opLifecycle/outbox.ts +120 -60
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +34 -27
- package/src/storageServiceWithAttachBlobs.ts +38 -0
- package/src/summary/index.ts +105 -0
- package/src/{runWhileConnectedCoordinator.ts → summary/runWhileConnectedCoordinator.ts} +7 -7
- package/src/{runningSummarizer.ts → summary/runningSummarizer.ts} +279 -139
- package/src/{summarizer.ts → summary/summarizer.ts} +12 -97
- package/src/{summarizerHeuristics.ts → summary/summarizerHeuristics.ts} +9 -4
- package/src/summary/summarizerNode/index.ts +12 -0
- package/src/summary/summarizerNode/summarizerNode.ts +766 -0
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +214 -0
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +644 -0
- package/src/{summarizerTypes.ts → summary/summarizerTypes.ts} +8 -22
- package/src/{summaryFormat.ts → summary/summaryFormat.ts} +3 -29
- package/src/{summaryGenerator.ts → summary/summaryGenerator.ts} +12 -11
- package/src/{summaryManager.ts → summary/summaryManager.ts} +1 -1
- package/dist/garbageCollection.d.ts +0 -411
- package/dist/garbageCollection.d.ts.map +0 -1
- package/dist/garbageCollection.js.map +0 -1
- package/dist/garbageCollectionConstants.d.ts +0 -23
- package/dist/garbageCollectionConstants.d.ts.map +0 -1
- package/dist/garbageCollectionConstants.js +0 -36
- package/dist/garbageCollectionConstants.js.map +0 -1
- package/dist/garbageCollectionHelpers.d.ts +0 -15
- package/dist/garbageCollectionHelpers.d.ts.map +0 -1
- package/dist/garbageCollectionHelpers.js +0 -27
- package/dist/garbageCollectionHelpers.js.map +0 -1
- package/dist/gcSweepReadyUsageDetection.d.ts.map +0 -1
- package/dist/gcSweepReadyUsageDetection.js.map +0 -1
- package/dist/orderedClientElection.d.ts.map +0 -1
- package/dist/orderedClientElection.js.map +0 -1
- package/dist/runWhileConnectedCoordinator.d.ts.map +0 -1
- package/dist/runWhileConnectedCoordinator.js.map +0 -1
- package/dist/runningSummarizer.d.ts.map +0 -1
- package/dist/runningSummarizer.js.map +0 -1
- package/dist/serializedSnapshotStorage.d.ts +0 -58
- package/dist/serializedSnapshotStorage.d.ts.map +0 -1
- package/dist/serializedSnapshotStorage.js +0 -110
- package/dist/serializedSnapshotStorage.js.map +0 -1
- package/dist/summarizer.d.ts.map +0 -1
- package/dist/summarizer.js.map +0 -1
- package/dist/summarizerClientElection.d.ts.map +0 -1
- package/dist/summarizerClientElection.js.map +0 -1
- package/dist/summarizerHandle.d.ts +0 -12
- package/dist/summarizerHandle.d.ts.map +0 -1
- package/dist/summarizerHandle.js +0 -22
- package/dist/summarizerHandle.js.map +0 -1
- package/dist/summarizerHeuristics.d.ts.map +0 -1
- package/dist/summarizerHeuristics.js.map +0 -1
- package/dist/summarizerTypes.d.ts.map +0 -1
- package/dist/summaryCollection.d.ts.map +0 -1
- package/dist/summaryCollection.js.map +0 -1
- package/dist/summaryFormat.d.ts.map +0 -1
- package/dist/summaryFormat.js.map +0 -1
- package/dist/summaryGenerator.d.ts.map +0 -1
- package/dist/summaryGenerator.js.map +0 -1
- package/dist/summaryManager.d.ts.map +0 -1
- package/dist/summaryManager.js.map +0 -1
- package/lib/garbageCollection.d.ts +0 -411
- package/lib/garbageCollection.d.ts.map +0 -1
- package/lib/garbageCollection.js.map +0 -1
- package/lib/garbageCollectionConstants.d.ts +0 -23
- package/lib/garbageCollectionConstants.d.ts.map +0 -1
- package/lib/garbageCollectionConstants.js +0 -33
- package/lib/garbageCollectionConstants.js.map +0 -1
- package/lib/garbageCollectionHelpers.d.ts +0 -15
- package/lib/garbageCollectionHelpers.d.ts.map +0 -1
- package/lib/garbageCollectionHelpers.js +0 -23
- package/lib/garbageCollectionHelpers.js.map +0 -1
- package/lib/gcSweepReadyUsageDetection.d.ts.map +0 -1
- package/lib/gcSweepReadyUsageDetection.js.map +0 -1
- package/lib/orderedClientElection.d.ts.map +0 -1
- package/lib/orderedClientElection.js.map +0 -1
- package/lib/runWhileConnectedCoordinator.d.ts.map +0 -1
- package/lib/runWhileConnectedCoordinator.js.map +0 -1
- package/lib/runningSummarizer.d.ts.map +0 -1
- package/lib/runningSummarizer.js.map +0 -1
- package/lib/serializedSnapshotStorage.d.ts +0 -58
- package/lib/serializedSnapshotStorage.d.ts.map +0 -1
- package/lib/serializedSnapshotStorage.js +0 -106
- package/lib/serializedSnapshotStorage.js.map +0 -1
- package/lib/summarizer.d.ts.map +0 -1
- package/lib/summarizer.js.map +0 -1
- package/lib/summarizerClientElection.d.ts.map +0 -1
- package/lib/summarizerClientElection.js.map +0 -1
- package/lib/summarizerHandle.d.ts +0 -12
- package/lib/summarizerHandle.d.ts.map +0 -1
- package/lib/summarizerHandle.js +0 -18
- package/lib/summarizerHandle.js.map +0 -1
- package/lib/summarizerHeuristics.d.ts.map +0 -1
- package/lib/summarizerHeuristics.js.map +0 -1
- package/lib/summarizerTypes.d.ts.map +0 -1
- package/lib/summarizerTypes.js +0 -9
- package/lib/summarizerTypes.js.map +0 -1
- package/lib/summaryCollection.d.ts.map +0 -1
- package/lib/summaryCollection.js.map +0 -1
- package/lib/summaryFormat.d.ts.map +0 -1
- package/lib/summaryFormat.js.map +0 -1
- package/lib/summaryGenerator.d.ts.map +0 -1
- package/lib/summaryGenerator.js.map +0 -1
- package/lib/summaryManager.d.ts.map +0 -1
- package/lib/summaryManager.js.map +0 -1
- package/src/garbageCollectionConstants.ts +0 -38
- package/src/garbageCollectionHelpers.ts +0 -37
- package/src/serializedSnapshotStorage.ts +0 -151
- package/src/summarizerHandle.ts +0 -23
- /package/dist/{gcSweepReadyUsageDetection.d.ts → gc/gcSweepReadyUsageDetection.d.ts} +0 -0
- /package/dist/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
- /package/dist/{orderedClientElection.js → summary/orderedClientElection.js} +0 -0
- /package/dist/{summarizerClientElection.d.ts → summary/summarizerClientElection.d.ts} +0 -0
- /package/dist/{summarizerClientElection.js → summary/summarizerClientElection.js} +0 -0
- /package/dist/{summaryCollection.d.ts → summary/summaryCollection.d.ts} +0 -0
- /package/dist/{summaryCollection.js → summary/summaryCollection.js} +0 -0
- /package/dist/{summaryGenerator.d.ts → summary/summaryGenerator.d.ts} +0 -0
- /package/dist/{summaryManager.js → summary/summaryManager.js} +0 -0
- /package/lib/{gcSweepReadyUsageDetection.d.ts → gc/gcSweepReadyUsageDetection.d.ts} +0 -0
- /package/lib/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
- /package/lib/{orderedClientElection.js → summary/orderedClientElection.js} +0 -0
- /package/lib/{summarizerClientElection.d.ts → summary/summarizerClientElection.d.ts} +0 -0
- /package/lib/{summarizerClientElection.js → summary/summarizerClientElection.js} +0 -0
- /package/lib/{summaryCollection.d.ts → summary/summaryCollection.d.ts} +0 -0
- /package/lib/{summaryCollection.js → summary/summaryCollection.js} +0 -0
- /package/lib/{summaryGenerator.d.ts → summary/summaryGenerator.d.ts} +0 -0
- /package/lib/{summaryManager.js → summary/summaryManager.js} +0 -0
- /package/src/{orderedClientElection.ts → summary/orderedClientElection.ts} +0 -0
- /package/src/{summarizerClientElection.ts → summary/summarizerClientElection.ts} +0 -0
- /package/src/{summaryCollection.ts → summary/summaryCollection.ts} +0 -0
package/lib/containerRuntime.js
CHANGED
|
@@ -1,35 +1,28 @@
|
|
|
1
1
|
import { AttachState, LoaderHeader, } from "@fluidframework/container-definitions";
|
|
2
|
-
import { assert, Trace, TypedEventEmitter, unreachableCase } from "@fluidframework/common-utils";
|
|
2
|
+
import { assert, LazyPromise, Trace, TypedEventEmitter, unreachableCase, } from "@fluidframework/common-utils";
|
|
3
3
|
import { ChildLogger, raiseConnectedEvent, PerformanceEvent, TaggedLoggerAdapter, loggerToMonitoringContext, wrapError, } from "@fluidframework/telemetry-utils";
|
|
4
4
|
import { DriverHeader, FetchSource, } from "@fluidframework/driver-definitions";
|
|
5
5
|
import { readAndParse } from "@fluidframework/driver-utils";
|
|
6
6
|
import { DataCorruptionError, DataProcessingError, GenericError, UsageError, } from "@fluidframework/container-utils";
|
|
7
7
|
import { MessageType, SummaryType, } from "@fluidframework/protocol-definitions";
|
|
8
|
-
import { FlushMode, gcTreeKey, channelsTreeName, } from "@fluidframework/runtime-definitions";
|
|
9
|
-
import { addBlobToSummary, addSummarizeResultToSummary, addTreeToSummary,
|
|
10
|
-
import { GCDataBuilder, trimLeadingAndTrailingSlashes } from "@fluidframework/garbage-collector";
|
|
8
|
+
import { FlushMode, FlushModeExperimental, gcTreeKey, channelsTreeName, } from "@fluidframework/runtime-definitions";
|
|
9
|
+
import { addBlobToSummary, addSummarizeResultToSummary, addTreeToSummary, RequestParser, create404Response, exceptionToResponse, GCDataBuilder, requestFluidObject, seqFromTree, calculateStats, TelemetryContext, } from "@fluidframework/runtime-utils";
|
|
11
10
|
import { v4 as uuid } from "uuid";
|
|
12
11
|
import { ContainerFluidHandleContext } from "./containerHandleContext";
|
|
13
12
|
import { FluidDataStoreRegistry } from "./dataStoreRegistry";
|
|
14
|
-
import { Summarizer } from "./summarizer";
|
|
15
|
-
import { SummaryManager } from "./summaryManager";
|
|
16
13
|
import { ReportOpPerfTelemetry } from "./connectionTelemetry";
|
|
17
14
|
import { PendingStateManager } from "./pendingStateManager";
|
|
18
15
|
import { pkgVersion } from "./packageVersion";
|
|
19
16
|
import { BlobManager } from "./blobManager";
|
|
20
17
|
import { DataStores, getSummaryForDatastores } from "./dataStores";
|
|
21
|
-
import { aliasBlobName, blobsTreeName, chunksBlobName, electedSummarizerBlobName, extractSummaryMetadataMessage, metadataBlobName, wrapSummaryInChannelsTree, } from "./
|
|
22
|
-
import { SummaryCollection } from "./summaryCollection";
|
|
23
|
-
import { OrderedClientCollection, OrderedClientElection, } from "./orderedClientElection";
|
|
24
|
-
import { SummarizerClientElection, summarizerClientType } from "./summarizerClientElection";
|
|
18
|
+
import { aliasBlobName, blobsTreeName, chunksBlobName, createRootSummarizerNodeWithGC, electedSummarizerBlobName, extractSummaryMetadataMessage, metadataBlobName, Summarizer, SummaryManager, wrapSummaryInChannelsTree, SummaryCollection, OrderedClientCollection, OrderedClientElection, SummarizerClientElection, summarizerClientType, RunWhileConnectedCoordinator, } from "./summary";
|
|
25
19
|
import { formExponentialFn, Throttler } from "./throttler";
|
|
26
|
-
import {
|
|
27
|
-
import { GarbageCollector, GCNodeType, } from "./garbageCollection";
|
|
20
|
+
import { GarbageCollector, GCNodeType, gcTombstoneGenerationOptionName, shouldAllowGcTombstoneEnforcement, trimLeadingAndTrailingSlashes, } from "./gc";
|
|
28
21
|
import { channelToDataStore, isDataStoreAliasMessage } from "./dataStore";
|
|
29
22
|
import { BindBatchTracker } from "./batchTracker";
|
|
30
|
-
import { SerializedSnapshotStorage, } from "./serializedSnapshotStorage";
|
|
31
23
|
import { ScheduleManager } from "./scheduleManager";
|
|
32
24
|
import { OpCompressor, OpDecompressor, Outbox, OpSplitter, RemoteMessageProcessor, } from "./opLifecycle";
|
|
25
|
+
import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy";
|
|
33
26
|
export var ContainerMessageType;
|
|
34
27
|
(function (ContainerMessageType) {
|
|
35
28
|
// An op to be delivered to store
|
|
@@ -66,11 +59,6 @@ export var RuntimeHeaders;
|
|
|
66
59
|
(function (RuntimeHeaders) {
|
|
67
60
|
/** True to wait for a data store to be created and loaded before returning it. */
|
|
68
61
|
RuntimeHeaders["wait"] = "wait";
|
|
69
|
-
/**
|
|
70
|
-
* True if the request is from an external app. Used for GC to handle scenarios where a data store
|
|
71
|
-
* is deleted and requested via an external app.
|
|
72
|
-
*/
|
|
73
|
-
RuntimeHeaders["externalRequest"] = "externalRequest";
|
|
74
62
|
/** True if the request is coming from an IFluidHandle. */
|
|
75
63
|
RuntimeHeaders["viaHandle"] = "viaHandle";
|
|
76
64
|
})(RuntimeHeaders || (RuntimeHeaders = {}));
|
|
@@ -81,7 +69,6 @@ export const TombstoneResponseHeaderKey = "isTombstoned";
|
|
|
81
69
|
/** Default values for Runtime Headers */
|
|
82
70
|
export const defaultRuntimeHeaderData = {
|
|
83
71
|
wait: true,
|
|
84
|
-
externalRequest: false,
|
|
85
72
|
viaHandle: false,
|
|
86
73
|
allowTombstone: false,
|
|
87
74
|
};
|
|
@@ -98,7 +85,13 @@ const defaultFlushMode = FlushMode.TurnBased;
|
|
|
98
85
|
// We can't estimate it fully, as we
|
|
99
86
|
// - do not know what properties relay service will add
|
|
100
87
|
// - we do not stringify final op, thus we do not know how much escaping will be added.
|
|
101
|
-
const defaultMaxBatchSizeInBytes =
|
|
88
|
+
const defaultMaxBatchSizeInBytes = 700 * 1024;
|
|
89
|
+
const defaultCompressionConfig = {
|
|
90
|
+
// Batches with content size exceeding this value will be compressed
|
|
91
|
+
minimumBatchSizeInBytes: 614400,
|
|
92
|
+
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
93
|
+
};
|
|
94
|
+
const defaultChunkSizeInBytes = 204800;
|
|
102
95
|
/**
|
|
103
96
|
* @deprecated - use ContainerRuntimeMessage instead
|
|
104
97
|
*/
|
|
@@ -145,8 +138,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
145
138
|
/**
|
|
146
139
|
* @internal
|
|
147
140
|
*/
|
|
148
|
-
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, requestHandler, summaryConfiguration) {
|
|
149
|
-
var _a, _b, _c, _d, _e, _f;
|
|
141
|
+
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, requestHandler, summaryConfiguration, initializeEntryPoint) {
|
|
142
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
150
143
|
if (summaryConfiguration === void 0) { summaryConfiguration = Object.assign(Object.assign({}, DefaultSummaryConfiguration), (_a = runtimeOptions.summaryOptions) === null || _a === void 0 ? void 0 : _a.summaryConfigOverrides); }
|
|
151
144
|
super();
|
|
152
145
|
this.context = context;
|
|
@@ -159,8 +152,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
159
152
|
this.summaryConfiguration = summaryConfiguration;
|
|
160
153
|
this.defaultMaxConsecutiveReconnects = 7;
|
|
161
154
|
this._orderSequentiallyCalls = 0;
|
|
162
|
-
this.
|
|
163
|
-
this.savedOps = [];
|
|
155
|
+
this.flushTaskExists = false;
|
|
164
156
|
this.consecutiveReconnects = 0;
|
|
165
157
|
this.ensureNoDataModelChangesCalls = 0;
|
|
166
158
|
/**
|
|
@@ -207,6 +199,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
207
199
|
throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
208
200
|
}
|
|
209
201
|
};
|
|
202
|
+
this.innerDeltaManager = context.deltaManager;
|
|
203
|
+
this.deltaManager = new DeltaManagerSummarizerProxy(context.deltaManager);
|
|
210
204
|
let loadSummaryNumber;
|
|
211
205
|
// Get the container creation metadata. For new container, we initialize these. For existing containers,
|
|
212
206
|
// get the values from the metadata blob.
|
|
@@ -229,29 +223,46 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
229
223
|
this.nextSummaryNumber = loadSummaryNumber + 1;
|
|
230
224
|
this.messageAtLastSummary = metadata === null || metadata === void 0 ? void 0 : metadata.message;
|
|
231
225
|
this._connected = this.context.connected;
|
|
226
|
+
this.gcTombstoneEnforcementAllowed = shouldAllowGcTombstoneEnforcement((_c = metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix) === null || _c === void 0 ? void 0 : _c.tombstoneGeneration /* persisted */, this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName] /* current */);
|
|
232
227
|
this.mc = loggerToMonitoringContext(ChildLogger.create(this.logger, "ContainerRuntime"));
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
:
|
|
236
|
-
|
|
228
|
+
this.mc.logger.sendTelemetryEvent({
|
|
229
|
+
eventName: "GCFeatureMatrix",
|
|
230
|
+
metadataValue: JSON.stringify(metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix),
|
|
231
|
+
inputs: JSON.stringify({
|
|
232
|
+
gcOptions_gcTombstoneGeneration: this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName],
|
|
233
|
+
}),
|
|
234
|
+
});
|
|
235
|
+
this.telemetryDocumentId = (_d = metadata === null || metadata === void 0 ? void 0 : metadata.telemetryDocumentId) !== null && _d !== void 0 ? _d : uuid();
|
|
236
|
+
this.disableAttachReorder = this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder");
|
|
237
|
+
const disableChunking = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionChunkingDisabled");
|
|
238
|
+
const opSplitter = new OpSplitter(chunks, this.context.submitBatchFn, disableChunking === true ? Number.POSITIVE_INFINITY : runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
|
|
239
|
+
this.remoteMessageProcessor = new RemoteMessageProcessor(opSplitter, new OpDecompressor(this.mc.logger));
|
|
237
240
|
this.handleContext = new ContainerFluidHandleContext("", this);
|
|
238
241
|
if (this.summaryConfiguration.state === "enabled") {
|
|
239
242
|
this.validateSummaryHeuristicConfiguration(this.summaryConfiguration);
|
|
240
243
|
}
|
|
244
|
+
const disableOpReentryCheck = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisableOpReentryCheck");
|
|
241
245
|
this.enableOpReentryCheck =
|
|
242
246
|
runtimeOptions.enableOpReentryCheck === true &&
|
|
243
247
|
// Allow for a break-glass config to override the options
|
|
244
|
-
|
|
248
|
+
disableOpReentryCheck !== true;
|
|
245
249
|
this.summariesDisabled = this.isSummariesDisabled();
|
|
246
250
|
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
247
251
|
this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
|
|
248
252
|
this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
|
|
249
253
|
this.maxConsecutiveReconnects =
|
|
250
|
-
(
|
|
251
|
-
|
|
254
|
+
(_e = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _e !== void 0 ? _e : this.defaultMaxConsecutiveReconnects;
|
|
255
|
+
if (runtimeOptions.flushMode === FlushModeExperimental.Async &&
|
|
256
|
+
((_f = context.supportedFeatures) === null || _f === void 0 ? void 0 : _f.get("referenceSequenceNumbers")) !== true) {
|
|
257
|
+
// The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
|
|
258
|
+
this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
|
|
259
|
+
this._flushMode = FlushMode.TurnBased;
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
this._flushMode = runtimeOptions.flushMode;
|
|
263
|
+
}
|
|
252
264
|
const pendingRuntimeState = context.pendingLocalState;
|
|
253
|
-
const
|
|
254
|
-
const maxSnapshotCacheDurationMs = (_f = (_e = this._storage) === null || _e === void 0 ? void 0 : _e.policies) === null || _f === void 0 ? void 0 : _f.maximumCacheDurationMs;
|
|
265
|
+
const maxSnapshotCacheDurationMs = (_h = (_g = this._storage) === null || _g === void 0 ? void 0 : _g.policies) === null || _h === void 0 ? void 0 : _h.maximumCacheDurationMs;
|
|
255
266
|
if (maxSnapshotCacheDurationMs !== undefined &&
|
|
256
267
|
maxSnapshotCacheDurationMs > 5 * 24 * 60 * 60 * 1000) {
|
|
257
268
|
// This is a runtime enforcement of what's already explicit in the policy's type itself,
|
|
@@ -262,7 +273,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
262
273
|
this.garbageCollector = GarbageCollector.create({
|
|
263
274
|
runtime: this,
|
|
264
275
|
gcOptions: this.runtimeOptions.gcOptions,
|
|
265
|
-
baseSnapshot,
|
|
276
|
+
baseSnapshot: context.baseSnapshot,
|
|
266
277
|
baseLogger: this.mc.logger,
|
|
267
278
|
existing,
|
|
268
279
|
metadata,
|
|
@@ -272,7 +283,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
272
283
|
getLastSummaryTimestampMs: () => { var _a; return (_a = this.messageAtLastSummary) === null || _a === void 0 ? void 0 : _a.timestamp; },
|
|
273
284
|
readAndParseBlob: async (id) => readAndParse(this.storage, id),
|
|
274
285
|
getContainerDiagnosticId: () => this.context.id,
|
|
275
|
-
|
|
286
|
+
// GC runs in summarizer client and needs access to the real (non-proxy) active information. The proxy
|
|
287
|
+
// delta manager would always return false for summarizer client.
|
|
288
|
+
activeConnection: () => this.innerDeltaManager.active,
|
|
276
289
|
});
|
|
277
290
|
const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
|
|
278
291
|
this.summarizerNode = createRootSummarizerNodeWithGC(ChildLogger.create(this.logger, "SummarizerNode"),
|
|
@@ -281,7 +294,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
281
294
|
// Latest change sequence number, no changes since summary applied yet
|
|
282
295
|
loadedFromSequenceNumber,
|
|
283
296
|
// Summary reference sequence number, undefined if no summary yet
|
|
284
|
-
baseSnapshot ? loadedFromSequenceNumber : undefined, {
|
|
297
|
+
context.baseSnapshot ? loadedFromSequenceNumber : undefined, {
|
|
285
298
|
// Must set to false to prevent sending summary handle which would be pointing to
|
|
286
299
|
// a summary with an older protocol state.
|
|
287
300
|
canReuseHandle: false,
|
|
@@ -295,10 +308,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
295
308
|
async (fullGC) => this.getGCDataInternal(fullGC),
|
|
296
309
|
// Function to get the GC details from the base snapshot we loaded from.
|
|
297
310
|
async () => this.garbageCollector.getBaseGCDetails());
|
|
298
|
-
if (baseSnapshot) {
|
|
299
|
-
this.summarizerNode.updateBaseSummaryState(baseSnapshot);
|
|
311
|
+
if (context.baseSnapshot) {
|
|
312
|
+
this.summarizerNode.updateBaseSummaryState(context.baseSnapshot);
|
|
300
313
|
}
|
|
301
|
-
this.dataStores = new DataStores(getSummaryForDatastores(baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn
|
|
314
|
+
this.dataStores = new DataStores(getSummaryForDatastores(context.baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), (path) => this.garbageCollector.isNodeDeleted(path), new Map(dataStoreAliasMap));
|
|
302
315
|
this.blobManager = new BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (localId, blobId) => {
|
|
303
316
|
if (!this.disposed) {
|
|
304
317
|
this.submit(ContainerMessageType.BlobAttach, undefined, undefined, {
|
|
@@ -306,7 +319,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
306
319
|
blobId,
|
|
307
320
|
});
|
|
308
321
|
}
|
|
309
|
-
}, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (
|
|
322
|
+
}, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (blobPath) => this.garbageCollector.isNodeDeleted(blobPath), this, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pendingAttachmentBlobs, () => this.getCurrentReferenceTimestampMs());
|
|
310
323
|
this.scheduleManager = new ScheduleManager(context.deltaManager, this, () => this.clientId, ChildLogger.create(this.logger, "ScheduleManager"));
|
|
311
324
|
this.pendingStateManager = new PendingStateManager({
|
|
312
325
|
applyStashedOp: this.applyStashedOp.bind(this),
|
|
@@ -317,12 +330,14 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
317
330
|
rollback: this.rollback.bind(this),
|
|
318
331
|
orderSequentially: this.orderSequentially.bind(this),
|
|
319
332
|
}, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pending);
|
|
320
|
-
const
|
|
333
|
+
const disableCompression = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionDisabled");
|
|
334
|
+
const compressionOptions = disableCompression === true
|
|
321
335
|
? {
|
|
322
336
|
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
323
337
|
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
324
338
|
}
|
|
325
339
|
: runtimeOptions.compressionOptions;
|
|
340
|
+
const disablePartialFlush = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisablePartialFlush");
|
|
326
341
|
this.outbox = new Outbox({
|
|
327
342
|
shouldSend: () => this.canSendOps(),
|
|
328
343
|
pendingStateManager: this.pendingStateManager,
|
|
@@ -332,7 +347,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
332
347
|
config: {
|
|
333
348
|
compressionOptions,
|
|
334
349
|
maxBatchSizeInBytes: runtimeOptions.maxBatchSizeInBytes,
|
|
335
|
-
|
|
350
|
+
disablePartialFlush: disablePartialFlush === true,
|
|
336
351
|
},
|
|
337
352
|
logger: this.mc.logger,
|
|
338
353
|
});
|
|
@@ -353,7 +368,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
353
368
|
const orderedClientElectionForSummarizer = new OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData !== null && electedSummarizerData !== void 0 ? electedSummarizerData : this.context.deltaManager.lastSequenceNumber, SummarizerClientElection.isClientEligible);
|
|
354
369
|
this.summarizerClientElection = new SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary);
|
|
355
370
|
if (this.context.clientDetails.type === summarizerClientType) {
|
|
356
|
-
this._summarizer = new Summarizer(
|
|
371
|
+
this._summarizer = new Summarizer(this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => RunWhileConnectedCoordinator.create(runtime,
|
|
372
|
+
// Summarization runs in summarizer client and needs access to the real (non-proxy) active
|
|
373
|
+
// information. The proxy delta manager would always return false for summarizer client.
|
|
374
|
+
() => this.innerDeltaManager.active));
|
|
357
375
|
}
|
|
358
376
|
else if (SummarizerClientElection.clientDetailsPermitElection(this.context.clientDetails)) {
|
|
359
377
|
// Only create a SummaryManager and SummarizerClientElection
|
|
@@ -388,7 +406,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
388
406
|
this.deltaManager.on("readonly", (readonly) => {
|
|
389
407
|
// we accumulate ops while being in read-only state.
|
|
390
408
|
// once user gets write permissions and we have active connection, flush all pending ops.
|
|
391
|
-
|
|
409
|
+
// Note that the inner (non-proxy) delta manager is needed here to get the readonly information.
|
|
410
|
+
assert(readonly === this.innerDeltaManager.readOnlyInfo.readonly, 0x124 /* "inconsistent readonly property/event state" */);
|
|
392
411
|
// We need to be very careful with when we (re)send pending ops, to ensure that we only send ops
|
|
393
412
|
// when we either never send an op, or attempted to send it but we know for sure it was not
|
|
394
413
|
// sequenced by server and will never be sequenced (i.e. was lost)
|
|
@@ -406,9 +425,22 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
406
425
|
});
|
|
407
426
|
// logging hardware telemetry
|
|
408
427
|
logger.sendTelemetryEvent(Object.assign({ eventName: "DeviceSpec" }, getDeviceSpec()));
|
|
409
|
-
this.logger.sendTelemetryEvent(Object.assign(Object.assign(Object.assign({ eventName: "ContainerLoadStats" }, this.createContainerMetadata), this.dataStores.containerLoadStats), { summaryNumber: loadSummaryNumber, summaryFormatVersion: metadata === null || metadata === void 0 ? void 0 : metadata.summaryFormatVersion, disableIsolatedChannels: metadata === null || metadata === void 0 ? void 0 : metadata.disableIsolatedChannels, gcVersion: metadata === null || metadata === void 0 ? void 0 : metadata.gcFeature
|
|
428
|
+
this.logger.sendTelemetryEvent(Object.assign(Object.assign(Object.assign({ eventName: "ContainerLoadStats" }, this.createContainerMetadata), this.dataStores.containerLoadStats), { summaryNumber: loadSummaryNumber, summaryFormatVersion: metadata === null || metadata === void 0 ? void 0 : metadata.summaryFormatVersion, disableIsolatedChannels: metadata === null || metadata === void 0 ? void 0 : metadata.disableIsolatedChannels, gcVersion: metadata === null || metadata === void 0 ? void 0 : metadata.gcFeature, options: JSON.stringify(runtimeOptions), featureGates: JSON.stringify({
|
|
429
|
+
disableCompression,
|
|
430
|
+
disableOpReentryCheck,
|
|
431
|
+
disableChunking,
|
|
432
|
+
disableAttachReorder: this.disableAttachReorder,
|
|
433
|
+
disablePartialFlush,
|
|
434
|
+
}), telemetryDocumentId: this.telemetryDocumentId }));
|
|
410
435
|
ReportOpPerfTelemetry(this.context.clientId, this.deltaManager, this.logger);
|
|
411
436
|
BindBatchTracker(this, this.logger);
|
|
437
|
+
this.entryPoint = new LazyPromise(async () => {
|
|
438
|
+
if (this.context.clientDetails.type === summarizerClientType) {
|
|
439
|
+
assert(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
|
|
440
|
+
return this._summarizer;
|
|
441
|
+
}
|
|
442
|
+
return initializeEntryPoint === null || initializeEntryPoint === void 0 ? void 0 : initializeEntryPoint(this);
|
|
443
|
+
});
|
|
412
444
|
}
|
|
413
445
|
get IContainerRuntime() {
|
|
414
446
|
return this;
|
|
@@ -446,17 +478,20 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
446
478
|
* Load the stores from a snapshot and returns the runtime.
|
|
447
479
|
* @param params - An object housing the runtime properties:
|
|
448
480
|
* - context - Context of the container.
|
|
449
|
-
* - registryEntries - Mapping to
|
|
450
|
-
* - existing -
|
|
451
|
-
* - requestHandler - Request
|
|
481
|
+
* - registryEntries - Mapping from data store types to their corresponding factories.
|
|
482
|
+
* - existing - Pass 'true' if loading from an existing snapshot.
|
|
483
|
+
* - requestHandler - (optional) Request handler for the request() method of the container runtime.
|
|
484
|
+
* Only relevant for back-compat while we remove the request() method and move fully to entryPoint as the main pattern.
|
|
452
485
|
* - runtimeOptions - Additional options to be passed to the runtime
|
|
453
486
|
* - containerScope - runtime services provided with context
|
|
454
487
|
* - containerRuntimeCtor - Constructor to use to create the ContainerRuntime instance.
|
|
455
488
|
* This allows mixin classes to leverage this method to define their own async initializer.
|
|
489
|
+
* - initializeEntryPoint - Promise that resolves to an object which will act as entryPoint for the Container.
|
|
490
|
+
* This object should provide all the functionality that the Container is expected to provide to the loader layer.
|
|
456
491
|
*/
|
|
457
492
|
static async loadRuntime(params) {
|
|
458
493
|
var _a, _b, _c, _d;
|
|
459
|
-
const { context, registryEntries, existing, requestHandler, runtimeOptions = {}, containerScope = {}, containerRuntimeCtor = ContainerRuntime, } = params;
|
|
494
|
+
const { context, registryEntries, existing, requestHandler, runtimeOptions = {}, containerScope = {}, containerRuntimeCtor = ContainerRuntime, initializeEntryPoint, } = params;
|
|
460
495
|
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
461
496
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
462
497
|
const backCompatContext = context;
|
|
@@ -466,25 +501,16 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
466
501
|
runtimeVersion: pkgVersion,
|
|
467
502
|
},
|
|
468
503
|
});
|
|
469
|
-
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode,
|
|
470
|
-
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
471
|
-
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
472
|
-
}, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, chunkSizeInBytes = Number.POSITIVE_INFINITY, enableOpReentryCheck = false, } = runtimeOptions;
|
|
473
|
-
const pendingRuntimeState = context.pendingLocalState;
|
|
474
|
-
const baseSnapshot = (_b = pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.baseSnapshot) !== null && _b !== void 0 ? _b : context.baseSnapshot;
|
|
475
|
-
const storage = !pendingRuntimeState
|
|
476
|
-
? context.storage
|
|
477
|
-
: new SerializedSnapshotStorage(() => {
|
|
478
|
-
return context.storage;
|
|
479
|
-
}, pendingRuntimeState.snapshotBlobs);
|
|
504
|
+
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, } = runtimeOptions;
|
|
480
505
|
const registry = new FluidDataStoreRegistry(registryEntries);
|
|
481
506
|
const tryFetchBlob = async (blobName) => {
|
|
482
|
-
|
|
483
|
-
|
|
507
|
+
var _a;
|
|
508
|
+
const blobId = (_a = context.baseSnapshot) === null || _a === void 0 ? void 0 : _a.blobs[blobName];
|
|
509
|
+
if (context.baseSnapshot && blobId) {
|
|
484
510
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
485
511
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
486
|
-
assert(storage !== undefined, 0x1f5 /* "Attached state should have storage" */);
|
|
487
|
-
return readAndParse(storage, blobId);
|
|
512
|
+
assert(context.storage !== undefined, 0x1f5 /* "Attached state should have storage" */);
|
|
513
|
+
return readAndParse(context.storage, blobId);
|
|
488
514
|
}
|
|
489
515
|
};
|
|
490
516
|
const [chunks, metadata, electedSummarizerData, aliases] = await Promise.all([
|
|
@@ -495,16 +521,16 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
495
521
|
]);
|
|
496
522
|
const loadExisting = existing === true || context.existing === true;
|
|
497
523
|
// read snapshot blobs needed for BlobManager to load
|
|
498
|
-
const blobManagerSnapshot = await BlobManager.load(baseSnapshot === null ||
|
|
524
|
+
const blobManagerSnapshot = await BlobManager.load((_b = context.baseSnapshot) === null || _b === void 0 ? void 0 : _b.trees[blobsTreeName], async (id) => {
|
|
499
525
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
500
526
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
501
|
-
assert(storage !== undefined, 0x256 /* "storage undefined in attached container" */);
|
|
502
|
-
return readAndParse(storage, id);
|
|
527
|
+
assert(context.storage !== undefined, 0x256 /* "storage undefined in attached container" */);
|
|
528
|
+
return readAndParse(context.storage, id);
|
|
503
529
|
});
|
|
504
530
|
// Verify summary runtime sequence number matches protocol sequence number.
|
|
505
531
|
const runtimeSequenceNumber = (_c = metadata === null || metadata === void 0 ? void 0 : metadata.message) === null || _c === void 0 ? void 0 : _c.sequenceNumber;
|
|
506
532
|
// When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
|
|
507
|
-
if (!
|
|
533
|
+
if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
|
|
508
534
|
const protocolSequenceNumber = context.deltaManager.initialSequenceNumber;
|
|
509
535
|
// Unless bypass is explicitly set, then take action when sequence numbers mismatch.
|
|
510
536
|
if (loadSequenceNumberVerification !== "bypass" &&
|
|
@@ -528,17 +554,15 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
528
554
|
gcOptions,
|
|
529
555
|
loadSequenceNumberVerification,
|
|
530
556
|
flushMode,
|
|
531
|
-
enableOfflineLoad,
|
|
532
557
|
compressionOptions,
|
|
533
558
|
maxBatchSizeInBytes,
|
|
534
559
|
chunkSizeInBytes,
|
|
535
560
|
enableOpReentryCheck,
|
|
536
|
-
}, containerScope, logger, loadExisting, blobManagerSnapshot, storage, requestHandler
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
}
|
|
561
|
+
}, containerScope, logger, loadExisting, blobManagerSnapshot, context.storage, requestHandler, undefined, // summaryConfiguration
|
|
562
|
+
initializeEntryPoint);
|
|
563
|
+
// It's possible to have ops with a reference sequence number of 0. Op sequence numbers start
|
|
564
|
+
// at 1, so we won't see a replayed saved op with a sequence number of 0.
|
|
565
|
+
await runtime.pendingStateManager.applyStashedOpsAt(0);
|
|
542
566
|
// Initialize the base state of the runtime before it's returned.
|
|
543
567
|
await runtime.initializeBaseState();
|
|
544
568
|
return runtime;
|
|
@@ -552,9 +576,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
552
576
|
get clientDetails() {
|
|
553
577
|
return this.context.clientDetails;
|
|
554
578
|
}
|
|
555
|
-
get deltaManager() {
|
|
556
|
-
return this.context.deltaManager;
|
|
557
|
-
}
|
|
558
579
|
get storage() {
|
|
559
580
|
return this._storage;
|
|
560
581
|
}
|
|
@@ -647,7 +668,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
647
668
|
* Initializes the state from the base snapshot this container runtime loaded from.
|
|
648
669
|
*/
|
|
649
670
|
async initializeBaseState() {
|
|
650
|
-
await this.initializeBaseSnapshotBlobs();
|
|
651
671
|
await this.garbageCollector.initializeBaseState();
|
|
652
672
|
}
|
|
653
673
|
dispose(error) {
|
|
@@ -672,16 +692,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
672
692
|
this.emit("dispose");
|
|
673
693
|
this.removeAllListeners();
|
|
674
694
|
}
|
|
675
|
-
get IFluidTokenProvider() {
|
|
676
|
-
var _a;
|
|
677
|
-
if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.intelligence) {
|
|
678
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
679
|
-
return {
|
|
680
|
-
intelligence: this.options.intelligence,
|
|
681
|
-
};
|
|
682
|
-
}
|
|
683
|
-
return undefined;
|
|
684
|
-
}
|
|
685
695
|
/**
|
|
686
696
|
* Notifies this object about the request made to the container.
|
|
687
697
|
* @param request - Request made to the handler.
|
|
@@ -744,12 +754,18 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
744
754
|
return exceptionToResponse(error);
|
|
745
755
|
}
|
|
746
756
|
}
|
|
757
|
+
/**
|
|
758
|
+
* {@inheritDoc @fluidframework/container-definitions#IRuntime.getEntryPoint}
|
|
759
|
+
*/
|
|
760
|
+
async getEntryPoint() {
|
|
761
|
+
return this.entryPoint;
|
|
762
|
+
}
|
|
747
763
|
internalId(maybeAlias) {
|
|
748
764
|
var _a;
|
|
749
765
|
return (_a = this.dataStores.aliases.get(maybeAlias)) !== null && _a !== void 0 ? _a : maybeAlias;
|
|
750
766
|
}
|
|
751
767
|
async getDataStoreFromRequest(id, request) {
|
|
752
|
-
var _a, _b, _c
|
|
768
|
+
var _a, _b, _c;
|
|
753
769
|
const headerData = {};
|
|
754
770
|
if (typeof ((_a = request.headers) === null || _a === void 0 ? void 0 : _a[RuntimeHeaders.wait]) === "boolean") {
|
|
755
771
|
headerData.wait = request.headers[RuntimeHeaders.wait];
|
|
@@ -763,23 +779,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
763
779
|
await this.dataStores.waitIfPendingAlias(id);
|
|
764
780
|
const internalId = this.internalId(id);
|
|
765
781
|
const dataStoreContext = await this.dataStores.getDataStore(internalId, headerData);
|
|
766
|
-
/**
|
|
767
|
-
* If GC should run and this an external app request with "externalRequest" header, we need to return
|
|
768
|
-
* an error if the data store being requested is marked as unreferenced as per the data store's base
|
|
769
|
-
* GC data.
|
|
770
|
-
*
|
|
771
|
-
* This is a workaround to handle scenarios where a data store shared with an external app is deleted
|
|
772
|
-
* and marked as unreferenced by GC. Returning an error will fail to load the data store for the app.
|
|
773
|
-
*/
|
|
774
|
-
if (((_d = request.headers) === null || _d === void 0 ? void 0 : _d[RuntimeHeaders.externalRequest]) &&
|
|
775
|
-
this.garbageCollector.shouldRunGC) {
|
|
776
|
-
// The data store is referenced if used routes in the base summary has a route to self.
|
|
777
|
-
// Older documents may not have used routes in the summary. They are considered referenced.
|
|
778
|
-
const usedRoutes = (await dataStoreContext.getBaseGCDetails()).usedRoutes;
|
|
779
|
-
if (!(usedRoutes === undefined || usedRoutes.includes("") || usedRoutes.includes("/"))) {
|
|
780
|
-
throw responseToException(create404Response(request), request);
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
782
|
const dataStoreChannel = await dataStoreContext.realize();
|
|
784
783
|
// Remove query params, leading and trailing slashes from the url. This is done to make sure the format is
|
|
785
784
|
// the same as GC nodes id.
|
|
@@ -795,7 +794,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
795
794
|
summaryNumber: this.nextSummaryNumber++, summaryFormatVersion: 1 }), this.garbageCollector.getMetadata()), {
|
|
796
795
|
// The last message processed at the time of summary. If there are no new messages, use the message from the
|
|
797
796
|
// last summary.
|
|
798
|
-
message: (_a = extractSummaryMetadataMessage(this.deltaManager.lastMessage)) !== null && _a !== void 0 ? _a : this.messageAtLastSummary });
|
|
797
|
+
message: (_a = extractSummaryMetadataMessage(this.deltaManager.lastMessage)) !== null && _a !== void 0 ? _a : this.messageAtLastSummary, telemetryDocumentId: this.telemetryDocumentId });
|
|
799
798
|
addBlobToSummary(summaryTree, metadataBlobName, JSON.stringify(metadata));
|
|
800
799
|
}
|
|
801
800
|
addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
|
|
@@ -911,7 +910,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
911
910
|
// If attachment blobs were added while disconnected, we need to delay
|
|
912
911
|
// propagation of the "connected" event until we have uploaded them to
|
|
913
912
|
// ensure we don't submit ops referencing a blob that has not been uploaded
|
|
914
|
-
|
|
913
|
+
// Note that the inner (non-proxy) delta manager is needed here to get the readonly information.
|
|
914
|
+
const connecting = connected && !this._connected && !this.innerDeltaManager.readOnlyInfo.readonly;
|
|
915
915
|
if (connecting && this.blobManager.hasPendingOfflineUploads) {
|
|
916
916
|
assert(!this.delayConnectClientId, 0x392 /* Connect event delay must be canceled before subsequent connect event */);
|
|
917
917
|
assert(!!clientId, 0x393 /* Must have clientId when connecting */);
|
|
@@ -961,12 +961,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
961
961
|
this.garbageCollector.setConnectionState(connected, clientId);
|
|
962
962
|
raiseConnectedEvent(this.mc.logger, this, connected, clientId);
|
|
963
963
|
}
|
|
964
|
+
async notifyOpReplay(message) {
|
|
965
|
+
await this.pendingStateManager.applyStashedOpsAt(message.sequenceNumber);
|
|
966
|
+
}
|
|
964
967
|
process(messageArg, local) {
|
|
965
968
|
var _a;
|
|
966
969
|
this.verifyNotClosed();
|
|
967
|
-
if ((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad) {
|
|
968
|
-
this.savedOps.push(messageArg);
|
|
969
|
-
}
|
|
970
970
|
// Whether or not the message is actually a runtime message.
|
|
971
971
|
// It may be a legacy runtime message (ie already unpacked and ContainerMessageType)
|
|
972
972
|
// or something different, like a system message.
|
|
@@ -1006,7 +1006,19 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1006
1006
|
case ContainerMessageType.Rejoin:
|
|
1007
1007
|
break;
|
|
1008
1008
|
default:
|
|
1009
|
-
|
|
1009
|
+
if (runtimeMessage) {
|
|
1010
|
+
const error = DataProcessingError.create(
|
|
1011
|
+
// Former assert 0x3ce
|
|
1012
|
+
"Runtime message of unknown type", "OpProcessing", message, {
|
|
1013
|
+
local,
|
|
1014
|
+
type: message.type,
|
|
1015
|
+
contentType: typeof message.contents,
|
|
1016
|
+
batch: (_a = message.metadata) === null || _a === void 0 ? void 0 : _a.batch,
|
|
1017
|
+
compression: message.compression,
|
|
1018
|
+
});
|
|
1019
|
+
this.closeFn(error);
|
|
1020
|
+
throw error;
|
|
1021
|
+
}
|
|
1010
1022
|
}
|
|
1011
1023
|
// For back-compat, notify only about runtime messages for now.
|
|
1012
1024
|
if (runtimeMessage) {
|
|
@@ -1067,7 +1079,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1067
1079
|
}
|
|
1068
1080
|
else if (envelope.clientSignalSequenceNumber ===
|
|
1069
1081
|
this._perfSignalData.trackingSignalSequenceNumber) {
|
|
1070
|
-
|
|
1082
|
+
// only logging for the first connection and the trackingSignalSequenceNUmber.
|
|
1083
|
+
if (this.consecutiveReconnects === 0) {
|
|
1084
|
+
this.sendSignalTelemetryEvent(envelope.clientSignalSequenceNumber);
|
|
1085
|
+
}
|
|
1071
1086
|
this._perfSignalData.trackingSignalSequenceNumber = undefined;
|
|
1072
1087
|
}
|
|
1073
1088
|
}
|
|
@@ -1164,13 +1179,15 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1164
1179
|
.realize();
|
|
1165
1180
|
}
|
|
1166
1181
|
canSendOps() {
|
|
1167
|
-
|
|
1182
|
+
// Note that the real (non-proxy) delta manager is needed here to get the readonly info. This is because
|
|
1183
|
+
// container runtime's ability to send ops depend on the actual readonly state of the delta manager.
|
|
1184
|
+
return this.connected && !this.innerDeltaManager.readOnlyInfo.readonly;
|
|
1168
1185
|
}
|
|
1169
1186
|
/**
|
|
1170
1187
|
* Are we in the middle of batching ops together?
|
|
1171
1188
|
*/
|
|
1172
1189
|
currentlyBatching() {
|
|
1173
|
-
return this.flushMode
|
|
1190
|
+
return this.flushMode !== FlushMode.Immediate || this._orderSequentiallyCalls !== 0;
|
|
1174
1191
|
}
|
|
1175
1192
|
getQuorum() {
|
|
1176
1193
|
return this.context.quorum;
|
|
@@ -1286,11 +1303,19 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1286
1303
|
async summarize(options) {
|
|
1287
1304
|
this.verifyNotClosed();
|
|
1288
1305
|
const { fullTree = false, trackState = true, summaryLogger = this.mc.logger, runGC = this.garbageCollector.shouldRunGC, runSweep, fullGC, } = options;
|
|
1306
|
+
const telemetryContext = new TelemetryContext();
|
|
1307
|
+
// Add the options that are used to generate this summary to the telemetry context.
|
|
1308
|
+
telemetryContext.setMultiple("fluid_Summarize", "Options", {
|
|
1309
|
+
fullTree,
|
|
1310
|
+
trackState,
|
|
1311
|
+
runGC,
|
|
1312
|
+
fullGC,
|
|
1313
|
+
runSweep,
|
|
1314
|
+
});
|
|
1289
1315
|
let gcStats;
|
|
1290
1316
|
if (runGC) {
|
|
1291
|
-
gcStats = await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC });
|
|
1317
|
+
gcStats = await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC }, telemetryContext);
|
|
1292
1318
|
}
|
|
1293
|
-
const telemetryContext = new TelemetryContext();
|
|
1294
1319
|
const { stats, summary } = await this.summarizerNode.summarize(fullTree, trackState, telemetryContext);
|
|
1295
1320
|
this.logger.sendTelemetryEvent({
|
|
1296
1321
|
eventName: "SummarizeTelemetry",
|
|
@@ -1300,10 +1325,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1300
1325
|
return { stats, summary, gcStats };
|
|
1301
1326
|
}
|
|
1302
1327
|
/**
|
|
1303
|
-
* Implementation of IGarbageCollectionRuntime::updateStateBeforeGC.
|
|
1304
1328
|
* Before GC runs, called by the garbage collector to update any pending GC state. This is mainly used to notify
|
|
1305
1329
|
* the garbage collector of references detected since the last GC run. Most references are notified immediately
|
|
1306
1330
|
* but there can be some for which async operation is required (such as detecting new root data stores).
|
|
1331
|
+
* @see IGarbageCollectionRuntime.updateStateBeforeGC
|
|
1307
1332
|
*/
|
|
1308
1333
|
async updateStateBeforeGC() {
|
|
1309
1334
|
return this.dataStores.updateStateBeforeGC();
|
|
@@ -1312,9 +1337,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1312
1337
|
return this.dataStores.getGCData(fullGC);
|
|
1313
1338
|
}
|
|
1314
1339
|
/**
|
|
1315
|
-
* Implementation of IGarbageCollectionRuntime::getGCData.
|
|
1316
1340
|
* Generates and returns the GC data for this container.
|
|
1317
1341
|
* @param fullGC - true to bypass optimizations and force full generation of GC data.
|
|
1342
|
+
* @see IGarbageCollectionRuntime.getGCData
|
|
1318
1343
|
*/
|
|
1319
1344
|
async getGCData(fullGC) {
|
|
1320
1345
|
const builder = new GCDataBuilder();
|
|
@@ -1325,9 +1350,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1325
1350
|
return builder.getGCData();
|
|
1326
1351
|
}
|
|
1327
1352
|
/**
|
|
1328
|
-
* Implementation of IGarbageCollectionRuntime::updateUsedRoutes.
|
|
1329
1353
|
* After GC has run, called to notify this container's nodes of routes that are used in it.
|
|
1330
1354
|
* @param usedRoutes - The routes that are used in all nodes in this Container.
|
|
1355
|
+
* @see IGarbageCollectionRuntime.updateUsedRoutes
|
|
1331
1356
|
*/
|
|
1332
1357
|
updateUsedRoutes(usedRoutes) {
|
|
1333
1358
|
// Update our summarizer node's used routes. Updating used routes in summarizer node before
|
|
@@ -1346,6 +1371,22 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1346
1371
|
this.blobManager.updateUnusedRoutes(blobManagerRoutes);
|
|
1347
1372
|
this.dataStores.updateUnusedRoutes(dataStoreRoutes);
|
|
1348
1373
|
}
|
|
1374
|
+
/**
|
|
1375
|
+
* @deprecated - Replaced by deleteSweepReadyNodes.
|
|
1376
|
+
*/
|
|
1377
|
+
deleteUnusedNodes(unusedRoutes) {
|
|
1378
|
+
throw new Error("deleteUnusedRoutes should not be called");
|
|
1379
|
+
}
|
|
1380
|
+
/**
|
|
1381
|
+
* After GC has run and identified nodes that are sweep ready, this is called to delete the sweep ready nodes.
|
|
1382
|
+
* @param sweepReadyRoutes - The routes of nodes that are sweep ready and should be deleted.
|
|
1383
|
+
* @returns - The routes of nodes that were deleted.
|
|
1384
|
+
*/
|
|
1385
|
+
deleteSweepReadyNodes(sweepReadyRoutes) {
|
|
1386
|
+
const { dataStoreRoutes, blobManagerRoutes } = this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
|
|
1387
|
+
const deletedRoutes = this.dataStores.deleteSweepReadyNodes(dataStoreRoutes);
|
|
1388
|
+
return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
|
|
1389
|
+
}
|
|
1349
1390
|
/**
|
|
1350
1391
|
* This is called to update objects that are tombstones.
|
|
1351
1392
|
* @param tombstonedRoutes - Data store and attachment blob routes that are tombstones in this Container.
|
|
@@ -1423,8 +1464,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1423
1464
|
* Runs garbage collection and updates the reference / used state of the nodes in the container.
|
|
1424
1465
|
* @returns the statistics of the garbage collection run; undefined if GC did not run.
|
|
1425
1466
|
*/
|
|
1426
|
-
async collectGarbage(options) {
|
|
1427
|
-
return this.garbageCollector.collectGarbage(options);
|
|
1467
|
+
async collectGarbage(options, telemetryContext) {
|
|
1468
|
+
return this.garbageCollector.collectGarbage(options, telemetryContext);
|
|
1428
1469
|
}
|
|
1429
1470
|
/**
|
|
1430
1471
|
* Called when a new outbound reference is added to another node. This is used by garbage collection to identify
|
|
@@ -1445,7 +1486,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1445
1486
|
*/
|
|
1446
1487
|
async submitSummary(options) {
|
|
1447
1488
|
var _a, _b;
|
|
1448
|
-
const { fullTree, refreshLatestAck, summaryLogger } = options;
|
|
1489
|
+
const { fullTree = false, refreshLatestAck, summaryLogger } = options;
|
|
1449
1490
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
1450
1491
|
// use it for all events logged during this summary.
|
|
1451
1492
|
const summaryNumber = this.nextSummaryNumber;
|
|
@@ -1461,8 +1502,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1461
1502
|
// We might need to catch up to the latest summary's reference sequence number before pausing.
|
|
1462
1503
|
await this.waitForDeltaManagerToCatchup(latestSnapshotRefSeq, summaryNumberLogger);
|
|
1463
1504
|
}
|
|
1505
|
+
const shouldPauseInboundSignal = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause") !== true;
|
|
1464
1506
|
try {
|
|
1465
1507
|
await this.deltaManager.inbound.pause();
|
|
1508
|
+
if (shouldPauseInboundSignal) {
|
|
1509
|
+
await this.deltaManager.inboundSignal.pause();
|
|
1510
|
+
}
|
|
1466
1511
|
const summaryRefSeqNum = this.deltaManager.lastSequenceNumber;
|
|
1467
1512
|
const minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
|
|
1468
1513
|
const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
|
|
@@ -1518,7 +1563,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1518
1563
|
const forcedFullTree = this.garbageCollector.summaryStateNeedsReset;
|
|
1519
1564
|
try {
|
|
1520
1565
|
summarizeResult = await this.summarize({
|
|
1521
|
-
fullTree: fullTree
|
|
1566
|
+
fullTree: fullTree || forcedFullTree,
|
|
1522
1567
|
trackState: true,
|
|
1523
1568
|
summaryLogger: summaryNumberLogger,
|
|
1524
1569
|
runGC: this.garbageCollector.shouldRunGC,
|
|
@@ -1607,7 +1652,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1607
1652
|
}
|
|
1608
1653
|
let clientSequenceNumber;
|
|
1609
1654
|
try {
|
|
1610
|
-
clientSequenceNumber = this.submitSummaryMessage(summaryMessage);
|
|
1655
|
+
clientSequenceNumber = this.submitSummaryMessage(summaryMessage, summaryRefSeqNum);
|
|
1611
1656
|
}
|
|
1612
1657
|
catch (error) {
|
|
1613
1658
|
return Object.assign(Object.assign({ stage: "upload" }, uploadData), { error });
|
|
@@ -1621,6 +1666,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1621
1666
|
this.summarizerNode.clearSummary();
|
|
1622
1667
|
// Restart the delta manager
|
|
1623
1668
|
this.deltaManager.inbound.resume();
|
|
1669
|
+
if (shouldPauseInboundSignal) {
|
|
1670
|
+
this.deltaManager.inboundSignal.resume();
|
|
1671
|
+
}
|
|
1624
1672
|
}
|
|
1625
1673
|
}
|
|
1626
1674
|
hasPendingMessages() {
|
|
@@ -1666,9 +1714,10 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1666
1714
|
this.verifyCanSubmitOps();
|
|
1667
1715
|
// There should be no ops in detached container state!
|
|
1668
1716
|
assert(this.attachState !== AttachState.Detached, 0x132 /* "sending ops in detached container" */);
|
|
1669
|
-
const
|
|
1670
|
-
|
|
1671
|
-
|
|
1717
|
+
const serializedContent = JSON.stringify({ type, contents });
|
|
1718
|
+
// Note that the real (non-proxy) delta manager is used here to get the readonly info. This is because
|
|
1719
|
+
// container runtime's ability to submit ops depend on the actual readonly state of the delta manager.
|
|
1720
|
+
if (this.innerDeltaManager.readOnlyInfo.readonly) {
|
|
1672
1721
|
this.logger.sendTelemetryEvent({
|
|
1673
1722
|
eventName: "SubmitOpInReadonly",
|
|
1674
1723
|
connected: this.connected,
|
|
@@ -1676,7 +1725,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1676
1725
|
}
|
|
1677
1726
|
const message = {
|
|
1678
1727
|
contents: serializedContent,
|
|
1679
|
-
deserializedContent,
|
|
1728
|
+
deserializedContent: JSON.parse(serializedContent),
|
|
1680
1729
|
metadata,
|
|
1681
1730
|
localOpMetadata,
|
|
1682
1731
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
@@ -1704,7 +1753,7 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1704
1753
|
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
1705
1754
|
if (this.currentlyBatching() &&
|
|
1706
1755
|
type === ContainerMessageType.Attach &&
|
|
1707
|
-
this.
|
|
1756
|
+
this.disableAttachReorder !== true) {
|
|
1708
1757
|
this.outbox.submitAttach(message);
|
|
1709
1758
|
}
|
|
1710
1759
|
else {
|
|
@@ -1713,17 +1762,8 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1713
1762
|
if (!this.currentlyBatching()) {
|
|
1714
1763
|
this.flush();
|
|
1715
1764
|
}
|
|
1716
|
-
else
|
|
1717
|
-
this.
|
|
1718
|
-
// Queue a microtask to detect the end of the turn and force a flush.
|
|
1719
|
-
Promise.resolve()
|
|
1720
|
-
.then(() => {
|
|
1721
|
-
this.flushMicroTaskExists = false;
|
|
1722
|
-
this.flush();
|
|
1723
|
-
})
|
|
1724
|
-
.catch((error) => {
|
|
1725
|
-
this.closeFn(error);
|
|
1726
|
-
});
|
|
1765
|
+
else {
|
|
1766
|
+
this.scheduleFlush();
|
|
1727
1767
|
}
|
|
1728
1768
|
}
|
|
1729
1769
|
catch (error) {
|
|
@@ -1734,14 +1774,47 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1734
1774
|
this.updateDocumentDirtyState(true);
|
|
1735
1775
|
}
|
|
1736
1776
|
}
|
|
1737
|
-
|
|
1777
|
+
scheduleFlush() {
|
|
1778
|
+
if (this.flushTaskExists) {
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1781
|
+
this.flushTaskExists = true;
|
|
1782
|
+
const flush = () => {
|
|
1783
|
+
this.flushTaskExists = false;
|
|
1784
|
+
try {
|
|
1785
|
+
this.flush();
|
|
1786
|
+
}
|
|
1787
|
+
catch (error) {
|
|
1788
|
+
this.closeFn(error);
|
|
1789
|
+
}
|
|
1790
|
+
};
|
|
1791
|
+
switch (this.flushMode) {
|
|
1792
|
+
case FlushMode.TurnBased:
|
|
1793
|
+
// When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
|
|
1794
|
+
// batch at the end of the turn
|
|
1795
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1796
|
+
Promise.resolve().then(flush);
|
|
1797
|
+
break;
|
|
1798
|
+
// FlushModeExperimental is experimental and not exposed directly in the runtime APIs
|
|
1799
|
+
case FlushModeExperimental.Async:
|
|
1800
|
+
// When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
|
|
1801
|
+
// batch when all micro-tasks are complete.
|
|
1802
|
+
// Compared to TurnBased, this flush mode will capture more ops into the same batch.
|
|
1803
|
+
setTimeout(flush, 0);
|
|
1804
|
+
break;
|
|
1805
|
+
default:
|
|
1806
|
+
assert(this._orderSequentiallyCalls > 0, 0x587 /* Unreachable unless running under orderSequentially */);
|
|
1807
|
+
break;
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
submitSummaryMessage(contents, referenceSequenceNumber) {
|
|
1738
1811
|
this.verifyNotClosed();
|
|
1739
1812
|
assert(this.connected, 0x133 /* "Container disconnected when trying to submit system message" */);
|
|
1740
1813
|
// System message should not be sent in the middle of the batch.
|
|
1741
1814
|
assert(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
|
|
1742
1815
|
// back-compat: ADO #1385: Make this call unconditional in the future
|
|
1743
1816
|
return this.context.submitSummaryFn !== undefined
|
|
1744
|
-
? this.context.submitSummaryFn(contents)
|
|
1817
|
+
? this.context.submitSummaryFn(contents, referenceSequenceNumber)
|
|
1745
1818
|
: this.context.submitFn(MessageType.Summarize, contents, false);
|
|
1746
1819
|
}
|
|
1747
1820
|
/**
|
|
@@ -1837,14 +1910,12 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1837
1910
|
// The call to fetch the snapshot is very expensive and not always needed.
|
|
1838
1911
|
// It should only be done by the summarizerNode, if required.
|
|
1839
1912
|
// When fetching from storage we will always get the latest version and do not use the ackHandle.
|
|
1840
|
-
const
|
|
1841
|
-
|
|
1842
|
-
eventName: "
|
|
1913
|
+
const fetchLatestSnapshot = async () => {
|
|
1914
|
+
let fetchResult = await this.fetchLatestSnapshotFromStorage(summaryLogger, {
|
|
1915
|
+
eventName: "RefreshLatestSummaryAckFetch",
|
|
1843
1916
|
ackHandle,
|
|
1844
|
-
summaryRefSeq,
|
|
1845
|
-
|
|
1846
|
-
});
|
|
1847
|
-
const latestSnapshotRefSeq = await seqFromTree(fetchResult.snapshotTree, readAndParseBlob);
|
|
1917
|
+
targetSequenceNumber: summaryRefSeq,
|
|
1918
|
+
}, readAndParseBlob);
|
|
1848
1919
|
/**
|
|
1849
1920
|
* If the fetched snapshot is older than the one for which the ack was received, close the container.
|
|
1850
1921
|
* This should never happen because an ack should be sent after the latest summary is updated in the server.
|
|
@@ -1855,29 +1926,34 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1855
1926
|
* such cases, the file will be rolled back along with the ack and we will eventually reach a consistent
|
|
1856
1927
|
* state.
|
|
1857
1928
|
*/
|
|
1858
|
-
if (latestSnapshotRefSeq < summaryRefSeq) {
|
|
1859
|
-
|
|
1929
|
+
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
1930
|
+
/* before failing, let's try to retrieve the latest snapshot for that specific ackHandle */
|
|
1931
|
+
fetchResult = await this.fetchSnapshotFromStorage(summaryLogger, {
|
|
1932
|
+
eventName: "RefreshLatestSummaryAckFetch",
|
|
1860
1933
|
ackHandle,
|
|
1861
|
-
summaryRefSeq,
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1934
|
+
targetSequenceNumber: summaryRefSeq,
|
|
1935
|
+
}, readAndParseBlob, ackHandle);
|
|
1936
|
+
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
1937
|
+
const error = DataProcessingError.create("Fetched snapshot is older than the received ack", "RefreshLatestSummaryAck", undefined /* sequencedMessage */, {
|
|
1938
|
+
ackHandle,
|
|
1939
|
+
summaryRefSeq,
|
|
1940
|
+
fetchedSnapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
1941
|
+
});
|
|
1942
|
+
this.closeFn(error);
|
|
1943
|
+
throw error;
|
|
1944
|
+
}
|
|
1866
1945
|
}
|
|
1867
|
-
summaryLogger.sendTelemetryEvent({
|
|
1868
|
-
eventName: "LatestSummaryRetrieved",
|
|
1869
|
-
ackHandle,
|
|
1870
|
-
lastSequenceNumber: latestSnapshotRefSeq,
|
|
1871
|
-
targetSequenceNumber: summaryRefSeq,
|
|
1872
|
-
});
|
|
1873
1946
|
// In case we had to retrieve the latest snapshot and it is different than summaryRefSeq,
|
|
1874
1947
|
// wait for the delta manager to catch up before refreshing the latest Summary.
|
|
1875
|
-
await this.waitForDeltaManagerToCatchup(latestSnapshotRefSeq, summaryLogger);
|
|
1876
|
-
return
|
|
1948
|
+
await this.waitForDeltaManagerToCatchup(fetchResult.latestSnapshotRefSeq, summaryLogger);
|
|
1949
|
+
return {
|
|
1950
|
+
snapshotTree: fetchResult.snapshotTree,
|
|
1951
|
+
snapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
1952
|
+
};
|
|
1877
1953
|
};
|
|
1878
|
-
const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq,
|
|
1954
|
+
const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq, fetchLatestSnapshot, readAndParseBlob, summaryLogger);
|
|
1879
1955
|
// Notify the garbage collector so it can update its latest summary state.
|
|
1880
|
-
await this.garbageCollector.refreshLatestSummary(
|
|
1956
|
+
await this.garbageCollector.refreshLatestSummary(proposalHandle, result, readAndParseBlob);
|
|
1881
1957
|
}
|
|
1882
1958
|
/**
|
|
1883
1959
|
* Fetches the latest snapshot from storage and uses it to refresh SummarizerNode's
|
|
@@ -1886,53 +1962,45 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1886
1962
|
* @returns downloaded snapshot's reference sequence number
|
|
1887
1963
|
*/
|
|
1888
1964
|
async refreshLatestSummaryAckFromServer(summaryLogger) {
|
|
1889
|
-
const { snapshotTree, versionId } = await this.fetchLatestSnapshotFromStorage(summaryLogger, {
|
|
1890
|
-
eventName: "RefreshLatestSummaryGetSnapshot",
|
|
1891
|
-
fetchLatest: true,
|
|
1892
|
-
});
|
|
1893
1965
|
const readAndParseBlob = async (id) => readAndParse(this.storage, id);
|
|
1894
|
-
const latestSnapshotRefSeq = await
|
|
1895
|
-
|
|
1966
|
+
const { snapshotTree, versionId, latestSnapshotRefSeq } = await this.fetchLatestSnapshotFromStorage(summaryLogger, {
|
|
1967
|
+
eventName: "RefreshLatestSummaryFromServerFetch",
|
|
1968
|
+
}, readAndParseBlob);
|
|
1969
|
+
const fetchLatestSnapshot = {
|
|
1970
|
+
snapshotTree,
|
|
1971
|
+
snapshotRefSeq: latestSnapshotRefSeq,
|
|
1972
|
+
};
|
|
1973
|
+
const result = await this.summarizerNode.refreshLatestSummary(undefined /* proposalHandle */, latestSnapshotRefSeq, async () => fetchLatestSnapshot, readAndParseBlob, summaryLogger);
|
|
1896
1974
|
// Notify the garbage collector so it can update its latest summary state.
|
|
1897
|
-
await this.garbageCollector.refreshLatestSummary(
|
|
1975
|
+
await this.garbageCollector.refreshLatestSummary(undefined /* proposalHandle */, result, readAndParseBlob);
|
|
1898
1976
|
return { latestSnapshotRefSeq, latestSnapshotVersionId: versionId };
|
|
1899
1977
|
}
|
|
1900
|
-
async fetchLatestSnapshotFromStorage(logger, event) {
|
|
1978
|
+
async fetchLatestSnapshotFromStorage(logger, event, readAndParseBlob) {
|
|
1979
|
+
return this.fetchSnapshotFromStorage(logger, event, readAndParseBlob, null /* latest */);
|
|
1980
|
+
}
|
|
1981
|
+
async fetchSnapshotFromStorage(logger, event, readAndParseBlob, versionId) {
|
|
1901
1982
|
return PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
|
|
1902
1983
|
const stats = {};
|
|
1903
1984
|
const trace = Trace.start();
|
|
1904
|
-
const versions = await this.storage.getVersions(
|
|
1985
|
+
const versions = await this.storage.getVersions(versionId, 1, "refreshLatestSummaryAckFromServer", versionId === null ? FetchSource.noCache : undefined);
|
|
1905
1986
|
assert(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
|
|
1906
1987
|
stats.getVersionDuration = trace.trace().duration;
|
|
1907
1988
|
const maybeSnapshot = await this.storage.getSnapshotTree(versions[0]);
|
|
1908
1989
|
assert(!!maybeSnapshot, 0x138 /* "Failed to get snapshot from storage" */);
|
|
1909
1990
|
stats.getSnapshotDuration = trace.trace().duration;
|
|
1991
|
+
const latestSnapshotRefSeq = await seqFromTree(maybeSnapshot, readAndParseBlob);
|
|
1992
|
+
stats.snapshotRefSeq = latestSnapshotRefSeq;
|
|
1993
|
+
stats.snapshotVersion = versions[0].id;
|
|
1910
1994
|
perfEvent.end(stats);
|
|
1911
|
-
return {
|
|
1995
|
+
return {
|
|
1996
|
+
snapshotTree: maybeSnapshot,
|
|
1997
|
+
versionId: versions[0].id,
|
|
1998
|
+
latestSnapshotRefSeq,
|
|
1999
|
+
};
|
|
1912
2000
|
});
|
|
1913
2001
|
}
|
|
1914
|
-
notifyAttaching(
|
|
1915
|
-
var _a;
|
|
1916
|
-
if ((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad) {
|
|
1917
|
-
this.baseSnapshotBlobs =
|
|
1918
|
-
SerializedSnapshotStorage.serializeTreeWithBlobContents(snapshot);
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
1921
|
-
async initializeBaseSnapshotBlobs() {
|
|
1922
|
-
var _a;
|
|
1923
|
-
if (!((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad) ||
|
|
1924
|
-
this.attachState !== AttachState.Attached ||
|
|
1925
|
-
this.context.pendingLocalState) {
|
|
1926
|
-
return;
|
|
1927
|
-
}
|
|
1928
|
-
assert(!!this.context.baseSnapshot, 0x2e5 /* "Must have a base snapshot" */);
|
|
1929
|
-
this.baseSnapshotBlobs = await SerializedSnapshotStorage.serializeTree(this.context.baseSnapshot, this.storage);
|
|
1930
|
-
}
|
|
2002
|
+
notifyAttaching() { } // do nothing (deprecated method)
|
|
1931
2003
|
getPendingLocalState() {
|
|
1932
|
-
var _a;
|
|
1933
|
-
if (!((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad)) {
|
|
1934
|
-
throw new UsageError("can't get state when offline load disabled");
|
|
1935
|
-
}
|
|
1936
2004
|
if (this._orderSequentiallyCalls !== 0) {
|
|
1937
2005
|
throw new UsageError("can't get state during orderSequentially");
|
|
1938
2006
|
}
|
|
@@ -1940,24 +2008,9 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1940
2008
|
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
1941
2009
|
// to close current batch.
|
|
1942
2010
|
this.flush();
|
|
1943
|
-
const previousPendingState = this.context.pendingLocalState;
|
|
1944
|
-
if (previousPendingState) {
|
|
1945
|
-
return {
|
|
1946
|
-
pending: this.pendingStateManager.getLocalState(),
|
|
1947
|
-
pendingAttachmentBlobs: this.blobManager.getPendingBlobs(),
|
|
1948
|
-
snapshotBlobs: previousPendingState.snapshotBlobs,
|
|
1949
|
-
baseSnapshot: previousPendingState.baseSnapshot,
|
|
1950
|
-
savedOps: this.savedOps,
|
|
1951
|
-
};
|
|
1952
|
-
}
|
|
1953
|
-
assert(!!this.context.baseSnapshot, 0x2e6 /* "Must have a base snapshot" */);
|
|
1954
|
-
assert(!!this.baseSnapshotBlobs, 0x2e7 /* "Must serialize base snapshot blobs before getting runtime state" */);
|
|
1955
2011
|
return {
|
|
1956
2012
|
pending: this.pendingStateManager.getLocalState(),
|
|
1957
2013
|
pendingAttachmentBlobs: this.blobManager.getPendingBlobs(),
|
|
1958
|
-
snapshotBlobs: this.baseSnapshotBlobs,
|
|
1959
|
-
baseSnapshot: this.context.baseSnapshot,
|
|
1960
|
-
savedOps: this.savedOps,
|
|
1961
2014
|
};
|
|
1962
2015
|
}
|
|
1963
2016
|
/**
|
|
@@ -1986,20 +2039,6 @@ export class ContainerRuntime extends TypedEventEmitter {
|
|
|
1986
2039
|
return summarizer;
|
|
1987
2040
|
};
|
|
1988
2041
|
}
|
|
1989
|
-
async processSavedOps(state) {
|
|
1990
|
-
for (const op of state.savedOps) {
|
|
1991
|
-
this.process(op, false);
|
|
1992
|
-
await this.pendingStateManager.applyStashedOpsAt(op.sequenceNumber);
|
|
1993
|
-
}
|
|
1994
|
-
// we may not have seen every sequence number (because of system ops) so apply everything once we
|
|
1995
|
-
// don't have any more saved ops
|
|
1996
|
-
await this.pendingStateManager.applyStashedOpsAt();
|
|
1997
|
-
// If it's not the case, we should take it into account when calculating dirty state.
|
|
1998
|
-
assert(this.context.attachState === AttachState.Attached, 0x3d5 /* this function is called for attached containers only */);
|
|
1999
|
-
if (!this.hasPendingMessages()) {
|
|
2000
|
-
this.updateDocumentDirtyState(false);
|
|
2001
|
-
}
|
|
2002
|
-
}
|
|
2003
2042
|
validateSummaryHeuristicConfiguration(configuration) {
|
|
2004
2043
|
// eslint-disable-next-line no-restricted-syntax
|
|
2005
2044
|
for (const prop in configuration) {
|