@fluidframework/container-runtime 2.0.0-dev.2.3.0.115467 → 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/.eslintrc.js +21 -10
- package/.mocharc.js +2 -2
- package/api-extractor.json +2 -2
- package/dist/batchTracker.d.ts +1 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +2 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +74 -42
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +321 -152
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +11 -9
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +3 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +148 -114
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +534 -342
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +11 -9
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +40 -13
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +146 -66
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +7 -3
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +3 -1
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts +39 -12
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +164 -76
- 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/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +8 -3
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +204 -0
- package/dist/gc/garbageCollection.d.ts.map +1 -0
- package/dist/gc/garbageCollection.js +926 -0
- 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/{lib → dist/gc}/gcSweepReadyUsageDetection.d.ts +5 -5
- package/dist/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
- package/dist/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +15 -11
- 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 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -13
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +10 -0
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +37 -8
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +29 -1
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +3 -3
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +3 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +46 -17
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +6 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +72 -18
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +46 -2
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +142 -5
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +23 -2
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +101 -51
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +17 -2
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/opProperties.d.ts.map +1 -1
- package/dist/opProperties.js +1 -3
- package/dist/opProperties.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 +6 -15
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +137 -165
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts +0 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +11 -21
- package/dist/scheduleManager.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/{orderedClientElection.js → summary/orderedClientElection.js} +10 -4
- package/dist/summary/orderedClientElection.js.map +1 -0
- package/{lib → dist/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} +191 -77
- package/dist/summary/runningSummarizer.js.map +1 -0
- package/dist/{summarizer.d.ts → summary/summarizer.d.ts} +6 -12
- package/dist/summary/summarizer.d.ts.map +1 -0
- package/dist/{summarizer.js → summary/summarizer.js} +32 -76
- package/dist/summary/summarizer.js.map +1 -0
- package/dist/{summarizerClientElection.d.ts → summary/summarizerClientElection.d.ts} +1 -2
- package/dist/summary/summarizerClientElection.d.ts.map +1 -0
- package/dist/{summarizerClientElection.js → summary/summarizerClientElection.js} +3 -30
- package/dist/summary/summarizerClientElection.js.map +1 -0
- package/dist/{summarizerHeuristics.d.ts → summary/summarizerHeuristics.d.ts} +1 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -0
- package/dist/{summarizerHeuristics.js → summary/summarizerHeuristics.js} +9 -12
- 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 +29 -42
- 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/{summaryCollection.js → summary/summaryCollection.js} +18 -8
- 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} +19 -21
- package/dist/summary/summaryFormat.js.map +1 -0
- package/dist/summary/summaryGenerator.d.ts.map +1 -0
- package/dist/{summaryGenerator.js → summary/summaryGenerator.js} +34 -16
- 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/{summaryManager.js → summary/summaryManager.js} +21 -9
- package/dist/summary/summaryManager.js.map +1 -0
- package/dist/throttler.d.ts +2 -2
- package/dist/throttler.d.ts.map +1 -1
- package/dist/throttler.js +4 -4
- package/dist/throttler.js.map +1 -1
- package/lib/batchTracker.d.ts +1 -2
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +74 -42
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +322 -153
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +11 -9
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +3 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +148 -114
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +506 -314
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +11 -9
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +40 -13
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +136 -56
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +7 -3
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +3 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts +39 -12
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +162 -74
- 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/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +9 -4
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +204 -0
- package/lib/gc/garbageCollection.d.ts.map +1 -0
- package/lib/gc/garbageCollection.js +922 -0
- 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/{dist → lib/gc}/gcSweepReadyUsageDetection.d.ts +5 -5
- package/lib/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
- package/lib/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +15 -11
- 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 -8
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -6
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +10 -0
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +35 -7
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +29 -1
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +3 -3
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js +2 -2
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +47 -18
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +6 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +72 -18
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +46 -2
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +141 -5
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +23 -2
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +103 -53
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +17 -2
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/opProperties.d.ts.map +1 -1
- package/lib/opProperties.js +1 -3
- package/lib/opProperties.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 +6 -15
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +137 -165
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.d.ts +0 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +11 -21
- package/lib/scheduleManager.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/{orderedClientElection.js → summary/orderedClientElection.js} +10 -4
- package/lib/summary/orderedClientElection.js.map +1 -0
- package/{dist → lib/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} +193 -79
- package/lib/summary/runningSummarizer.js.map +1 -0
- package/lib/{summarizer.d.ts → summary/summarizer.d.ts} +6 -12
- package/lib/summary/summarizer.d.ts.map +1 -0
- package/lib/{summarizer.js → summary/summarizer.js} +34 -78
- package/lib/summary/summarizer.js.map +1 -0
- package/lib/{summarizerClientElection.d.ts → summary/summarizerClientElection.d.ts} +1 -2
- package/lib/summary/summarizerClientElection.d.ts.map +1 -0
- package/lib/{summarizerClientElection.js → summary/summarizerClientElection.js} +3 -30
- package/lib/summary/summarizerClientElection.js.map +1 -0
- package/lib/{summarizerHeuristics.d.ts → summary/summarizerHeuristics.d.ts} +1 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
- package/lib/{summarizerHeuristics.js → summary/summarizerHeuristics.js} +9 -12
- 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 +29 -42
- package/lib/summary/summarizerTypes.d.ts.map +1 -0
- package/lib/summary/summarizerTypes.js +6 -0
- package/lib/summary/summarizerTypes.js.map +1 -0
- package/lib/summary/summaryCollection.d.ts.map +1 -0
- package/lib/{summaryCollection.js → summary/summaryCollection.js} +18 -8
- 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} +20 -21
- package/lib/summary/summaryFormat.js.map +1 -0
- package/lib/summary/summaryGenerator.d.ts.map +1 -0
- package/lib/{summaryGenerator.js → summary/summaryGenerator.js} +34 -16
- 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/{summaryManager.js → summary/summaryManager.js} +21 -9
- package/lib/summary/summaryManager.js.map +1 -0
- package/lib/throttler.d.ts +2 -2
- package/lib/throttler.d.ts.map +1 -1
- package/lib/throttler.js +4 -4
- package/lib/throttler.js.map +1 -1
- package/package.json +67 -61
- package/prettier.config.cjs +1 -1
- package/src/batchTracker.ts +55 -50
- package/src/blobManager.ts +863 -594
- package/src/connectionTelemetry.ts +280 -249
- package/src/containerHandleContext.ts +27 -29
- package/src/containerRuntime.ts +3174 -2805
- package/src/dataStore.ts +172 -159
- package/src/dataStoreContext.ts +1141 -993
- package/src/dataStoreContexts.ts +178 -161
- package/src/dataStoreRegistry.ts +25 -20
- package/src/dataStores.ts +887 -716
- package/src/deltaManagerSummarizerProxy.ts +46 -0
- package/src/deltaScheduler.ts +158 -150
- package/{garbageCollection.md → src/gc/garbageCollection.md} +16 -3
- package/src/gc/garbageCollection.ts +1250 -0
- 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/gc/gcSweepReadyUsageDetection.ts +145 -0
- package/src/gc/gcUnreferencedStateTracker.ts +114 -0
- package/src/gc/index.ts +65 -0
- package/src/index.ts +61 -75
- package/src/opLifecycle/README.md +157 -0
- package/src/opLifecycle/batchManager.ts +119 -86
- package/src/opLifecycle/definitions.ts +49 -19
- package/src/opLifecycle/index.ts +7 -6
- package/src/opLifecycle/opCompressor.ts +78 -40
- package/src/opLifecycle/opDecompressor.ts +148 -64
- package/src/opLifecycle/opSplitter.ts +269 -66
- package/src/opLifecycle/outbox.ts +268 -184
- package/src/opLifecycle/remoteMessageProcessor.ts +63 -47
- package/src/opProperties.ts +11 -9
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +386 -381
- package/src/scheduleManager.ts +299 -280
- package/src/storageServiceWithAttachBlobs.ts +38 -0
- package/src/summary/index.ts +105 -0
- package/src/summary/orderedClientElection.ts +564 -0
- package/src/summary/runWhileConnectedCoordinator.ts +113 -0
- package/src/summary/runningSummarizer.ts +788 -0
- package/src/summary/summarizer.ts +372 -0
- package/src/summary/summarizerClientElection.ts +139 -0
- package/src/summary/summarizerHeuristics.ts +224 -0
- 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/summary/summarizerTypes.ts +507 -0
- package/src/summary/summaryCollection.ts +450 -0
- package/src/summary/summaryFormat.ts +228 -0
- package/src/summary/summaryGenerator.ts +505 -0
- package/src/summary/summaryManager.ts +423 -0
- package/src/throttler.ts +131 -122
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +9 -13
- package/dist/garbageCollection.d.ts +0 -387
- package/dist/garbageCollection.d.ts.map +0 -1
- package/dist/garbageCollection.js +0 -1138
- package/dist/garbageCollection.js.map +0 -1
- package/dist/garbageCollectionConstants.d.ts +0 -19
- package/dist/garbageCollectionConstants.d.ts.map +0 -1
- package/dist/garbageCollectionConstants.js +0 -34
- package/dist/garbageCollectionConstants.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 -108
- 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/summarizerTypes.js.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 -387
- package/lib/garbageCollection.d.ts.map +0 -1
- package/lib/garbageCollection.js +0 -1133
- package/lib/garbageCollection.js.map +0 -1
- package/lib/garbageCollectionConstants.d.ts +0 -19
- package/lib/garbageCollectionConstants.d.ts.map +0 -1
- package/lib/garbageCollectionConstants.js +0 -31
- package/lib/garbageCollectionConstants.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 -104
- 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/garbageCollection.ts +0 -1646
- package/src/garbageCollectionConstants.ts +0 -35
- package/src/gcSweepReadyUsageDetection.ts +0 -139
- package/src/orderedClientElection.ts +0 -532
- package/src/runWhileConnectedCoordinator.ts +0 -106
- package/src/runningSummarizer.ts +0 -611
- package/src/serializedSnapshotStorage.ts +0 -146
- package/src/summarizer.ts +0 -421
- package/src/summarizerClientElection.ts +0 -161
- package/src/summarizerHandle.ts +0 -21
- package/src/summarizerHeuristics.ts +0 -222
- package/src/summarizerTypes.ts +0 -510
- package/src/summaryCollection.ts +0 -421
- package/src/summaryFormat.ts +0 -235
- package/src/summaryGenerator.ts +0 -446
- package/src/summaryManager.ts +0 -394
- /package/dist/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
- /package/dist/{summaryCollection.d.ts → summary/summaryCollection.d.ts} +0 -0
- /package/dist/{summaryGenerator.d.ts → summary/summaryGenerator.d.ts} +0 -0
- /package/lib/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
- /package/lib/{summaryCollection.d.ts → summary/summaryCollection.d.ts} +0 -0
- /package/lib/{summaryGenerator.d.ts → summary/summaryGenerator.d.ts} +0 -0
package/dist/containerRuntime.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ContainerRuntime = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.RuntimeMessage = exports.CompressionAlgorithms = exports.RuntimeHeaders = exports.DefaultSummaryConfiguration = exports.ContainerMessageType = void 0;
|
|
3
|
+
exports.ContainerRuntime = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.RuntimeMessage = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.TombstoneResponseHeaderKey = exports.AllowTombstoneRequestHeaderKey = exports.RuntimeHeaders = exports.DefaultSummaryConfiguration = exports.ContainerMessageType = void 0;
|
|
4
4
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
5
5
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
6
6
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
@@ -10,30 +10,22 @@ const container_utils_1 = require("@fluidframework/container-utils");
|
|
|
10
10
|
const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
11
11
|
const runtime_definitions_1 = require("@fluidframework/runtime-definitions");
|
|
12
12
|
const runtime_utils_1 = require("@fluidframework/runtime-utils");
|
|
13
|
-
const garbage_collector_1 = require("@fluidframework/garbage-collector");
|
|
14
13
|
const uuid_1 = require("uuid");
|
|
15
14
|
const containerHandleContext_1 = require("./containerHandleContext");
|
|
16
15
|
const dataStoreRegistry_1 = require("./dataStoreRegistry");
|
|
17
|
-
const summarizer_1 = require("./summarizer");
|
|
18
|
-
const summaryManager_1 = require("./summaryManager");
|
|
19
16
|
const connectionTelemetry_1 = require("./connectionTelemetry");
|
|
20
17
|
const pendingStateManager_1 = require("./pendingStateManager");
|
|
21
18
|
const packageVersion_1 = require("./packageVersion");
|
|
22
19
|
const blobManager_1 = require("./blobManager");
|
|
23
20
|
const dataStores_1 = require("./dataStores");
|
|
24
|
-
const
|
|
25
|
-
const summaryCollection_1 = require("./summaryCollection");
|
|
26
|
-
const orderedClientElection_1 = require("./orderedClientElection");
|
|
27
|
-
const summarizerClientElection_1 = require("./summarizerClientElection");
|
|
21
|
+
const summary_1 = require("./summary");
|
|
28
22
|
const throttler_1 = require("./throttler");
|
|
29
|
-
const
|
|
30
|
-
const garbageCollection_1 = require("./garbageCollection");
|
|
31
|
-
const garbageCollectionConstants_1 = require("./garbageCollectionConstants");
|
|
23
|
+
const gc_1 = require("./gc");
|
|
32
24
|
const dataStore_1 = require("./dataStore");
|
|
33
25
|
const batchTracker_1 = require("./batchTracker");
|
|
34
|
-
const serializedSnapshotStorage_1 = require("./serializedSnapshotStorage");
|
|
35
26
|
const scheduleManager_1 = require("./scheduleManager");
|
|
36
27
|
const opLifecycle_1 = require("./opLifecycle");
|
|
28
|
+
const deltaManagerSummarizerProxy_1 = require("./deltaManagerSummarizerProxy");
|
|
37
29
|
var ContainerMessageType;
|
|
38
30
|
(function (ContainerMessageType) {
|
|
39
31
|
// An op to be delivered to store
|
|
@@ -59,7 +51,6 @@ exports.DefaultSummaryConfiguration = {
|
|
|
59
51
|
maxAckWaitTime: 10 * 60 * 1000,
|
|
60
52
|
maxOpsSinceLastSummary: 7000,
|
|
61
53
|
initialSummarizerDelayMs: 5 * 1000,
|
|
62
|
-
summarizerClientElection: false,
|
|
63
54
|
nonRuntimeOpWeight: 0.1,
|
|
64
55
|
runtimeOpWeight: 1.0,
|
|
65
56
|
nonRuntimeHeuristicThreshold: 20,
|
|
@@ -71,14 +62,19 @@ var RuntimeHeaders;
|
|
|
71
62
|
(function (RuntimeHeaders) {
|
|
72
63
|
/** True to wait for a data store to be created and loaded before returning it. */
|
|
73
64
|
RuntimeHeaders["wait"] = "wait";
|
|
74
|
-
/**
|
|
75
|
-
* True if the request is from an external app. Used for GC to handle scenarios where a data store
|
|
76
|
-
* is deleted and requested via an external app.
|
|
77
|
-
*/
|
|
78
|
-
RuntimeHeaders["externalRequest"] = "externalRequest";
|
|
79
65
|
/** True if the request is coming from an IFluidHandle. */
|
|
80
66
|
RuntimeHeaders["viaHandle"] = "viaHandle";
|
|
81
67
|
})(RuntimeHeaders = exports.RuntimeHeaders || (exports.RuntimeHeaders = {}));
|
|
68
|
+
/** True if a tombstoned object should be returned without erroring */
|
|
69
|
+
exports.AllowTombstoneRequestHeaderKey = "allowTombstone"; // Belongs in the enum above, but avoiding the breaking change
|
|
70
|
+
/** Tombstone error responses will have this header set to true */
|
|
71
|
+
exports.TombstoneResponseHeaderKey = "isTombstoned";
|
|
72
|
+
/** Default values for Runtime Headers */
|
|
73
|
+
exports.defaultRuntimeHeaderData = {
|
|
74
|
+
wait: true,
|
|
75
|
+
viaHandle: false,
|
|
76
|
+
allowTombstone: false,
|
|
77
|
+
};
|
|
82
78
|
/**
|
|
83
79
|
* Available compression algorithms for op compression.
|
|
84
80
|
*/
|
|
@@ -92,7 +88,13 @@ const defaultFlushMode = runtime_definitions_1.FlushMode.TurnBased;
|
|
|
92
88
|
// We can't estimate it fully, as we
|
|
93
89
|
// - do not know what properties relay service will add
|
|
94
90
|
// - we do not stringify final op, thus we do not know how much escaping will be added.
|
|
95
|
-
const defaultMaxBatchSizeInBytes =
|
|
91
|
+
const defaultMaxBatchSizeInBytes = 700 * 1024;
|
|
92
|
+
const defaultCompressionConfig = {
|
|
93
|
+
// Batches with content size exceeding this value will be compressed
|
|
94
|
+
minimumBatchSizeInBytes: 614400,
|
|
95
|
+
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
96
|
+
};
|
|
97
|
+
const defaultChunkSizeInBytes = 204800;
|
|
96
98
|
/**
|
|
97
99
|
* @deprecated - use ContainerRuntimeMessage instead
|
|
98
100
|
*/
|
|
@@ -129,8 +131,7 @@ function getDeviceSpec() {
|
|
|
129
131
|
};
|
|
130
132
|
}
|
|
131
133
|
}
|
|
132
|
-
catch (_a) {
|
|
133
|
-
}
|
|
134
|
+
catch (_a) { }
|
|
134
135
|
return {};
|
|
135
136
|
}
|
|
136
137
|
exports.getDeviceSpec = getDeviceSpec;
|
|
@@ -142,8 +143,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
142
143
|
/**
|
|
143
144
|
* @internal
|
|
144
145
|
*/
|
|
145
|
-
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, requestHandler, summaryConfiguration) {
|
|
146
|
-
var _a, _b, _c, _d, _e, _f;
|
|
146
|
+
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, requestHandler, summaryConfiguration, initializeEntryPoint) {
|
|
147
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
147
148
|
if (summaryConfiguration === void 0) { summaryConfiguration = Object.assign(Object.assign({}, exports.DefaultSummaryConfiguration), (_a = runtimeOptions.summaryOptions) === null || _a === void 0 ? void 0 : _a.summaryConfigOverrides); }
|
|
148
149
|
super();
|
|
149
150
|
this.context = context;
|
|
@@ -156,9 +157,16 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
156
157
|
this.summaryConfiguration = summaryConfiguration;
|
|
157
158
|
this.defaultMaxConsecutiveReconnects = 7;
|
|
158
159
|
this._orderSequentiallyCalls = 0;
|
|
159
|
-
this.
|
|
160
|
-
this.savedOps = [];
|
|
160
|
+
this.flushTaskExists = false;
|
|
161
161
|
this.consecutiveReconnects = 0;
|
|
162
|
+
this.ensureNoDataModelChangesCalls = 0;
|
|
163
|
+
/**
|
|
164
|
+
* Tracks the number of detected reentrant ops to report,
|
|
165
|
+
* in order to self-throttle the telemetry events.
|
|
166
|
+
*
|
|
167
|
+
* This should be removed as part of ADO:2322
|
|
168
|
+
*/
|
|
169
|
+
this.opReentryCallsToReport = 5;
|
|
162
170
|
this._disposed = false;
|
|
163
171
|
this.emitDirtyDocumentEvent = true;
|
|
164
172
|
this.defaultTelemetrySignalSampleCount = 100;
|
|
@@ -169,7 +177,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
169
177
|
trackingSignalSequenceNumber: undefined,
|
|
170
178
|
};
|
|
171
179
|
this.summarizeOnDemand = (...args) => {
|
|
172
|
-
if (this.clientDetails.type ===
|
|
180
|
+
if (this.clientDetails.type === summary_1.summarizerClientType) {
|
|
173
181
|
return this.summarizer.summarizeOnDemand(...args);
|
|
174
182
|
}
|
|
175
183
|
else if (this.summaryManager !== undefined) {
|
|
@@ -183,7 +191,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
183
191
|
}
|
|
184
192
|
};
|
|
185
193
|
this.enqueueSummarize = (...args) => {
|
|
186
|
-
if (this.clientDetails.type ===
|
|
194
|
+
if (this.clientDetails.type === summary_1.summarizerClientType) {
|
|
187
195
|
return this.summarizer.enqueueSummarize(...args);
|
|
188
196
|
}
|
|
189
197
|
else if (this.summaryManager !== undefined) {
|
|
@@ -196,6 +204,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
196
204
|
throw new container_utils_1.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
197
205
|
}
|
|
198
206
|
};
|
|
207
|
+
this.innerDeltaManager = context.deltaManager;
|
|
208
|
+
this.deltaManager = new deltaManagerSummarizerProxy_1.DeltaManagerSummarizerProxy(context.deltaManager);
|
|
199
209
|
let loadSummaryNumber;
|
|
200
210
|
// Get the container creation metadata. For new container, we initialize these. For existing containers,
|
|
201
211
|
// get the values from the metadata blob.
|
|
@@ -218,52 +228,78 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
218
228
|
this.nextSummaryNumber = loadSummaryNumber + 1;
|
|
219
229
|
this.messageAtLastSummary = metadata === null || metadata === void 0 ? void 0 : metadata.message;
|
|
220
230
|
this._connected = this.context.connected;
|
|
221
|
-
this.
|
|
222
|
-
this.handleContext = new containerHandleContext_1.ContainerFluidHandleContext("", this);
|
|
231
|
+
this.gcTombstoneEnforcementAllowed = (0, gc_1.shouldAllowGcTombstoneEnforcement)((_c = metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix) === null || _c === void 0 ? void 0 : _c.tombstoneGeneration /* persisted */, this.runtimeOptions.gcOptions[gc_1.gcTombstoneGenerationOptionName] /* current */);
|
|
223
232
|
this.mc = (0, telemetry_utils_1.loggerToMonitoringContext)(telemetry_utils_1.ChildLogger.create(this.logger, "ContainerRuntime"));
|
|
233
|
+
this.mc.logger.sendTelemetryEvent({
|
|
234
|
+
eventName: "GCFeatureMatrix",
|
|
235
|
+
metadataValue: JSON.stringify(metadata === null || metadata === void 0 ? void 0 : metadata.gcFeatureMatrix),
|
|
236
|
+
inputs: JSON.stringify({
|
|
237
|
+
gcOptions_gcTombstoneGeneration: this.runtimeOptions.gcOptions[gc_1.gcTombstoneGenerationOptionName],
|
|
238
|
+
}),
|
|
239
|
+
});
|
|
240
|
+
this.telemetryDocumentId = (_d = metadata === null || metadata === void 0 ? void 0 : metadata.telemetryDocumentId) !== null && _d !== void 0 ? _d : (0, uuid_1.v4)();
|
|
241
|
+
this.disableAttachReorder = this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder");
|
|
242
|
+
const disableChunking = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionChunkingDisabled");
|
|
243
|
+
const opSplitter = new opLifecycle_1.OpSplitter(chunks, this.context.submitBatchFn, disableChunking === true ? Number.POSITIVE_INFINITY : runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
|
|
244
|
+
this.remoteMessageProcessor = new opLifecycle_1.RemoteMessageProcessor(opSplitter, new opLifecycle_1.OpDecompressor(this.mc.logger));
|
|
245
|
+
this.handleContext = new containerHandleContext_1.ContainerFluidHandleContext("", this);
|
|
224
246
|
if (this.summaryConfiguration.state === "enabled") {
|
|
225
247
|
this.validateSummaryHeuristicConfiguration(this.summaryConfiguration);
|
|
226
248
|
}
|
|
249
|
+
const disableOpReentryCheck = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisableOpReentryCheck");
|
|
250
|
+
this.enableOpReentryCheck =
|
|
251
|
+
runtimeOptions.enableOpReentryCheck === true &&
|
|
252
|
+
// Allow for a break-glass config to override the options
|
|
253
|
+
disableOpReentryCheck !== true;
|
|
227
254
|
this.summariesDisabled = this.isSummariesDisabled();
|
|
228
255
|
this.heuristicsDisabled = this.isHeuristicsDisabled();
|
|
229
|
-
this.summarizerClientElectionEnabled = this.isSummarizerClientElectionEnabled();
|
|
230
256
|
this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
|
|
231
257
|
this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
|
|
232
258
|
this.maxConsecutiveReconnects =
|
|
233
|
-
(
|
|
234
|
-
|
|
259
|
+
(_e = this.mc.config.getNumber(maxConsecutiveReconnectsKey)) !== null && _e !== void 0 ? _e : this.defaultMaxConsecutiveReconnects;
|
|
260
|
+
if (runtimeOptions.flushMode === runtime_definitions_1.FlushModeExperimental.Async &&
|
|
261
|
+
((_f = context.supportedFeatures) === null || _f === void 0 ? void 0 : _f.get("referenceSequenceNumbers")) !== true) {
|
|
262
|
+
// The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
|
|
263
|
+
this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
|
|
264
|
+
this._flushMode = runtime_definitions_1.FlushMode.TurnBased;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
this._flushMode = runtimeOptions.flushMode;
|
|
268
|
+
}
|
|
235
269
|
const pendingRuntimeState = context.pendingLocalState;
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
270
|
+
const maxSnapshotCacheDurationMs = (_h = (_g = this._storage) === null || _g === void 0 ? void 0 : _g.policies) === null || _h === void 0 ? void 0 : _h.maximumCacheDurationMs;
|
|
271
|
+
if (maxSnapshotCacheDurationMs !== undefined &&
|
|
272
|
+
maxSnapshotCacheDurationMs > 5 * 24 * 60 * 60 * 1000) {
|
|
239
273
|
// This is a runtime enforcement of what's already explicit in the policy's type itself,
|
|
240
274
|
// which dictates the value is either undefined or exactly 5 days in ms.
|
|
241
275
|
// As long as the actual value is less than 5 days, the assumptions GC makes here are valid.
|
|
242
276
|
throw new container_utils_1.UsageError("Driver's maximumCacheDurationMs policy cannot exceed 5 days");
|
|
243
277
|
}
|
|
244
|
-
this.garbageCollector =
|
|
278
|
+
this.garbageCollector = gc_1.GarbageCollector.create({
|
|
245
279
|
runtime: this,
|
|
246
280
|
gcOptions: this.runtimeOptions.gcOptions,
|
|
247
|
-
baseSnapshot,
|
|
281
|
+
baseSnapshot: context.baseSnapshot,
|
|
248
282
|
baseLogger: this.mc.logger,
|
|
249
283
|
existing,
|
|
250
284
|
metadata,
|
|
251
285
|
createContainerMetadata: this.createContainerMetadata,
|
|
252
|
-
isSummarizerClient: this.context.clientDetails.type ===
|
|
286
|
+
isSummarizerClient: this.context.clientDetails.type === summary_1.summarizerClientType,
|
|
253
287
|
getNodePackagePath: async (nodePath) => this.getGCNodePackagePath(nodePath),
|
|
254
288
|
getLastSummaryTimestampMs: () => { var _a; return (_a = this.messageAtLastSummary) === null || _a === void 0 ? void 0 : _a.timestamp; },
|
|
255
289
|
readAndParseBlob: async (id) => (0, driver_utils_1.readAndParse)(this.storage, id),
|
|
256
290
|
getContainerDiagnosticId: () => this.context.id,
|
|
257
|
-
|
|
291
|
+
// GC runs in summarizer client and needs access to the real (non-proxy) active information. The proxy
|
|
292
|
+
// delta manager would always return false for summarizer client.
|
|
293
|
+
activeConnection: () => this.innerDeltaManager.active,
|
|
258
294
|
});
|
|
259
295
|
const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
|
|
260
|
-
this.summarizerNode = (0,
|
|
296
|
+
this.summarizerNode = (0, summary_1.createRootSummarizerNodeWithGC)(telemetry_utils_1.ChildLogger.create(this.logger, "SummarizerNode"),
|
|
261
297
|
// Summarize function to call when summarize is called. Summarizer node always tracks summary state.
|
|
262
298
|
async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
|
|
263
299
|
// Latest change sequence number, no changes since summary applied yet
|
|
264
300
|
loadedFromSequenceNumber,
|
|
265
301
|
// Summary reference sequence number, undefined if no summary yet
|
|
266
|
-
baseSnapshot ? loadedFromSequenceNumber : undefined, {
|
|
302
|
+
context.baseSnapshot ? loadedFromSequenceNumber : undefined, {
|
|
267
303
|
// Must set to false to prevent sending summary handle which would be pointing to
|
|
268
304
|
// a summary with an older protocol state.
|
|
269
305
|
canReuseHandle: false,
|
|
@@ -272,56 +308,77 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
272
308
|
throwOnFailure: true,
|
|
273
309
|
// If GC should not run, let the summarizer node know so that it does not track GC state.
|
|
274
310
|
gcDisabled: !this.garbageCollector.shouldRunGC,
|
|
275
|
-
}
|
|
276
|
-
if
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
311
|
+
},
|
|
312
|
+
// Function to get GC data if needed. This will always be called by the root summarizer node to get GC data.
|
|
313
|
+
async (fullGC) => this.getGCDataInternal(fullGC),
|
|
314
|
+
// Function to get the GC details from the base snapshot we loaded from.
|
|
315
|
+
async () => this.garbageCollector.getBaseGCDetails());
|
|
316
|
+
if (context.baseSnapshot) {
|
|
317
|
+
this.summarizerNode.updateBaseSummaryState(context.baseSnapshot);
|
|
318
|
+
}
|
|
319
|
+
this.dataStores = new dataStores_1.DataStores((0, dataStores_1.getSummaryForDatastores)(context.baseSnapshot, metadata), this, (attachMsg) => this.submit(ContainerMessageType.Attach, attachMsg), (id, createParam) => (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), (path) => this.garbageCollector.isNodeDeleted(path), new Map(dataStoreAliasMap));
|
|
320
|
+
this.blobManager = new blobManager_1.BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (localId, blobId) => {
|
|
281
321
|
if (!this.disposed) {
|
|
282
|
-
this.submit(ContainerMessageType.BlobAttach, undefined, undefined, {
|
|
322
|
+
this.submit(ContainerMessageType.BlobAttach, undefined, undefined, {
|
|
323
|
+
localId,
|
|
324
|
+
blobId,
|
|
325
|
+
});
|
|
283
326
|
}
|
|
284
|
-
}, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), this, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pendingAttachmentBlobs);
|
|
327
|
+
}, (blobPath) => this.garbageCollector.nodeUpdated(blobPath, "Loaded"), (blobPath) => this.garbageCollector.isNodeDeleted(blobPath), this, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pendingAttachmentBlobs, () => this.getCurrentReferenceTimestampMs());
|
|
285
328
|
this.scheduleManager = new scheduleManager_1.ScheduleManager(context.deltaManager, this, () => this.clientId, telemetry_utils_1.ChildLogger.create(this.logger, "ScheduleManager"));
|
|
286
329
|
this.pendingStateManager = new pendingStateManager_1.PendingStateManager({
|
|
287
330
|
applyStashedOp: this.applyStashedOp.bind(this),
|
|
288
331
|
clientId: () => this.clientId,
|
|
289
332
|
close: this.closeFn,
|
|
290
333
|
connected: () => this.connected,
|
|
291
|
-
flush: this.flush.bind(this),
|
|
292
334
|
reSubmit: this.reSubmit.bind(this),
|
|
293
335
|
rollback: this.rollback.bind(this),
|
|
294
336
|
orderSequentially: this.orderSequentially.bind(this),
|
|
295
337
|
}, pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.pending);
|
|
338
|
+
const disableCompression = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionDisabled");
|
|
339
|
+
const compressionOptions = disableCompression === true
|
|
340
|
+
? {
|
|
341
|
+
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
342
|
+
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
343
|
+
}
|
|
344
|
+
: runtimeOptions.compressionOptions;
|
|
345
|
+
const disablePartialFlush = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisablePartialFlush");
|
|
296
346
|
this.outbox = new opLifecycle_1.Outbox({
|
|
297
347
|
shouldSend: () => this.canSendOps(),
|
|
298
348
|
pendingStateManager: this.pendingStateManager,
|
|
299
349
|
containerContext: this.context,
|
|
300
350
|
compressor: new opLifecycle_1.OpCompressor(this.mc.logger),
|
|
351
|
+
splitter: opSplitter,
|
|
301
352
|
config: {
|
|
302
|
-
compressionOptions
|
|
353
|
+
compressionOptions,
|
|
303
354
|
maxBatchSizeInBytes: runtimeOptions.maxBatchSizeInBytes,
|
|
355
|
+
disablePartialFlush: disablePartialFlush === true,
|
|
304
356
|
},
|
|
357
|
+
logger: this.mc.logger,
|
|
305
358
|
});
|
|
306
359
|
this.context.quorum.on("removeMember", (clientId) => {
|
|
307
360
|
this.remoteMessageProcessor.clearPartialMessagesFor(clientId);
|
|
308
361
|
});
|
|
309
|
-
this.summaryCollection = new
|
|
310
|
-
this.dirtyContainer =
|
|
311
|
-
|
|
362
|
+
this.summaryCollection = new summary_1.SummaryCollection(this.deltaManager, this.logger);
|
|
363
|
+
this.dirtyContainer =
|
|
364
|
+
this.context.attachState !== container_definitions_1.AttachState.Attached ||
|
|
365
|
+
this.pendingStateManager.hasPendingMessages();
|
|
312
366
|
this.context.updateDirtyContainerState(this.dirtyContainer);
|
|
313
367
|
if (this.summariesDisabled) {
|
|
314
368
|
this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
|
|
315
369
|
}
|
|
316
370
|
else {
|
|
317
371
|
const orderedClientLogger = telemetry_utils_1.ChildLogger.create(this.logger, "OrderedClientElection");
|
|
318
|
-
const orderedClientCollection = new
|
|
319
|
-
const orderedClientElectionForSummarizer = new
|
|
320
|
-
this.summarizerClientElection = new
|
|
321
|
-
if (this.context.clientDetails.type ===
|
|
322
|
-
this._summarizer = new
|
|
372
|
+
const orderedClientCollection = new summary_1.OrderedClientCollection(orderedClientLogger, this.context.deltaManager, this.context.quorum);
|
|
373
|
+
const orderedClientElectionForSummarizer = new summary_1.OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData !== null && electedSummarizerData !== void 0 ? electedSummarizerData : this.context.deltaManager.lastSequenceNumber, summary_1.SummarizerClientElection.isClientEligible);
|
|
374
|
+
this.summarizerClientElection = new summary_1.SummarizerClientElection(orderedClientLogger, this.summaryCollection, orderedClientElectionForSummarizer, this.maxOpsSinceLastSummary);
|
|
375
|
+
if (this.context.clientDetails.type === summary_1.summarizerClientType) {
|
|
376
|
+
this._summarizer = new summary_1.Summarizer(this /* ISummarizerRuntime */, () => this.summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, this.summaryCollection, async (runtime) => summary_1.RunWhileConnectedCoordinator.create(runtime,
|
|
377
|
+
// Summarization runs in summarizer client and needs access to the real (non-proxy) active
|
|
378
|
+
// information. The proxy delta manager would always return false for summarizer client.
|
|
379
|
+
() => this.innerDeltaManager.active));
|
|
323
380
|
}
|
|
324
|
-
else if (
|
|
381
|
+
else if (summary_1.SummarizerClientElection.clientDetailsPermitElection(this.context.clientDetails)) {
|
|
325
382
|
// Only create a SummaryManager and SummarizerClientElection
|
|
326
383
|
// if summaries are enabled and we are not the summarizer client.
|
|
327
384
|
const defaultAction = () => {
|
|
@@ -341,7 +398,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
341
398
|
};
|
|
342
399
|
this.summaryCollection.on("default", defaultAction);
|
|
343
400
|
// Create the SummaryManager and mark the initial state
|
|
344
|
-
this.summaryManager = new
|
|
401
|
+
this.summaryManager = new summary_1.SummaryManager(this.summarizerClientElection, this, // IConnectedState
|
|
345
402
|
this.summaryCollection, this.logger, this.formRequestSummarizerFn(this.context.loader), new throttler_1.Throttler(60 * 1000, // 60 sec delay window
|
|
346
403
|
30 * 1000, // 30 sec max delay
|
|
347
404
|
// throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
|
|
@@ -354,7 +411,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
354
411
|
this.deltaManager.on("readonly", (readonly) => {
|
|
355
412
|
// we accumulate ops while being in read-only state.
|
|
356
413
|
// once user gets write permissions and we have active connection, flush all pending ops.
|
|
357
|
-
(
|
|
414
|
+
// Note that the inner (non-proxy) delta manager is needed here to get the readonly information.
|
|
415
|
+
(0, common_utils_1.assert)(readonly === this.innerDeltaManager.readOnlyInfo.readonly, 0x124 /* "inconsistent readonly property/event state" */);
|
|
358
416
|
// We need to be very careful with when we (re)send pending ops, to ensure that we only send ops
|
|
359
417
|
// when we either never send an op, or attempted to send it but we know for sure it was not
|
|
360
418
|
// sequenced by server and will never be sequenced (i.e. was lost)
|
|
@@ -372,13 +430,31 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
372
430
|
});
|
|
373
431
|
// logging hardware telemetry
|
|
374
432
|
logger.sendTelemetryEvent(Object.assign({ eventName: "DeviceSpec" }, getDeviceSpec()));
|
|
375
|
-
this.logger.sendTelemetryEvent(Object.assign(Object.assign(Object.assign({ eventName: "ContainerLoadStats" }, this.createContainerMetadata), this.dataStores.containerLoadStats), { summaryNumber: loadSummaryNumber, summaryFormatVersion: metadata === null || metadata === void 0 ? void 0 : metadata.summaryFormatVersion, disableIsolatedChannels: metadata === null || metadata === void 0 ? void 0 : metadata.disableIsolatedChannels, gcVersion: metadata === null || metadata === void 0 ? void 0 : metadata.gcFeature
|
|
433
|
+
this.logger.sendTelemetryEvent(Object.assign(Object.assign(Object.assign({ eventName: "ContainerLoadStats" }, this.createContainerMetadata), this.dataStores.containerLoadStats), { summaryNumber: loadSummaryNumber, summaryFormatVersion: metadata === null || metadata === void 0 ? void 0 : metadata.summaryFormatVersion, disableIsolatedChannels: metadata === null || metadata === void 0 ? void 0 : metadata.disableIsolatedChannels, gcVersion: metadata === null || metadata === void 0 ? void 0 : metadata.gcFeature, options: JSON.stringify(runtimeOptions), featureGates: JSON.stringify({
|
|
434
|
+
disableCompression,
|
|
435
|
+
disableOpReentryCheck,
|
|
436
|
+
disableChunking,
|
|
437
|
+
disableAttachReorder: this.disableAttachReorder,
|
|
438
|
+
disablePartialFlush,
|
|
439
|
+
}), telemetryDocumentId: this.telemetryDocumentId }));
|
|
376
440
|
(0, connectionTelemetry_1.ReportOpPerfTelemetry)(this.context.clientId, this.deltaManager, this.logger);
|
|
377
441
|
(0, batchTracker_1.BindBatchTracker)(this, this.logger);
|
|
442
|
+
this.entryPoint = new common_utils_1.LazyPromise(async () => {
|
|
443
|
+
if (this.context.clientDetails.type === summary_1.summarizerClientType) {
|
|
444
|
+
(0, common_utils_1.assert)(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
|
|
445
|
+
return this._summarizer;
|
|
446
|
+
}
|
|
447
|
+
return initializeEntryPoint === null || initializeEntryPoint === void 0 ? void 0 : initializeEntryPoint(this);
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
get IContainerRuntime() {
|
|
451
|
+
return this;
|
|
452
|
+
}
|
|
453
|
+
get IFluidRouter() {
|
|
454
|
+
return this;
|
|
378
455
|
}
|
|
379
|
-
get IContainerRuntime() { return this; }
|
|
380
|
-
get IFluidRouter() { return this; }
|
|
381
456
|
/**
|
|
457
|
+
* @deprecated - use loadRuntime instead.
|
|
382
458
|
* Load the stores from a snapshot and returns the runtime.
|
|
383
459
|
* @param context - Context of the container.
|
|
384
460
|
* @param registryEntries - Mapping to the stores.
|
|
@@ -389,7 +465,38 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
389
465
|
* allows mixin classes to leverage this method to define their own async initializer.
|
|
390
466
|
*/
|
|
391
467
|
static async load(context, registryEntries, requestHandler, runtimeOptions = {}, containerScope = context.scope, existing, containerRuntimeCtor = ContainerRuntime) {
|
|
392
|
-
|
|
468
|
+
let existingFlag = true;
|
|
469
|
+
if (!existing) {
|
|
470
|
+
existingFlag = false;
|
|
471
|
+
}
|
|
472
|
+
return this.loadRuntime({
|
|
473
|
+
context,
|
|
474
|
+
registryEntries,
|
|
475
|
+
existing: existingFlag,
|
|
476
|
+
requestHandler,
|
|
477
|
+
runtimeOptions,
|
|
478
|
+
containerScope,
|
|
479
|
+
containerRuntimeCtor,
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Load the stores from a snapshot and returns the runtime.
|
|
484
|
+
* @param params - An object housing the runtime properties:
|
|
485
|
+
* - context - Context of the container.
|
|
486
|
+
* - registryEntries - Mapping from data store types to their corresponding factories.
|
|
487
|
+
* - existing - Pass 'true' if loading from an existing snapshot.
|
|
488
|
+
* - requestHandler - (optional) Request handler for the request() method of the container runtime.
|
|
489
|
+
* Only relevant for back-compat while we remove the request() method and move fully to entryPoint as the main pattern.
|
|
490
|
+
* - runtimeOptions - Additional options to be passed to the runtime
|
|
491
|
+
* - containerScope - runtime services provided with context
|
|
492
|
+
* - containerRuntimeCtor - Constructor to use to create the ContainerRuntime instance.
|
|
493
|
+
* This allows mixin classes to leverage this method to define their own async initializer.
|
|
494
|
+
* - initializeEntryPoint - Promise that resolves to an object which will act as entryPoint for the Container.
|
|
495
|
+
* This object should provide all the functionality that the Container is expected to provide to the loader layer.
|
|
496
|
+
*/
|
|
497
|
+
static async loadRuntime(params) {
|
|
498
|
+
var _a, _b, _c, _d;
|
|
499
|
+
const { context, registryEntries, existing, requestHandler, runtimeOptions = {}, containerScope = {}, containerRuntimeCtor = ContainerRuntime, initializeEntryPoint, } = params;
|
|
393
500
|
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
394
501
|
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
395
502
|
const backCompatContext = context;
|
|
@@ -399,46 +506,40 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
399
506
|
runtimeVersion: packageVersion_1.pkgVersion,
|
|
400
507
|
},
|
|
401
508
|
});
|
|
402
|
-
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode,
|
|
403
|
-
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
404
|
-
compressionAlgorithm: CompressionAlgorithms.lz4
|
|
405
|
-
}, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, } = runtimeOptions;
|
|
406
|
-
const pendingRuntimeState = context.pendingLocalState;
|
|
407
|
-
const baseSnapshot = (_b = pendingRuntimeState === null || pendingRuntimeState === void 0 ? void 0 : pendingRuntimeState.baseSnapshot) !== null && _b !== void 0 ? _b : context.baseSnapshot;
|
|
408
|
-
const storage = !pendingRuntimeState ?
|
|
409
|
-
context.storage :
|
|
410
|
-
new serializedSnapshotStorage_1.SerializedSnapshotStorage(() => { return context.storage; }, pendingRuntimeState.snapshotBlobs);
|
|
509
|
+
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, } = runtimeOptions;
|
|
411
510
|
const registry = new dataStoreRegistry_1.FluidDataStoreRegistry(registryEntries);
|
|
412
511
|
const tryFetchBlob = async (blobName) => {
|
|
413
|
-
|
|
414
|
-
|
|
512
|
+
var _a;
|
|
513
|
+
const blobId = (_a = context.baseSnapshot) === null || _a === void 0 ? void 0 : _a.blobs[blobName];
|
|
514
|
+
if (context.baseSnapshot && blobId) {
|
|
415
515
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
416
516
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
417
|
-
(0, common_utils_1.assert)(storage !== undefined, 0x1f5 /* "Attached state should have storage" */);
|
|
418
|
-
return (0, driver_utils_1.readAndParse)(storage, blobId);
|
|
517
|
+
(0, common_utils_1.assert)(context.storage !== undefined, 0x1f5 /* "Attached state should have storage" */);
|
|
518
|
+
return (0, driver_utils_1.readAndParse)(context.storage, blobId);
|
|
419
519
|
}
|
|
420
520
|
};
|
|
421
521
|
const [chunks, metadata, electedSummarizerData, aliases] = await Promise.all([
|
|
422
|
-
tryFetchBlob(
|
|
423
|
-
tryFetchBlob(
|
|
424
|
-
tryFetchBlob(
|
|
425
|
-
tryFetchBlob(
|
|
522
|
+
tryFetchBlob(summary_1.chunksBlobName),
|
|
523
|
+
tryFetchBlob(summary_1.metadataBlobName),
|
|
524
|
+
tryFetchBlob(summary_1.electedSummarizerBlobName),
|
|
525
|
+
tryFetchBlob(summary_1.aliasBlobName),
|
|
426
526
|
]);
|
|
427
527
|
const loadExisting = existing === true || context.existing === true;
|
|
428
528
|
// read snapshot blobs needed for BlobManager to load
|
|
429
|
-
const blobManagerSnapshot = await blobManager_1.BlobManager.load(baseSnapshot === null ||
|
|
529
|
+
const blobManagerSnapshot = await blobManager_1.BlobManager.load((_b = context.baseSnapshot) === null || _b === void 0 ? void 0 : _b.trees[summary_1.blobsTreeName], async (id) => {
|
|
430
530
|
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
431
531
|
// So once we release 0.40 container-defn package we can remove this check.
|
|
432
|
-
(0, common_utils_1.assert)(storage !== undefined, 0x256 /* "storage undefined in attached container" */);
|
|
433
|
-
return (0, driver_utils_1.readAndParse)(storage, id);
|
|
532
|
+
(0, common_utils_1.assert)(context.storage !== undefined, 0x256 /* "storage undefined in attached container" */);
|
|
533
|
+
return (0, driver_utils_1.readAndParse)(context.storage, id);
|
|
434
534
|
});
|
|
435
535
|
// Verify summary runtime sequence number matches protocol sequence number.
|
|
436
536
|
const runtimeSequenceNumber = (_c = metadata === null || metadata === void 0 ? void 0 : metadata.message) === null || _c === void 0 ? void 0 : _c.sequenceNumber;
|
|
437
537
|
// When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
|
|
438
|
-
if (!
|
|
538
|
+
if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
|
|
439
539
|
const protocolSequenceNumber = context.deltaManager.initialSequenceNumber;
|
|
440
540
|
// Unless bypass is explicitly set, then take action when sequence numbers mismatch.
|
|
441
|
-
if (loadSequenceNumberVerification !== "bypass" &&
|
|
541
|
+
if (loadSequenceNumberVerification !== "bypass" &&
|
|
542
|
+
runtimeSequenceNumber !== protocolSequenceNumber) {
|
|
442
543
|
// "Load from summary, runtime metadata sequenceNumber !== initialSequenceNumber"
|
|
443
544
|
const error = new container_utils_1.DataCorruptionError(
|
|
444
545
|
// pre-0.58 error message: SummaryMetadataMismatch
|
|
@@ -447,7 +548,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
447
548
|
logger.sendErrorEvent({ eventName: "SequenceNumberMismatch" }, error);
|
|
448
549
|
}
|
|
449
550
|
else {
|
|
551
|
+
// Call both close and dispose as closeFn implementation will no longer dispose runtime in future
|
|
450
552
|
context.closeFn(error);
|
|
553
|
+
(_d = context.disposeFn) === null || _d === void 0 ? void 0 : _d.call(context, error);
|
|
451
554
|
}
|
|
452
555
|
}
|
|
453
556
|
}
|
|
@@ -456,15 +559,15 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
456
559
|
gcOptions,
|
|
457
560
|
loadSequenceNumberVerification,
|
|
458
561
|
flushMode,
|
|
459
|
-
enableOfflineLoad,
|
|
460
562
|
compressionOptions,
|
|
461
563
|
maxBatchSizeInBytes,
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
564
|
+
chunkSizeInBytes,
|
|
565
|
+
enableOpReentryCheck,
|
|
566
|
+
}, containerScope, logger, loadExisting, blobManagerSnapshot, context.storage, requestHandler, undefined, // summaryConfiguration
|
|
567
|
+
initializeEntryPoint);
|
|
568
|
+
// It's possible to have ops with a reference sequence number of 0. Op sequence numbers start
|
|
569
|
+
// at 1, so we won't see a replayed saved op with a sequence number of 0.
|
|
570
|
+
await runtime.pendingStateManager.applyStashedOpsAt(0);
|
|
468
571
|
// Initialize the base state of the runtime before it's returned.
|
|
469
572
|
await runtime.initializeBaseState();
|
|
470
573
|
return runtime;
|
|
@@ -478,9 +581,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
478
581
|
get clientDetails() {
|
|
479
582
|
return this.context.clientDetails;
|
|
480
583
|
}
|
|
481
|
-
get deltaManager() {
|
|
482
|
-
return this.context.deltaManager;
|
|
483
|
-
}
|
|
484
584
|
get storage() {
|
|
485
585
|
return this._storage;
|
|
486
586
|
}
|
|
@@ -488,8 +588,18 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
488
588
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
489
589
|
return this.reSubmit;
|
|
490
590
|
}
|
|
591
|
+
get disposeFn() {
|
|
592
|
+
var _a;
|
|
593
|
+
// In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
|
|
594
|
+
return (_a = this.context.disposeFn) !== null && _a !== void 0 ? _a : this.context.closeFn;
|
|
595
|
+
}
|
|
491
596
|
get closeFn() {
|
|
492
|
-
|
|
597
|
+
// Also call disposeFn to retain functionality of runtime being disposed on close
|
|
598
|
+
return (error) => {
|
|
599
|
+
var _a, _b;
|
|
600
|
+
this.context.closeFn(error);
|
|
601
|
+
(_b = (_a = this.context).disposeFn) === null || _b === void 0 ? void 0 : _b.call(_a, error);
|
|
602
|
+
};
|
|
493
603
|
}
|
|
494
604
|
get flushMode() {
|
|
495
605
|
return this._flushMode;
|
|
@@ -506,6 +616,23 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
506
616
|
get IFluidHandleContext() {
|
|
507
617
|
return this.handleContext;
|
|
508
618
|
}
|
|
619
|
+
/**
|
|
620
|
+
* Invokes the given callback and expects that no ops are submitted
|
|
621
|
+
* until execution finishes. If an op is submitted, an error will be raised.
|
|
622
|
+
*
|
|
623
|
+
* Can be disabled by feature gate `Fluid.ContainerRuntime.DisableOpReentryCheck`
|
|
624
|
+
*
|
|
625
|
+
* @param callback - the callback to be invoked
|
|
626
|
+
*/
|
|
627
|
+
ensureNoDataModelChanges(callback) {
|
|
628
|
+
this.ensureNoDataModelChangesCalls++;
|
|
629
|
+
try {
|
|
630
|
+
return callback();
|
|
631
|
+
}
|
|
632
|
+
finally {
|
|
633
|
+
this.ensureNoDataModelChangesCalls--;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
509
636
|
get connected() {
|
|
510
637
|
return this._connected;
|
|
511
638
|
}
|
|
@@ -514,48 +641,20 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
514
641
|
var _a;
|
|
515
642
|
return (_a = this.summarizerClientElection) === null || _a === void 0 ? void 0 : _a.electedClientId;
|
|
516
643
|
}
|
|
517
|
-
get disposed() {
|
|
644
|
+
get disposed() {
|
|
645
|
+
return this._disposed;
|
|
646
|
+
}
|
|
518
647
|
get summarizer() {
|
|
519
648
|
(0, common_utils_1.assert)(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
|
|
520
649
|
return this._summarizer;
|
|
521
650
|
}
|
|
522
651
|
isSummariesDisabled() {
|
|
523
|
-
// back-compat: disableSummaries was moved from ISummaryRuntimeOptions
|
|
524
|
-
// to ISummaryConfiguration in 0.60.
|
|
525
|
-
if (this.runtimeOptions.summaryOptions.disableSummaries === true) {
|
|
526
|
-
return true;
|
|
527
|
-
}
|
|
528
652
|
return this.summaryConfiguration.state === "disabled";
|
|
529
653
|
}
|
|
530
654
|
isHeuristicsDisabled() {
|
|
531
|
-
var _a;
|
|
532
|
-
// back-compat: disableHeuristics was moved from ISummarizerOptions
|
|
533
|
-
// to ISummaryConfiguration in 0.60.
|
|
534
|
-
if (((_a = this.runtimeOptions.summaryOptions.summarizerOptions) === null || _a === void 0 ? void 0 : _a.disableHeuristics) === true) {
|
|
535
|
-
return true;
|
|
536
|
-
}
|
|
537
655
|
return this.summaryConfiguration.state === "disableHeuristics";
|
|
538
656
|
}
|
|
539
|
-
isSummarizerClientElectionEnabled() {
|
|
540
|
-
var _a;
|
|
541
|
-
if (this.mc.config.getBoolean("Fluid.ContainerRuntime.summarizerClientElection")) {
|
|
542
|
-
return (_a = this.mc.config.getBoolean("Fluid.ContainerRuntime.summarizerClientElection")) !== null && _a !== void 0 ? _a : true;
|
|
543
|
-
}
|
|
544
|
-
// back-compat: summarizerClientElection was moved from ISummaryRuntimeOptions
|
|
545
|
-
// to ISummaryConfiguration in 0.60.
|
|
546
|
-
if (this.runtimeOptions.summaryOptions.summarizerClientElection === true) {
|
|
547
|
-
return true;
|
|
548
|
-
}
|
|
549
|
-
return this.summaryConfiguration.state !== "disabled"
|
|
550
|
-
? this.summaryConfiguration.summarizerClientElection === true
|
|
551
|
-
: false;
|
|
552
|
-
}
|
|
553
657
|
getMaxOpsSinceLastSummary() {
|
|
554
|
-
// back-compat: maxOpsSinceLastSummary was moved from ISummaryRuntimeOptions
|
|
555
|
-
// to ISummaryConfiguration in 0.60.
|
|
556
|
-
if (this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary !== undefined) {
|
|
557
|
-
return this.runtimeOptions.summaryOptions.maxOpsSinceLastSummary;
|
|
558
|
-
}
|
|
559
658
|
return this.summaryConfiguration.state !== "disabled"
|
|
560
659
|
? this.summaryConfiguration.maxOpsSinceLastSummary
|
|
561
660
|
: 0;
|
|
@@ -574,7 +673,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
574
673
|
* Initializes the state from the base snapshot this container runtime loaded from.
|
|
575
674
|
*/
|
|
576
675
|
async initializeBaseState() {
|
|
577
|
-
await this.initializeBaseSnapshotBlobs();
|
|
578
676
|
await this.garbageCollector.initializeBaseState();
|
|
579
677
|
}
|
|
580
678
|
dispose(error) {
|
|
@@ -599,16 +697,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
599
697
|
this.emit("dispose");
|
|
600
698
|
this.removeAllListeners();
|
|
601
699
|
}
|
|
602
|
-
get IFluidTokenProvider() {
|
|
603
|
-
var _a;
|
|
604
|
-
if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.intelligence) {
|
|
605
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
606
|
-
return {
|
|
607
|
-
intelligence: this.options.intelligence,
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
|
-
return undefined;
|
|
611
|
-
}
|
|
612
700
|
/**
|
|
613
701
|
* Notifies this object about the request made to the container.
|
|
614
702
|
* @param request - Request made to the handler.
|
|
@@ -654,7 +742,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
654
742
|
status: 200,
|
|
655
743
|
mimeType: "fluid/object",
|
|
656
744
|
value: blob,
|
|
657
|
-
}
|
|
745
|
+
}
|
|
746
|
+
: (0, runtime_utils_1.create404Response)(request);
|
|
658
747
|
}
|
|
659
748
|
else if (requestParser.pathParts.length > 0) {
|
|
660
749
|
const dataStore = await this.getDataStoreFromRequest(id, request);
|
|
@@ -670,41 +759,35 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
670
759
|
return (0, runtime_utils_1.exceptionToResponse)(error);
|
|
671
760
|
}
|
|
672
761
|
}
|
|
762
|
+
/**
|
|
763
|
+
* {@inheritDoc @fluidframework/container-definitions#IRuntime.getEntryPoint}
|
|
764
|
+
*/
|
|
765
|
+
async getEntryPoint() {
|
|
766
|
+
return this.entryPoint;
|
|
767
|
+
}
|
|
673
768
|
internalId(maybeAlias) {
|
|
674
769
|
var _a;
|
|
675
770
|
return (_a = this.dataStores.aliases.get(maybeAlias)) !== null && _a !== void 0 ? _a : maybeAlias;
|
|
676
771
|
}
|
|
677
772
|
async getDataStoreFromRequest(id, request) {
|
|
678
|
-
var _a, _b, _c
|
|
679
|
-
const
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
773
|
+
var _a, _b, _c;
|
|
774
|
+
const headerData = {};
|
|
775
|
+
if (typeof ((_a = request.headers) === null || _a === void 0 ? void 0 : _a[RuntimeHeaders.wait]) === "boolean") {
|
|
776
|
+
headerData.wait = request.headers[RuntimeHeaders.wait];
|
|
777
|
+
}
|
|
778
|
+
if (typeof ((_b = request.headers) === null || _b === void 0 ? void 0 : _b[RuntimeHeaders.viaHandle]) === "boolean") {
|
|
779
|
+
headerData.viaHandle = request.headers[RuntimeHeaders.viaHandle];
|
|
780
|
+
}
|
|
781
|
+
if (typeof ((_c = request.headers) === null || _c === void 0 ? void 0 : _c[exports.AllowTombstoneRequestHeaderKey]) === "boolean") {
|
|
782
|
+
headerData.allowTombstone = request.headers[exports.AllowTombstoneRequestHeaderKey];
|
|
783
|
+
}
|
|
685
784
|
await this.dataStores.waitIfPendingAlias(id);
|
|
686
785
|
const internalId = this.internalId(id);
|
|
687
|
-
const dataStoreContext = await this.dataStores.getDataStore(internalId,
|
|
688
|
-
/**
|
|
689
|
-
* If GC should run and this an external app request with "externalRequest" header, we need to return
|
|
690
|
-
* an error if the data store being requested is marked as unreferenced as per the data store's base
|
|
691
|
-
* GC data.
|
|
692
|
-
*
|
|
693
|
-
* This is a workaround to handle scenarios where a data store shared with an external app is deleted
|
|
694
|
-
* and marked as unreferenced by GC. Returning an error will fail to load the data store for the app.
|
|
695
|
-
*/
|
|
696
|
-
if (((_e = request.headers) === null || _e === void 0 ? void 0 : _e[RuntimeHeaders.externalRequest]) && this.garbageCollector.shouldRunGC) {
|
|
697
|
-
// The data store is referenced if used routes in the base summary has a route to self.
|
|
698
|
-
// Older documents may not have used routes in the summary. They are considered referenced.
|
|
699
|
-
const usedRoutes = (await dataStoreContext.getBaseGCDetails()).usedRoutes;
|
|
700
|
-
if (!(usedRoutes === undefined || usedRoutes.includes("") || usedRoutes.includes("/"))) {
|
|
701
|
-
throw (0, runtime_utils_1.responseToException)((0, runtime_utils_1.create404Response)(request), request);
|
|
702
|
-
}
|
|
703
|
-
}
|
|
786
|
+
const dataStoreContext = await this.dataStores.getDataStore(internalId, headerData);
|
|
704
787
|
const dataStoreChannel = await dataStoreContext.realize();
|
|
705
788
|
// Remove query params, leading and trailing slashes from the url. This is done to make sure the format is
|
|
706
789
|
// the same as GC nodes id.
|
|
707
|
-
const urlWithoutQuery = (0,
|
|
790
|
+
const urlWithoutQuery = (0, gc_1.trimLeadingAndTrailingSlashes)(request.url.split("?")[0]);
|
|
708
791
|
this.garbageCollector.nodeUpdated(`/${urlWithoutQuery}`, "Loaded", undefined /* timestampMs */, dataStoreContext.packagePath, request === null || request === void 0 ? void 0 : request.headers);
|
|
709
792
|
return dataStoreChannel;
|
|
710
793
|
}
|
|
@@ -716,33 +799,33 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
716
799
|
summaryNumber: this.nextSummaryNumber++, summaryFormatVersion: 1 }), this.garbageCollector.getMetadata()), {
|
|
717
800
|
// The last message processed at the time of summary. If there are no new messages, use the message from the
|
|
718
801
|
// last summary.
|
|
719
|
-
message: (_a = (0,
|
|
720
|
-
(0, runtime_utils_1.addBlobToSummary)(summaryTree,
|
|
802
|
+
message: (_a = (0, summary_1.extractSummaryMetadataMessage)(this.deltaManager.lastMessage)) !== null && _a !== void 0 ? _a : this.messageAtLastSummary, telemetryDocumentId: this.telemetryDocumentId });
|
|
803
|
+
(0, runtime_utils_1.addBlobToSummary)(summaryTree, summary_1.metadataBlobName, JSON.stringify(metadata));
|
|
721
804
|
}
|
|
722
805
|
addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
|
|
723
806
|
var _a;
|
|
724
807
|
this.addMetadataToSummary(summaryTree);
|
|
725
808
|
if (this.remoteMessageProcessor.partialMessages.size > 0) {
|
|
726
809
|
const content = JSON.stringify([...this.remoteMessageProcessor.partialMessages]);
|
|
727
|
-
(0, runtime_utils_1.addBlobToSummary)(summaryTree,
|
|
810
|
+
(0, runtime_utils_1.addBlobToSummary)(summaryTree, summary_1.chunksBlobName, content);
|
|
728
811
|
}
|
|
729
812
|
const dataStoreAliases = this.dataStores.aliases;
|
|
730
813
|
if (dataStoreAliases.size > 0) {
|
|
731
|
-
(0, runtime_utils_1.addBlobToSummary)(summaryTree,
|
|
814
|
+
(0, runtime_utils_1.addBlobToSummary)(summaryTree, summary_1.aliasBlobName, JSON.stringify([...dataStoreAliases]));
|
|
732
815
|
}
|
|
733
816
|
if (this.summarizerClientElection) {
|
|
734
817
|
const electedSummarizerContent = JSON.stringify((_a = this.summarizerClientElection) === null || _a === void 0 ? void 0 : _a.serialize());
|
|
735
|
-
(0, runtime_utils_1.addBlobToSummary)(summaryTree,
|
|
818
|
+
(0, runtime_utils_1.addBlobToSummary)(summaryTree, summary_1.electedSummarizerBlobName, electedSummarizerContent);
|
|
736
819
|
}
|
|
737
820
|
const blobManagerSummary = this.blobManager.summarize();
|
|
738
821
|
// Some storage (like git) doesn't allow empty tree, so we can omit it.
|
|
739
822
|
// and the blob manager can handle the tree not existing when loading
|
|
740
823
|
if (Object.keys(blobManagerSummary.summary.tree).length > 0) {
|
|
741
|
-
(0, runtime_utils_1.addTreeToSummary)(summaryTree,
|
|
824
|
+
(0, runtime_utils_1.addTreeToSummary)(summaryTree, summary_1.blobsTreeName, blobManagerSummary);
|
|
742
825
|
}
|
|
743
826
|
const gcSummary = this.garbageCollector.summarize(fullTree, trackState, telemetryContext);
|
|
744
827
|
if (gcSummary !== undefined) {
|
|
745
|
-
(0, runtime_utils_1.addSummarizeResultToSummary)(summaryTree,
|
|
828
|
+
(0, runtime_utils_1.addSummarizeResultToSummary)(summaryTree, runtime_definitions_1.gcTreeKey, gcSummary);
|
|
746
829
|
}
|
|
747
830
|
}
|
|
748
831
|
// Track how many times the container tries to reconnect with pending messages.
|
|
@@ -832,7 +915,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
832
915
|
// If attachment blobs were added while disconnected, we need to delay
|
|
833
916
|
// propagation of the "connected" event until we have uploaded them to
|
|
834
917
|
// ensure we don't submit ops referencing a blob that has not been uploaded
|
|
835
|
-
|
|
918
|
+
// Note that the inner (non-proxy) delta manager is needed here to get the readonly information.
|
|
919
|
+
const connecting = connected && !this._connected && !this.innerDeltaManager.readOnlyInfo.readonly;
|
|
836
920
|
if (connecting && this.blobManager.hasPendingOfflineUploads) {
|
|
837
921
|
(0, common_utils_1.assert)(!this.delayConnectClientId, 0x392 /* Connect event delay must be canceled before subsequent connect event */);
|
|
838
922
|
(0, common_utils_1.assert)(!!clientId, 0x393 /* Must have clientId when connecting */);
|
|
@@ -867,9 +951,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
867
951
|
if (reconnection) {
|
|
868
952
|
this.consecutiveReconnects++;
|
|
869
953
|
if (!this.shouldContinueReconnecting()) {
|
|
870
|
-
this.closeFn(container_utils_1.DataProcessingError.create(
|
|
871
|
-
// eslint-disable-next-line max-len
|
|
872
|
-
"Runtime detected too many reconnects with no progress syncing local ops. Batch of ops is likely too large (over 1Mb)", "setConnectionState", undefined, {
|
|
954
|
+
this.closeFn(container_utils_1.DataProcessingError.create("Runtime detected too many reconnects with no progress syncing local ops.", "setConnectionState", undefined, {
|
|
873
955
|
dataLoss: 1,
|
|
874
956
|
attempts: this.consecutiveReconnects,
|
|
875
957
|
pendingMessages: this.pendingStateManager.pendingMessagesCount,
|
|
@@ -884,12 +966,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
884
966
|
this.garbageCollector.setConnectionState(connected, clientId);
|
|
885
967
|
(0, telemetry_utils_1.raiseConnectedEvent)(this.mc.logger, this, connected, clientId);
|
|
886
968
|
}
|
|
969
|
+
async notifyOpReplay(message) {
|
|
970
|
+
await this.pendingStateManager.applyStashedOpsAt(message.sequenceNumber);
|
|
971
|
+
}
|
|
887
972
|
process(messageArg, local) {
|
|
888
973
|
var _a;
|
|
889
974
|
this.verifyNotClosed();
|
|
890
|
-
if ((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad) {
|
|
891
|
-
this.savedOps.push(messageArg);
|
|
892
|
-
}
|
|
893
975
|
// Whether or not the message is actually a runtime message.
|
|
894
976
|
// It may be a legacy runtime message (ie already unpacked and ContainerMessageType)
|
|
895
977
|
// or something different, like a system message.
|
|
@@ -903,7 +985,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
903
985
|
this.scheduleManager.beforeOpProcessing(message);
|
|
904
986
|
try {
|
|
905
987
|
let localOpMetadata;
|
|
906
|
-
if (local && runtimeMessage) {
|
|
988
|
+
if (local && runtimeMessage && message.type !== ContainerMessageType.ChunkedOp) {
|
|
907
989
|
localOpMetadata = this.pendingStateManager.processPendingLocalMessage(message);
|
|
908
990
|
}
|
|
909
991
|
// If there are no more pending messages after processing a local message,
|
|
@@ -929,7 +1011,19 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
929
1011
|
case ContainerMessageType.Rejoin:
|
|
930
1012
|
break;
|
|
931
1013
|
default:
|
|
932
|
-
|
|
1014
|
+
if (runtimeMessage) {
|
|
1015
|
+
const error = container_utils_1.DataProcessingError.create(
|
|
1016
|
+
// Former assert 0x3ce
|
|
1017
|
+
"Runtime message of unknown type", "OpProcessing", message, {
|
|
1018
|
+
local,
|
|
1019
|
+
type: message.type,
|
|
1020
|
+
contentType: typeof message.contents,
|
|
1021
|
+
batch: (_a = message.metadata) === null || _a === void 0 ? void 0 : _a.batch,
|
|
1022
|
+
compression: message.compression,
|
|
1023
|
+
});
|
|
1024
|
+
this.closeFn(error);
|
|
1025
|
+
throw error;
|
|
1026
|
+
}
|
|
933
1027
|
}
|
|
934
1028
|
// For back-compat, notify only about runtime messages for now.
|
|
935
1029
|
if (runtimeMessage) {
|
|
@@ -976,7 +1070,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
976
1070
|
if (message.clientId === this.clientId && this.connected) {
|
|
977
1071
|
// Check to see if the signal was lost.
|
|
978
1072
|
if (this._perfSignalData.trackingSignalSequenceNumber !== undefined &&
|
|
979
|
-
envelope.clientSignalSequenceNumber >
|
|
1073
|
+
envelope.clientSignalSequenceNumber >
|
|
1074
|
+
this._perfSignalData.trackingSignalSequenceNumber) {
|
|
980
1075
|
this._perfSignalData.signalsLost++;
|
|
981
1076
|
this._perfSignalData.trackingSignalSequenceNumber = undefined;
|
|
982
1077
|
this.logger.sendErrorEvent({
|
|
@@ -987,8 +1082,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
987
1082
|
clientSignalSequenceNumber: envelope.clientSignalSequenceNumber,
|
|
988
1083
|
});
|
|
989
1084
|
}
|
|
990
|
-
else if (envelope.clientSignalSequenceNumber ===
|
|
991
|
-
this.
|
|
1085
|
+
else if (envelope.clientSignalSequenceNumber ===
|
|
1086
|
+
this._perfSignalData.trackingSignalSequenceNumber) {
|
|
1087
|
+
// only logging for the first connection and the trackingSignalSequenceNUmber.
|
|
1088
|
+
if (this.consecutiveReconnects === 0) {
|
|
1089
|
+
this.sendSignalTelemetryEvent(envelope.clientSignalSequenceNumber);
|
|
1090
|
+
}
|
|
992
1091
|
this._perfSignalData.trackingSignalSequenceNumber = undefined;
|
|
993
1092
|
}
|
|
994
1093
|
}
|
|
@@ -1005,7 +1104,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1005
1104
|
async getRootDataStoreChannel(id, wait = true) {
|
|
1006
1105
|
await this.dataStores.waitIfPendingAlias(id);
|
|
1007
1106
|
const internalId = this.internalId(id);
|
|
1008
|
-
const context = await this.dataStores.getDataStore(internalId, wait
|
|
1107
|
+
const context = await this.dataStores.getDataStore(internalId, { wait });
|
|
1009
1108
|
(0, common_utils_1.assert)(await context.isRoot(), 0x12b /* "did not get root data store" */);
|
|
1010
1109
|
return context.realize();
|
|
1011
1110
|
}
|
|
@@ -1054,7 +1153,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1054
1153
|
finally {
|
|
1055
1154
|
this._orderSequentiallyCalls--;
|
|
1056
1155
|
}
|
|
1057
|
-
|
|
1156
|
+
// We don't flush on TurnBased since we expect all messages in the same JS turn to be part of the same batch
|
|
1157
|
+
if (this.flushMode !== runtime_definitions_1.FlushMode.TurnBased && this._orderSequentiallyCalls === 0) {
|
|
1058
1158
|
this.flush();
|
|
1059
1159
|
}
|
|
1060
1160
|
return result;
|
|
@@ -1073,7 +1173,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1073
1173
|
return this.dataStores.createDetachedDataStoreCore(pkg, false);
|
|
1074
1174
|
}
|
|
1075
1175
|
async _createDataStoreWithProps(pkg, props, id = (0, uuid_1.v4)()) {
|
|
1076
|
-
const fluidDataStore = await this.dataStores
|
|
1176
|
+
const fluidDataStore = await this.dataStores
|
|
1177
|
+
._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props)
|
|
1178
|
+
.realize();
|
|
1077
1179
|
return (0, dataStore_1.channelToDataStore)(fluidDataStore, id, this, this.dataStores, this.mc.logger);
|
|
1078
1180
|
}
|
|
1079
1181
|
async _createDataStore(pkg, id = (0, uuid_1.v4)(), props) {
|
|
@@ -1082,13 +1184,15 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1082
1184
|
.realize();
|
|
1083
1185
|
}
|
|
1084
1186
|
canSendOps() {
|
|
1085
|
-
|
|
1187
|
+
// Note that the real (non-proxy) delta manager is needed here to get the readonly info. This is because
|
|
1188
|
+
// container runtime's ability to send ops depend on the actual readonly state of the delta manager.
|
|
1189
|
+
return this.connected && !this.innerDeltaManager.readOnlyInfo.readonly;
|
|
1086
1190
|
}
|
|
1087
1191
|
/**
|
|
1088
1192
|
* Are we in the middle of batching ops together?
|
|
1089
1193
|
*/
|
|
1090
1194
|
currentlyBatching() {
|
|
1091
|
-
return this.flushMode
|
|
1195
|
+
return this.flushMode !== runtime_definitions_1.FlushMode.Immediate || this._orderSequentiallyCalls !== 0;
|
|
1092
1196
|
}
|
|
1093
1197
|
getQuorum() {
|
|
1094
1198
|
return this.context.quorum;
|
|
@@ -1177,7 +1281,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1177
1281
|
}
|
|
1178
1282
|
const summarizeResult = this.dataStores.createSummary(telemetryContext);
|
|
1179
1283
|
// Wrap data store summaries in .channels subtree.
|
|
1180
|
-
(0,
|
|
1284
|
+
(0, summary_1.wrapSummaryInChannelsTree)(summarizeResult);
|
|
1181
1285
|
this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
|
|
1182
1286
|
return summarizeResult.summary;
|
|
1183
1287
|
}
|
|
@@ -1193,7 +1297,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1193
1297
|
async summarizeInternal(fullTree, trackState, telemetryContext) {
|
|
1194
1298
|
const summarizeResult = await this.dataStores.summarize(fullTree, trackState, telemetryContext);
|
|
1195
1299
|
// Wrap data store summaries in .channels subtree.
|
|
1196
|
-
(0,
|
|
1300
|
+
(0, summary_1.wrapSummaryInChannelsTree)(summarizeResult);
|
|
1197
1301
|
const pathPartsForChildren = [runtime_definitions_1.channelsTreeName];
|
|
1198
1302
|
this.addContainerStateToSummary(summarizeResult, fullTree, trackState, telemetryContext);
|
|
1199
1303
|
return Object.assign(Object.assign({}, summarizeResult), { id: "", pathPartsForChildren });
|
|
@@ -1204,81 +1308,98 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1204
1308
|
async summarize(options) {
|
|
1205
1309
|
this.verifyNotClosed();
|
|
1206
1310
|
const { fullTree = false, trackState = true, summaryLogger = this.mc.logger, runGC = this.garbageCollector.shouldRunGC, runSweep, fullGC, } = options;
|
|
1311
|
+
const telemetryContext = new runtime_utils_1.TelemetryContext();
|
|
1312
|
+
// Add the options that are used to generate this summary to the telemetry context.
|
|
1313
|
+
telemetryContext.setMultiple("fluid_Summarize", "Options", {
|
|
1314
|
+
fullTree,
|
|
1315
|
+
trackState,
|
|
1316
|
+
runGC,
|
|
1317
|
+
fullGC,
|
|
1318
|
+
runSweep,
|
|
1319
|
+
});
|
|
1207
1320
|
let gcStats;
|
|
1208
1321
|
if (runGC) {
|
|
1209
|
-
gcStats = await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC });
|
|
1322
|
+
gcStats = await this.collectGarbage({ logger: summaryLogger, runSweep, fullGC }, telemetryContext);
|
|
1210
1323
|
}
|
|
1211
|
-
const telemetryContext = new runtime_utils_1.TelemetryContext();
|
|
1212
1324
|
const { stats, summary } = await this.summarizerNode.summarize(fullTree, trackState, telemetryContext);
|
|
1213
|
-
this.logger.sendTelemetryEvent({
|
|
1325
|
+
this.logger.sendTelemetryEvent({
|
|
1326
|
+
eventName: "SummarizeTelemetry",
|
|
1327
|
+
details: telemetryContext.serialize(),
|
|
1328
|
+
});
|
|
1214
1329
|
(0, common_utils_1.assert)(summary.type === protocol_definitions_1.SummaryType.Tree, 0x12f /* "Container Runtime's summarize should always return a tree" */);
|
|
1215
1330
|
return { stats, summary, gcStats };
|
|
1216
1331
|
}
|
|
1217
1332
|
/**
|
|
1218
|
-
* Implementation of IGarbageCollectionRuntime::updateStateBeforeGC.
|
|
1219
1333
|
* Before GC runs, called by the garbage collector to update any pending GC state. This is mainly used to notify
|
|
1220
1334
|
* the garbage collector of references detected since the last GC run. Most references are notified immediately
|
|
1221
1335
|
* but there can be some for which async operation is required (such as detecting new root data stores).
|
|
1336
|
+
* @see IGarbageCollectionRuntime.updateStateBeforeGC
|
|
1222
1337
|
*/
|
|
1223
1338
|
async updateStateBeforeGC() {
|
|
1224
1339
|
return this.dataStores.updateStateBeforeGC();
|
|
1225
1340
|
}
|
|
1341
|
+
async getGCDataInternal(fullGC) {
|
|
1342
|
+
return this.dataStores.getGCData(fullGC);
|
|
1343
|
+
}
|
|
1226
1344
|
/**
|
|
1227
|
-
* Implementation of IGarbageCollectionRuntime::getGCData.
|
|
1228
1345
|
* Generates and returns the GC data for this container.
|
|
1229
1346
|
* @param fullGC - true to bypass optimizations and force full generation of GC data.
|
|
1347
|
+
* @see IGarbageCollectionRuntime.getGCData
|
|
1230
1348
|
*/
|
|
1231
1349
|
async getGCData(fullGC) {
|
|
1232
|
-
const builder = new
|
|
1233
|
-
const dsGCData = await this.
|
|
1350
|
+
const builder = new runtime_utils_1.GCDataBuilder();
|
|
1351
|
+
const dsGCData = await this.summarizerNode.getGCData(fullGC);
|
|
1234
1352
|
builder.addNodes(dsGCData.gcNodes);
|
|
1235
1353
|
const blobsGCData = this.blobManager.getGCData(fullGC);
|
|
1236
1354
|
builder.addNodes(blobsGCData.gcNodes);
|
|
1237
1355
|
return builder.getGCData();
|
|
1238
1356
|
}
|
|
1239
1357
|
/**
|
|
1240
|
-
* Implementation of IGarbageCollectionRuntime::updateUsedRoutes.
|
|
1241
1358
|
* After GC has run, called to notify this container's nodes of routes that are used in it.
|
|
1242
1359
|
* @param usedRoutes - The routes that are used in all nodes in this Container.
|
|
1360
|
+
* @see IGarbageCollectionRuntime.updateUsedRoutes
|
|
1243
1361
|
*/
|
|
1244
1362
|
updateUsedRoutes(usedRoutes) {
|
|
1245
1363
|
// Update our summarizer node's used routes. Updating used routes in summarizer node before
|
|
1246
1364
|
// summarizing is required and asserted by the the summarizer node. We are the root and are
|
|
1247
1365
|
// always referenced, so the used routes is only self-route (empty string).
|
|
1248
1366
|
this.summarizerNode.updateUsedRoutes([""]);
|
|
1249
|
-
const
|
|
1250
|
-
|
|
1251
|
-
for (const route of usedRoutes) {
|
|
1252
|
-
if (this.isBlobPath(route)) {
|
|
1253
|
-
blobManagerUsedRoutes.push(route);
|
|
1254
|
-
}
|
|
1255
|
-
else {
|
|
1256
|
-
dataStoreUsedRoutes.push(route);
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
this.blobManager.updateUsedRoutes(blobManagerUsedRoutes);
|
|
1260
|
-
this.dataStores.updateUsedRoutes(dataStoreUsedRoutes);
|
|
1367
|
+
const { dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(usedRoutes);
|
|
1368
|
+
this.dataStores.updateUsedRoutes(dataStoreRoutes);
|
|
1261
1369
|
}
|
|
1262
1370
|
/**
|
|
1263
|
-
* This is called to update objects whose routes are unused.
|
|
1264
|
-
*
|
|
1265
|
-
* @param unusedRoutes - The routes that are unused in all data stores and attachment blobs in this Container.
|
|
1266
|
-
* @param tombstone - if true, the objects corresponding to unused routes are marked tombstones. Otherwise, they
|
|
1267
|
-
* are deleted.
|
|
1371
|
+
* This is called to update objects whose routes are unused.
|
|
1372
|
+
* @param unusedRoutes - Data store and attachment blob routes that are unused in this Container.
|
|
1268
1373
|
*/
|
|
1269
|
-
updateUnusedRoutes(unusedRoutes
|
|
1270
|
-
const
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1374
|
+
updateUnusedRoutes(unusedRoutes) {
|
|
1375
|
+
const { blobManagerRoutes, dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(unusedRoutes);
|
|
1376
|
+
this.blobManager.updateUnusedRoutes(blobManagerRoutes);
|
|
1377
|
+
this.dataStores.updateUnusedRoutes(dataStoreRoutes);
|
|
1378
|
+
}
|
|
1379
|
+
/**
|
|
1380
|
+
* @deprecated - Replaced by deleteSweepReadyNodes.
|
|
1381
|
+
*/
|
|
1382
|
+
deleteUnusedNodes(unusedRoutes) {
|
|
1383
|
+
throw new Error("deleteUnusedRoutes should not be called");
|
|
1384
|
+
}
|
|
1385
|
+
/**
|
|
1386
|
+
* After GC has run and identified nodes that are sweep ready, this is called to delete the sweep ready nodes.
|
|
1387
|
+
* @param sweepReadyRoutes - The routes of nodes that are sweep ready and should be deleted.
|
|
1388
|
+
* @returns - The routes of nodes that were deleted.
|
|
1389
|
+
*/
|
|
1390
|
+
deleteSweepReadyNodes(sweepReadyRoutes) {
|
|
1391
|
+
const { dataStoreRoutes, blobManagerRoutes } = this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
|
|
1392
|
+
const deletedRoutes = this.dataStores.deleteSweepReadyNodes(dataStoreRoutes);
|
|
1393
|
+
return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
|
|
1394
|
+
}
|
|
1395
|
+
/**
|
|
1396
|
+
* This is called to update objects that are tombstones.
|
|
1397
|
+
* @param tombstonedRoutes - Data store and attachment blob routes that are tombstones in this Container.
|
|
1398
|
+
*/
|
|
1399
|
+
updateTombstonedRoutes(tombstonedRoutes) {
|
|
1400
|
+
const { blobManagerRoutes, dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(tombstonedRoutes);
|
|
1401
|
+
this.blobManager.updateTombstonedRoutes(blobManagerRoutes);
|
|
1402
|
+
this.dataStores.updateTombstonedRoutes(dataStoreRoutes);
|
|
1282
1403
|
}
|
|
1283
1404
|
/**
|
|
1284
1405
|
* Returns a server generated referenced timestamp to be used to track unreferenced nodes by GC.
|
|
@@ -1296,9 +1417,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1296
1417
|
getNodeType(nodePath) {
|
|
1297
1418
|
var _a;
|
|
1298
1419
|
if (this.isBlobPath(nodePath)) {
|
|
1299
|
-
return
|
|
1420
|
+
return gc_1.GCNodeType.Blob;
|
|
1300
1421
|
}
|
|
1301
|
-
return (_a = this.dataStores.getGCNodeType(nodePath)) !== null && _a !== void 0 ? _a :
|
|
1422
|
+
return (_a = this.dataStores.getGCNodeType(nodePath)) !== null && _a !== void 0 ? _a : gc_1.GCNodeType.Other;
|
|
1302
1423
|
}
|
|
1303
1424
|
/**
|
|
1304
1425
|
* Called by GC to retrieve the package path of the node with the given path. The node should belong to a
|
|
@@ -1306,10 +1427,10 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1306
1427
|
*/
|
|
1307
1428
|
async getGCNodePackagePath(nodePath) {
|
|
1308
1429
|
switch (this.getNodeType(nodePath)) {
|
|
1309
|
-
case
|
|
1310
|
-
return [
|
|
1311
|
-
case
|
|
1312
|
-
case
|
|
1430
|
+
case gc_1.GCNodeType.Blob:
|
|
1431
|
+
return [blobManager_1.BlobManager.basePath];
|
|
1432
|
+
case gc_1.GCNodeType.DataStore:
|
|
1433
|
+
case gc_1.GCNodeType.SubDataStore:
|
|
1313
1434
|
return this.dataStores.getDataStorePackagePath(nodePath);
|
|
1314
1435
|
default:
|
|
1315
1436
|
(0, common_utils_1.assert)(false, 0x2de /* "Package path requested for unsupported node type." */);
|
|
@@ -1325,12 +1446,31 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1325
1446
|
}
|
|
1326
1447
|
return true;
|
|
1327
1448
|
}
|
|
1449
|
+
/**
|
|
1450
|
+
* From a given list of routes, separate and return routes that belong to blob manager and data stores.
|
|
1451
|
+
* @param routes - A list of routes that can belong to data stores or blob manager.
|
|
1452
|
+
* @returns - Two route lists - One that contains routes for blob manager and another one that contains routes
|
|
1453
|
+
* for data stores.
|
|
1454
|
+
*/
|
|
1455
|
+
getDataStoreAndBlobManagerRoutes(routes) {
|
|
1456
|
+
const blobManagerRoutes = [];
|
|
1457
|
+
const dataStoreRoutes = [];
|
|
1458
|
+
for (const route of routes) {
|
|
1459
|
+
if (this.isBlobPath(route)) {
|
|
1460
|
+
blobManagerRoutes.push(route);
|
|
1461
|
+
}
|
|
1462
|
+
else {
|
|
1463
|
+
dataStoreRoutes.push(route);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
return { blobManagerRoutes, dataStoreRoutes };
|
|
1467
|
+
}
|
|
1328
1468
|
/**
|
|
1329
1469
|
* Runs garbage collection and updates the reference / used state of the nodes in the container.
|
|
1330
1470
|
* @returns the statistics of the garbage collection run; undefined if GC did not run.
|
|
1331
1471
|
*/
|
|
1332
|
-
async collectGarbage(options) {
|
|
1333
|
-
return this.garbageCollector.collectGarbage(options);
|
|
1472
|
+
async collectGarbage(options, telemetryContext) {
|
|
1473
|
+
return this.garbageCollector.collectGarbage(options, telemetryContext);
|
|
1334
1474
|
}
|
|
1335
1475
|
/**
|
|
1336
1476
|
* Called when a new outbound reference is added to another node. This is used by garbage collection to identify
|
|
@@ -1351,7 +1491,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1351
1491
|
*/
|
|
1352
1492
|
async submitSummary(options) {
|
|
1353
1493
|
var _a, _b;
|
|
1354
|
-
const { fullTree, refreshLatestAck, summaryLogger } = options;
|
|
1494
|
+
const { fullTree = false, refreshLatestAck, summaryLogger } = options;
|
|
1355
1495
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
1356
1496
|
// use it for all events logged during this summary.
|
|
1357
1497
|
const summaryNumber = this.nextSummaryNumber;
|
|
@@ -1367,8 +1507,12 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1367
1507
|
// We might need to catch up to the latest summary's reference sequence number before pausing.
|
|
1368
1508
|
await this.waitForDeltaManagerToCatchup(latestSnapshotRefSeq, summaryNumberLogger);
|
|
1369
1509
|
}
|
|
1510
|
+
const shouldPauseInboundSignal = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause") !== true;
|
|
1370
1511
|
try {
|
|
1371
1512
|
await this.deltaManager.inbound.pause();
|
|
1513
|
+
if (shouldPauseInboundSignal) {
|
|
1514
|
+
await this.deltaManager.inboundSignal.pause();
|
|
1515
|
+
}
|
|
1372
1516
|
const summaryRefSeqNum = this.deltaManager.lastSequenceNumber;
|
|
1373
1517
|
const minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
|
|
1374
1518
|
const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
|
|
@@ -1396,7 +1540,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1396
1540
|
if (this.deltaManager.lastSequenceNumber !== summaryRefSeqNum) {
|
|
1397
1541
|
return {
|
|
1398
1542
|
continue: false,
|
|
1399
|
-
// eslint-disable-next-line max-len
|
|
1400
1543
|
error: `lastSequenceNumber changed before uploading to storage. ${this.deltaManager.lastSequenceNumber} !== ${summaryRefSeqNum}`,
|
|
1401
1544
|
};
|
|
1402
1545
|
}
|
|
@@ -1404,7 +1547,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1404
1547
|
if (lastAck !== this.summaryCollection.latestAck) {
|
|
1405
1548
|
return {
|
|
1406
1549
|
continue: false,
|
|
1407
|
-
// eslint-disable-next-line max-len
|
|
1408
1550
|
error: `Last summary changed while summarizing. ${this.summaryCollection.latestAck} !== ${lastAck}`,
|
|
1409
1551
|
};
|
|
1410
1552
|
}
|
|
@@ -1426,7 +1568,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1426
1568
|
const forcedFullTree = this.garbageCollector.summaryStateNeedsReset;
|
|
1427
1569
|
try {
|
|
1428
1570
|
summarizeResult = await this.summarize({
|
|
1429
|
-
fullTree: fullTree
|
|
1571
|
+
fullTree: fullTree || forcedFullTree,
|
|
1430
1572
|
trackState: true,
|
|
1431
1573
|
summaryLogger: summaryNumberLogger,
|
|
1432
1574
|
runGC: this.garbageCollector.shouldRunGC,
|
|
@@ -1449,8 +1591,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1449
1591
|
const dataStoreTree = summaryTree.tree[runtime_definitions_1.channelsTreeName];
|
|
1450
1592
|
(0, common_utils_1.assert)(dataStoreTree.type === protocol_definitions_1.SummaryType.Tree, 0x1fc /* "summary is not a tree" */);
|
|
1451
1593
|
const handleCount = Object.values(dataStoreTree.tree).filter((value) => value.type === protocol_definitions_1.SummaryType.Handle).length;
|
|
1452
|
-
const gcSummaryTreeStats = summaryTree.tree[
|
|
1453
|
-
? (0, runtime_utils_1.calculateStats)(summaryTree.tree[
|
|
1594
|
+
const gcSummaryTreeStats = summaryTree.tree[runtime_definitions_1.gcTreeKey]
|
|
1595
|
+
? (0, runtime_utils_1.calculateStats)(summaryTree.tree[runtime_definitions_1.gcTreeKey])
|
|
1454
1596
|
: undefined;
|
|
1455
1597
|
const summaryStats = Object.assign({ dataStoreCount: this.dataStores.size, summarizedDataStoreCount: this.dataStores.size - handleCount, gcStateUpdatedDataStoreCount: (_a = summarizeResult.gcStats) === null || _a === void 0 ? void 0 : _a.updatedDataStoreCount, gcBlobNodeCount: gcSummaryTreeStats === null || gcSummaryTreeStats === void 0 ? void 0 : gcSummaryTreeStats.blobNodeCount, gcTotalBlobsSize: gcSummaryTreeStats === null || gcSummaryTreeStats === void 0 ? void 0 : gcSummaryTreeStats.totalBlobSize, summaryNumber }, partialStats);
|
|
1456
1598
|
const generateSummaryData = {
|
|
@@ -1471,8 +1613,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1471
1613
|
// latestSnapshotVersionId from storage and it does not match with the lastAck ackHandle, then use
|
|
1472
1614
|
// the one fetched from storage as parent as that is the latest.
|
|
1473
1615
|
let summaryContext;
|
|
1474
|
-
if ((lastAck === null || lastAck === void 0 ? void 0 : lastAck.summaryAck.contents.handle) !== latestSnapshotVersionId
|
|
1475
|
-
|
|
1616
|
+
if ((lastAck === null || lastAck === void 0 ? void 0 : lastAck.summaryAck.contents.handle) !== latestSnapshotVersionId &&
|
|
1617
|
+
latestSnapshotVersionId !== undefined) {
|
|
1476
1618
|
summaryContext = {
|
|
1477
1619
|
proposalHandle: undefined,
|
|
1478
1620
|
ackHandle: latestSnapshotVersionId,
|
|
@@ -1515,7 +1657,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1515
1657
|
}
|
|
1516
1658
|
let clientSequenceNumber;
|
|
1517
1659
|
try {
|
|
1518
|
-
clientSequenceNumber = this.submitSummaryMessage(summaryMessage);
|
|
1660
|
+
clientSequenceNumber = this.submitSummaryMessage(summaryMessage, summaryRefSeqNum);
|
|
1519
1661
|
}
|
|
1520
1662
|
catch (error) {
|
|
1521
1663
|
return Object.assign(Object.assign({ stage: "upload" }, uploadData), { error });
|
|
@@ -1529,6 +1671,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1529
1671
|
this.summarizerNode.clearSummary();
|
|
1530
1672
|
// Restart the delta manager
|
|
1531
1673
|
this.deltaManager.inbound.resume();
|
|
1674
|
+
if (shouldPauseInboundSignal) {
|
|
1675
|
+
this.deltaManager.inboundSignal.resume();
|
|
1676
|
+
}
|
|
1532
1677
|
}
|
|
1533
1678
|
}
|
|
1534
1679
|
hasPendingMessages() {
|
|
@@ -1571,16 +1716,21 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1571
1716
|
}
|
|
1572
1717
|
submit(type, contents, localOpMetadata = undefined, metadata = undefined) {
|
|
1573
1718
|
this.verifyNotClosed();
|
|
1719
|
+
this.verifyCanSubmitOps();
|
|
1574
1720
|
// There should be no ops in detached container state!
|
|
1575
1721
|
(0, common_utils_1.assert)(this.attachState !== container_definitions_1.AttachState.Detached, 0x132 /* "sending ops in detached container" */);
|
|
1576
|
-
const
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1722
|
+
const serializedContent = JSON.stringify({ type, contents });
|
|
1723
|
+
// Note that the real (non-proxy) delta manager is used here to get the readonly info. This is because
|
|
1724
|
+
// container runtime's ability to submit ops depend on the actual readonly state of the delta manager.
|
|
1725
|
+
if (this.innerDeltaManager.readOnlyInfo.readonly) {
|
|
1726
|
+
this.logger.sendTelemetryEvent({
|
|
1727
|
+
eventName: "SubmitOpInReadonly",
|
|
1728
|
+
connected: this.connected,
|
|
1729
|
+
});
|
|
1580
1730
|
}
|
|
1581
1731
|
const message = {
|
|
1582
1732
|
contents: serializedContent,
|
|
1583
|
-
deserializedContent,
|
|
1733
|
+
deserializedContent: JSON.parse(serializedContent),
|
|
1584
1734
|
metadata,
|
|
1585
1735
|
localOpMetadata,
|
|
1586
1736
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
@@ -1606,8 +1756,9 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1606
1756
|
// issue than sending.
|
|
1607
1757
|
// Please note that this does not change file format, so it can be disabled in the future if this
|
|
1608
1758
|
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
1609
|
-
if (this.currentlyBatching() &&
|
|
1610
|
-
|
|
1759
|
+
if (this.currentlyBatching() &&
|
|
1760
|
+
type === ContainerMessageType.Attach &&
|
|
1761
|
+
this.disableAttachReorder !== true) {
|
|
1611
1762
|
this.outbox.submitAttach(message);
|
|
1612
1763
|
}
|
|
1613
1764
|
else {
|
|
@@ -1616,14 +1767,8 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1616
1767
|
if (!this.currentlyBatching()) {
|
|
1617
1768
|
this.flush();
|
|
1618
1769
|
}
|
|
1619
|
-
else
|
|
1620
|
-
this.
|
|
1621
|
-
// Queue a microtask to detect the end of the turn and force a flush.
|
|
1622
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1623
|
-
Promise.resolve().then(() => {
|
|
1624
|
-
this.flushMicroTaskExists = false;
|
|
1625
|
-
this.flush();
|
|
1626
|
-
}).catch((error) => { this.closeFn(error); });
|
|
1770
|
+
else {
|
|
1771
|
+
this.scheduleFlush();
|
|
1627
1772
|
}
|
|
1628
1773
|
}
|
|
1629
1774
|
catch (error) {
|
|
@@ -1634,14 +1779,47 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1634
1779
|
this.updateDocumentDirtyState(true);
|
|
1635
1780
|
}
|
|
1636
1781
|
}
|
|
1637
|
-
|
|
1782
|
+
scheduleFlush() {
|
|
1783
|
+
if (this.flushTaskExists) {
|
|
1784
|
+
return;
|
|
1785
|
+
}
|
|
1786
|
+
this.flushTaskExists = true;
|
|
1787
|
+
const flush = () => {
|
|
1788
|
+
this.flushTaskExists = false;
|
|
1789
|
+
try {
|
|
1790
|
+
this.flush();
|
|
1791
|
+
}
|
|
1792
|
+
catch (error) {
|
|
1793
|
+
this.closeFn(error);
|
|
1794
|
+
}
|
|
1795
|
+
};
|
|
1796
|
+
switch (this.flushMode) {
|
|
1797
|
+
case runtime_definitions_1.FlushMode.TurnBased:
|
|
1798
|
+
// When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
|
|
1799
|
+
// batch at the end of the turn
|
|
1800
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1801
|
+
Promise.resolve().then(flush);
|
|
1802
|
+
break;
|
|
1803
|
+
// FlushModeExperimental is experimental and not exposed directly in the runtime APIs
|
|
1804
|
+
case runtime_definitions_1.FlushModeExperimental.Async:
|
|
1805
|
+
// When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
|
|
1806
|
+
// batch when all micro-tasks are complete.
|
|
1807
|
+
// Compared to TurnBased, this flush mode will capture more ops into the same batch.
|
|
1808
|
+
setTimeout(flush, 0);
|
|
1809
|
+
break;
|
|
1810
|
+
default:
|
|
1811
|
+
(0, common_utils_1.assert)(this._orderSequentiallyCalls > 0, 0x587 /* Unreachable unless running under orderSequentially */);
|
|
1812
|
+
break;
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
submitSummaryMessage(contents, referenceSequenceNumber) {
|
|
1638
1816
|
this.verifyNotClosed();
|
|
1639
1817
|
(0, common_utils_1.assert)(this.connected, 0x133 /* "Container disconnected when trying to submit system message" */);
|
|
1640
1818
|
// System message should not be sent in the middle of the batch.
|
|
1641
1819
|
(0, common_utils_1.assert)(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
|
|
1642
1820
|
// back-compat: ADO #1385: Make this call unconditional in the future
|
|
1643
1821
|
return this.context.submitSummaryFn !== undefined
|
|
1644
|
-
? this.context.submitSummaryFn(contents)
|
|
1822
|
+
? this.context.submitSummaryFn(contents, referenceSequenceNumber)
|
|
1645
1823
|
: this.context.submitFn(protocol_definitions_1.MessageType.Summarize, contents, false);
|
|
1646
1824
|
}
|
|
1647
1825
|
/**
|
|
@@ -1653,6 +1831,32 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1653
1831
|
throw new Error("Runtime is closed");
|
|
1654
1832
|
}
|
|
1655
1833
|
}
|
|
1834
|
+
verifyCanSubmitOps() {
|
|
1835
|
+
if (this.ensureNoDataModelChangesCalls > 0) {
|
|
1836
|
+
const errorMessage = "Op was submitted from within a `ensureNoDataModelChanges` callback";
|
|
1837
|
+
if (this.opReentryCallsToReport > 0) {
|
|
1838
|
+
this.mc.logger.sendTelemetryEvent({ eventName: "OpReentry" },
|
|
1839
|
+
// We need to capture the call stack in order to inspect the source of this usage pattern
|
|
1840
|
+
new container_utils_1.UsageError(errorMessage));
|
|
1841
|
+
this.opReentryCallsToReport--;
|
|
1842
|
+
}
|
|
1843
|
+
// Creating ops while processing ops can lead
|
|
1844
|
+
// to undefined behavior and events observed in the wrong order.
|
|
1845
|
+
// For example, we have two callbacks registered for a DDS, A and B.
|
|
1846
|
+
// Then if on change #1 callback A creates change #2, the invocation flow will be:
|
|
1847
|
+
//
|
|
1848
|
+
// A because of #1
|
|
1849
|
+
// A because of #2
|
|
1850
|
+
// B because of #2
|
|
1851
|
+
// B because of #1
|
|
1852
|
+
//
|
|
1853
|
+
// The runtime must enforce op coherence by not allowing ops to be submitted
|
|
1854
|
+
// while ops are being processed.
|
|
1855
|
+
if (this.enableOpReentryCheck) {
|
|
1856
|
+
throw new container_utils_1.UsageError(errorMessage);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1656
1860
|
/**
|
|
1657
1861
|
* Finds the right store and asks it to resubmit the message. This typically happens when we
|
|
1658
1862
|
* reconnect and there are pending messages.
|
|
@@ -1711,28 +1915,50 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1711
1915
|
// The call to fetch the snapshot is very expensive and not always needed.
|
|
1712
1916
|
// It should only be done by the summarizerNode, if required.
|
|
1713
1917
|
// When fetching from storage we will always get the latest version and do not use the ackHandle.
|
|
1714
|
-
const
|
|
1715
|
-
|
|
1716
|
-
eventName: "
|
|
1717
|
-
ackHandle,
|
|
1718
|
-
summaryRefSeq,
|
|
1719
|
-
fetchLatest: true,
|
|
1720
|
-
});
|
|
1721
|
-
const latestSnapshotRefSeq = await (0, runtime_utils_1.seqFromTree)(fetchResult.snapshotTree, readAndParseBlob);
|
|
1722
|
-
summaryLogger.sendTelemetryEvent({
|
|
1723
|
-
eventName: "LatestSummaryRetrieved",
|
|
1918
|
+
const fetchLatestSnapshot = async () => {
|
|
1919
|
+
let fetchResult = await this.fetchLatestSnapshotFromStorage(summaryLogger, {
|
|
1920
|
+
eventName: "RefreshLatestSummaryAckFetch",
|
|
1724
1921
|
ackHandle,
|
|
1725
|
-
lastSequenceNumber: latestSnapshotRefSeq,
|
|
1726
1922
|
targetSequenceNumber: summaryRefSeq,
|
|
1727
|
-
});
|
|
1923
|
+
}, readAndParseBlob);
|
|
1924
|
+
/**
|
|
1925
|
+
* If the fetched snapshot is older than the one for which the ack was received, close the container.
|
|
1926
|
+
* This should never happen because an ack should be sent after the latest summary is updated in the server.
|
|
1927
|
+
* However, there are couple of scenarios where it's possible:
|
|
1928
|
+
* 1. A file was modified externally resulting in modifying the snapshot's sequence number. This can lead to
|
|
1929
|
+
* the document being unusable and we should not proceed.
|
|
1930
|
+
* 2. The server DB failed after the ack was sent which may delete the corresponding snapshot. Ideally, in
|
|
1931
|
+
* such cases, the file will be rolled back along with the ack and we will eventually reach a consistent
|
|
1932
|
+
* state.
|
|
1933
|
+
*/
|
|
1934
|
+
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
1935
|
+
/* before failing, let's try to retrieve the latest snapshot for that specific ackHandle */
|
|
1936
|
+
fetchResult = await this.fetchSnapshotFromStorage(summaryLogger, {
|
|
1937
|
+
eventName: "RefreshLatestSummaryAckFetch",
|
|
1938
|
+
ackHandle,
|
|
1939
|
+
targetSequenceNumber: summaryRefSeq,
|
|
1940
|
+
}, readAndParseBlob, ackHandle);
|
|
1941
|
+
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
1942
|
+
const error = container_utils_1.DataProcessingError.create("Fetched snapshot is older than the received ack", "RefreshLatestSummaryAck", undefined /* sequencedMessage */, {
|
|
1943
|
+
ackHandle,
|
|
1944
|
+
summaryRefSeq,
|
|
1945
|
+
fetchedSnapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
1946
|
+
});
|
|
1947
|
+
this.closeFn(error);
|
|
1948
|
+
throw error;
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1728
1951
|
// In case we had to retrieve the latest snapshot and it is different than summaryRefSeq,
|
|
1729
1952
|
// wait for the delta manager to catch up before refreshing the latest Summary.
|
|
1730
|
-
await this.waitForDeltaManagerToCatchup(latestSnapshotRefSeq, summaryLogger);
|
|
1731
|
-
return
|
|
1953
|
+
await this.waitForDeltaManagerToCatchup(fetchResult.latestSnapshotRefSeq, summaryLogger);
|
|
1954
|
+
return {
|
|
1955
|
+
snapshotTree: fetchResult.snapshotTree,
|
|
1956
|
+
snapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
1957
|
+
};
|
|
1732
1958
|
};
|
|
1733
|
-
const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq,
|
|
1959
|
+
const result = await this.summarizerNode.refreshLatestSummary(proposalHandle, summaryRefSeq, fetchLatestSnapshot, readAndParseBlob, summaryLogger);
|
|
1734
1960
|
// Notify the garbage collector so it can update its latest summary state.
|
|
1735
|
-
await this.garbageCollector.
|
|
1961
|
+
await this.garbageCollector.refreshLatestSummary(proposalHandle, result, readAndParseBlob);
|
|
1736
1962
|
}
|
|
1737
1963
|
/**
|
|
1738
1964
|
* Fetches the latest snapshot from storage and uses it to refresh SummarizerNode's
|
|
@@ -1741,76 +1967,55 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1741
1967
|
* @returns downloaded snapshot's reference sequence number
|
|
1742
1968
|
*/
|
|
1743
1969
|
async refreshLatestSummaryAckFromServer(summaryLogger) {
|
|
1744
|
-
const { snapshotTree, versionId } = await this.fetchSnapshotFromStorage(null, summaryLogger, {
|
|
1745
|
-
eventName: "RefreshLatestSummaryGetSnapshot",
|
|
1746
|
-
fetchLatest: true,
|
|
1747
|
-
}, driver_definitions_1.FetchSource.noCache);
|
|
1748
1970
|
const readAndParseBlob = async (id) => (0, driver_utils_1.readAndParse)(this.storage, id);
|
|
1749
|
-
const latestSnapshotRefSeq = await
|
|
1750
|
-
|
|
1971
|
+
const { snapshotTree, versionId, latestSnapshotRefSeq } = await this.fetchLatestSnapshotFromStorage(summaryLogger, {
|
|
1972
|
+
eventName: "RefreshLatestSummaryFromServerFetch",
|
|
1973
|
+
}, readAndParseBlob);
|
|
1974
|
+
const fetchLatestSnapshot = {
|
|
1975
|
+
snapshotTree,
|
|
1976
|
+
snapshotRefSeq: latestSnapshotRefSeq,
|
|
1977
|
+
};
|
|
1978
|
+
const result = await this.summarizerNode.refreshLatestSummary(undefined /* proposalHandle */, latestSnapshotRefSeq, async () => fetchLatestSnapshot, readAndParseBlob, summaryLogger);
|
|
1751
1979
|
// Notify the garbage collector so it can update its latest summary state.
|
|
1752
|
-
await this.garbageCollector.
|
|
1980
|
+
await this.garbageCollector.refreshLatestSummary(undefined /* proposalHandle */, result, readAndParseBlob);
|
|
1753
1981
|
return { latestSnapshotRefSeq, latestSnapshotVersionId: versionId };
|
|
1754
1982
|
}
|
|
1755
|
-
async
|
|
1983
|
+
async fetchLatestSnapshotFromStorage(logger, event, readAndParseBlob) {
|
|
1984
|
+
return this.fetchSnapshotFromStorage(logger, event, readAndParseBlob, null /* latest */);
|
|
1985
|
+
}
|
|
1986
|
+
async fetchSnapshotFromStorage(logger, event, readAndParseBlob, versionId) {
|
|
1756
1987
|
return telemetry_utils_1.PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
|
|
1757
1988
|
const stats = {};
|
|
1758
1989
|
const trace = common_utils_1.Trace.start();
|
|
1759
|
-
const versions = await this.storage.getVersions(versionId, 1, "refreshLatestSummaryAckFromServer",
|
|
1990
|
+
const versions = await this.storage.getVersions(versionId, 1, "refreshLatestSummaryAckFromServer", versionId === null ? driver_definitions_1.FetchSource.noCache : undefined);
|
|
1760
1991
|
(0, common_utils_1.assert)(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
|
|
1761
1992
|
stats.getVersionDuration = trace.trace().duration;
|
|
1762
1993
|
const maybeSnapshot = await this.storage.getSnapshotTree(versions[0]);
|
|
1763
1994
|
(0, common_utils_1.assert)(!!maybeSnapshot, 0x138 /* "Failed to get snapshot from storage" */);
|
|
1764
1995
|
stats.getSnapshotDuration = trace.trace().duration;
|
|
1996
|
+
const latestSnapshotRefSeq = await (0, runtime_utils_1.seqFromTree)(maybeSnapshot, readAndParseBlob);
|
|
1997
|
+
stats.snapshotRefSeq = latestSnapshotRefSeq;
|
|
1998
|
+
stats.snapshotVersion = versions[0].id;
|
|
1765
1999
|
perfEvent.end(stats);
|
|
1766
|
-
return {
|
|
2000
|
+
return {
|
|
2001
|
+
snapshotTree: maybeSnapshot,
|
|
2002
|
+
versionId: versions[0].id,
|
|
2003
|
+
latestSnapshotRefSeq,
|
|
2004
|
+
};
|
|
1767
2005
|
});
|
|
1768
2006
|
}
|
|
1769
|
-
notifyAttaching(
|
|
1770
|
-
var _a;
|
|
1771
|
-
if ((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad) {
|
|
1772
|
-
this.baseSnapshotBlobs = serializedSnapshotStorage_1.SerializedSnapshotStorage.serializeTreeWithBlobContents(snapshot);
|
|
1773
|
-
}
|
|
1774
|
-
}
|
|
1775
|
-
async initializeBaseSnapshotBlobs() {
|
|
1776
|
-
var _a;
|
|
1777
|
-
if (!((_a = this.mc.config.getBoolean("enableOfflineLoad")) !== null && _a !== void 0 ? _a : this.runtimeOptions.enableOfflineLoad) ||
|
|
1778
|
-
this.attachState !== container_definitions_1.AttachState.Attached || this.context.pendingLocalState) {
|
|
1779
|
-
return;
|
|
1780
|
-
}
|
|
1781
|
-
(0, common_utils_1.assert)(!!this.context.baseSnapshot, 0x2e5 /* "Must have a base snapshot" */);
|
|
1782
|
-
this.baseSnapshotBlobs = await serializedSnapshotStorage_1.SerializedSnapshotStorage.serializeTree(this.context.baseSnapshot, this.storage);
|
|
1783
|
-
}
|
|
2007
|
+
notifyAttaching() { } // do nothing (deprecated method)
|
|
1784
2008
|
getPendingLocalState() {
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
throw new container_utils_1.UsageError("can't get state when offline load disabled");
|
|
2009
|
+
if (this._orderSequentiallyCalls !== 0) {
|
|
2010
|
+
throw new container_utils_1.UsageError("can't get state during orderSequentially");
|
|
1788
2011
|
}
|
|
1789
2012
|
// Flush pending batch.
|
|
1790
2013
|
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
1791
2014
|
// to close current batch.
|
|
1792
2015
|
this.flush();
|
|
1793
|
-
if (this._orderSequentiallyCalls !== 0) {
|
|
1794
|
-
throw new container_utils_1.UsageError("can't get state during orderSequentially");
|
|
1795
|
-
}
|
|
1796
|
-
const previousPendingState = this.context.pendingLocalState;
|
|
1797
|
-
if (previousPendingState) {
|
|
1798
|
-
return {
|
|
1799
|
-
pending: this.pendingStateManager.getLocalState(),
|
|
1800
|
-
pendingAttachmentBlobs: this.blobManager.getPendingBlobs(),
|
|
1801
|
-
snapshotBlobs: previousPendingState.snapshotBlobs,
|
|
1802
|
-
baseSnapshot: previousPendingState.baseSnapshot,
|
|
1803
|
-
savedOps: this.savedOps,
|
|
1804
|
-
};
|
|
1805
|
-
}
|
|
1806
|
-
(0, common_utils_1.assert)(!!this.context.baseSnapshot, 0x2e6 /* "Must have a base snapshot" */);
|
|
1807
|
-
(0, common_utils_1.assert)(!!this.baseSnapshotBlobs, 0x2e7 /* "Must serialize base snapshot blobs before getting runtime state" */);
|
|
1808
2016
|
return {
|
|
1809
2017
|
pending: this.pendingStateManager.getLocalState(),
|
|
1810
2018
|
pendingAttachmentBlobs: this.blobManager.getPendingBlobs(),
|
|
1811
|
-
snapshotBlobs: this.baseSnapshotBlobs,
|
|
1812
|
-
baseSnapshot: this.context.baseSnapshot,
|
|
1813
|
-
savedOps: this.savedOps,
|
|
1814
2019
|
};
|
|
1815
2020
|
}
|
|
1816
2021
|
/**
|
|
@@ -1824,7 +2029,7 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1824
2029
|
[container_definitions_1.LoaderHeader.cache]: false,
|
|
1825
2030
|
[container_definitions_1.LoaderHeader.clientDetails]: {
|
|
1826
2031
|
capabilities: { interactive: false },
|
|
1827
|
-
type:
|
|
2032
|
+
type: summary_1.summarizerClientType,
|
|
1828
2033
|
},
|
|
1829
2034
|
[driver_definitions_1.DriverHeader.summarizingClient]: true,
|
|
1830
2035
|
[container_definitions_1.LoaderHeader.reconnect]: false,
|
|
@@ -1839,20 +2044,6 @@ class ContainerRuntime extends common_utils_1.TypedEventEmitter {
|
|
|
1839
2044
|
return summarizer;
|
|
1840
2045
|
};
|
|
1841
2046
|
}
|
|
1842
|
-
async processSavedOps(state) {
|
|
1843
|
-
for (const op of state.savedOps) {
|
|
1844
|
-
this.process(op, false);
|
|
1845
|
-
await this.pendingStateManager.applyStashedOpsAt(op.sequenceNumber);
|
|
1846
|
-
}
|
|
1847
|
-
// we may not have seen every sequence number (because of system ops) so apply everything once we
|
|
1848
|
-
// don't have any more saved ops
|
|
1849
|
-
await this.pendingStateManager.applyStashedOpsAt();
|
|
1850
|
-
// If it's not the case, we should take it into account when calculating dirty state.
|
|
1851
|
-
(0, common_utils_1.assert)(this.context.attachState === container_definitions_1.AttachState.Attached, 0x3d5 /* this function is called for attached containers only */);
|
|
1852
|
-
if (!this.hasPendingMessages()) {
|
|
1853
|
-
this.updateDocumentDirtyState(false);
|
|
1854
|
-
}
|
|
1855
|
-
}
|
|
1856
2047
|
validateSummaryHeuristicConfiguration(configuration) {
|
|
1857
2048
|
// eslint-disable-next-line no-restricted-syntax
|
|
1858
2049
|
for (const prop in configuration) {
|
|
@@ -1873,6 +2064,7 @@ exports.ContainerRuntime = ContainerRuntime;
|
|
|
1873
2064
|
const waitForSeq = async (deltaManager, targetSeq) => new Promise((resolve, reject) => {
|
|
1874
2065
|
// TODO: remove cast to any when actual event is determined
|
|
1875
2066
|
deltaManager.on("closed", reject);
|
|
2067
|
+
deltaManager.on("disposed", reject);
|
|
1876
2068
|
// If we already reached target sequence number, simply resolve the promise.
|
|
1877
2069
|
if (deltaManager.lastSequenceNumber >= targetSeq) {
|
|
1878
2070
|
resolve();
|