@fluidframework/container-runtime 2.0.0-dev.3.1.0.125672 → 2.0.0-dev.4.2.0.153917
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/README.md +69 -0
- package/dist/blobManager.d.ts +29 -24
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +162 -92
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +74 -76
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +328 -264
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +39 -13
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +112 -49
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +28 -4
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +107 -41
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.d.ts +19 -0
- package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -0
- package/dist/deltaManagerSummarizerProxy.js +40 -0
- package/dist/deltaManagerSummarizerProxy.js.map +1 -0
- package/dist/gc/garbageCollection.d.ts +204 -0
- package/dist/gc/garbageCollection.d.ts.map +1 -0
- package/dist/{garbageCollection.js → gc/garbageCollection.js} +190 -554
- package/dist/gc/garbageCollection.js.map +1 -0
- package/dist/gc/gcConfigs.d.ts +22 -0
- package/dist/gc/gcConfigs.d.ts.map +1 -0
- package/dist/gc/gcConfigs.js +143 -0
- package/dist/gc/gcConfigs.js.map +1 -0
- package/dist/gc/gcDefinitions.d.ts +320 -0
- package/dist/gc/gcDefinitions.d.ts.map +1 -0
- package/dist/gc/gcDefinitions.js +81 -0
- package/dist/gc/gcDefinitions.js.map +1 -0
- package/dist/gc/gcHelpers.d.ts +86 -0
- package/dist/gc/gcHelpers.d.ts.map +1 -0
- package/dist/gc/gcHelpers.js +268 -0
- package/dist/gc/gcHelpers.js.map +1 -0
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts +16 -0
- package/dist/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -0
- package/dist/gc/gcReferenceGraphAlgorithm.js +49 -0
- package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -0
- package/dist/gc/gcSummaryDefinitions.d.ts +52 -0
- package/dist/gc/gcSummaryDefinitions.d.ts.map +1 -0
- package/dist/gc/gcSummaryDefinitions.js +7 -0
- package/dist/gc/gcSummaryDefinitions.js.map +1 -0
- package/dist/gc/gcSummaryStateTracker.d.ts +93 -0
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -0
- package/dist/gc/gcSummaryStateTracker.js +239 -0
- package/dist/gc/gcSummaryStateTracker.js.map +1 -0
- package/dist/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
- package/dist/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +2 -2
- package/dist/gc/gcSweepReadyUsageDetection.js.map +1 -0
- package/dist/gc/gcUnreferencedStateTracker.d.ts +34 -0
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
- package/dist/gc/gcUnreferencedStateTracker.js +94 -0
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -0
- package/dist/gc/index.d.ts +13 -0
- package/dist/gc/index.d.ts.map +1 -0
- package/dist/gc/index.js +50 -0
- package/dist/gc/index.js.map +1 -0
- package/dist/index.d.ts +3 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -9
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +11 -13
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +26 -38
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +4 -0
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +2 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +4 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +25 -10
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +4 -0
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +43 -4
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +14 -0
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -0
- package/dist/opLifecycle/opGroupingManager.js +56 -0
- package/dist/opLifecycle/opGroupingManager.js.map +1 -0
- package/dist/opLifecycle/opSplitter.d.ts +16 -4
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +39 -15
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +21 -3
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +90 -51
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +4 -2
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +30 -20
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +3 -3
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +20 -21
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/storageServiceWithAttachBlobs.d.ts +17 -0
- package/dist/storageServiceWithAttachBlobs.d.ts.map +1 -0
- package/dist/storageServiceWithAttachBlobs.js +32 -0
- package/dist/storageServiceWithAttachBlobs.js.map +1 -0
- package/dist/summary/index.d.ts +17 -0
- package/dist/summary/index.d.ts.map +1 -0
- package/dist/summary/index.js +48 -0
- package/dist/summary/index.js.map +1 -0
- package/dist/summary/orderedClientElection.d.ts.map +1 -0
- package/dist/summary/orderedClientElection.js.map +1 -0
- package/dist/{runWhileConnectedCoordinator.d.ts → summary/runWhileConnectedCoordinator.d.ts} +3 -2
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/dist/{runWhileConnectedCoordinator.js → summary/runWhileConnectedCoordinator.js} +5 -4
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -0
- package/{lib → dist/summary}/runningSummarizer.d.ts +23 -20
- package/dist/summary/runningSummarizer.d.ts.map +1 -0
- package/dist/{runningSummarizer.js → summary/runningSummarizer.js} +191 -74
- package/dist/summary/runningSummarizer.js.map +1 -0
- package/dist/{summarizer.d.ts → summary/summarizer.d.ts} +4 -9
- package/dist/summary/summarizer.d.ts.map +1 -0
- package/dist/{summarizer.js → summary/summarizer.js} +10 -79
- package/dist/summary/summarizer.js.map +1 -0
- package/dist/summary/summarizerClientElection.d.ts.map +1 -0
- package/dist/summary/summarizerClientElection.js.map +1 -0
- package/dist/{summarizerHeuristics.d.ts → summary/summarizerHeuristics.d.ts} +2 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -0
- package/dist/{summarizerHeuristics.js → summary/summarizerHeuristics.js} +6 -3
- package/dist/summary/summarizerHeuristics.js.map +1 -0
- package/dist/summary/summarizerNode/index.d.ts +8 -0
- package/dist/summary/summarizerNode/index.d.ts.map +1 -0
- package/dist/summary/summarizerNode/index.js +12 -0
- package/dist/summary/summarizerNode/index.js.map +1 -0
- package/dist/summary/summarizerNode/summarizerNode.d.ts +149 -0
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -0
- package/dist/summary/summarizerNode/summarizerNode.js +531 -0
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -0
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +125 -0
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -0
- package/dist/summary/summarizerNode/summarizerNodeUtils.js +132 -0
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -0
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +148 -0
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -0
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +424 -0
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -0
- package/{lib → dist/summary}/summarizerTypes.d.ts +21 -19
- package/dist/summary/summarizerTypes.d.ts.map +1 -0
- package/dist/{summarizerTypes.js → summary/summarizerTypes.js} +0 -5
- package/dist/summary/summarizerTypes.js.map +1 -0
- package/dist/summary/summaryCollection.d.ts.map +1 -0
- package/dist/summary/summaryCollection.js.map +1 -0
- package/{lib → dist/summary}/summaryFormat.d.ts +3 -21
- package/dist/summary/summaryFormat.d.ts.map +1 -0
- package/dist/{summaryFormat.js → summary/summaryFormat.js} +1 -10
- package/dist/summary/summaryFormat.js.map +1 -0
- package/{lib → dist/summary}/summaryGenerator.d.ts +28 -2
- package/dist/summary/summaryGenerator.d.ts.map +1 -0
- package/dist/{summaryGenerator.js → summary/summaryGenerator.js} +23 -20
- package/dist/summary/summaryGenerator.js.map +1 -0
- package/dist/{summaryManager.d.ts → summary/summaryManager.d.ts} +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -0
- package/dist/summary/summaryManager.js.map +1 -0
- package/lib/blobManager.d.ts +29 -24
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +159 -89
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +74 -76
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +301 -237
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +39 -13
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +101 -38
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +28 -4
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +100 -34
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerSummarizerProxy.d.ts +19 -0
- package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -0
- package/lib/deltaManagerSummarizerProxy.js +36 -0
- package/lib/deltaManagerSummarizerProxy.js.map +1 -0
- package/lib/gc/garbageCollection.d.ts +204 -0
- package/lib/gc/garbageCollection.d.ts.map +1 -0
- package/lib/{garbageCollection.js → gc/garbageCollection.js} +172 -535
- package/lib/gc/garbageCollection.js.map +1 -0
- package/lib/gc/gcConfigs.d.ts +22 -0
- package/lib/gc/gcConfigs.d.ts.map +1 -0
- package/lib/gc/gcConfigs.js +139 -0
- package/lib/gc/gcConfigs.js.map +1 -0
- package/lib/gc/gcDefinitions.d.ts +320 -0
- package/lib/gc/gcDefinitions.d.ts.map +1 -0
- package/lib/gc/gcDefinitions.js +78 -0
- package/lib/gc/gcDefinitions.js.map +1 -0
- package/lib/gc/gcHelpers.d.ts +86 -0
- package/lib/gc/gcHelpers.d.ts.map +1 -0
- package/lib/gc/gcHelpers.js +254 -0
- package/lib/gc/gcHelpers.js.map +1 -0
- package/lib/gc/gcReferenceGraphAlgorithm.d.ts +16 -0
- package/lib/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -0
- package/lib/gc/gcReferenceGraphAlgorithm.js +45 -0
- package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -0
- package/lib/gc/gcSummaryDefinitions.d.ts +52 -0
- package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -0
- package/lib/gc/gcSummaryDefinitions.js +6 -0
- package/lib/gc/gcSummaryDefinitions.js.map +1 -0
- package/lib/gc/gcSummaryStateTracker.d.ts +93 -0
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -0
- package/lib/gc/gcSummaryStateTracker.js +235 -0
- package/lib/gc/gcSummaryStateTracker.js.map +1 -0
- package/lib/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
- package/lib/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +1 -1
- package/lib/gc/gcSweepReadyUsageDetection.js.map +1 -0
- package/lib/gc/gcUnreferencedStateTracker.d.ts +34 -0
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
- package/lib/gc/gcUnreferencedStateTracker.js +90 -0
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -0
- package/lib/gc/index.d.ts +13 -0
- package/lib/gc/index.d.ts.map +1 -0
- package/lib/gc/index.js +12 -0
- package/lib/gc/index.js.map +1 -0
- package/lib/index.d.ts +3 -7
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -4
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +11 -13
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +24 -37
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +4 -0
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +2 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js +2 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +26 -11
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +4 -0
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +43 -4
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +14 -0
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -0
- package/lib/opLifecycle/opGroupingManager.js +52 -0
- package/lib/opLifecycle/opGroupingManager.js.map +1 -0
- package/lib/opLifecycle/opSplitter.d.ts +16 -4
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +39 -15
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +21 -3
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +92 -53
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +4 -2
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +30 -20
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +3 -3
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +20 -21
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/storageServiceWithAttachBlobs.d.ts +17 -0
- package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -0
- package/lib/storageServiceWithAttachBlobs.js +28 -0
- package/lib/storageServiceWithAttachBlobs.js.map +1 -0
- package/lib/summary/index.d.ts +17 -0
- package/lib/summary/index.d.ts.map +1 -0
- package/lib/summary/index.js +16 -0
- package/lib/summary/index.js.map +1 -0
- package/lib/summary/orderedClientElection.d.ts.map +1 -0
- package/lib/summary/orderedClientElection.js.map +1 -0
- package/lib/{runWhileConnectedCoordinator.d.ts → summary/runWhileConnectedCoordinator.d.ts} +3 -2
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/lib/{runWhileConnectedCoordinator.js → summary/runWhileConnectedCoordinator.js} +5 -4
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -0
- package/{dist → lib/summary}/runningSummarizer.d.ts +23 -20
- package/lib/summary/runningSummarizer.d.ts.map +1 -0
- package/lib/{runningSummarizer.js → summary/runningSummarizer.js} +192 -75
- package/lib/summary/runningSummarizer.js.map +1 -0
- package/lib/{summarizer.d.ts → summary/summarizer.d.ts} +4 -9
- package/lib/summary/summarizer.d.ts.map +1 -0
- package/lib/{summarizer.js → summary/summarizer.js} +12 -81
- package/lib/summary/summarizer.js.map +1 -0
- package/lib/summary/summarizerClientElection.d.ts.map +1 -0
- package/lib/summary/summarizerClientElection.js.map +1 -0
- package/lib/{summarizerHeuristics.d.ts → summary/summarizerHeuristics.d.ts} +2 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
- package/lib/{summarizerHeuristics.js → summary/summarizerHeuristics.js} +6 -3
- package/lib/summary/summarizerHeuristics.js.map +1 -0
- package/lib/summary/summarizerNode/index.d.ts +8 -0
- package/lib/summary/summarizerNode/index.d.ts.map +1 -0
- package/lib/summary/summarizerNode/index.js +7 -0
- package/lib/summary/summarizerNode/index.js.map +1 -0
- package/lib/summary/summarizerNode/summarizerNode.d.ts +149 -0
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -0
- package/lib/summary/summarizerNode/summarizerNode.js +526 -0
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -0
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +125 -0
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -0
- package/lib/summary/summarizerNode/summarizerNodeUtils.js +125 -0
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -0
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +148 -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 +21 -19
- 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/summary/summaryCollection.js.map +1 -0
- package/{dist → lib/summary}/summaryFormat.d.ts +3 -21
- package/lib/summary/summaryFormat.d.ts.map +1 -0
- package/lib/{summaryFormat.js → summary/summaryFormat.js} +0 -8
- package/lib/summary/summaryFormat.js.map +1 -0
- package/{dist → lib/summary}/summaryGenerator.d.ts +28 -2
- package/lib/summary/summaryGenerator.d.ts.map +1 -0
- package/lib/{summaryGenerator.js → summary/summaryGenerator.js} +21 -19
- package/lib/summary/summaryGenerator.js.map +1 -0
- package/lib/{summaryManager.d.ts → summary/summaryManager.d.ts} +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -0
- package/lib/summary/summaryManager.js.map +1 -0
- package/package.json +66 -60
- package/src/blobManager.ts +196 -110
- package/src/containerRuntime.ts +491 -391
- package/src/dataStoreContext.ts +140 -49
- package/src/dataStores.ts +139 -41
- package/src/deltaManagerSummarizerProxy.ts +46 -0
- package/{garbageCollection.md → src/gc/garbageCollection.md} +2 -2
- package/src/{garbageCollection.ts → gc/garbageCollection.ts} +245 -890
- package/src/gc/gcConfigs.ts +193 -0
- package/src/gc/gcDefinitions.ts +387 -0
- package/src/gc/gcHelpers.ts +335 -0
- package/src/gc/gcReferenceGraphAlgorithm.ts +52 -0
- package/src/gc/gcSummaryDefinitions.ts +54 -0
- package/src/gc/gcSummaryStateTracker.ts +329 -0
- package/src/{gcSweepReadyUsageDetection.ts → gc/gcSweepReadyUsageDetection.ts} +1 -1
- package/src/gc/gcUnreferencedStateTracker.ts +114 -0
- package/src/gc/index.ts +65 -0
- package/src/index.ts +10 -22
- package/src/opLifecycle/README.md +263 -0
- package/src/opLifecycle/batchManager.ts +26 -55
- package/src/opLifecycle/definitions.ts +4 -0
- package/src/opLifecycle/index.ts +2 -1
- package/src/opLifecycle/opCompressor.ts +32 -12
- package/src/opLifecycle/opDecompressor.ts +50 -5
- package/src/opLifecycle/opGroupingManager.ts +78 -0
- package/src/opLifecycle/opSplitter.ts +56 -17
- package/src/opLifecycle/outbox.ts +126 -62
- package/src/opLifecycle/remoteMessageProcessor.ts +38 -22
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +34 -27
- package/src/storageServiceWithAttachBlobs.ts +38 -0
- package/src/summary/index.ts +105 -0
- package/src/{runWhileConnectedCoordinator.ts → summary/runWhileConnectedCoordinator.ts} +7 -7
- package/src/{runningSummarizer.ts → summary/runningSummarizer.ts} +318 -156
- package/src/{summarizer.ts → summary/summarizer.ts} +12 -105
- package/src/{summarizerHeuristics.ts → summary/summarizerHeuristics.ts} +13 -4
- package/src/summary/summarizerNode/index.ts +12 -0
- package/src/summary/summarizerNode/summarizerNode.ts +766 -0
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +214 -0
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +644 -0
- package/src/{summarizerTypes.ts → summary/summarizerTypes.ts} +28 -25
- package/src/{summaryFormat.ts → summary/summaryFormat.ts} +3 -29
- package/src/{summaryGenerator.ts → summary/summaryGenerator.ts} +34 -27
- package/src/{summaryManager.ts → summary/summaryManager.ts} +1 -1
- package/dist/garbageCollection.d.ts +0 -411
- package/dist/garbageCollection.d.ts.map +0 -1
- package/dist/garbageCollection.js.map +0 -1
- package/dist/garbageCollectionConstants.d.ts +0 -23
- package/dist/garbageCollectionConstants.d.ts.map +0 -1
- package/dist/garbageCollectionConstants.js +0 -36
- package/dist/garbageCollectionConstants.js.map +0 -1
- package/dist/garbageCollectionHelpers.d.ts +0 -15
- package/dist/garbageCollectionHelpers.d.ts.map +0 -1
- package/dist/garbageCollectionHelpers.js +0 -27
- package/dist/garbageCollectionHelpers.js.map +0 -1
- package/dist/gcSweepReadyUsageDetection.d.ts.map +0 -1
- package/dist/gcSweepReadyUsageDetection.js.map +0 -1
- package/dist/orderedClientElection.d.ts.map +0 -1
- package/dist/orderedClientElection.js.map +0 -1
- package/dist/runWhileConnectedCoordinator.d.ts.map +0 -1
- package/dist/runWhileConnectedCoordinator.js.map +0 -1
- package/dist/runningSummarizer.d.ts.map +0 -1
- package/dist/runningSummarizer.js.map +0 -1
- package/dist/serializedSnapshotStorage.d.ts +0 -58
- package/dist/serializedSnapshotStorage.d.ts.map +0 -1
- package/dist/serializedSnapshotStorage.js +0 -110
- package/dist/serializedSnapshotStorage.js.map +0 -1
- package/dist/summarizer.d.ts.map +0 -1
- package/dist/summarizer.js.map +0 -1
- package/dist/summarizerClientElection.d.ts.map +0 -1
- package/dist/summarizerClientElection.js.map +0 -1
- package/dist/summarizerHandle.d.ts +0 -12
- package/dist/summarizerHandle.d.ts.map +0 -1
- package/dist/summarizerHandle.js +0 -22
- package/dist/summarizerHandle.js.map +0 -1
- package/dist/summarizerHeuristics.d.ts.map +0 -1
- package/dist/summarizerHeuristics.js.map +0 -1
- package/dist/summarizerTypes.d.ts.map +0 -1
- package/dist/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 -411
- package/lib/garbageCollection.d.ts.map +0 -1
- package/lib/garbageCollection.js.map +0 -1
- package/lib/garbageCollectionConstants.d.ts +0 -23
- package/lib/garbageCollectionConstants.d.ts.map +0 -1
- package/lib/garbageCollectionConstants.js +0 -33
- package/lib/garbageCollectionConstants.js.map +0 -1
- package/lib/garbageCollectionHelpers.d.ts +0 -15
- package/lib/garbageCollectionHelpers.d.ts.map +0 -1
- package/lib/garbageCollectionHelpers.js +0 -23
- package/lib/garbageCollectionHelpers.js.map +0 -1
- package/lib/gcSweepReadyUsageDetection.d.ts.map +0 -1
- package/lib/gcSweepReadyUsageDetection.js.map +0 -1
- package/lib/orderedClientElection.d.ts.map +0 -1
- package/lib/orderedClientElection.js.map +0 -1
- package/lib/runWhileConnectedCoordinator.d.ts.map +0 -1
- package/lib/runWhileConnectedCoordinator.js.map +0 -1
- package/lib/runningSummarizer.d.ts.map +0 -1
- package/lib/runningSummarizer.js.map +0 -1
- package/lib/serializedSnapshotStorage.d.ts +0 -58
- package/lib/serializedSnapshotStorage.d.ts.map +0 -1
- package/lib/serializedSnapshotStorage.js +0 -106
- package/lib/serializedSnapshotStorage.js.map +0 -1
- package/lib/summarizer.d.ts.map +0 -1
- package/lib/summarizer.js.map +0 -1
- package/lib/summarizerClientElection.d.ts.map +0 -1
- package/lib/summarizerClientElection.js.map +0 -1
- package/lib/summarizerHandle.d.ts +0 -12
- package/lib/summarizerHandle.d.ts.map +0 -1
- package/lib/summarizerHandle.js +0 -18
- package/lib/summarizerHandle.js.map +0 -1
- package/lib/summarizerHeuristics.d.ts.map +0 -1
- package/lib/summarizerHeuristics.js.map +0 -1
- package/lib/summarizerTypes.d.ts.map +0 -1
- package/lib/summarizerTypes.js +0 -9
- package/lib/summarizerTypes.js.map +0 -1
- package/lib/summaryCollection.d.ts.map +0 -1
- package/lib/summaryCollection.js.map +0 -1
- package/lib/summaryFormat.d.ts.map +0 -1
- package/lib/summaryFormat.js.map +0 -1
- package/lib/summaryGenerator.d.ts.map +0 -1
- package/lib/summaryGenerator.js.map +0 -1
- package/lib/summaryManager.d.ts.map +0 -1
- package/lib/summaryManager.js.map +0 -1
- package/src/garbageCollectionConstants.ts +0 -38
- package/src/garbageCollectionHelpers.ts +0 -37
- package/src/serializedSnapshotStorage.ts +0 -151
- package/src/summarizerHandle.ts +0 -23
- /package/dist/{gcSweepReadyUsageDetection.d.ts → gc/gcSweepReadyUsageDetection.d.ts} +0 -0
- /package/dist/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
- /package/dist/{orderedClientElection.js → summary/orderedClientElection.js} +0 -0
- /package/dist/{summarizerClientElection.d.ts → summary/summarizerClientElection.d.ts} +0 -0
- /package/dist/{summarizerClientElection.js → summary/summarizerClientElection.js} +0 -0
- /package/dist/{summaryCollection.d.ts → summary/summaryCollection.d.ts} +0 -0
- /package/dist/{summaryCollection.js → summary/summaryCollection.js} +0 -0
- /package/dist/{summaryManager.js → summary/summaryManager.js} +0 -0
- /package/lib/{gcSweepReadyUsageDetection.d.ts → gc/gcSweepReadyUsageDetection.d.ts} +0 -0
- /package/lib/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
- /package/lib/{orderedClientElection.js → summary/orderedClientElection.js} +0 -0
- /package/lib/{summarizerClientElection.d.ts → summary/summarizerClientElection.d.ts} +0 -0
- /package/lib/{summarizerClientElection.js → summary/summarizerClientElection.js} +0 -0
- /package/lib/{summaryCollection.d.ts → summary/summaryCollection.d.ts} +0 -0
- /package/lib/{summaryCollection.js → summary/summaryCollection.js} +0 -0
- /package/lib/{summaryManager.js → summary/summaryManager.js} +0 -0
- /package/src/{orderedClientElection.ts → summary/orderedClientElection.ts} +0 -0
- /package/src/{summarizerClientElection.ts → summary/summarizerClientElection.ts} +0 -0
- /package/src/{summaryCollection.ts → summary/summaryCollection.ts} +0 -0
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
14
14
|
import { ChildLogger } from "@fluidframework/telemetry-utils";
|
|
15
15
|
import { ContainerMessageType, ContainerRuntimeMessage } from "../containerRuntime";
|
|
16
|
+
import { estimateSocketSize } from "./batchManager";
|
|
16
17
|
import { BatchMessage, IBatch, IChunkedOp, IMessageProcessingResult } from "./definitions";
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -25,8 +26,10 @@ export class OpSplitter {
|
|
|
25
26
|
|
|
26
27
|
constructor(
|
|
27
28
|
chunks: [string, string[]][],
|
|
28
|
-
private readonly submitBatchFn:
|
|
29
|
-
|
|
29
|
+
private readonly submitBatchFn:
|
|
30
|
+
| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)
|
|
31
|
+
| undefined,
|
|
32
|
+
public readonly chunkSizeInBytes: number,
|
|
30
33
|
private readonly maxBatchSizeInBytes: number,
|
|
31
34
|
logger: ITelemetryLogger,
|
|
32
35
|
) {
|
|
@@ -132,12 +135,16 @@ export class OpSplitter {
|
|
|
132
135
|
* @param batch - the compressed batch which needs to be processed
|
|
133
136
|
* @returns A new adjusted batch which can be sent over the wire
|
|
134
137
|
*/
|
|
135
|
-
public
|
|
138
|
+
public splitFirstBatchMessage(batch: IBatch): IBatch {
|
|
136
139
|
assert(this.isBatchChunkingEnabled, 0x513 /* Chunking needs to be enabled */);
|
|
137
140
|
assert(
|
|
138
141
|
batch.contentSizeInBytes > 0 && batch.content.length > 0,
|
|
139
142
|
0x514 /* Batch needs to be non-empty */,
|
|
140
143
|
);
|
|
144
|
+
assert(
|
|
145
|
+
batch.referenceSequenceNumber !== undefined,
|
|
146
|
+
0x58a /* Batch must have a reference sequence number if non-empty */,
|
|
147
|
+
);
|
|
141
148
|
assert(this.chunkSizeInBytes !== 0, 0x515 /* Chunk size needs to be non-zero */);
|
|
142
149
|
assert(
|
|
143
150
|
this.chunkSizeInBytes < this.maxBatchSizeInBytes,
|
|
@@ -145,43 +152,53 @@ export class OpSplitter {
|
|
|
145
152
|
);
|
|
146
153
|
|
|
147
154
|
const firstMessage = batch.content[0]; // we expect this to be the large compressed op, which needs to be split
|
|
148
|
-
assert(
|
|
149
|
-
firstMessage.metadata?.compressed === true || firstMessage.compression !== undefined,
|
|
150
|
-
0x517 /* Batch needs to be compressed */,
|
|
151
|
-
);
|
|
152
155
|
assert(
|
|
153
156
|
(firstMessage.contents?.length ?? 0) >= this.chunkSizeInBytes,
|
|
154
157
|
0x518 /* First message in the batch needs to be chunkable */,
|
|
155
158
|
);
|
|
156
159
|
|
|
157
160
|
const restOfMessages = batch.content.slice(1); // we expect these to be empty ops, created to reserve sequence numbers
|
|
158
|
-
const
|
|
161
|
+
const socketSize = estimateSocketSize(batch);
|
|
162
|
+
const chunks = splitOp(
|
|
163
|
+
firstMessage,
|
|
164
|
+
this.chunkSizeInBytes,
|
|
165
|
+
// If we estimate that the socket batch size will exceed the batch limit
|
|
166
|
+
// we will inject an empty op to minimize the risk of the payload failing due to
|
|
167
|
+
// the overhead from the trailing empty ops in the batch.
|
|
168
|
+
socketSize >= this.maxBatchSizeInBytes,
|
|
169
|
+
);
|
|
159
170
|
|
|
160
171
|
assert(this.submitBatchFn !== undefined, 0x519 /* We don't support old loaders */);
|
|
161
172
|
// Send the first N-1 chunks immediately
|
|
162
173
|
for (const chunk of chunks.slice(0, -1)) {
|
|
163
|
-
this.submitBatchFn(
|
|
174
|
+
this.submitBatchFn(
|
|
175
|
+
[chunkToBatchMessage(chunk, batch.referenceSequenceNumber)],
|
|
176
|
+
batch.referenceSequenceNumber,
|
|
177
|
+
);
|
|
164
178
|
}
|
|
165
179
|
|
|
166
180
|
// The last chunk will be part of the new batch and needs to
|
|
167
181
|
// preserve the batch metadata of the original batch
|
|
168
182
|
const lastChunk = chunkToBatchMessage(
|
|
169
183
|
chunks[chunks.length - 1],
|
|
170
|
-
|
|
184
|
+
batch.referenceSequenceNumber,
|
|
171
185
|
{ batch: firstMessage.metadata?.batch },
|
|
172
186
|
);
|
|
173
187
|
|
|
174
188
|
this.logger.sendPerformanceEvent({
|
|
175
|
-
|
|
189
|
+
// Used to be "Chunked compressed batch"
|
|
190
|
+
eventName: "CompressedChunkedBatch",
|
|
176
191
|
length: batch.content.length,
|
|
177
192
|
sizeInBytes: batch.contentSizeInBytes,
|
|
178
193
|
chunks: chunks.length,
|
|
179
194
|
chunkSizeInBytes: this.chunkSizeInBytes,
|
|
195
|
+
socketSize,
|
|
180
196
|
});
|
|
181
197
|
|
|
182
198
|
return {
|
|
183
199
|
content: [lastChunk, ...restOfMessages],
|
|
184
200
|
contentSizeInBytes: lastChunk.contents?.length ?? 0,
|
|
201
|
+
referenceSequenceNumber: batch.referenceSequenceNumber,
|
|
185
202
|
};
|
|
186
203
|
}
|
|
187
204
|
}
|
|
@@ -204,7 +221,23 @@ const chunkToBatchMessage = (
|
|
|
204
221
|
};
|
|
205
222
|
};
|
|
206
223
|
|
|
207
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Splits an op into smaller ops (chunks), based on the size of the op and the `chunkSizeInBytes` parameter.
|
|
226
|
+
*
|
|
227
|
+
* The last op of the result will be bundled with empty ops in the same batch. There is a risk of the batch payload
|
|
228
|
+
* exceeding the 1MB limit due to the overhead from the empty ops. If the last op is large, the risk is even higher.
|
|
229
|
+
* To minimize the odds, an extra empty op can be added to the result using the `extraOp` parameter.
|
|
230
|
+
*
|
|
231
|
+
* @param op - the op to be split
|
|
232
|
+
* @param chunkSizeInBytes - how large should the chunks be
|
|
233
|
+
* @param extraOp - should an extra empty op be added to the result
|
|
234
|
+
* @returns an array of chunked ops
|
|
235
|
+
*/
|
|
236
|
+
export const splitOp = (
|
|
237
|
+
op: BatchMessage,
|
|
238
|
+
chunkSizeInBytes: number,
|
|
239
|
+
extraOp: boolean = false,
|
|
240
|
+
): IChunkedOp[] => {
|
|
208
241
|
const chunks: IChunkedOp[] = [];
|
|
209
242
|
assert(
|
|
210
243
|
op.contents !== undefined && op.contents !== null,
|
|
@@ -212,17 +245,17 @@ export const splitOp = (op: BatchMessage, chunkSizeInBytes: number): IChunkedOp[
|
|
|
212
245
|
);
|
|
213
246
|
|
|
214
247
|
const contentLength = op.contents.length;
|
|
215
|
-
const
|
|
248
|
+
const chunkCount = Math.floor((contentLength - 1) / chunkSizeInBytes) + 1 + (extraOp ? 1 : 0);
|
|
216
249
|
let offset = 0;
|
|
217
|
-
for (let
|
|
250
|
+
for (let chunkId = 1; chunkId <= chunkCount; chunkId++) {
|
|
218
251
|
const chunk: IChunkedOp = {
|
|
219
|
-
chunkId
|
|
252
|
+
chunkId,
|
|
220
253
|
contents: op.contents.substr(offset, chunkSizeInBytes),
|
|
221
254
|
originalType: op.deserializedContent.type,
|
|
222
|
-
totalChunks:
|
|
255
|
+
totalChunks: chunkCount,
|
|
223
256
|
};
|
|
224
257
|
|
|
225
|
-
if (
|
|
258
|
+
if (chunkId === chunkCount) {
|
|
226
259
|
// We don't need to port these to all the chunks,
|
|
227
260
|
// as we rebuild the original op when we process the
|
|
228
261
|
// last chunk, therefore it is the only one that needs it.
|
|
@@ -232,7 +265,13 @@ export const splitOp = (op: BatchMessage, chunkSizeInBytes: number): IChunkedOp[
|
|
|
232
265
|
|
|
233
266
|
chunks.push(chunk);
|
|
234
267
|
offset += chunkSizeInBytes;
|
|
268
|
+
assert(
|
|
269
|
+
chunkId >= chunkCount - 1 || offset <= contentLength,
|
|
270
|
+
0x58b /* Content offset within bounds */,
|
|
271
|
+
);
|
|
235
272
|
}
|
|
236
273
|
|
|
274
|
+
assert(offset >= contentLength, 0x58c /* Content offset equal or larger than content length */);
|
|
275
|
+
assert(chunks.length === chunkCount, 0x5a5 /* Expected number of chunks */);
|
|
237
276
|
return chunks;
|
|
238
277
|
};
|
|
@@ -6,20 +6,26 @@
|
|
|
6
6
|
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
7
7
|
import { assert } from "@fluidframework/common-utils";
|
|
8
8
|
import { IContainerContext } from "@fluidframework/container-definitions";
|
|
9
|
-
import { GenericError } from "@fluidframework/container-utils";
|
|
9
|
+
import { GenericError, UsageError } from "@fluidframework/container-utils";
|
|
10
10
|
import { MessageType } from "@fluidframework/protocol-definitions";
|
|
11
|
+
import {
|
|
12
|
+
ChildLogger,
|
|
13
|
+
loggerToMonitoringContext,
|
|
14
|
+
MonitoringContext,
|
|
15
|
+
} from "@fluidframework/telemetry-utils";
|
|
11
16
|
import { ICompressionRuntimeOptions } from "../containerRuntime";
|
|
12
17
|
import { PendingStateManager } from "../pendingStateManager";
|
|
13
|
-
import { BatchManager } from "./batchManager";
|
|
18
|
+
import { BatchManager, estimateSocketSize } from "./batchManager";
|
|
14
19
|
import { BatchMessage, IBatch } from "./definitions";
|
|
15
20
|
import { OpCompressor } from "./opCompressor";
|
|
21
|
+
import { OpGroupingManager } from "./opGroupingManager";
|
|
16
22
|
import { OpSplitter } from "./opSplitter";
|
|
17
23
|
|
|
18
24
|
export interface IOutboxConfig {
|
|
19
25
|
readonly compressionOptions: ICompressionRuntimeOptions;
|
|
20
26
|
// The maximum size of a batch that we can send over the wire.
|
|
21
27
|
readonly maxBatchSizeInBytes: number;
|
|
22
|
-
readonly
|
|
28
|
+
readonly disablePartialFlush: boolean;
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
export interface IOutboxParameters {
|
|
@@ -30,14 +36,26 @@ export interface IOutboxParameters {
|
|
|
30
36
|
readonly compressor: OpCompressor;
|
|
31
37
|
readonly splitter: OpSplitter;
|
|
32
38
|
readonly logger: ITelemetryLogger;
|
|
39
|
+
readonly groupingManager: OpGroupingManager;
|
|
33
40
|
}
|
|
34
41
|
|
|
35
42
|
export class Outbox {
|
|
43
|
+
private readonly mc: MonitoringContext;
|
|
36
44
|
private readonly attachFlowBatch: BatchManager;
|
|
37
45
|
private readonly mainBatch: BatchManager;
|
|
38
|
-
private readonly defaultAttachFlowSoftLimitInBytes =
|
|
46
|
+
private readonly defaultAttachFlowSoftLimitInBytes = 320 * 1024;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Track the number of ops which were detected to have a mismatched
|
|
50
|
+
* reference sequence number, in order to self-throttle the telemetry events.
|
|
51
|
+
*
|
|
52
|
+
* This should be removed as part of ADO:2322
|
|
53
|
+
*/
|
|
54
|
+
private readonly maxMismatchedOpsToReport = 3;
|
|
55
|
+
private mismatchedOpsReported = 0;
|
|
39
56
|
|
|
40
57
|
constructor(private readonly params: IOutboxParameters) {
|
|
58
|
+
this.mc = loggerToMonitoringContext(ChildLogger.create(params.logger, "Outbox"));
|
|
41
59
|
const isCompressionEnabled =
|
|
42
60
|
this.params.config.compressionOptions.minimumBatchSizeInBytes !==
|
|
43
61
|
Number.POSITIVE_INFINITY;
|
|
@@ -45,28 +63,63 @@ export class Outbox {
|
|
|
45
63
|
const hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;
|
|
46
64
|
const softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;
|
|
47
65
|
|
|
48
|
-
this.attachFlowBatch = new BatchManager(
|
|
49
|
-
|
|
50
|
-
hardLimit,
|
|
51
|
-
softLimit,
|
|
52
|
-
enableOpReentryCheck: params.config.enableOpReentryCheck,
|
|
53
|
-
},
|
|
54
|
-
params.logger,
|
|
55
|
-
);
|
|
56
|
-
this.mainBatch = new BatchManager(
|
|
57
|
-
{
|
|
58
|
-
hardLimit,
|
|
59
|
-
enableOpReentryCheck: params.config.enableOpReentryCheck,
|
|
60
|
-
},
|
|
61
|
-
params.logger,
|
|
62
|
-
);
|
|
66
|
+
this.attachFlowBatch = new BatchManager({ hardLimit, softLimit });
|
|
67
|
+
this.mainBatch = new BatchManager({ hardLimit });
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
public get isEmpty(): boolean {
|
|
66
71
|
return this.attachFlowBatch.length === 0 && this.mainBatch.length === 0;
|
|
67
72
|
}
|
|
68
73
|
|
|
74
|
+
/**
|
|
75
|
+
* If we detect that the reference sequence number of the incoming message does not match
|
|
76
|
+
* what was already in the batch managers, this means that batching has been interrupted so
|
|
77
|
+
* we will flush the accumulated messages to account for that and create a new batch with the new
|
|
78
|
+
* message as the first message.
|
|
79
|
+
*
|
|
80
|
+
* @param message - the incoming message
|
|
81
|
+
*/
|
|
82
|
+
private maybeFlushPartialBatch(message: BatchMessage) {
|
|
83
|
+
const mainBatchReference = this.mainBatch.referenceSequenceNumber;
|
|
84
|
+
const attachFlowBatchReference = this.attachFlowBatch.referenceSequenceNumber;
|
|
85
|
+
assert(
|
|
86
|
+
this.params.config.disablePartialFlush ||
|
|
87
|
+
mainBatchReference === undefined ||
|
|
88
|
+
attachFlowBatchReference === undefined ||
|
|
89
|
+
mainBatchReference === attachFlowBatchReference,
|
|
90
|
+
0x58d /* Reference sequence numbers from both batches must be in sync */,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
if (
|
|
94
|
+
(mainBatchReference === undefined ||
|
|
95
|
+
mainBatchReference === message.referenceSequenceNumber) &&
|
|
96
|
+
(attachFlowBatchReference === undefined ||
|
|
97
|
+
attachFlowBatchReference === message.referenceSequenceNumber)
|
|
98
|
+
) {
|
|
99
|
+
// The reference sequence numbers are stable, there is nothing to do
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {
|
|
104
|
+
this.mc.logger.sendErrorEvent(
|
|
105
|
+
{
|
|
106
|
+
eventName: "ReferenceSequenceNumberMismatch",
|
|
107
|
+
mainReferenceSequenceNumber: mainBatchReference,
|
|
108
|
+
attachReferenceSequenceNumber: attachFlowBatchReference,
|
|
109
|
+
messageReferenceSequenceNumber: message.referenceSequenceNumber,
|
|
110
|
+
},
|
|
111
|
+
new UsageError("Submission of an out of order message"),
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!this.params.config.disablePartialFlush) {
|
|
116
|
+
this.flush();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
69
120
|
public submit(message: BatchMessage) {
|
|
121
|
+
this.maybeFlushPartialBatch(message);
|
|
122
|
+
|
|
70
123
|
if (!this.mainBatch.push(message)) {
|
|
71
124
|
throw new GenericError("BatchTooLarge", /* error */ undefined, {
|
|
72
125
|
opSize: message.contents?.length ?? 0,
|
|
@@ -78,6 +131,8 @@ export class Outbox {
|
|
|
78
131
|
}
|
|
79
132
|
|
|
80
133
|
public submitAttach(message: BatchMessage) {
|
|
134
|
+
this.maybeFlushPartialBatch(message);
|
|
135
|
+
|
|
81
136
|
if (!this.attachFlowBatch.push(message)) {
|
|
82
137
|
// BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged
|
|
83
138
|
// when queue is not empty.
|
|
@@ -113,69 +168,82 @@ export class Outbox {
|
|
|
113
168
|
|
|
114
169
|
private flushInternal(rawBatch: IBatch) {
|
|
115
170
|
const processedBatch = this.compressBatch(rawBatch);
|
|
116
|
-
|
|
171
|
+
this.sendBatch(processedBatch);
|
|
117
172
|
|
|
118
|
-
this.persistBatch(
|
|
173
|
+
this.persistBatch(rawBatch.content);
|
|
119
174
|
}
|
|
120
175
|
|
|
121
176
|
private compressBatch(batch: IBatch): IBatch {
|
|
122
177
|
if (
|
|
123
178
|
batch.content.length === 0 ||
|
|
124
179
|
this.params.config.compressionOptions === undefined ||
|
|
125
|
-
this.params.config.compressionOptions.minimumBatchSizeInBytes >
|
|
180
|
+
this.params.config.compressionOptions.minimumBatchSizeInBytes >
|
|
181
|
+
batch.contentSizeInBytes ||
|
|
182
|
+
this.params.containerContext.submitBatchFn === undefined
|
|
126
183
|
) {
|
|
127
|
-
// Nothing to do if the batch is empty or if compression is disabled or if we don't need to compress
|
|
128
|
-
return batch;
|
|
184
|
+
// Nothing to do if the batch is empty or if compression is disabled or not supported, or if we don't need to compress
|
|
185
|
+
return this.params.groupingManager.groupBatch(batch);
|
|
129
186
|
}
|
|
130
187
|
|
|
131
|
-
const compressedBatch = this.params.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return compressedBatch;
|
|
135
|
-
}
|
|
188
|
+
const compressedBatch = this.params.groupingManager.groupBatch(
|
|
189
|
+
this.params.compressor.compressBatch(batch),
|
|
190
|
+
);
|
|
136
191
|
|
|
137
192
|
if (this.params.splitter.isBatchChunkingEnabled) {
|
|
138
|
-
return this.params.splitter.
|
|
193
|
+
return compressedBatch.contentSizeInBytes <= this.params.splitter.chunkSizeInBytes
|
|
194
|
+
? compressedBatch
|
|
195
|
+
: this.params.splitter.splitFirstBatchMessage(compressedBatch);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (compressedBatch.contentSizeInBytes >= this.params.config.maxBatchSizeInBytes) {
|
|
199
|
+
throw new GenericError("BatchTooLarge", /* error */ undefined, {
|
|
200
|
+
batchSize: batch.contentSizeInBytes,
|
|
201
|
+
compressedBatchSize: compressedBatch.contentSizeInBytes,
|
|
202
|
+
count: compressedBatch.content.length,
|
|
203
|
+
limit: this.params.config.maxBatchSizeInBytes,
|
|
204
|
+
chunkingEnabled: this.params.splitter.isBatchChunkingEnabled,
|
|
205
|
+
compressionOptions: JSON.stringify(this.params.config.compressionOptions),
|
|
206
|
+
socketSize: estimateSocketSize(batch),
|
|
207
|
+
});
|
|
139
208
|
}
|
|
140
209
|
|
|
141
|
-
|
|
142
|
-
throw new GenericError("BatchTooLarge", /* error */ undefined, {
|
|
143
|
-
batchSize: batch.contentSizeInBytes,
|
|
144
|
-
compressedBatchSize: compressedBatch.contentSizeInBytes,
|
|
145
|
-
count: compressedBatch.content.length,
|
|
146
|
-
limit: this.params.config.maxBatchSizeInBytes,
|
|
147
|
-
chunkingEnabled: this.params.splitter.isBatchChunkingEnabled,
|
|
148
|
-
compressionOptions: JSON.stringify(this.params.config.compressionOptions),
|
|
149
|
-
});
|
|
210
|
+
return compressedBatch;
|
|
150
211
|
}
|
|
151
212
|
|
|
152
213
|
/**
|
|
153
214
|
* Sends the batch object to the container context to be sent over the wire.
|
|
154
215
|
*
|
|
155
216
|
* @param batch - batch to be sent
|
|
156
|
-
* @returns the client sequence number of the last batched op which was sent and
|
|
157
|
-
* -1 if there are no ops or the container cannot send ops.
|
|
158
217
|
*/
|
|
159
|
-
private sendBatch(batch: IBatch)
|
|
160
|
-
let clientSequenceNumber: number = -1;
|
|
218
|
+
private sendBatch(batch: IBatch) {
|
|
161
219
|
const length = batch.content.length;
|
|
162
220
|
|
|
163
221
|
// Did we disconnect in the middle of turn-based batch?
|
|
164
222
|
// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.
|
|
165
223
|
if (length === 0 || !this.params.shouldSend()) {
|
|
166
|
-
return
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const socketSize = estimateSocketSize(batch);
|
|
228
|
+
if (socketSize >= this.params.config.maxBatchSizeInBytes) {
|
|
229
|
+
this.mc.logger.sendPerformanceEvent({
|
|
230
|
+
eventName: "LargeBatch",
|
|
231
|
+
length: batch.content.length,
|
|
232
|
+
sizeInBytes: batch.contentSizeInBytes,
|
|
233
|
+
socketSize,
|
|
234
|
+
});
|
|
167
235
|
}
|
|
168
236
|
|
|
169
237
|
if (this.params.containerContext.submitBatchFn === undefined) {
|
|
170
238
|
// Legacy path - supporting old loader versions. Can be removed only when LTS moves above
|
|
171
239
|
// version that has support for batches (submitBatchFn)
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if
|
|
175
|
-
|
|
176
|
-
}
|
|
240
|
+
assert(
|
|
241
|
+
batch.content[0].compression === undefined,
|
|
242
|
+
0x5a6 /* Compression should not have happened if the loader does not support it */,
|
|
243
|
+
);
|
|
177
244
|
|
|
178
|
-
|
|
245
|
+
for (const message of batch.content) {
|
|
246
|
+
this.params.containerContext.submitFn(
|
|
179
247
|
MessageType.Operation,
|
|
180
248
|
message.deserializedContent,
|
|
181
249
|
true, // batch
|
|
@@ -185,37 +253,33 @@ export class Outbox {
|
|
|
185
253
|
|
|
186
254
|
this.params.containerContext.deltaManager.flush();
|
|
187
255
|
} else {
|
|
188
|
-
|
|
189
|
-
|
|
256
|
+
assert(
|
|
257
|
+
batch.referenceSequenceNumber !== undefined,
|
|
258
|
+
0x58e /* Batch must not be empty */,
|
|
259
|
+
);
|
|
260
|
+
this.params.containerContext.submitBatchFn(
|
|
190
261
|
batch.content.map((message) => ({
|
|
191
262
|
contents: message.contents,
|
|
192
263
|
metadata: message.metadata,
|
|
193
264
|
compression: message.compression,
|
|
265
|
+
referenceSequenceNumber: message.referenceSequenceNumber,
|
|
194
266
|
})),
|
|
267
|
+
batch.referenceSequenceNumber,
|
|
195
268
|
);
|
|
196
269
|
}
|
|
197
|
-
|
|
198
|
-
// Convert from clientSequenceNumber of last message in the batch to clientSequenceNumber of first message.
|
|
199
|
-
clientSequenceNumber -= length - 1;
|
|
200
|
-
assert(clientSequenceNumber >= 0, 0x3d0 /* clientSequenceNumber can't be negative */);
|
|
201
|
-
return clientSequenceNumber;
|
|
202
270
|
}
|
|
203
271
|
|
|
204
|
-
private persistBatch(
|
|
205
|
-
let clientSequenceNumber = initialClientSequenceNumber;
|
|
272
|
+
private persistBatch(batch: BatchMessage[]) {
|
|
206
273
|
// Let the PendingStateManager know that a message was submitted.
|
|
207
274
|
// In future, need to shift toward keeping batch as a whole!
|
|
208
275
|
for (const message of batch) {
|
|
209
276
|
this.params.pendingStateManager.onSubmitMessage(
|
|
210
277
|
message.deserializedContent.type,
|
|
211
|
-
clientSequenceNumber,
|
|
212
278
|
message.referenceSequenceNumber,
|
|
213
279
|
message.deserializedContent.contents,
|
|
214
280
|
message.localOpMetadata,
|
|
215
281
|
message.metadata,
|
|
216
282
|
);
|
|
217
|
-
|
|
218
|
-
clientSequenceNumber++;
|
|
219
283
|
}
|
|
220
284
|
}
|
|
221
285
|
|
|
@@ -6,12 +6,14 @@
|
|
|
6
6
|
import { ISequencedDocumentMessage, MessageType } from "@fluidframework/protocol-definitions";
|
|
7
7
|
import { ContainerMessageType, ContainerRuntimeMessage } from "../containerRuntime";
|
|
8
8
|
import { OpDecompressor } from "./opDecompressor";
|
|
9
|
+
import { OpGroupingManager } from "./opGroupingManager";
|
|
9
10
|
import { OpSplitter } from "./opSplitter";
|
|
10
11
|
|
|
11
12
|
export class RemoteMessageProcessor {
|
|
12
13
|
constructor(
|
|
13
14
|
private readonly opSplitter: OpSplitter,
|
|
14
15
|
private readonly opDecompressor: OpDecompressor,
|
|
16
|
+
private readonly opGroupingManager: OpGroupingManager,
|
|
15
17
|
) {}
|
|
16
18
|
|
|
17
19
|
public get partialMessages(): ReadonlyMap<string, string[]> {
|
|
@@ -22,30 +24,44 @@ export class RemoteMessageProcessor {
|
|
|
22
24
|
this.opSplitter.clearPartialChunks(clientId);
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
public process(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage {
|
|
26
|
-
|
|
27
|
-
message = this.opDecompressor.processMessage(message).message;
|
|
28
|
-
unpackRuntimeMessage(message);
|
|
29
|
-
|
|
30
|
-
const chunkProcessingResult = this.opSplitter.processRemoteMessage(message);
|
|
31
|
-
message = chunkProcessingResult.message;
|
|
32
|
-
if (chunkProcessingResult.state !== "Processed") {
|
|
33
|
-
// If the message is not chunked or if the splitter is still rebuilding the original message,
|
|
34
|
-
// there is no need to continue processing
|
|
35
|
-
return message;
|
|
36
|
-
}
|
|
27
|
+
public process(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage[] {
|
|
28
|
+
const result: ISequencedDocumentMessage[] = [];
|
|
37
29
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// there is no need to continue processing
|
|
43
|
-
return message;
|
|
44
|
-
}
|
|
30
|
+
// Ungroup before processing chunks
|
|
31
|
+
for (let ungroupedMessage of this.opGroupingManager.ungroupOp(copy(remoteMessage))) {
|
|
32
|
+
ungroupedMessage = this.opDecompressor.processMessage(ungroupedMessage).message;
|
|
33
|
+
unpackRuntimeMessage(ungroupedMessage);
|
|
45
34
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
35
|
+
const chunkProcessingResult = this.opSplitter.processRemoteMessage(ungroupedMessage);
|
|
36
|
+
ungroupedMessage = chunkProcessingResult.message;
|
|
37
|
+
if (chunkProcessingResult.state !== "Processed") {
|
|
38
|
+
// If the message is not chunked or if the splitter is still rebuilding the original message,
|
|
39
|
+
// there is no need to continue processing
|
|
40
|
+
result.push(ungroupedMessage);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Ungroup the chunked message before decompressing
|
|
45
|
+
for (let ungroupedMessageAfterChunking of this.opGroupingManager.ungroupOp(
|
|
46
|
+
ungroupedMessage,
|
|
47
|
+
)) {
|
|
48
|
+
const decompressionAfterChunking = this.opDecompressor.processMessage(
|
|
49
|
+
ungroupedMessageAfterChunking,
|
|
50
|
+
);
|
|
51
|
+
ungroupedMessageAfterChunking = decompressionAfterChunking.message;
|
|
52
|
+
if (decompressionAfterChunking.state === "Skipped") {
|
|
53
|
+
// After chunking, if the original message was not compressed,
|
|
54
|
+
// there is no need to continue processing
|
|
55
|
+
result.push(ungroupedMessageAfterChunking);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// The message needs to be unpacked after chunking + decompression
|
|
60
|
+
unpack(ungroupedMessageAfterChunking);
|
|
61
|
+
result.push(ungroupedMessageAfterChunking);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
49
65
|
}
|
|
50
66
|
}
|
|
51
67
|
|
package/src/packageVersion.ts
CHANGED
|
@@ -29,12 +29,13 @@ export interface IPendingMessage {
|
|
|
29
29
|
/**
|
|
30
30
|
* This represents an explicit flush call and is added to the pending queue when flush is called on the ContainerRuntime
|
|
31
31
|
* to flush pending messages.
|
|
32
|
-
*
|
|
32
|
+
* ! TODO: Remove in "2.0.0-internal.5.0.0" AB#2496
|
|
33
33
|
*/
|
|
34
34
|
export interface IPendingFlush {
|
|
35
35
|
type: "flush";
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/** ! TODO: Remove in "2.0.0-internal.5.0.0" AB#2496 */
|
|
38
39
|
export type IPendingState = IPendingMessage | IPendingFlush;
|
|
39
40
|
|
|
40
41
|
export interface IPendingLocalState {
|
|
@@ -107,17 +108,11 @@ export class PendingStateManager implements IDisposable {
|
|
|
107
108
|
);
|
|
108
109
|
if (!this.pendingMessages.isEmpty()) {
|
|
109
110
|
return {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// TODO: Remove in 2.0.0-internal.4.0.0 (AB#2496)
|
|
116
|
-
if (message.opMetadata?.batch === false) {
|
|
117
|
-
arr.push({ type: "flush" });
|
|
118
|
-
}
|
|
119
|
-
return arr;
|
|
120
|
-
}, new Array<IPendingState>()),
|
|
111
|
+
// delete localOpMetadata since it may not be serializable
|
|
112
|
+
// and will be regenerated by applyStashedOp()
|
|
113
|
+
pendingStates: this.pendingMessages
|
|
114
|
+
.toArray()
|
|
115
|
+
.map((message) => ({ ...message, localOpMetadata: undefined })),
|
|
121
116
|
};
|
|
122
117
|
}
|
|
123
118
|
}
|
|
@@ -130,7 +125,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
130
125
|
* Convert old local state format to the new format
|
|
131
126
|
* The old format contained "flush" messages as the indicator of batch ends
|
|
132
127
|
* The new format instead uses batch metadata on the last message to indicate batch ends
|
|
133
|
-
* ! TODO: Remove this conversion in "2.0.0-internal.
|
|
128
|
+
* ! TODO: Remove this conversion in "2.0.0-internal.5.0.0" as version from "2.0.0-internal.4.0.0" will be new format
|
|
134
129
|
* AB#2496 tracks removal
|
|
135
130
|
*/
|
|
136
131
|
if (initialLocalState?.pendingStates) {
|
|
@@ -168,13 +163,11 @@ export class PendingStateManager implements IDisposable {
|
|
|
168
163
|
* Called when a message is submitted locally. Adds the message and the associated details to the pending state
|
|
169
164
|
* queue.
|
|
170
165
|
* @param type - The container message type.
|
|
171
|
-
* @param clientSequenceNumber - The clientSequenceNumber associated with the message.
|
|
172
166
|
* @param content - The message content.
|
|
173
167
|
* @param localOpMetadata - The local metadata associated with the message.
|
|
174
168
|
*/
|
|
175
169
|
public onSubmitMessage(
|
|
176
170
|
type: ContainerMessageType,
|
|
177
|
-
clientSequenceNumber: number,
|
|
178
171
|
referenceSequenceNumber: number,
|
|
179
172
|
content: any,
|
|
180
173
|
localOpMetadata: unknown,
|
|
@@ -183,7 +176,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
183
176
|
const pendingMessage: IPendingMessage = {
|
|
184
177
|
type: "message",
|
|
185
178
|
messageType: type,
|
|
186
|
-
clientSequenceNumber,
|
|
179
|
+
clientSequenceNumber: -1, // dummy value (not to be used anywhere)
|
|
187
180
|
referenceSequenceNumber,
|
|
188
181
|
content,
|
|
189
182
|
localOpMetadata,
|
|
@@ -241,18 +234,34 @@ export class PendingStateManager implements IDisposable {
|
|
|
241
234
|
);
|
|
242
235
|
this.pendingMessages.shift();
|
|
243
236
|
|
|
244
|
-
|
|
245
|
-
// The clientSequenceNumber of the incoming message must match that of the pending message.
|
|
246
|
-
if (pendingMessage.clientSequenceNumber !== message.clientSequenceNumber) {
|
|
237
|
+
if (pendingMessage.messageType !== message.type) {
|
|
247
238
|
// Close the container because this could indicate data corruption.
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
239
|
+
this.stateHandler.close(
|
|
240
|
+
DataProcessingError.create(
|
|
241
|
+
"pending local message type mismatch",
|
|
242
|
+
"unexpectedAckReceived",
|
|
243
|
+
message,
|
|
244
|
+
{
|
|
245
|
+
expectedMessageType: pendingMessage.messageType,
|
|
246
|
+
},
|
|
247
|
+
),
|
|
253
248
|
);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
254
251
|
|
|
255
|
-
|
|
252
|
+
const pendingMessageContent = JSON.stringify(pendingMessage.content);
|
|
253
|
+
const messageContent = JSON.stringify(message.contents);
|
|
254
|
+
|
|
255
|
+
// Stringified content does not match
|
|
256
|
+
if (pendingMessageContent !== messageContent) {
|
|
257
|
+
// Close the container because this could indicate data corruption.
|
|
258
|
+
this.stateHandler.close(
|
|
259
|
+
DataProcessingError.create(
|
|
260
|
+
"pending local message content mismatch",
|
|
261
|
+
"unexpectedAckReceived",
|
|
262
|
+
message,
|
|
263
|
+
),
|
|
264
|
+
);
|
|
256
265
|
return;
|
|
257
266
|
}
|
|
258
267
|
|
|
@@ -322,8 +331,6 @@ export class PendingStateManager implements IDisposable {
|
|
|
322
331
|
hasBatchStart: batchBeginMetadata === true,
|
|
323
332
|
hasBatchEnd: batchEndMetadata === false,
|
|
324
333
|
messageType: message.type,
|
|
325
|
-
batchStartSequenceNumber:
|
|
326
|
-
this.pendingBatchBeginMessage.clientSequenceNumber,
|
|
327
334
|
pendingMessagesCount: this.pendingMessagesCount,
|
|
328
335
|
},
|
|
329
336
|
),
|