@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/src/containerRuntime.ts
CHANGED
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
} from "@fluidframework/core-interfaces";
|
|
18
18
|
import {
|
|
19
19
|
IAudience,
|
|
20
|
-
IFluidTokenProvider,
|
|
21
20
|
IContainerContext,
|
|
22
21
|
IDeltaManager,
|
|
23
22
|
IRuntime,
|
|
@@ -25,13 +24,18 @@ import {
|
|
|
25
24
|
AttachState,
|
|
26
25
|
ILoaderOptions,
|
|
27
26
|
LoaderHeader,
|
|
28
|
-
ISnapshotTreeWithBlobContents,
|
|
29
27
|
} from "@fluidframework/container-definitions";
|
|
30
28
|
import {
|
|
31
29
|
IContainerRuntime,
|
|
32
30
|
IContainerRuntimeEvents,
|
|
33
31
|
} from "@fluidframework/container-runtime-definitions";
|
|
34
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
assert,
|
|
34
|
+
LazyPromise,
|
|
35
|
+
Trace,
|
|
36
|
+
TypedEventEmitter,
|
|
37
|
+
unreachableCase,
|
|
38
|
+
} from "@fluidframework/common-utils";
|
|
35
39
|
import {
|
|
36
40
|
ChildLogger,
|
|
37
41
|
raiseConnectedEvent,
|
|
@@ -68,13 +72,13 @@ import {
|
|
|
68
72
|
} from "@fluidframework/protocol-definitions";
|
|
69
73
|
import {
|
|
70
74
|
FlushMode,
|
|
75
|
+
FlushModeExperimental,
|
|
71
76
|
gcTreeKey,
|
|
72
77
|
InboundAttachMessage,
|
|
73
78
|
IFluidDataStoreContextDetached,
|
|
74
79
|
IFluidDataStoreRegistry,
|
|
75
80
|
IFluidDataStoreChannel,
|
|
76
81
|
IGarbageCollectionData,
|
|
77
|
-
IGarbageCollectionDetailsBase,
|
|
78
82
|
IEnvelope,
|
|
79
83
|
IInboundSignalMessage,
|
|
80
84
|
ISignalEnvelope,
|
|
@@ -92,23 +96,19 @@ import {
|
|
|
92
96
|
addBlobToSummary,
|
|
93
97
|
addSummarizeResultToSummary,
|
|
94
98
|
addTreeToSummary,
|
|
95
|
-
createRootSummarizerNodeWithGC,
|
|
96
|
-
IRootSummarizerNodeWithGC,
|
|
97
99
|
RequestParser,
|
|
98
100
|
create404Response,
|
|
99
101
|
exceptionToResponse,
|
|
102
|
+
GCDataBuilder,
|
|
100
103
|
requestFluidObject,
|
|
101
|
-
responseToException,
|
|
102
104
|
seqFromTree,
|
|
103
105
|
calculateStats,
|
|
104
106
|
TelemetryContext,
|
|
107
|
+
ReadAndParseBlob,
|
|
105
108
|
} from "@fluidframework/runtime-utils";
|
|
106
|
-
import { GCDataBuilder, trimLeadingAndTrailingSlashes } from "@fluidframework/garbage-collector";
|
|
107
109
|
import { v4 as uuid } from "uuid";
|
|
108
110
|
import { ContainerFluidHandleContext } from "./containerHandleContext";
|
|
109
111
|
import { FluidDataStoreRegistry } from "./dataStoreRegistry";
|
|
110
|
-
import { Summarizer } from "./summarizer";
|
|
111
|
-
import { SummaryManager } from "./summaryManager";
|
|
112
112
|
import { ReportOpPerfTelemetry, IPerfSignalReport } from "./connectionTelemetry";
|
|
113
113
|
import { IPendingLocalState, PendingStateManager } from "./pendingStateManager";
|
|
114
114
|
import { pkgVersion } from "./packageVersion";
|
|
@@ -118,22 +118,24 @@ import {
|
|
|
118
118
|
aliasBlobName,
|
|
119
119
|
blobsTreeName,
|
|
120
120
|
chunksBlobName,
|
|
121
|
+
createRootSummarizerNodeWithGC,
|
|
121
122
|
electedSummarizerBlobName,
|
|
122
123
|
extractSummaryMetadataMessage,
|
|
123
124
|
IContainerRuntimeMetadata,
|
|
124
125
|
ICreateContainerMetadata,
|
|
126
|
+
IFetchSnapshotResult,
|
|
127
|
+
IRootSummarizerNodeWithGC,
|
|
125
128
|
ISummaryMetadataMessage,
|
|
126
129
|
metadataBlobName,
|
|
130
|
+
Summarizer,
|
|
131
|
+
SummaryManager,
|
|
127
132
|
wrapSummaryInChannelsTree,
|
|
128
|
-
|
|
129
|
-
import { SummaryCollection } from "./summaryCollection";
|
|
130
|
-
import {
|
|
133
|
+
SummaryCollection,
|
|
131
134
|
ISerializedElection,
|
|
132
135
|
OrderedClientCollection,
|
|
133
136
|
OrderedClientElection,
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
import {
|
|
137
|
+
SummarizerClientElection,
|
|
138
|
+
summarizerClientType,
|
|
137
139
|
SubmitSummaryResult,
|
|
138
140
|
IConnectableRuntime,
|
|
139
141
|
IGeneratedSummaryStats,
|
|
@@ -142,22 +144,21 @@ import {
|
|
|
142
144
|
ISummarizerInternalsProvider,
|
|
143
145
|
ISummarizerRuntime,
|
|
144
146
|
IRefreshSummaryAckOptions,
|
|
145
|
-
|
|
147
|
+
RunWhileConnectedCoordinator,
|
|
148
|
+
} from "./summary";
|
|
146
149
|
import { formExponentialFn, Throttler } from "./throttler";
|
|
147
|
-
import { RunWhileConnectedCoordinator } from "./runWhileConnectedCoordinator";
|
|
148
150
|
import {
|
|
149
151
|
GarbageCollector,
|
|
150
152
|
GCNodeType,
|
|
151
|
-
|
|
153
|
+
gcTombstoneGenerationOptionName,
|
|
152
154
|
IGarbageCollector,
|
|
155
|
+
IGCRuntimeOptions,
|
|
153
156
|
IGCStats,
|
|
154
|
-
|
|
157
|
+
shouldAllowGcTombstoneEnforcement,
|
|
158
|
+
trimLeadingAndTrailingSlashes,
|
|
159
|
+
} from "./gc";
|
|
155
160
|
import { channelToDataStore, IDataStoreAliasMessage, isDataStoreAliasMessage } from "./dataStore";
|
|
156
161
|
import { BindBatchTracker } from "./batchTracker";
|
|
157
|
-
import {
|
|
158
|
-
ISerializedBaseSnapshotBlobs,
|
|
159
|
-
SerializedSnapshotStorage,
|
|
160
|
-
} from "./serializedSnapshotStorage";
|
|
161
162
|
import { ScheduleManager } from "./scheduleManager";
|
|
162
163
|
import {
|
|
163
164
|
BatchMessage,
|
|
@@ -168,6 +169,7 @@ import {
|
|
|
168
169
|
OpSplitter,
|
|
169
170
|
RemoteMessageProcessor,
|
|
170
171
|
} from "./opLifecycle";
|
|
172
|
+
import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy";
|
|
171
173
|
|
|
172
174
|
export enum ContainerMessageType {
|
|
173
175
|
// An op to be delivered to store
|
|
@@ -312,54 +314,6 @@ export const DefaultSummaryConfiguration: ISummaryConfiguration = {
|
|
|
312
314
|
nonRuntimeHeuristicThreshold: 20,
|
|
313
315
|
};
|
|
314
316
|
|
|
315
|
-
export interface IGCRuntimeOptions {
|
|
316
|
-
/**
|
|
317
|
-
* Flag that if true, will enable running garbage collection (GC) for a new container.
|
|
318
|
-
*
|
|
319
|
-
* GC has mark phase and sweep phase. In mark phase, unreferenced objects are identified
|
|
320
|
-
* and marked as such in the summary. This option enables the mark phase.
|
|
321
|
-
* In sweep phase, unreferenced objects are eventually deleted from the container if they meet certain conditions.
|
|
322
|
-
* Sweep phase can be enabled via the "sweepAllowed" option.
|
|
323
|
-
*
|
|
324
|
-
* Note: This setting is persisted in the container's summary and cannot be changed.
|
|
325
|
-
*/
|
|
326
|
-
gcAllowed?: boolean;
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Flag that if true, enables GC's sweep phase for a new container.
|
|
330
|
-
*
|
|
331
|
-
* This will allow GC to eventually delete unreferenced objects from the container.
|
|
332
|
-
* This flag should only be set to true if "gcAllowed" is true.
|
|
333
|
-
*
|
|
334
|
-
* Note: This setting is persisted in the container's summary and cannot be changed.
|
|
335
|
-
*/
|
|
336
|
-
sweepAllowed?: boolean;
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Flag that if true, will disable garbage collection for the session.
|
|
340
|
-
* Can be used to disable running GC on containers where it is allowed via the gcAllowed option.
|
|
341
|
-
*/
|
|
342
|
-
disableGC?: boolean;
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* Flag that will bypass optimizations and generate GC data for all nodes irrespective of whether a node
|
|
346
|
-
* changed or not.
|
|
347
|
-
*/
|
|
348
|
-
runFullGC?: boolean;
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Maximum session duration for a new container. If not present, a default value will be used.
|
|
352
|
-
*
|
|
353
|
-
* Note: This setting is persisted in the container's summary and cannot be changed.
|
|
354
|
-
*/
|
|
355
|
-
sessionExpiryTimeoutMs?: number;
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Allows additional GC options to be passed.
|
|
359
|
-
*/
|
|
360
|
-
[key: string]: any;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
317
|
export interface ISummaryRuntimeOptions {
|
|
364
318
|
/** Override summary configurations set by the server. */
|
|
365
319
|
summaryConfigOverrides?: ISummaryConfiguration;
|
|
@@ -411,10 +365,6 @@ export interface IContainerRuntimeOptions {
|
|
|
411
365
|
* By default, flush mode is TurnBased.
|
|
412
366
|
*/
|
|
413
367
|
readonly flushMode?: FlushMode;
|
|
414
|
-
/**
|
|
415
|
-
* Save enough runtime state to be able to serialize upon request and load to the same state in a new container.
|
|
416
|
-
*/
|
|
417
|
-
readonly enableOfflineLoad?: boolean;
|
|
418
368
|
/**
|
|
419
369
|
* Enables the runtime to compress ops. Compression is disabled when undefined.
|
|
420
370
|
* @experimental Not ready for use.
|
|
@@ -433,7 +383,8 @@ export interface IContainerRuntimeOptions {
|
|
|
433
383
|
readonly maxBatchSizeInBytes?: number;
|
|
434
384
|
/**
|
|
435
385
|
* If the op payload needs to be chunked in order to work around the maximum size of the batch, this value represents
|
|
436
|
-
* how large the individual chunks will be. This is only supported when compression is enabled.
|
|
386
|
+
* how large the individual chunks will be. This is only supported when compression is enabled. If after compression, the
|
|
387
|
+
* batch size exceeds this value, it will be chunked into smaller ops of this size.
|
|
437
388
|
*
|
|
438
389
|
* If unspecified, if a batch exceeds `maxBatchSizeInBytes` after compression, the container will close with an instance
|
|
439
390
|
* of `GenericError` with the `BatchTooLarge` message.
|
|
@@ -467,11 +418,6 @@ export interface IRootSummaryTreeWithStats extends ISummaryTreeWithStats {
|
|
|
467
418
|
export enum RuntimeHeaders {
|
|
468
419
|
/** True to wait for a data store to be created and loaded before returning it. */
|
|
469
420
|
wait = "wait",
|
|
470
|
-
/**
|
|
471
|
-
* True if the request is from an external app. Used for GC to handle scenarios where a data store
|
|
472
|
-
* is deleted and requested via an external app.
|
|
473
|
-
*/
|
|
474
|
-
externalRequest = "externalRequest",
|
|
475
421
|
/** True if the request is coming from an IFluidHandle. */
|
|
476
422
|
viaHandle = "viaHandle",
|
|
477
423
|
}
|
|
@@ -487,7 +433,6 @@ export const TombstoneResponseHeaderKey = "isTombstoned";
|
|
|
487
433
|
*/
|
|
488
434
|
export interface RuntimeHeaderData {
|
|
489
435
|
wait?: boolean;
|
|
490
|
-
externalRequest?: boolean;
|
|
491
436
|
viaHandle?: boolean;
|
|
492
437
|
allowTombstone?: boolean;
|
|
493
438
|
}
|
|
@@ -495,7 +440,6 @@ export interface RuntimeHeaderData {
|
|
|
495
440
|
/** Default values for Runtime Headers */
|
|
496
441
|
export const defaultRuntimeHeaderData: Required<RuntimeHeaderData> = {
|
|
497
442
|
wait: true,
|
|
498
|
-
externalRequest: false,
|
|
499
443
|
viaHandle: false,
|
|
500
444
|
allowTombstone: false,
|
|
501
445
|
};
|
|
@@ -532,21 +476,6 @@ interface IPendingRuntimeState {
|
|
|
532
476
|
* Pending blobs from BlobManager
|
|
533
477
|
*/
|
|
534
478
|
pendingAttachmentBlobs?: IPendingBlobs;
|
|
535
|
-
/**
|
|
536
|
-
* A base snapshot at a sequence number prior to the first pending op
|
|
537
|
-
*/
|
|
538
|
-
baseSnapshot: ISnapshotTree;
|
|
539
|
-
/**
|
|
540
|
-
* Serialized blobs from the base snapshot. Used to load offline since
|
|
541
|
-
* storage is not available.
|
|
542
|
-
*/
|
|
543
|
-
snapshotBlobs: ISerializedBaseSnapshotBlobs;
|
|
544
|
-
/**
|
|
545
|
-
* All runtime ops since base snapshot sequence number up to the latest op
|
|
546
|
-
* seen when the container was closed. Used to apply stashed (saved pending)
|
|
547
|
-
* ops at the same sequence number at which they were made.
|
|
548
|
-
*/
|
|
549
|
-
savedOps: ISequencedDocumentMessage[];
|
|
550
479
|
}
|
|
551
480
|
|
|
552
481
|
const maxConsecutiveReconnectsKey = "Fluid.ContainerRuntime.MaxConsecutiveReconnects";
|
|
@@ -557,7 +486,15 @@ const defaultFlushMode = FlushMode.TurnBased;
|
|
|
557
486
|
// We can't estimate it fully, as we
|
|
558
487
|
// - do not know what properties relay service will add
|
|
559
488
|
// - we do not stringify final op, thus we do not know how much escaping will be added.
|
|
560
|
-
const defaultMaxBatchSizeInBytes =
|
|
489
|
+
const defaultMaxBatchSizeInBytes = 700 * 1024;
|
|
490
|
+
|
|
491
|
+
const defaultCompressionConfig = {
|
|
492
|
+
// Batches with content size exceeding this value will be compressed
|
|
493
|
+
minimumBatchSizeInBytes: 614400,
|
|
494
|
+
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
const defaultChunkSizeInBytes = 204800;
|
|
561
498
|
|
|
562
499
|
/**
|
|
563
500
|
* @deprecated - use ContainerRuntimeMessage instead
|
|
@@ -605,12 +542,7 @@ export function getDeviceSpec() {
|
|
|
605
542
|
*/
|
|
606
543
|
export class ContainerRuntime
|
|
607
544
|
extends TypedEventEmitter<IContainerRuntimeEvents>
|
|
608
|
-
implements
|
|
609
|
-
IContainerRuntime,
|
|
610
|
-
IGarbageCollectionRuntime,
|
|
611
|
-
IRuntime,
|
|
612
|
-
ISummarizerRuntime,
|
|
613
|
-
ISummarizerInternalsProvider
|
|
545
|
+
implements IContainerRuntime, IRuntime, ISummarizerRuntime, ISummarizerInternalsProvider
|
|
614
546
|
{
|
|
615
547
|
public get IContainerRuntime() {
|
|
616
548
|
return this;
|
|
@@ -658,13 +590,16 @@ export class ContainerRuntime
|
|
|
658
590
|
* Load the stores from a snapshot and returns the runtime.
|
|
659
591
|
* @param params - An object housing the runtime properties:
|
|
660
592
|
* - context - Context of the container.
|
|
661
|
-
* - registryEntries - Mapping to
|
|
662
|
-
* - existing -
|
|
663
|
-
* - requestHandler - Request
|
|
593
|
+
* - registryEntries - Mapping from data store types to their corresponding factories.
|
|
594
|
+
* - existing - Pass 'true' if loading from an existing snapshot.
|
|
595
|
+
* - requestHandler - (optional) Request handler for the request() method of the container runtime.
|
|
596
|
+
* Only relevant for back-compat while we remove the request() method and move fully to entryPoint as the main pattern.
|
|
664
597
|
* - runtimeOptions - Additional options to be passed to the runtime
|
|
665
598
|
* - containerScope - runtime services provided with context
|
|
666
599
|
* - containerRuntimeCtor - Constructor to use to create the ContainerRuntime instance.
|
|
667
600
|
* This allows mixin classes to leverage this method to define their own async initializer.
|
|
601
|
+
* - initializeEntryPoint - Promise that resolves to an object which will act as entryPoint for the Container.
|
|
602
|
+
* This object should provide all the functionality that the Container is expected to provide to the loader layer.
|
|
668
603
|
*/
|
|
669
604
|
public static async loadRuntime(params: {
|
|
670
605
|
context: IContainerContext;
|
|
@@ -674,6 +609,7 @@ export class ContainerRuntime
|
|
|
674
609
|
runtimeOptions?: IContainerRuntimeOptions;
|
|
675
610
|
containerScope?: FluidObject;
|
|
676
611
|
containerRuntimeCtor?: typeof ContainerRuntime;
|
|
612
|
+
initializeEntryPoint?: (containerRuntime: IContainerRuntime) => Promise<FluidObject>;
|
|
677
613
|
}): Promise<ContainerRuntime> {
|
|
678
614
|
const {
|
|
679
615
|
context,
|
|
@@ -683,6 +619,7 @@ export class ContainerRuntime
|
|
|
683
619
|
runtimeOptions = {},
|
|
684
620
|
containerScope = {},
|
|
685
621
|
containerRuntimeCtor = ContainerRuntime,
|
|
622
|
+
initializeEntryPoint,
|
|
686
623
|
} = params;
|
|
687
624
|
|
|
688
625
|
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
@@ -702,34 +639,24 @@ export class ContainerRuntime
|
|
|
702
639
|
gcOptions = {},
|
|
703
640
|
loadSequenceNumberVerification = "close",
|
|
704
641
|
flushMode = defaultFlushMode,
|
|
705
|
-
|
|
706
|
-
compressionOptions = {
|
|
707
|
-
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
708
|
-
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
709
|
-
},
|
|
642
|
+
compressionOptions = defaultCompressionConfig,
|
|
710
643
|
maxBatchSizeInBytes = defaultMaxBatchSizeInBytes,
|
|
711
|
-
chunkSizeInBytes =
|
|
644
|
+
chunkSizeInBytes = defaultChunkSizeInBytes,
|
|
712
645
|
enableOpReentryCheck = false,
|
|
713
646
|
} = runtimeOptions;
|
|
714
647
|
|
|
715
|
-
const pendingRuntimeState = context.pendingLocalState as IPendingRuntimeState | undefined;
|
|
716
|
-
const baseSnapshot: ISnapshotTree | undefined =
|
|
717
|
-
pendingRuntimeState?.baseSnapshot ?? context.baseSnapshot;
|
|
718
|
-
const storage = !pendingRuntimeState
|
|
719
|
-
? context.storage
|
|
720
|
-
: new SerializedSnapshotStorage(() => {
|
|
721
|
-
return context.storage;
|
|
722
|
-
}, pendingRuntimeState.snapshotBlobs);
|
|
723
|
-
|
|
724
648
|
const registry = new FluidDataStoreRegistry(registryEntries);
|
|
725
649
|
|
|
726
650
|
const tryFetchBlob = async <T>(blobName: string): Promise<T | undefined> => {
|
|
727
|
-
const blobId = baseSnapshot?.blobs[blobName];
|
|
728
|
-
if (baseSnapshot && blobId) {
|
|
651
|
+
const blobId = context.baseSnapshot?.blobs[blobName];
|
|
652
|
+
if (context.baseSnapshot && blobId) {
|
|
729
653
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
730
654
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
731
|
-
assert(
|
|
732
|
-
|
|
655
|
+
assert(
|
|
656
|
+
context.storage !== undefined,
|
|
657
|
+
0x1f5 /* "Attached state should have storage" */,
|
|
658
|
+
);
|
|
659
|
+
return readAndParse<T>(context.storage, blobId);
|
|
733
660
|
}
|
|
734
661
|
};
|
|
735
662
|
|
|
@@ -744,22 +671,22 @@ export class ContainerRuntime
|
|
|
744
671
|
|
|
745
672
|
// read snapshot blobs needed for BlobManager to load
|
|
746
673
|
const blobManagerSnapshot = await BlobManager.load(
|
|
747
|
-
baseSnapshot?.trees[blobsTreeName],
|
|
674
|
+
context.baseSnapshot?.trees[blobsTreeName],
|
|
748
675
|
async (id) => {
|
|
749
676
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
750
677
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
751
678
|
assert(
|
|
752
|
-
storage !== undefined,
|
|
679
|
+
context.storage !== undefined,
|
|
753
680
|
0x256 /* "storage undefined in attached container" */,
|
|
754
681
|
);
|
|
755
|
-
return readAndParse(storage, id);
|
|
682
|
+
return readAndParse(context.storage, id);
|
|
756
683
|
},
|
|
757
684
|
);
|
|
758
685
|
|
|
759
686
|
// Verify summary runtime sequence number matches protocol sequence number.
|
|
760
687
|
const runtimeSequenceNumber = metadata?.message?.sequenceNumber;
|
|
761
688
|
// When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
|
|
762
|
-
if (!
|
|
689
|
+
if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
|
|
763
690
|
const protocolSequenceNumber = context.deltaManager.initialSequenceNumber;
|
|
764
691
|
// Unless bypass is explicitly set, then take action when sequence numbers mismatch.
|
|
765
692
|
if (
|
|
@@ -795,7 +722,6 @@ export class ContainerRuntime
|
|
|
795
722
|
gcOptions,
|
|
796
723
|
loadSequenceNumberVerification,
|
|
797
724
|
flushMode,
|
|
798
|
-
enableOfflineLoad,
|
|
799
725
|
compressionOptions,
|
|
800
726
|
maxBatchSizeInBytes,
|
|
801
727
|
chunkSizeInBytes,
|
|
@@ -805,15 +731,15 @@ export class ContainerRuntime
|
|
|
805
731
|
logger,
|
|
806
732
|
loadExisting,
|
|
807
733
|
blobManagerSnapshot,
|
|
808
|
-
storage,
|
|
734
|
+
context.storage,
|
|
809
735
|
requestHandler,
|
|
736
|
+
undefined, // summaryConfiguration
|
|
737
|
+
initializeEntryPoint,
|
|
810
738
|
);
|
|
811
739
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
pendingRuntimeState.savedOps = [];
|
|
816
|
-
}
|
|
740
|
+
// It's possible to have ops with a reference sequence number of 0. Op sequence numbers start
|
|
741
|
+
// at 1, so we won't see a replayed saved op with a sequence number of 0.
|
|
742
|
+
await runtime.pendingStateManager.applyStashedOpsAt(0);
|
|
817
743
|
|
|
818
744
|
// Initialize the base state of the runtime before it's returned.
|
|
819
745
|
await runtime.initializeBaseState();
|
|
@@ -833,10 +759,6 @@ export class ContainerRuntime
|
|
|
833
759
|
return this.context.clientDetails;
|
|
834
760
|
}
|
|
835
761
|
|
|
836
|
-
public get deltaManager(): IDeltaManager<ISequencedDocumentMessage, IDocumentMessage> {
|
|
837
|
-
return this.context.deltaManager;
|
|
838
|
-
}
|
|
839
|
-
|
|
840
762
|
public get storage(): IDocumentStorageService {
|
|
841
763
|
return this._storage;
|
|
842
764
|
}
|
|
@@ -885,6 +807,19 @@ export class ContainerRuntime
|
|
|
885
807
|
}
|
|
886
808
|
private readonly handleContext: ContainerFluidHandleContext;
|
|
887
809
|
|
|
810
|
+
/**
|
|
811
|
+
* This is a proxy to the delta manager provided by the container context (innerDeltaManager). It restricts certain
|
|
812
|
+
* accesses such as sets "read-only" mode for the summarizer client. This is the default delta manager that should
|
|
813
|
+
* be used unless the innerDeltaManager is required.
|
|
814
|
+
*/
|
|
815
|
+
public readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
|
|
816
|
+
/**
|
|
817
|
+
* The delta manager provided by the container context. By default, using the default delta manager (proxy)
|
|
818
|
+
* should be sufficient. This should be used only if necessary. For example, for validating and propagating connected
|
|
819
|
+
* events which requires access to the actual real only info, this is needed.
|
|
820
|
+
*/
|
|
821
|
+
private readonly innerDeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
|
|
822
|
+
|
|
888
823
|
// internal logger for ContainerRuntime. Use this.logger for stores, summaries, etc.
|
|
889
824
|
private readonly mc: MonitoringContext;
|
|
890
825
|
|
|
@@ -904,13 +839,10 @@ export class ContainerRuntime
|
|
|
904
839
|
|
|
905
840
|
private _orderSequentiallyCalls: number = 0;
|
|
906
841
|
private readonly _flushMode: FlushMode;
|
|
907
|
-
private
|
|
842
|
+
private flushTaskExists = false;
|
|
908
843
|
|
|
909
844
|
private _connected: boolean;
|
|
910
845
|
|
|
911
|
-
private readonly savedOps: ISequencedDocumentMessage[] = [];
|
|
912
|
-
private baseSnapshotBlobs?: ISerializedBaseSnapshotBlobs;
|
|
913
|
-
|
|
914
846
|
private consecutiveReconnects = 0;
|
|
915
847
|
|
|
916
848
|
/**
|
|
@@ -963,6 +895,7 @@ export class ContainerRuntime
|
|
|
963
895
|
private dirtyContainer: boolean;
|
|
964
896
|
private emitDirtyDocumentEvent = true;
|
|
965
897
|
private readonly enableOpReentryCheck: boolean;
|
|
898
|
+
private readonly disableAttachReorder: boolean | undefined;
|
|
966
899
|
|
|
967
900
|
private readonly defaultTelemetrySignalSampleCount = 100;
|
|
968
901
|
private _perfSignalData: IPerfSignalReport = {
|
|
@@ -982,7 +915,6 @@ export class ContainerRuntime
|
|
|
982
915
|
private readonly blobManager: BlobManager;
|
|
983
916
|
private readonly pendingStateManager: PendingStateManager;
|
|
984
917
|
private readonly outbox: Outbox;
|
|
985
|
-
|
|
986
918
|
private readonly garbageCollector: IGarbageCollector;
|
|
987
919
|
|
|
988
920
|
private readonly dataStores: DataStores;
|
|
@@ -1032,6 +964,17 @@ export class ContainerRuntime
|
|
|
1032
964
|
*/
|
|
1033
965
|
private nextSummaryNumber: number;
|
|
1034
966
|
|
|
967
|
+
/**
|
|
968
|
+
* If false, loading or using a Tombstoned object should merely log, not fail
|
|
969
|
+
*/
|
|
970
|
+
public readonly gcTombstoneEnforcementAllowed: boolean;
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* GUID to identify a document in telemetry
|
|
974
|
+
* ! Note: should not be used for anything other than telemetry and is not considered a stable GUID
|
|
975
|
+
*/
|
|
976
|
+
private readonly telemetryDocumentId: string;
|
|
977
|
+
|
|
1035
978
|
/**
|
|
1036
979
|
* @internal
|
|
1037
980
|
*/
|
|
@@ -1058,9 +1001,13 @@ export class ContainerRuntime
|
|
|
1058
1001
|
// the runtime configuration overrides
|
|
1059
1002
|
...runtimeOptions.summaryOptions?.summaryConfigOverrides,
|
|
1060
1003
|
},
|
|
1004
|
+
initializeEntryPoint?: (containerRuntime: IContainerRuntime) => Promise<FluidObject>,
|
|
1061
1005
|
) {
|
|
1062
1006
|
super();
|
|
1063
1007
|
|
|
1008
|
+
this.innerDeltaManager = context.deltaManager;
|
|
1009
|
+
this.deltaManager = new DeltaManagerSummarizerProxy(context.deltaManager);
|
|
1010
|
+
|
|
1064
1011
|
let loadSummaryNumber: number;
|
|
1065
1012
|
// Get the container creation metadata. For new container, we initialize these. For existing containers,
|
|
1066
1013
|
// get the values from the metadata blob.
|
|
@@ -1085,18 +1032,41 @@ export class ContainerRuntime
|
|
|
1085
1032
|
|
|
1086
1033
|
this._connected = this.context.connected;
|
|
1087
1034
|
|
|
1035
|
+
this.gcTombstoneEnforcementAllowed = shouldAllowGcTombstoneEnforcement(
|
|
1036
|
+
metadata?.gcFeatureMatrix?.tombstoneGeneration /* persisted */,
|
|
1037
|
+
this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName] /* current */,
|
|
1038
|
+
);
|
|
1039
|
+
|
|
1088
1040
|
this.mc = loggerToMonitoringContext(ChildLogger.create(this.logger, "ContainerRuntime"));
|
|
1089
1041
|
|
|
1042
|
+
this.mc.logger.sendTelemetryEvent({
|
|
1043
|
+
eventName: "GCFeatureMatrix",
|
|
1044
|
+
metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
|
|
1045
|
+
inputs: JSON.stringify({
|
|
1046
|
+
gcOptions_gcTombstoneGeneration:
|
|
1047
|
+
this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName],
|
|
1048
|
+
}),
|
|
1049
|
+
});
|
|
1050
|
+
|
|
1051
|
+
this.telemetryDocumentId = metadata?.telemetryDocumentId ?? uuid();
|
|
1052
|
+
|
|
1053
|
+
this.disableAttachReorder = this.mc.config.getBoolean(
|
|
1054
|
+
"Fluid.ContainerRuntime.disableAttachOpReorder",
|
|
1055
|
+
);
|
|
1056
|
+
const disableChunking = this.mc.config.getBoolean(
|
|
1057
|
+
"Fluid.ContainerRuntime.CompressionChunkingDisabled",
|
|
1058
|
+
);
|
|
1090
1059
|
const opSplitter = new OpSplitter(
|
|
1091
1060
|
chunks,
|
|
1092
1061
|
this.context.submitBatchFn,
|
|
1093
|
-
|
|
1094
|
-
? Number.POSITIVE_INFINITY
|
|
1095
|
-
: runtimeOptions.chunkSizeInBytes,
|
|
1062
|
+
disableChunking === true ? Number.POSITIVE_INFINITY : runtimeOptions.chunkSizeInBytes,
|
|
1096
1063
|
runtimeOptions.maxBatchSizeInBytes,
|
|
1097
1064
|
this.mc.logger,
|
|
1098
1065
|
);
|
|
1099
|
-
this.remoteMessageProcessor = new RemoteMessageProcessor(
|
|
1066
|
+
this.remoteMessageProcessor = new RemoteMessageProcessor(
|
|
1067
|
+
opSplitter,
|
|
1068
|
+
new OpDecompressor(this.mc.logger),
|
|
1069
|
+
);
|
|
1100
1070
|
|
|
1101
1071
|
this.handleContext = new ContainerFluidHandleContext("", this);
|
|
1102
1072
|
|
|
@@ -1104,10 +1074,13 @@ export class ContainerRuntime
|
|
|
1104
1074
|
this.validateSummaryHeuristicConfiguration(this.summaryConfiguration);
|
|
1105
1075
|
}
|
|
1106
1076
|
|
|
1077
|
+
const disableOpReentryCheck = this.mc.config.getBoolean(
|
|
1078
|
+
"Fluid.ContainerRuntime.DisableOpReentryCheck",
|
|
1079
|
+
);
|
|
1107
1080
|
this.enableOpReentryCheck =
|
|
1108
1081
|
runtimeOptions.enableOpReentryCheck === true &&
|
|
1109
1082
|
// Allow for a break-glass config to override the options
|
|
1110
|
-
|
|
1083
|
+
disableOpReentryCheck !== true;
|
|
1111
1084
|
|
|
1112
1085
|
this.summariesDisabled = this.isSummariesDisabled();
|
|
1113
1086
|
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
@@ -1118,11 +1091,18 @@ export class ContainerRuntime
|
|
|
1118
1091
|
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
|
|
1119
1092
|
this.defaultMaxConsecutiveReconnects;
|
|
1120
1093
|
|
|
1121
|
-
|
|
1094
|
+
if (
|
|
1095
|
+
runtimeOptions.flushMode === (FlushModeExperimental.Async as unknown as FlushMode) &&
|
|
1096
|
+
context.supportedFeatures?.get("referenceSequenceNumbers") !== true
|
|
1097
|
+
) {
|
|
1098
|
+
// The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
|
|
1099
|
+
this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
|
|
1100
|
+
this._flushMode = FlushMode.TurnBased;
|
|
1101
|
+
} else {
|
|
1102
|
+
this._flushMode = runtimeOptions.flushMode;
|
|
1103
|
+
}
|
|
1122
1104
|
|
|
1123
1105
|
const pendingRuntimeState = context.pendingLocalState as IPendingRuntimeState | undefined;
|
|
1124
|
-
const baseSnapshot: ISnapshotTree | undefined =
|
|
1125
|
-
pendingRuntimeState?.baseSnapshot ?? context.baseSnapshot;
|
|
1126
1106
|
|
|
1127
1107
|
const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
|
|
1128
1108
|
if (
|
|
@@ -1138,7 +1118,7 @@ export class ContainerRuntime
|
|
|
1138
1118
|
this.garbageCollector = GarbageCollector.create({
|
|
1139
1119
|
runtime: this,
|
|
1140
1120
|
gcOptions: this.runtimeOptions.gcOptions,
|
|
1141
|
-
baseSnapshot,
|
|
1121
|
+
baseSnapshot: context.baseSnapshot,
|
|
1142
1122
|
baseLogger: this.mc.logger,
|
|
1143
1123
|
existing,
|
|
1144
1124
|
metadata,
|
|
@@ -1148,7 +1128,9 @@ export class ContainerRuntime
|
|
|
1148
1128
|
getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
|
|
1149
1129
|
readAndParseBlob: async <T>(id: string) => readAndParse<T>(this.storage, id),
|
|
1150
1130
|
getContainerDiagnosticId: () => this.context.id,
|
|
1151
|
-
|
|
1131
|
+
// GC runs in summarizer client and needs access to the real (non-proxy) active information. The proxy
|
|
1132
|
+
// delta manager would always return false for summarizer client.
|
|
1133
|
+
activeConnection: () => this.innerDeltaManager.active,
|
|
1152
1134
|
});
|
|
1153
1135
|
|
|
1154
1136
|
const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
|
|
@@ -1160,7 +1142,7 @@ export class ContainerRuntime
|
|
|
1160
1142
|
// Latest change sequence number, no changes since summary applied yet
|
|
1161
1143
|
loadedFromSequenceNumber,
|
|
1162
1144
|
// Summary reference sequence number, undefined if no summary yet
|
|
1163
|
-
baseSnapshot ? loadedFromSequenceNumber : undefined,
|
|
1145
|
+
context.baseSnapshot ? loadedFromSequenceNumber : undefined,
|
|
1164
1146
|
{
|
|
1165
1147
|
// Must set to false to prevent sending summary handle which would be pointing to
|
|
1166
1148
|
// a summary with an older protocol state.
|
|
@@ -1177,19 +1159,18 @@ export class ContainerRuntime
|
|
|
1177
1159
|
async () => this.garbageCollector.getBaseGCDetails(),
|
|
1178
1160
|
);
|
|
1179
1161
|
|
|
1180
|
-
if (baseSnapshot) {
|
|
1181
|
-
this.summarizerNode.updateBaseSummaryState(baseSnapshot);
|
|
1162
|
+
if (context.baseSnapshot) {
|
|
1163
|
+
this.summarizerNode.updateBaseSummaryState(context.baseSnapshot);
|
|
1182
1164
|
}
|
|
1183
1165
|
|
|
1184
1166
|
this.dataStores = new DataStores(
|
|
1185
|
-
getSummaryForDatastores(baseSnapshot, metadata),
|
|
1167
|
+
getSummaryForDatastores(context.baseSnapshot, metadata),
|
|
1186
1168
|
this,
|
|
1187
1169
|
(attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg),
|
|
1188
1170
|
(id: string, createParam: CreateChildSummarizerNodeParam) =>
|
|
1189
1171
|
(
|
|
1190
1172
|
summarizeInternal: SummarizeInternalFn,
|
|
1191
1173
|
getGCDataFn: (fullGC?: boolean) => Promise<IGarbageCollectionData>,
|
|
1192
|
-
getBaseGCDetailsFn?: () => Promise<IGarbageCollectionDetailsBase>,
|
|
1193
1174
|
) =>
|
|
1194
1175
|
this.summarizerNode.createChild(
|
|
1195
1176
|
summarizeInternal,
|
|
@@ -1197,13 +1178,12 @@ export class ContainerRuntime
|
|
|
1197
1178
|
createParam,
|
|
1198
1179
|
undefined,
|
|
1199
1180
|
getGCDataFn,
|
|
1200
|
-
getBaseGCDetailsFn,
|
|
1201
1181
|
),
|
|
1202
1182
|
(id: string) => this.summarizerNode.deleteChild(id),
|
|
1203
1183
|
this.mc.logger,
|
|
1204
|
-
async () => this.garbageCollector.getBaseGCDetails(),
|
|
1205
1184
|
(path: string, timestampMs: number, packagePath?: readonly string[]) =>
|
|
1206
1185
|
this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath),
|
|
1186
|
+
(path: string) => this.garbageCollector.isNodeDeleted(path),
|
|
1207
1187
|
new Map<string, string>(dataStoreAliasMap),
|
|
1208
1188
|
);
|
|
1209
1189
|
|
|
@@ -1220,8 +1200,6 @@ export class ContainerRuntime
|
|
|
1220
1200
|
}
|
|
1221
1201
|
},
|
|
1222
1202
|
(blobPath: string) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"),
|
|
1223
|
-
(fromPath: string, toPath: string) =>
|
|
1224
|
-
this.garbageCollector.addedOutboundReference(fromPath, toPath),
|
|
1225
1203
|
(blobPath: string) => this.garbageCollector.isNodeDeleted(blobPath),
|
|
1226
1204
|
this,
|
|
1227
1205
|
pendingRuntimeState?.pendingAttachmentBlobs,
|
|
@@ -1248,14 +1226,20 @@ export class ContainerRuntime
|
|
|
1248
1226
|
pendingRuntimeState?.pending,
|
|
1249
1227
|
);
|
|
1250
1228
|
|
|
1229
|
+
const disableCompression = this.mc.config.getBoolean(
|
|
1230
|
+
"Fluid.ContainerRuntime.CompressionDisabled",
|
|
1231
|
+
);
|
|
1251
1232
|
const compressionOptions =
|
|
1252
|
-
|
|
1233
|
+
disableCompression === true
|
|
1253
1234
|
? {
|
|
1254
1235
|
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
1255
1236
|
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
1256
1237
|
}
|
|
1257
1238
|
: runtimeOptions.compressionOptions;
|
|
1258
1239
|
|
|
1240
|
+
const disablePartialFlush = this.mc.config.getBoolean(
|
|
1241
|
+
"Fluid.ContainerRuntime.DisablePartialFlush",
|
|
1242
|
+
);
|
|
1259
1243
|
this.outbox = new Outbox({
|
|
1260
1244
|
shouldSend: () => this.canSendOps(),
|
|
1261
1245
|
pendingStateManager: this.pendingStateManager,
|
|
@@ -1265,7 +1249,7 @@ export class ContainerRuntime
|
|
|
1265
1249
|
config: {
|
|
1266
1250
|
compressionOptions,
|
|
1267
1251
|
maxBatchSizeInBytes: runtimeOptions.maxBatchSizeInBytes,
|
|
1268
|
-
|
|
1252
|
+
disablePartialFlush: disablePartialFlush === true,
|
|
1269
1253
|
},
|
|
1270
1254
|
logger: this.mc.logger,
|
|
1271
1255
|
});
|
|
@@ -1306,14 +1290,18 @@ export class ContainerRuntime
|
|
|
1306
1290
|
|
|
1307
1291
|
if (this.context.clientDetails.type === summarizerClientType) {
|
|
1308
1292
|
this._summarizer = new Summarizer(
|
|
1309
|
-
"/_summarizer",
|
|
1310
1293
|
this /* ISummarizerRuntime */,
|
|
1311
1294
|
() => this.summaryConfiguration,
|
|
1312
1295
|
this /* ISummarizerInternalsProvider */,
|
|
1313
1296
|
this.handleContext,
|
|
1314
1297
|
this.summaryCollection,
|
|
1315
1298
|
async (runtime: IConnectableRuntime) =>
|
|
1316
|
-
RunWhileConnectedCoordinator.create(
|
|
1299
|
+
RunWhileConnectedCoordinator.create(
|
|
1300
|
+
runtime,
|
|
1301
|
+
// Summarization runs in summarizer client and needs access to the real (non-proxy) active
|
|
1302
|
+
// information. The proxy delta manager would always return false for summarizer client.
|
|
1303
|
+
() => this.innerDeltaManager.active,
|
|
1304
|
+
),
|
|
1317
1305
|
);
|
|
1318
1306
|
} else if (
|
|
1319
1307
|
SummarizerClientElection.clientDetailsPermitElection(this.context.clientDetails)
|
|
@@ -1363,8 +1351,9 @@ export class ContainerRuntime
|
|
|
1363
1351
|
this.deltaManager.on("readonly", (readonly: boolean) => {
|
|
1364
1352
|
// we accumulate ops while being in read-only state.
|
|
1365
1353
|
// once user gets write permissions and we have active connection, flush all pending ops.
|
|
1354
|
+
// Note that the inner (non-proxy) delta manager is needed here to get the readonly information.
|
|
1366
1355
|
assert(
|
|
1367
|
-
readonly === this.
|
|
1356
|
+
readonly === this.innerDeltaManager.readOnlyInfo.readonly,
|
|
1368
1357
|
0x124 /* "inconsistent readonly property/event state" */,
|
|
1369
1358
|
);
|
|
1370
1359
|
|
|
@@ -1402,17 +1391,36 @@ export class ContainerRuntime
|
|
|
1402
1391
|
summaryFormatVersion: metadata?.summaryFormatVersion,
|
|
1403
1392
|
disableIsolatedChannels: metadata?.disableIsolatedChannels,
|
|
1404
1393
|
gcVersion: metadata?.gcFeature,
|
|
1394
|
+
options: JSON.stringify(runtimeOptions),
|
|
1395
|
+
featureGates: JSON.stringify({
|
|
1396
|
+
disableCompression,
|
|
1397
|
+
disableOpReentryCheck,
|
|
1398
|
+
disableChunking,
|
|
1399
|
+
disableAttachReorder: this.disableAttachReorder,
|
|
1400
|
+
disablePartialFlush,
|
|
1401
|
+
}),
|
|
1402
|
+
telemetryDocumentId: this.telemetryDocumentId,
|
|
1405
1403
|
});
|
|
1406
1404
|
|
|
1407
1405
|
ReportOpPerfTelemetry(this.context.clientId, this.deltaManager, this.logger);
|
|
1408
1406
|
BindBatchTracker(this, this.logger);
|
|
1407
|
+
|
|
1408
|
+
this.entryPoint = new LazyPromise(async () => {
|
|
1409
|
+
if (this.context.clientDetails.type === summarizerClientType) {
|
|
1410
|
+
assert(
|
|
1411
|
+
this._summarizer !== undefined,
|
|
1412
|
+
0x5bf /* Summarizer object is undefined in a summarizer client */,
|
|
1413
|
+
);
|
|
1414
|
+
return this._summarizer;
|
|
1415
|
+
}
|
|
1416
|
+
return initializeEntryPoint?.(this);
|
|
1417
|
+
});
|
|
1409
1418
|
}
|
|
1410
1419
|
|
|
1411
1420
|
/**
|
|
1412
1421
|
* Initializes the state from the base snapshot this container runtime loaded from.
|
|
1413
1422
|
*/
|
|
1414
1423
|
private async initializeBaseState(): Promise<void> {
|
|
1415
|
-
await this.initializeBaseSnapshotBlobs();
|
|
1416
1424
|
await this.garbageCollector.initializeBaseState();
|
|
1417
1425
|
}
|
|
1418
1426
|
|
|
@@ -1443,16 +1451,6 @@ export class ContainerRuntime
|
|
|
1443
1451
|
this.removeAllListeners();
|
|
1444
1452
|
}
|
|
1445
1453
|
|
|
1446
|
-
public get IFluidTokenProvider() {
|
|
1447
|
-
if (this.options?.intelligence) {
|
|
1448
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
1449
|
-
return {
|
|
1450
|
-
intelligence: this.options.intelligence,
|
|
1451
|
-
} as IFluidTokenProvider;
|
|
1452
|
-
}
|
|
1453
|
-
return undefined;
|
|
1454
|
-
}
|
|
1455
|
-
|
|
1456
1454
|
/**
|
|
1457
1455
|
* Notifies this object about the request made to the container.
|
|
1458
1456
|
* @param request - Request made to the handler.
|
|
@@ -1522,6 +1520,14 @@ export class ContainerRuntime
|
|
|
1522
1520
|
}
|
|
1523
1521
|
}
|
|
1524
1522
|
|
|
1523
|
+
/**
|
|
1524
|
+
* {@inheritDoc @fluidframework/container-definitions#IRuntime.getEntryPoint}
|
|
1525
|
+
*/
|
|
1526
|
+
public async getEntryPoint?(): Promise<FluidObject | undefined> {
|
|
1527
|
+
return this.entryPoint;
|
|
1528
|
+
}
|
|
1529
|
+
private readonly entryPoint: LazyPromise<FluidObject | undefined>;
|
|
1530
|
+
|
|
1525
1531
|
private internalId(maybeAlias: string): string {
|
|
1526
1532
|
return this.dataStores.aliases.get(maybeAlias) ?? maybeAlias;
|
|
1527
1533
|
}
|
|
@@ -1541,29 +1547,6 @@ export class ContainerRuntime
|
|
|
1541
1547
|
await this.dataStores.waitIfPendingAlias(id);
|
|
1542
1548
|
const internalId = this.internalId(id);
|
|
1543
1549
|
const dataStoreContext = await this.dataStores.getDataStore(internalId, headerData);
|
|
1544
|
-
|
|
1545
|
-
/**
|
|
1546
|
-
* If GC should run and this an external app request with "externalRequest" header, we need to return
|
|
1547
|
-
* an error if the data store being requested is marked as unreferenced as per the data store's base
|
|
1548
|
-
* GC data.
|
|
1549
|
-
*
|
|
1550
|
-
* This is a workaround to handle scenarios where a data store shared with an external app is deleted
|
|
1551
|
-
* and marked as unreferenced by GC. Returning an error will fail to load the data store for the app.
|
|
1552
|
-
*/
|
|
1553
|
-
if (
|
|
1554
|
-
request.headers?.[RuntimeHeaders.externalRequest] &&
|
|
1555
|
-
this.garbageCollector.shouldRunGC
|
|
1556
|
-
) {
|
|
1557
|
-
// The data store is referenced if used routes in the base summary has a route to self.
|
|
1558
|
-
// Older documents may not have used routes in the summary. They are considered referenced.
|
|
1559
|
-
const usedRoutes = (await dataStoreContext.getBaseGCDetails()).usedRoutes;
|
|
1560
|
-
if (
|
|
1561
|
-
!(usedRoutes === undefined || usedRoutes.includes("") || usedRoutes.includes("/"))
|
|
1562
|
-
) {
|
|
1563
|
-
throw responseToException(create404Response(request), request);
|
|
1564
|
-
}
|
|
1565
|
-
}
|
|
1566
|
-
|
|
1567
1550
|
const dataStoreChannel = await dataStoreContext.realize();
|
|
1568
1551
|
|
|
1569
1552
|
// Remove query params, leading and trailing slashes from the url. This is done to make sure the format is
|
|
@@ -1592,6 +1575,7 @@ export class ContainerRuntime
|
|
|
1592
1575
|
message:
|
|
1593
1576
|
extractSummaryMetadataMessage(this.deltaManager.lastMessage) ??
|
|
1594
1577
|
this.messageAtLastSummary,
|
|
1578
|
+
telemetryDocumentId: this.telemetryDocumentId,
|
|
1595
1579
|
};
|
|
1596
1580
|
addBlobToSummary(summaryTree, metadataBlobName, JSON.stringify(metadata));
|
|
1597
1581
|
}
|
|
@@ -1736,8 +1720,9 @@ export class ContainerRuntime
|
|
|
1736
1720
|
// If attachment blobs were added while disconnected, we need to delay
|
|
1737
1721
|
// propagation of the "connected" event until we have uploaded them to
|
|
1738
1722
|
// ensure we don't submit ops referencing a blob that has not been uploaded
|
|
1723
|
+
// Note that the inner (non-proxy) delta manager is needed here to get the readonly information.
|
|
1739
1724
|
const connecting =
|
|
1740
|
-
connected && !this._connected && !this.
|
|
1725
|
+
connected && !this._connected && !this.innerDeltaManager.readOnlyInfo.readonly;
|
|
1741
1726
|
if (connecting && this.blobManager.hasPendingOfflineUploads) {
|
|
1742
1727
|
assert(
|
|
1743
1728
|
!this.delayConnectClientId,
|
|
@@ -1815,16 +1800,13 @@ export class ContainerRuntime
|
|
|
1815
1800
|
raiseConnectedEvent(this.mc.logger, this, connected, clientId);
|
|
1816
1801
|
}
|
|
1817
1802
|
|
|
1803
|
+
public async notifyOpReplay(message: ISequencedDocumentMessage) {
|
|
1804
|
+
await this.pendingStateManager.applyStashedOpsAt(message.sequenceNumber);
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1818
1807
|
public process(messageArg: ISequencedDocumentMessage, local: boolean) {
|
|
1819
1808
|
this.verifyNotClosed();
|
|
1820
1809
|
|
|
1821
|
-
if (
|
|
1822
|
-
this.mc.config.getBoolean("enableOfflineLoad") ??
|
|
1823
|
-
this.runtimeOptions.enableOfflineLoad
|
|
1824
|
-
) {
|
|
1825
|
-
this.savedOps.push(messageArg);
|
|
1826
|
-
}
|
|
1827
|
-
|
|
1828
1810
|
// Whether or not the message is actually a runtime message.
|
|
1829
1811
|
// It may be a legacy runtime message (ie already unpacked and ContainerMessageType)
|
|
1830
1812
|
// or something different, like a system message.
|
|
@@ -1869,7 +1851,23 @@ export class ContainerRuntime
|
|
|
1869
1851
|
case ContainerMessageType.Rejoin:
|
|
1870
1852
|
break;
|
|
1871
1853
|
default:
|
|
1872
|
-
|
|
1854
|
+
if (runtimeMessage) {
|
|
1855
|
+
const error = DataProcessingError.create(
|
|
1856
|
+
// Former assert 0x3ce
|
|
1857
|
+
"Runtime message of unknown type",
|
|
1858
|
+
"OpProcessing",
|
|
1859
|
+
message,
|
|
1860
|
+
{
|
|
1861
|
+
local,
|
|
1862
|
+
type: message.type,
|
|
1863
|
+
contentType: typeof message.contents,
|
|
1864
|
+
batch: message.metadata?.batch,
|
|
1865
|
+
compression: message.compression,
|
|
1866
|
+
},
|
|
1867
|
+
);
|
|
1868
|
+
this.closeFn(error);
|
|
1869
|
+
throw error;
|
|
1870
|
+
}
|
|
1873
1871
|
}
|
|
1874
1872
|
|
|
1875
1873
|
// For back-compat, notify only about runtime messages for now.
|
|
@@ -1944,7 +1942,10 @@ export class ContainerRuntime
|
|
|
1944
1942
|
envelope.clientSignalSequenceNumber ===
|
|
1945
1943
|
this._perfSignalData.trackingSignalSequenceNumber
|
|
1946
1944
|
) {
|
|
1947
|
-
|
|
1945
|
+
// only logging for the first connection and the trackingSignalSequenceNUmber.
|
|
1946
|
+
if (this.consecutiveReconnects === 0) {
|
|
1947
|
+
this.sendSignalTelemetryEvent(envelope.clientSignalSequenceNumber);
|
|
1948
|
+
}
|
|
1948
1949
|
this._perfSignalData.trackingSignalSequenceNumber = undefined;
|
|
1949
1950
|
}
|
|
1950
1951
|
}
|
|
@@ -2084,14 +2085,16 @@ export class ContainerRuntime
|
|
|
2084
2085
|
}
|
|
2085
2086
|
|
|
2086
2087
|
private canSendOps() {
|
|
2087
|
-
|
|
2088
|
+
// Note that the real (non-proxy) delta manager is needed here to get the readonly info. This is because
|
|
2089
|
+
// container runtime's ability to send ops depend on the actual readonly state of the delta manager.
|
|
2090
|
+
return this.connected && !this.innerDeltaManager.readOnlyInfo.readonly;
|
|
2088
2091
|
}
|
|
2089
2092
|
|
|
2090
2093
|
/**
|
|
2091
2094
|
* Are we in the middle of batching ops together?
|
|
2092
2095
|
*/
|
|
2093
2096
|
private currentlyBatching() {
|
|
2094
|
-
return this.flushMode
|
|
2097
|
+
return this.flushMode !== FlushMode.Immediate || this._orderSequentiallyCalls !== 0;
|
|
2095
2098
|
}
|
|
2096
2099
|
|
|
2097
2100
|
public getQuorum(): IQuorumClients {
|
|
@@ -2278,12 +2281,24 @@ export class ContainerRuntime
|
|
|
2278
2281
|
fullGC,
|
|
2279
2282
|
} = options;
|
|
2280
2283
|
|
|
2284
|
+
const telemetryContext = new TelemetryContext();
|
|
2285
|
+
// Add the options that are used to generate this summary to the telemetry context.
|
|
2286
|
+
telemetryContext.setMultiple("fluid_Summarize", "Options", {
|
|
2287
|
+
fullTree,
|
|
2288
|
+
trackState,
|
|
2289
|
+
runGC,
|
|
2290
|
+
fullGC,
|
|
2291
|
+
runSweep,
|
|
2292
|
+
});
|
|
2293
|
+
|
|
2281
2294
|
let gcStats: IGCStats | undefined;
|
|
2282
2295
|
if (runGC) {
|
|
2283
|
-
gcStats = await this.collectGarbage(
|
|
2296
|
+
gcStats = await this.collectGarbage(
|
|
2297
|
+
{ logger: summaryLogger, runSweep, fullGC },
|
|
2298
|
+
telemetryContext,
|
|
2299
|
+
);
|
|
2284
2300
|
}
|
|
2285
2301
|
|
|
2286
|
-
const telemetryContext = new TelemetryContext();
|
|
2287
2302
|
const { stats, summary } = await this.summarizerNode.summarize(
|
|
2288
2303
|
fullTree,
|
|
2289
2304
|
trackState,
|
|
@@ -2304,10 +2319,10 @@ export class ContainerRuntime
|
|
|
2304
2319
|
}
|
|
2305
2320
|
|
|
2306
2321
|
/**
|
|
2307
|
-
* Implementation of IGarbageCollectionRuntime::updateStateBeforeGC.
|
|
2308
2322
|
* Before GC runs, called by the garbage collector to update any pending GC state. This is mainly used to notify
|
|
2309
2323
|
* the garbage collector of references detected since the last GC run. Most references are notified immediately
|
|
2310
2324
|
* but there can be some for which async operation is required (such as detecting new root data stores).
|
|
2325
|
+
* @see IGarbageCollectionRuntime.updateStateBeforeGC
|
|
2311
2326
|
*/
|
|
2312
2327
|
public async updateStateBeforeGC() {
|
|
2313
2328
|
return this.dataStores.updateStateBeforeGC();
|
|
@@ -2318,9 +2333,9 @@ export class ContainerRuntime
|
|
|
2318
2333
|
}
|
|
2319
2334
|
|
|
2320
2335
|
/**
|
|
2321
|
-
* Implementation of IGarbageCollectionRuntime::getGCData.
|
|
2322
2336
|
* Generates and returns the GC data for this container.
|
|
2323
2337
|
* @param fullGC - true to bypass optimizations and force full generation of GC data.
|
|
2338
|
+
* @see IGarbageCollectionRuntime.getGCData
|
|
2324
2339
|
*/
|
|
2325
2340
|
public async getGCData(fullGC?: boolean): Promise<IGarbageCollectionData> {
|
|
2326
2341
|
const builder = new GCDataBuilder();
|
|
@@ -2333,9 +2348,9 @@ export class ContainerRuntime
|
|
|
2333
2348
|
}
|
|
2334
2349
|
|
|
2335
2350
|
/**
|
|
2336
|
-
* Implementation of IGarbageCollectionRuntime::updateUsedRoutes.
|
|
2337
2351
|
* After GC has run, called to notify this container's nodes of routes that are used in it.
|
|
2338
2352
|
* @param usedRoutes - The routes that are used in all nodes in this Container.
|
|
2353
|
+
* @see IGarbageCollectionRuntime.updateUsedRoutes
|
|
2339
2354
|
*/
|
|
2340
2355
|
public updateUsedRoutes(usedRoutes: string[]) {
|
|
2341
2356
|
// Update our summarizer node's used routes. Updating used routes in summarizer node before
|
|
@@ -2358,6 +2373,26 @@ export class ContainerRuntime
|
|
|
2358
2373
|
this.dataStores.updateUnusedRoutes(dataStoreRoutes);
|
|
2359
2374
|
}
|
|
2360
2375
|
|
|
2376
|
+
/**
|
|
2377
|
+
* @deprecated - Replaced by deleteSweepReadyNodes.
|
|
2378
|
+
*/
|
|
2379
|
+
public deleteUnusedNodes(unusedRoutes: string[]): string[] {
|
|
2380
|
+
throw new Error("deleteUnusedRoutes should not be called");
|
|
2381
|
+
}
|
|
2382
|
+
|
|
2383
|
+
/**
|
|
2384
|
+
* After GC has run and identified nodes that are sweep ready, this is called to delete the sweep ready nodes.
|
|
2385
|
+
* @param sweepReadyRoutes - The routes of nodes that are sweep ready and should be deleted.
|
|
2386
|
+
* @returns - The routes of nodes that were deleted.
|
|
2387
|
+
*/
|
|
2388
|
+
public deleteSweepReadyNodes(sweepReadyRoutes: string[]): string[] {
|
|
2389
|
+
const { dataStoreRoutes, blobManagerRoutes } =
|
|
2390
|
+
this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
|
|
2391
|
+
|
|
2392
|
+
const deletedRoutes = this.dataStores.deleteSweepReadyNodes(dataStoreRoutes);
|
|
2393
|
+
return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2361
2396
|
/**
|
|
2362
2397
|
* This is called to update objects that are tombstones.
|
|
2363
2398
|
* @param tombstonedRoutes - Data store and attachment blob routes that are tombstones in this Container.
|
|
@@ -2439,15 +2474,18 @@ export class ContainerRuntime
|
|
|
2439
2474
|
* Runs garbage collection and updates the reference / used state of the nodes in the container.
|
|
2440
2475
|
* @returns the statistics of the garbage collection run; undefined if GC did not run.
|
|
2441
2476
|
*/
|
|
2442
|
-
public async collectGarbage(
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2477
|
+
public async collectGarbage(
|
|
2478
|
+
options: {
|
|
2479
|
+
/** Logger to use for logging GC events */
|
|
2480
|
+
logger?: ITelemetryLogger;
|
|
2481
|
+
/** True to run GC sweep phase after the mark phase */
|
|
2482
|
+
runSweep?: boolean;
|
|
2483
|
+
/** True to generate full GC data */
|
|
2484
|
+
fullGC?: boolean;
|
|
2485
|
+
},
|
|
2486
|
+
telemetryContext?: ITelemetryContext,
|
|
2487
|
+
): Promise<IGCStats | undefined> {
|
|
2488
|
+
return this.garbageCollector.collectGarbage(options, telemetryContext);
|
|
2451
2489
|
}
|
|
2452
2490
|
|
|
2453
2491
|
/**
|
|
@@ -2472,7 +2510,7 @@ export class ContainerRuntime
|
|
|
2472
2510
|
* @param options - options controlling how the summary is generated or submitted
|
|
2473
2511
|
*/
|
|
2474
2512
|
public async submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult> {
|
|
2475
|
-
const { fullTree, refreshLatestAck, summaryLogger } = options;
|
|
2513
|
+
const { fullTree = false, refreshLatestAck, summaryLogger } = options;
|
|
2476
2514
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
2477
2515
|
// use it for all events logged during this summary.
|
|
2478
2516
|
const summaryNumber = this.nextSummaryNumber;
|
|
@@ -2494,8 +2532,15 @@ export class ContainerRuntime
|
|
|
2494
2532
|
await this.waitForDeltaManagerToCatchup(latestSnapshotRefSeq, summaryNumberLogger);
|
|
2495
2533
|
}
|
|
2496
2534
|
|
|
2535
|
+
const shouldPauseInboundSignal =
|
|
2536
|
+
this.mc.config.getBoolean(
|
|
2537
|
+
"Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause",
|
|
2538
|
+
) !== true;
|
|
2497
2539
|
try {
|
|
2498
2540
|
await this.deltaManager.inbound.pause();
|
|
2541
|
+
if (shouldPauseInboundSignal) {
|
|
2542
|
+
await this.deltaManager.inboundSignal.pause();
|
|
2543
|
+
}
|
|
2499
2544
|
|
|
2500
2545
|
const summaryRefSeqNum = this.deltaManager.lastSequenceNumber;
|
|
2501
2546
|
const minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
|
|
@@ -2560,7 +2605,7 @@ export class ContainerRuntime
|
|
|
2560
2605
|
const forcedFullTree = this.garbageCollector.summaryStateNeedsReset;
|
|
2561
2606
|
try {
|
|
2562
2607
|
summarizeResult = await this.summarize({
|
|
2563
|
-
fullTree: fullTree
|
|
2608
|
+
fullTree: fullTree || forcedFullTree,
|
|
2564
2609
|
trackState: true,
|
|
2565
2610
|
summaryLogger: summaryNumberLogger,
|
|
2566
2611
|
runGC: this.garbageCollector.shouldRunGC,
|
|
@@ -2674,7 +2719,7 @@ export class ContainerRuntime
|
|
|
2674
2719
|
|
|
2675
2720
|
let clientSequenceNumber: number;
|
|
2676
2721
|
try {
|
|
2677
|
-
clientSequenceNumber = this.submitSummaryMessage(summaryMessage);
|
|
2722
|
+
clientSequenceNumber = this.submitSummaryMessage(summaryMessage, summaryRefSeqNum);
|
|
2678
2723
|
} catch (error) {
|
|
2679
2724
|
return { stage: "upload", ...uploadData, error };
|
|
2680
2725
|
}
|
|
@@ -2691,8 +2736,12 @@ export class ContainerRuntime
|
|
|
2691
2736
|
} finally {
|
|
2692
2737
|
// Cleanup wip summary in case of failure
|
|
2693
2738
|
this.summarizerNode.clearSummary();
|
|
2739
|
+
|
|
2694
2740
|
// Restart the delta manager
|
|
2695
2741
|
this.deltaManager.inbound.resume();
|
|
2742
|
+
if (shouldPauseInboundSignal) {
|
|
2743
|
+
this.deltaManager.inboundSignal.resume();
|
|
2744
|
+
}
|
|
2696
2745
|
}
|
|
2697
2746
|
}
|
|
2698
2747
|
|
|
@@ -2763,10 +2812,11 @@ export class ContainerRuntime
|
|
|
2763
2812
|
0x132 /* "sending ops in detached container" */,
|
|
2764
2813
|
);
|
|
2765
2814
|
|
|
2766
|
-
const
|
|
2767
|
-
const serializedContent = JSON.stringify(deserializedContent);
|
|
2815
|
+
const serializedContent = JSON.stringify({ type, contents });
|
|
2768
2816
|
|
|
2769
|
-
|
|
2817
|
+
// Note that the real (non-proxy) delta manager is used here to get the readonly info. This is because
|
|
2818
|
+
// container runtime's ability to submit ops depend on the actual readonly state of the delta manager.
|
|
2819
|
+
if (this.innerDeltaManager.readOnlyInfo.readonly) {
|
|
2770
2820
|
this.logger.sendTelemetryEvent({
|
|
2771
2821
|
eventName: "SubmitOpInReadonly",
|
|
2772
2822
|
connected: this.connected,
|
|
@@ -2775,7 +2825,7 @@ export class ContainerRuntime
|
|
|
2775
2825
|
|
|
2776
2826
|
const message: BatchMessage = {
|
|
2777
2827
|
contents: serializedContent,
|
|
2778
|
-
deserializedContent,
|
|
2828
|
+
deserializedContent: JSON.parse(serializedContent), // Deep copy in case caller changes reference object
|
|
2779
2829
|
metadata,
|
|
2780
2830
|
localOpMetadata,
|
|
2781
2831
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
@@ -2805,7 +2855,7 @@ export class ContainerRuntime
|
|
|
2805
2855
|
if (
|
|
2806
2856
|
this.currentlyBatching() &&
|
|
2807
2857
|
type === ContainerMessageType.Attach &&
|
|
2808
|
-
this.
|
|
2858
|
+
this.disableAttachReorder !== true
|
|
2809
2859
|
) {
|
|
2810
2860
|
this.outbox.submitAttach(message);
|
|
2811
2861
|
} else {
|
|
@@ -2814,17 +2864,8 @@ export class ContainerRuntime
|
|
|
2814
2864
|
|
|
2815
2865
|
if (!this.currentlyBatching()) {
|
|
2816
2866
|
this.flush();
|
|
2817
|
-
} else
|
|
2818
|
-
this.
|
|
2819
|
-
// Queue a microtask to detect the end of the turn and force a flush.
|
|
2820
|
-
Promise.resolve()
|
|
2821
|
-
.then(() => {
|
|
2822
|
-
this.flushMicroTaskExists = false;
|
|
2823
|
-
this.flush();
|
|
2824
|
-
})
|
|
2825
|
-
.catch((error) => {
|
|
2826
|
-
this.closeFn(error as GenericError);
|
|
2827
|
-
});
|
|
2867
|
+
} else {
|
|
2868
|
+
this.scheduleFlush();
|
|
2828
2869
|
}
|
|
2829
2870
|
} catch (error) {
|
|
2830
2871
|
this.closeFn(error as GenericError);
|
|
@@ -2836,7 +2877,47 @@ export class ContainerRuntime
|
|
|
2836
2877
|
}
|
|
2837
2878
|
}
|
|
2838
2879
|
|
|
2839
|
-
private
|
|
2880
|
+
private scheduleFlush() {
|
|
2881
|
+
if (this.flushTaskExists) {
|
|
2882
|
+
return;
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
this.flushTaskExists = true;
|
|
2886
|
+
const flush = () => {
|
|
2887
|
+
this.flushTaskExists = false;
|
|
2888
|
+
try {
|
|
2889
|
+
this.flush();
|
|
2890
|
+
} catch (error) {
|
|
2891
|
+
this.closeFn(error as GenericError);
|
|
2892
|
+
}
|
|
2893
|
+
};
|
|
2894
|
+
|
|
2895
|
+
switch (this.flushMode) {
|
|
2896
|
+
case FlushMode.TurnBased:
|
|
2897
|
+
// When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
|
|
2898
|
+
// batch at the end of the turn
|
|
2899
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
2900
|
+
Promise.resolve().then(flush);
|
|
2901
|
+
break;
|
|
2902
|
+
|
|
2903
|
+
// FlushModeExperimental is experimental and not exposed directly in the runtime APIs
|
|
2904
|
+
case FlushModeExperimental.Async as unknown as FlushMode:
|
|
2905
|
+
// When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
|
|
2906
|
+
// batch when all micro-tasks are complete.
|
|
2907
|
+
// Compared to TurnBased, this flush mode will capture more ops into the same batch.
|
|
2908
|
+
setTimeout(flush, 0);
|
|
2909
|
+
break;
|
|
2910
|
+
|
|
2911
|
+
default:
|
|
2912
|
+
assert(
|
|
2913
|
+
this._orderSequentiallyCalls > 0,
|
|
2914
|
+
0x587 /* Unreachable unless running under orderSequentially */,
|
|
2915
|
+
);
|
|
2916
|
+
break;
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
|
|
2920
|
+
private submitSummaryMessage(contents: ISummaryContent, referenceSequenceNumber: number) {
|
|
2840
2921
|
this.verifyNotClosed();
|
|
2841
2922
|
assert(
|
|
2842
2923
|
this.connected,
|
|
@@ -2848,7 +2929,7 @@ export class ContainerRuntime
|
|
|
2848
2929
|
|
|
2849
2930
|
// back-compat: ADO #1385: Make this call unconditional in the future
|
|
2850
2931
|
return this.context.submitSummaryFn !== undefined
|
|
2851
|
-
? this.context.submitSummaryFn(contents)
|
|
2932
|
+
? this.context.submitSummaryFn(contents, referenceSequenceNumber)
|
|
2852
2933
|
: this.context.submitFn(MessageType.Summarize, contents, false);
|
|
2853
2934
|
}
|
|
2854
2935
|
|
|
@@ -2967,18 +3048,17 @@ export class ContainerRuntime
|
|
|
2967
3048
|
// The call to fetch the snapshot is very expensive and not always needed.
|
|
2968
3049
|
// It should only be done by the summarizerNode, if required.
|
|
2969
3050
|
// When fetching from storage we will always get the latest version and do not use the ackHandle.
|
|
2970
|
-
const
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
const latestSnapshotRefSeq = await seqFromTree(
|
|
2979
|
-
fetchResult.snapshotTree,
|
|
3051
|
+
const fetchLatestSnapshot: () => Promise<IFetchSnapshotResult> = async () => {
|
|
3052
|
+
let fetchResult = await this.fetchLatestSnapshotFromStorage(
|
|
3053
|
+
summaryLogger,
|
|
3054
|
+
{
|
|
3055
|
+
eventName: "RefreshLatestSummaryAckFetch",
|
|
3056
|
+
ackHandle,
|
|
3057
|
+
targetSequenceNumber: summaryRefSeq,
|
|
3058
|
+
},
|
|
2980
3059
|
readAndParseBlob,
|
|
2981
3060
|
);
|
|
3061
|
+
|
|
2982
3062
|
/**
|
|
2983
3063
|
* If the fetched snapshot is older than the one for which the ack was received, close the container.
|
|
2984
3064
|
* This should never happen because an ack should be sent after the latest summary is updated in the server.
|
|
@@ -2989,50 +3069,58 @@ export class ContainerRuntime
|
|
|
2989
3069
|
* such cases, the file will be rolled back along with the ack and we will eventually reach a consistent
|
|
2990
3070
|
* state.
|
|
2991
3071
|
*/
|
|
2992
|
-
if (latestSnapshotRefSeq < summaryRefSeq) {
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
undefined /* sequencedMessage */,
|
|
3072
|
+
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
3073
|
+
/* before failing, let's try to retrieve the latest snapshot for that specific ackHandle */
|
|
3074
|
+
fetchResult = await this.fetchSnapshotFromStorage(
|
|
3075
|
+
summaryLogger,
|
|
2997
3076
|
{
|
|
3077
|
+
eventName: "RefreshLatestSummaryAckFetch",
|
|
2998
3078
|
ackHandle,
|
|
2999
|
-
summaryRefSeq,
|
|
3000
|
-
latestSnapshotRefSeq,
|
|
3079
|
+
targetSequenceNumber: summaryRefSeq,
|
|
3001
3080
|
},
|
|
3081
|
+
readAndParseBlob,
|
|
3082
|
+
ackHandle,
|
|
3002
3083
|
);
|
|
3003
|
-
this.closeFn(error);
|
|
3004
|
-
throw error;
|
|
3005
|
-
}
|
|
3006
3084
|
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3085
|
+
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
3086
|
+
const error = DataProcessingError.create(
|
|
3087
|
+
"Fetched snapshot is older than the received ack",
|
|
3088
|
+
"RefreshLatestSummaryAck",
|
|
3089
|
+
undefined /* sequencedMessage */,
|
|
3090
|
+
{
|
|
3091
|
+
ackHandle,
|
|
3092
|
+
summaryRefSeq,
|
|
3093
|
+
fetchedSnapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
3094
|
+
},
|
|
3095
|
+
);
|
|
3096
|
+
this.closeFn(error);
|
|
3097
|
+
throw error;
|
|
3098
|
+
}
|
|
3099
|
+
}
|
|
3013
3100
|
|
|
3014
3101
|
// In case we had to retrieve the latest snapshot and it is different than summaryRefSeq,
|
|
3015
3102
|
// wait for the delta manager to catch up before refreshing the latest Summary.
|
|
3016
|
-
await this.waitForDeltaManagerToCatchup(
|
|
3103
|
+
await this.waitForDeltaManagerToCatchup(
|
|
3104
|
+
fetchResult.latestSnapshotRefSeq,
|
|
3105
|
+
summaryLogger,
|
|
3106
|
+
);
|
|
3017
3107
|
|
|
3018
|
-
return
|
|
3108
|
+
return {
|
|
3109
|
+
snapshotTree: fetchResult.snapshotTree,
|
|
3110
|
+
snapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
3111
|
+
};
|
|
3019
3112
|
};
|
|
3020
3113
|
|
|
3021
3114
|
const result = await this.summarizerNode.refreshLatestSummary(
|
|
3022
3115
|
proposalHandle,
|
|
3023
3116
|
summaryRefSeq,
|
|
3024
|
-
|
|
3117
|
+
fetchLatestSnapshot,
|
|
3025
3118
|
readAndParseBlob,
|
|
3026
3119
|
summaryLogger,
|
|
3027
3120
|
);
|
|
3028
3121
|
|
|
3029
3122
|
// Notify the garbage collector so it can update its latest summary state.
|
|
3030
|
-
await this.garbageCollector.refreshLatestSummary(
|
|
3031
|
-
result,
|
|
3032
|
-
proposalHandle,
|
|
3033
|
-
summaryRefSeq,
|
|
3034
|
-
readAndParseBlob,
|
|
3035
|
-
);
|
|
3123
|
+
await this.garbageCollector.refreshLatestSummary(proposalHandle, result, readAndParseBlob);
|
|
3036
3124
|
}
|
|
3037
3125
|
|
|
3038
3126
|
/**
|
|
@@ -3044,30 +3132,31 @@ export class ContainerRuntime
|
|
|
3044
3132
|
private async refreshLatestSummaryAckFromServer(
|
|
3045
3133
|
summaryLogger: ITelemetryLogger,
|
|
3046
3134
|
): Promise<{ latestSnapshotRefSeq: number; latestSnapshotVersionId: string | undefined }> {
|
|
3047
|
-
const { snapshotTree, versionId } = await this.fetchLatestSnapshotFromStorage(
|
|
3048
|
-
summaryLogger,
|
|
3049
|
-
{
|
|
3050
|
-
eventName: "RefreshLatestSummaryGetSnapshot",
|
|
3051
|
-
fetchLatest: true,
|
|
3052
|
-
},
|
|
3053
|
-
);
|
|
3054
|
-
|
|
3055
3135
|
const readAndParseBlob = async <T>(id: string) => readAndParse<T>(this.storage, id);
|
|
3056
|
-
const
|
|
3057
|
-
|
|
3136
|
+
const { snapshotTree, versionId, latestSnapshotRefSeq } =
|
|
3137
|
+
await this.fetchLatestSnapshotFromStorage(
|
|
3138
|
+
summaryLogger,
|
|
3139
|
+
{
|
|
3140
|
+
eventName: "RefreshLatestSummaryFromServerFetch",
|
|
3141
|
+
},
|
|
3142
|
+
readAndParseBlob,
|
|
3143
|
+
);
|
|
3144
|
+
const fetchLatestSnapshot: IFetchSnapshotResult = {
|
|
3145
|
+
snapshotTree,
|
|
3146
|
+
snapshotRefSeq: latestSnapshotRefSeq,
|
|
3147
|
+
};
|
|
3058
3148
|
const result = await this.summarizerNode.refreshLatestSummary(
|
|
3059
|
-
undefined
|
|
3149
|
+
undefined /* proposalHandle */,
|
|
3060
3150
|
latestSnapshotRefSeq,
|
|
3061
|
-
async () =>
|
|
3151
|
+
async () => fetchLatestSnapshot,
|
|
3062
3152
|
readAndParseBlob,
|
|
3063
3153
|
summaryLogger,
|
|
3064
3154
|
);
|
|
3065
3155
|
|
|
3066
3156
|
// Notify the garbage collector so it can update its latest summary state.
|
|
3067
3157
|
await this.garbageCollector.refreshLatestSummary(
|
|
3158
|
+
undefined /* proposalHandle */,
|
|
3068
3159
|
result,
|
|
3069
|
-
undefined,
|
|
3070
|
-
latestSnapshotRefSeq,
|
|
3071
3160
|
readAndParseBlob,
|
|
3072
3161
|
);
|
|
3073
3162
|
|
|
@@ -3077,7 +3166,17 @@ export class ContainerRuntime
|
|
|
3077
3166
|
private async fetchLatestSnapshotFromStorage(
|
|
3078
3167
|
logger: ITelemetryLogger,
|
|
3079
3168
|
event: ITelemetryGenericEvent,
|
|
3080
|
-
|
|
3169
|
+
readAndParseBlob: ReadAndParseBlob,
|
|
3170
|
+
): Promise<{ snapshotTree: ISnapshotTree; versionId: string; latestSnapshotRefSeq: number }> {
|
|
3171
|
+
return this.fetchSnapshotFromStorage(logger, event, readAndParseBlob, null /* latest */);
|
|
3172
|
+
}
|
|
3173
|
+
|
|
3174
|
+
private async fetchSnapshotFromStorage(
|
|
3175
|
+
logger: ITelemetryLogger,
|
|
3176
|
+
event: ITelemetryGenericEvent,
|
|
3177
|
+
readAndParseBlob: ReadAndParseBlob,
|
|
3178
|
+
versionId: string | null,
|
|
3179
|
+
): Promise<{ snapshotTree: ISnapshotTree; versionId: string; latestSnapshotRefSeq: number }> {
|
|
3081
3180
|
return PerformanceEvent.timedExecAsync(
|
|
3082
3181
|
logger,
|
|
3083
3182
|
event,
|
|
@@ -3085,16 +3184,23 @@ export class ContainerRuntime
|
|
|
3085
3184
|
end: (arg0: {
|
|
3086
3185
|
getVersionDuration?: number | undefined;
|
|
3087
3186
|
getSnapshotDuration?: number | undefined;
|
|
3187
|
+
snapshotRefSeq?: number | undefined;
|
|
3188
|
+
snapshotVersion?: string | undefined;
|
|
3088
3189
|
}) => void;
|
|
3089
3190
|
}) => {
|
|
3090
|
-
const stats: {
|
|
3191
|
+
const stats: {
|
|
3192
|
+
getVersionDuration?: number;
|
|
3193
|
+
getSnapshotDuration?: number;
|
|
3194
|
+
snapshotRefSeq?: number;
|
|
3195
|
+
snapshotVersion?: string;
|
|
3196
|
+
} = {};
|
|
3091
3197
|
const trace = Trace.start();
|
|
3092
3198
|
|
|
3093
3199
|
const versions = await this.storage.getVersions(
|
|
3094
|
-
|
|
3200
|
+
versionId,
|
|
3095
3201
|
1,
|
|
3096
3202
|
"refreshLatestSummaryAckFromServer",
|
|
3097
|
-
FetchSource.noCache,
|
|
3203
|
+
versionId === null ? FetchSource.noCache : undefined,
|
|
3098
3204
|
);
|
|
3099
3205
|
assert(
|
|
3100
3206
|
!!versions && !!versions[0],
|
|
@@ -3105,51 +3211,23 @@ export class ContainerRuntime
|
|
|
3105
3211
|
const maybeSnapshot = await this.storage.getSnapshotTree(versions[0]);
|
|
3106
3212
|
assert(!!maybeSnapshot, 0x138 /* "Failed to get snapshot from storage" */);
|
|
3107
3213
|
stats.getSnapshotDuration = trace.trace().duration;
|
|
3214
|
+
const latestSnapshotRefSeq = await seqFromTree(maybeSnapshot, readAndParseBlob);
|
|
3215
|
+
stats.snapshotRefSeq = latestSnapshotRefSeq;
|
|
3216
|
+
stats.snapshotVersion = versions[0].id;
|
|
3108
3217
|
|
|
3109
3218
|
perfEvent.end(stats);
|
|
3110
|
-
return {
|
|
3219
|
+
return {
|
|
3220
|
+
snapshotTree: maybeSnapshot,
|
|
3221
|
+
versionId: versions[0].id,
|
|
3222
|
+
latestSnapshotRefSeq,
|
|
3223
|
+
};
|
|
3111
3224
|
},
|
|
3112
3225
|
);
|
|
3113
3226
|
}
|
|
3114
3227
|
|
|
3115
|
-
public notifyAttaching(
|
|
3116
|
-
if (
|
|
3117
|
-
this.mc.config.getBoolean("enableOfflineLoad") ??
|
|
3118
|
-
this.runtimeOptions.enableOfflineLoad
|
|
3119
|
-
) {
|
|
3120
|
-
this.baseSnapshotBlobs =
|
|
3121
|
-
SerializedSnapshotStorage.serializeTreeWithBlobContents(snapshot);
|
|
3122
|
-
}
|
|
3123
|
-
}
|
|
3124
|
-
|
|
3125
|
-
private async initializeBaseSnapshotBlobs(): Promise<void> {
|
|
3126
|
-
if (
|
|
3127
|
-
!(
|
|
3128
|
-
this.mc.config.getBoolean("enableOfflineLoad") ??
|
|
3129
|
-
this.runtimeOptions.enableOfflineLoad
|
|
3130
|
-
) ||
|
|
3131
|
-
this.attachState !== AttachState.Attached ||
|
|
3132
|
-
this.context.pendingLocalState
|
|
3133
|
-
) {
|
|
3134
|
-
return;
|
|
3135
|
-
}
|
|
3136
|
-
assert(!!this.context.baseSnapshot, 0x2e5 /* "Must have a base snapshot" */);
|
|
3137
|
-
this.baseSnapshotBlobs = await SerializedSnapshotStorage.serializeTree(
|
|
3138
|
-
this.context.baseSnapshot,
|
|
3139
|
-
this.storage,
|
|
3140
|
-
);
|
|
3141
|
-
}
|
|
3228
|
+
public notifyAttaching() {} // do nothing (deprecated method)
|
|
3142
3229
|
|
|
3143
3230
|
public getPendingLocalState(): unknown {
|
|
3144
|
-
if (
|
|
3145
|
-
!(
|
|
3146
|
-
this.mc.config.getBoolean("enableOfflineLoad") ??
|
|
3147
|
-
this.runtimeOptions.enableOfflineLoad
|
|
3148
|
-
)
|
|
3149
|
-
) {
|
|
3150
|
-
throw new UsageError("can't get state when offline load disabled");
|
|
3151
|
-
}
|
|
3152
|
-
|
|
3153
3231
|
if (this._orderSequentiallyCalls !== 0) {
|
|
3154
3232
|
throw new UsageError("can't get state during orderSequentially");
|
|
3155
3233
|
}
|
|
@@ -3158,29 +3236,9 @@ export class ContainerRuntime
|
|
|
3158
3236
|
// to close current batch.
|
|
3159
3237
|
this.flush();
|
|
3160
3238
|
|
|
3161
|
-
const previousPendingState = this.context.pendingLocalState as
|
|
3162
|
-
| IPendingRuntimeState
|
|
3163
|
-
| undefined;
|
|
3164
|
-
if (previousPendingState) {
|
|
3165
|
-
return {
|
|
3166
|
-
pending: this.pendingStateManager.getLocalState(),
|
|
3167
|
-
pendingAttachmentBlobs: this.blobManager.getPendingBlobs(),
|
|
3168
|
-
snapshotBlobs: previousPendingState.snapshotBlobs,
|
|
3169
|
-
baseSnapshot: previousPendingState.baseSnapshot,
|
|
3170
|
-
savedOps: this.savedOps,
|
|
3171
|
-
};
|
|
3172
|
-
}
|
|
3173
|
-
assert(!!this.context.baseSnapshot, 0x2e6 /* "Must have a base snapshot" */);
|
|
3174
|
-
assert(
|
|
3175
|
-
!!this.baseSnapshotBlobs,
|
|
3176
|
-
0x2e7 /* "Must serialize base snapshot blobs before getting runtime state" */,
|
|
3177
|
-
);
|
|
3178
3239
|
return {
|
|
3179
3240
|
pending: this.pendingStateManager.getLocalState(),
|
|
3180
3241
|
pendingAttachmentBlobs: this.blobManager.getPendingBlobs(),
|
|
3181
|
-
snapshotBlobs: this.baseSnapshotBlobs,
|
|
3182
|
-
baseSnapshot: this.context.baseSnapshot,
|
|
3183
|
-
savedOps: this.savedOps,
|
|
3184
3242
|
};
|
|
3185
3243
|
}
|
|
3186
3244
|
|
|
@@ -3243,25 +3301,6 @@ export class ContainerRuntime
|
|
|
3243
3301
|
};
|
|
3244
3302
|
}
|
|
3245
3303
|
|
|
3246
|
-
private async processSavedOps(state: IPendingRuntimeState) {
|
|
3247
|
-
for (const op of state.savedOps) {
|
|
3248
|
-
this.process(op, false);
|
|
3249
|
-
await this.pendingStateManager.applyStashedOpsAt(op.sequenceNumber);
|
|
3250
|
-
}
|
|
3251
|
-
// we may not have seen every sequence number (because of system ops) so apply everything once we
|
|
3252
|
-
// don't have any more saved ops
|
|
3253
|
-
await this.pendingStateManager.applyStashedOpsAt();
|
|
3254
|
-
|
|
3255
|
-
// If it's not the case, we should take it into account when calculating dirty state.
|
|
3256
|
-
assert(
|
|
3257
|
-
this.context.attachState === AttachState.Attached,
|
|
3258
|
-
0x3d5 /* this function is called for attached containers only */,
|
|
3259
|
-
);
|
|
3260
|
-
if (!this.hasPendingMessages()) {
|
|
3261
|
-
this.updateDocumentDirtyState(false);
|
|
3262
|
-
}
|
|
3263
|
-
}
|
|
3264
|
-
|
|
3265
3304
|
private validateSummaryHeuristicConfiguration(configuration: ISummaryConfigurationHeuristics) {
|
|
3266
3305
|
// eslint-disable-next-line no-restricted-syntax
|
|
3267
3306
|
for (const prop in configuration) {
|