@fluidframework/container-runtime 2.0.0-dev-rc.2.0.0.246488 → 2.0.0-dev-rc.3.0.0.250606
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/api-report/container-runtime.api.md +78 -25
- package/dist/batchTracker.d.ts +1 -1
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +2 -2
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +3 -3
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +3 -3
- package/dist/blobManager.js.map +1 -1
- package/dist/channelCollection.d.ts +5 -5
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +44 -11
- package/dist/channelCollection.js.map +1 -1
- package/dist/connectionTelemetry.d.ts +2 -2
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +3 -3
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/container-runtime-alpha.d.ts +205 -11
- package/dist/container-runtime-beta.d.ts +16 -2
- package/dist/container-runtime-public.d.ts +16 -2
- package/dist/container-runtime-untrimmed.d.ts +205 -24
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +32 -26
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +213 -119
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +2 -2
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +4 -4
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +18 -18
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/deltaScheduler.d.ts +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +1 -1
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +1 -1
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +1 -1
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +1 -1
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +1 -1
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +1 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +11 -5
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js +4 -0
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +1 -19
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +3 -3
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +3 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +2 -3
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +15 -4
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +60 -61
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +2 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +9 -11
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +11 -3
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +48 -38
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +7 -12
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +8 -0
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +36 -35
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +1 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +2 -2
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +178 -0
- package/dist/summary/documentSchema.d.ts.map +1 -0
- package/dist/summary/documentSchema.js +345 -0
- package/dist/summary/documentSchema.js.map +1 -0
- package/dist/summary/index.d.ts +2 -1
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js +4 -1
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +2 -2
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +3 -2
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +2 -2
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +2 -2
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +2 -2
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +2 -2
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +2 -2
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.d.ts +1 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +2 -2
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +3 -3
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +3 -3
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +2 -2
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +1 -1
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +5 -16
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +2 -2
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +2 -2
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +2 -2
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/batchTracker.d.ts +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -2
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +3 -3
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +5 -5
- package/lib/blobManager.js.map +1 -1
- package/lib/channelCollection.d.ts +5 -5
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +46 -13
- package/lib/channelCollection.js.map +1 -1
- package/lib/connectionTelemetry.d.ts +2 -2
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +3 -3
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/container-runtime-alpha.d.ts +205 -11
- package/lib/container-runtime-beta.d.ts +16 -2
- package/lib/container-runtime-public.d.ts +16 -2
- package/lib/container-runtime-untrimmed.d.ts +205 -24
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +32 -26
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +175 -81
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +2 -2
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +4 -4
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +3 -3
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/deltaScheduler.d.ts +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +1 -1
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +1 -1
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +3 -3
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts +1 -1
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +1 -1
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +1 -1
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +1 -1
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +1 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +1 -1
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/messageTypes.d.ts +11 -5
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js +4 -0
- package/lib/messageTypes.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +1 -19
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +3 -3
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js +2 -2
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +2 -3
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +15 -4
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +60 -61
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +2 -1
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +7 -10
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +11 -3
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +46 -37
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +7 -12
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +8 -0
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +36 -35
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +1 -1
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.d.ts +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +2 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +178 -0
- package/lib/summary/documentSchema.d.ts.map +1 -0
- package/lib/summary/documentSchema.js +341 -0
- package/lib/summary/documentSchema.js.map +1 -0
- package/lib/summary/index.d.ts +2 -1
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js +1 -0
- package/lib/summary/index.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +2 -2
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +3 -2
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts +1 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +2 -2
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +3 -3
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +2 -2
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +3 -3
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts +2 -2
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.d.ts +1 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +2 -2
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +4 -4
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +3 -3
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +2 -2
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +1 -1
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +5 -16
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js +1 -1
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +2 -2
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +3 -3
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +2 -2
- package/lib/summary/summaryManager.js.map +1 -1
- package/lib/test/blobManager.spec.js +3 -3
- package/lib/test/blobManager.spec.js.map +1 -1
- package/lib/test/containerRuntime.spec.js +6 -4
- package/lib/test/containerRuntime.spec.js.map +1 -1
- package/lib/test/dataStoreContext.spec.js +4 -4
- package/lib/test/dataStoreContext.spec.js.map +1 -1
- package/lib/test/dataStoreCreation.spec.js +1 -1
- package/lib/test/dataStoreCreation.spec.js.map +1 -1
- package/lib/test/dataStoreRegistry.spec.js.map +1 -1
- package/lib/test/documentSchema.spec.js +282 -0
- package/lib/test/documentSchema.spec.js.map +1 -0
- package/lib/test/fuzz/fuzzUtils.js +11 -7
- package/lib/test/fuzz/fuzzUtils.js.map +1 -1
- package/lib/test/fuzz/summarizer.fuzz.spec.js +9 -7
- package/lib/test/fuzz/summarizer.fuzz.spec.js.map +1 -1
- package/lib/test/fuzz/summarizerFuzzMocks.js +43 -25
- package/lib/test/fuzz/summarizerFuzzMocks.js.map +1 -1
- package/lib/test/fuzz/summarizerFuzzSuite.js +7 -4
- package/lib/test/fuzz/summarizerFuzzSuite.js.map +1 -1
- package/lib/test/gc/garbageCollection.spec.js +5 -5
- package/lib/test/gc/garbageCollection.spec.js.map +1 -1
- package/lib/test/gc/gcConfigs.spec.js +2 -2
- package/lib/test/gc/gcConfigs.spec.js.map +1 -1
- package/lib/test/gc/gcHelpers.spec.js.map +1 -1
- package/lib/test/gc/gcStats.spec.js +2 -2
- package/lib/test/gc/gcStats.spec.js.map +1 -1
- package/lib/test/gc/gcSummaryStateTracker.spec.js +1 -1
- package/lib/test/gc/gcSummaryStateTracker.spec.js.map +1 -1
- package/lib/test/gc/gcTelemetry.spec.js +3 -3
- package/lib/test/gc/gcTelemetry.spec.js.map +1 -1
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js +1 -1
- package/lib/test/gc/gcUnreferencedStateTracker.spec.js.map +1 -1
- package/lib/test/getPendingBlobs.spec.js +1 -1
- package/lib/test/getPendingBlobs.spec.js.map +1 -1
- package/lib/test/hardwareStats.spec.js +1 -1
- package/lib/test/hardwareStats.spec.js.map +1 -1
- package/lib/test/opLifecycle/OpGroupingManager.spec.js +95 -118
- package/lib/test/opLifecycle/OpGroupingManager.spec.js.map +1 -1
- package/lib/test/opLifecycle/batchManager.spec.js +1 -1
- package/lib/test/opLifecycle/batchManager.spec.js.map +1 -1
- package/lib/test/opLifecycle/opCompressor.spec.js +0 -1
- package/lib/test/opLifecycle/opCompressor.spec.js.map +1 -1
- package/lib/test/opLifecycle/opDecompressor.spec.js +60 -55
- package/lib/test/opLifecycle/opDecompressor.spec.js.map +1 -1
- package/lib/test/opLifecycle/opSplitter.spec.js +56 -41
- package/lib/test/opLifecycle/opSplitter.spec.js.map +1 -1
- package/lib/test/opLifecycle/outbox.spec.js +118 -10
- package/lib/test/opLifecycle/outbox.spec.js.map +1 -1
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js +115 -91
- package/lib/test/opLifecycle/remoteMessageProcessor.spec.js.map +1 -1
- package/lib/test/pendingStateManager.spec.js +1 -1
- package/lib/test/pendingStateManager.spec.js.map +1 -1
- package/lib/test/scheduleManager.spec.js +1 -1
- package/lib/test/scheduleManager.spec.js.map +1 -1
- package/lib/test/summarizerNode.spec.js +1 -1
- package/lib/test/summarizerNode.spec.js.map +1 -1
- package/lib/test/summarizerNodeWithGc.spec.js +1 -1
- package/lib/test/summarizerNodeWithGc.spec.js.map +1 -1
- package/lib/test/summary/runningSummarizer.spec.js +4 -4
- package/lib/test/summary/runningSummarizer.spec.js.map +1 -1
- package/lib/test/summary/summarizer.spec.js.map +1 -1
- package/lib/test/summary/summarizerClientElection.spec.js +2 -2
- package/lib/test/summary/summarizerClientElection.spec.js.map +1 -1
- package/lib/test/summary/summarizerHeuristics.spec.js +1 -1
- package/lib/test/summary/summarizerHeuristics.spec.js.map +1 -1
- package/lib/test/summary/summaryCollection.spec.js +1 -1
- package/lib/test/summary/summaryCollection.spec.js.map +1 -1
- package/lib/test/summary/summaryManager.spec.js +3 -3
- package/lib/test/summary/summaryManager.spec.js.map +1 -1
- package/lib/test/throttler.spec.js +1 -1
- package/lib/test/throttler.spec.js.map +1 -1
- package/lib/test/types/validateContainerRuntimePrevious.generated.js +6 -4
- package/lib/test/types/validateContainerRuntimePrevious.generated.js.map +1 -1
- package/package.json +35 -21
- package/src/batchTracker.ts +3 -3
- package/src/blobManager.ts +15 -15
- package/src/channelCollection.ts +75 -35
- package/src/connectionTelemetry.ts +10 -10
- package/src/containerHandleContext.ts +1 -1
- package/src/containerRuntime.ts +352 -197
- package/src/dataStore.ts +2 -2
- package/src/dataStoreContext.ts +19 -19
- package/src/dataStoreContexts.ts +2 -2
- package/src/dataStoreRegistry.ts +1 -1
- package/src/deltaScheduler.ts +1 -1
- package/src/gc/garbageCollection.ts +12 -12
- package/src/gc/gcConfigs.ts +11 -11
- package/src/gc/gcDefinitions.ts +2 -2
- package/src/gc/gcHelpers.ts +2 -2
- package/src/gc/gcSummaryStateTracker.ts +4 -4
- package/src/gc/gcTelemetry.ts +6 -6
- package/src/index.ts +8 -1
- package/src/messageTypes.ts +18 -5
- package/src/opLifecycle/README.md +89 -0
- package/src/opLifecycle/definitions.ts +1 -20
- package/src/opLifecycle/index.ts +3 -9
- package/src/opLifecycle/opCompressor.ts +4 -5
- package/src/opLifecycle/opDecompressor.ts +83 -100
- package/src/opLifecycle/opGroupingManager.ts +9 -12
- package/src/opLifecycle/opSplitter.ts +73 -47
- package/src/opLifecycle/outbox.ts +13 -31
- package/src/opLifecycle/remoteMessageProcessor.ts +41 -59
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +2 -2
- package/src/scheduleManager.ts +7 -7
- package/src/summary/documentSchema.ts +553 -0
- package/src/summary/index.ts +10 -1
- package/src/summary/orderedClientElection.ts +6 -5
- package/src/summary/runWhileConnectedCoordinator.ts +1 -1
- package/src/summary/runningSummarizer.ts +19 -19
- package/src/summary/summarizer.ts +14 -14
- package/src/summary/summarizerClientElection.ts +2 -2
- package/src/summary/summarizerHeuristics.ts +2 -2
- package/src/summary/summarizerNode/summarizerNode.ts +15 -15
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +1 -1
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +4 -4
- package/src/summary/summarizerTypes.ts +3 -3
- package/src/summary/summaryCollection.ts +3 -3
- package/src/summary/summaryFormat.ts +8 -19
- package/src/summary/summaryGenerator.ts +10 -10
- package/src/summary/summaryManager.ts +4 -4
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { decompress } from "lz4js";
|
|
7
|
-
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
8
|
-
import { assert } from "@fluidframework/core-utils";
|
|
9
6
|
import { IsoBuffer, Uint8ArrayToString } from "@fluid-internal/client-utils";
|
|
10
|
-
import { createChildLogger } from "@fluidframework/telemetry-utils";
|
|
11
7
|
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
8
|
+
import { assert } from "@fluidframework/core-utils";
|
|
9
|
+
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
10
|
+
import { createChildLogger } from "@fluidframework/telemetry-utils";
|
|
11
|
+
import { decompress } from "lz4js";
|
|
12
12
|
import { CompressionAlgorithms } from "../containerRuntime.js";
|
|
13
13
|
import { IBatchMetadata } from "../metadata.js";
|
|
14
|
-
import { IMessageProcessingResult } from "./definitions.js";
|
|
15
14
|
|
|
16
15
|
/**
|
|
17
16
|
* Compression makes assumptions about the shape of message contents. This interface codifies those assumptions, but does not validate them.
|
|
@@ -38,100 +37,7 @@ export class OpDecompressor {
|
|
|
38
37
|
this.logger = createChildLogger({ logger, namespace: "OpDecompressor" });
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
public
|
|
42
|
-
assert(
|
|
43
|
-
message.compression === undefined || message.compression === CompressionAlgorithms.lz4,
|
|
44
|
-
0x511 /* Only lz4 compression is supported */,
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
if (
|
|
48
|
-
(message.metadata as IBatchMetadata | undefined)?.batch === true &&
|
|
49
|
-
this.isCompressed(message)
|
|
50
|
-
) {
|
|
51
|
-
// Beginning of a compressed batch
|
|
52
|
-
assert(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);
|
|
53
|
-
this.activeBatch = true;
|
|
54
|
-
|
|
55
|
-
const contents = IsoBuffer.from(
|
|
56
|
-
(message.contents as IPackedContentsContents).packedContents,
|
|
57
|
-
"base64",
|
|
58
|
-
);
|
|
59
|
-
const decompressedMessage = decompress(contents);
|
|
60
|
-
const intoString = Uint8ArrayToString(decompressedMessage);
|
|
61
|
-
const asObj = JSON.parse(intoString);
|
|
62
|
-
this.rootMessageContents = asObj;
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
message: newMessage(message, this.rootMessageContents[this.processedCount++]),
|
|
66
|
-
state: "Accepted",
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (
|
|
71
|
-
this.rootMessageContents !== undefined &&
|
|
72
|
-
(message.metadata as IBatchMetadata | undefined)?.batch === undefined &&
|
|
73
|
-
this.activeBatch
|
|
74
|
-
) {
|
|
75
|
-
assert(message.contents === undefined, 0x512 /* Expecting empty message */);
|
|
76
|
-
|
|
77
|
-
// Continuation of compressed batch
|
|
78
|
-
return {
|
|
79
|
-
message: newMessage(message, this.rootMessageContents[this.processedCount++]),
|
|
80
|
-
state: "Accepted",
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (
|
|
85
|
-
this.rootMessageContents !== undefined &&
|
|
86
|
-
(message.metadata as IBatchMetadata | undefined)?.batch === false
|
|
87
|
-
) {
|
|
88
|
-
// End of compressed batch
|
|
89
|
-
const returnMessage = newMessage(
|
|
90
|
-
message,
|
|
91
|
-
this.rootMessageContents[this.processedCount++],
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
this.activeBatch = false;
|
|
95
|
-
this.rootMessageContents = undefined;
|
|
96
|
-
this.processedCount = 0;
|
|
97
|
-
|
|
98
|
-
return {
|
|
99
|
-
message: returnMessage,
|
|
100
|
-
state: "Processed",
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (
|
|
105
|
-
(message.metadata as IBatchMetadata | undefined)?.batch === undefined &&
|
|
106
|
-
this.isCompressed(message)
|
|
107
|
-
) {
|
|
108
|
-
// Single compressed message
|
|
109
|
-
assert(
|
|
110
|
-
this.activeBatch === false,
|
|
111
|
-
0x4ba /* shouldn't receive compressed message in middle of a batch */,
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
const contents = IsoBuffer.from(
|
|
115
|
-
(message.contents as IPackedContentsContents).packedContents,
|
|
116
|
-
"base64",
|
|
117
|
-
);
|
|
118
|
-
const decompressedMessage = decompress(contents);
|
|
119
|
-
const intoString = new TextDecoder().decode(decompressedMessage);
|
|
120
|
-
const asObj = JSON.parse(intoString);
|
|
121
|
-
|
|
122
|
-
return {
|
|
123
|
-
message: newMessage(message, asObj[0]),
|
|
124
|
-
state: "Processed",
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
message,
|
|
130
|
-
state: "Skipped",
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
private isCompressed(message: ISequencedDocumentMessage) {
|
|
40
|
+
public isCompressedMessage(message: ISequencedDocumentMessage): boolean {
|
|
135
41
|
if (message.compression === CompressionAlgorithms.lz4) {
|
|
136
42
|
return true;
|
|
137
43
|
}
|
|
@@ -174,6 +80,80 @@ export class OpDecompressor {
|
|
|
174
80
|
|
|
175
81
|
return false;
|
|
176
82
|
}
|
|
83
|
+
|
|
84
|
+
public get currentlyUnrolling() {
|
|
85
|
+
return this.activeBatch;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Is the decompressed and stored batch only comprised of a single message */
|
|
89
|
+
private isSingleMessageBatch = false;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Decompress the given compressed message and store it to be subsequently unrolled.
|
|
93
|
+
* The stored message will be of type `any[]` where each element represents a message's `contents`
|
|
94
|
+
*/
|
|
95
|
+
public decompressAndStore(message: ISequencedDocumentMessage): void {
|
|
96
|
+
assert(
|
|
97
|
+
message.compression === undefined || message.compression === CompressionAlgorithms.lz4,
|
|
98
|
+
0x511 /* Only lz4 compression is supported */,
|
|
99
|
+
);
|
|
100
|
+
assert(this.isCompressedMessage(message), "provided message should be compressed");
|
|
101
|
+
|
|
102
|
+
assert(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);
|
|
103
|
+
this.activeBatch = true;
|
|
104
|
+
|
|
105
|
+
const batchMetadata = (message.metadata as IBatchMetadata | undefined)?.batch;
|
|
106
|
+
if (batchMetadata === undefined) {
|
|
107
|
+
this.isSingleMessageBatch = true;
|
|
108
|
+
} else {
|
|
109
|
+
assert(batchMetadata === true, "invalid batch metadata");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const contents = IsoBuffer.from(
|
|
113
|
+
(message.contents as IPackedContentsContents).packedContents,
|
|
114
|
+
"base64",
|
|
115
|
+
);
|
|
116
|
+
const decompressedMessage = decompress(contents);
|
|
117
|
+
const intoString = Uint8ArrayToString(decompressedMessage);
|
|
118
|
+
const asObj = JSON.parse(intoString);
|
|
119
|
+
this.rootMessageContents = asObj;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Unroll the next message from the decompressed content provided to {@link decompressAndStore}
|
|
124
|
+
* @returns the unrolled `ISequencedDocumentMessage`
|
|
125
|
+
*/
|
|
126
|
+
public unroll(message: ISequencedDocumentMessage): ISequencedDocumentMessage {
|
|
127
|
+
assert(this.currentlyUnrolling, "not currently unrolling");
|
|
128
|
+
assert(this.rootMessageContents !== undefined, "missing rootMessageContents");
|
|
129
|
+
assert(this.rootMessageContents.length > this.processedCount, "no more content to unroll");
|
|
130
|
+
|
|
131
|
+
const batchMetadata = (message.metadata as IBatchMetadata | undefined)?.batch;
|
|
132
|
+
|
|
133
|
+
if (batchMetadata === false || this.isSingleMessageBatch) {
|
|
134
|
+
// End of compressed batch
|
|
135
|
+
const returnMessage = newMessage(
|
|
136
|
+
message,
|
|
137
|
+
this.rootMessageContents[this.processedCount],
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
this.activeBatch = false;
|
|
141
|
+
this.isSingleMessageBatch = false;
|
|
142
|
+
this.rootMessageContents = undefined;
|
|
143
|
+
this.processedCount = 0;
|
|
144
|
+
|
|
145
|
+
return returnMessage;
|
|
146
|
+
} else if (batchMetadata === true) {
|
|
147
|
+
// Start of compressed batch
|
|
148
|
+
return newMessage(message, this.rootMessageContents[this.processedCount++]);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
assert(batchMetadata === undefined, "invalid batch metadata");
|
|
152
|
+
assert(message.contents === undefined, 0x512 /* Expecting empty message */);
|
|
153
|
+
|
|
154
|
+
// Continuation of compressed batch
|
|
155
|
+
return newMessage(message, this.rootMessageContents[this.processedCount++]);
|
|
156
|
+
}
|
|
177
157
|
}
|
|
178
158
|
|
|
179
159
|
// We should not be mutating the input message nor its metadata
|
|
@@ -186,5 +166,8 @@ const newMessage = (
|
|
|
186
166
|
compression: undefined,
|
|
187
167
|
// TODO: It should already be the case that we're not modifying any metadata, not clear if/why this shallow clone should be required.
|
|
188
168
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
189
|
-
metadata:
|
|
169
|
+
metadata:
|
|
170
|
+
originalMessage.metadata === undefined
|
|
171
|
+
? undefined
|
|
172
|
+
: { ...(originalMessage.metadata as any) },
|
|
190
173
|
});
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
6
7
|
import { assert } from "@fluidframework/core-utils";
|
|
7
8
|
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
8
9
|
import { createChildLogger } from "@fluidframework/telemetry-utils";
|
|
9
|
-
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
10
|
-
import { ContainerMessageType } from "../messageTypes.js";
|
|
11
10
|
import { IBatch } from "./definitions.js";
|
|
12
11
|
|
|
13
12
|
/**
|
|
@@ -28,6 +27,10 @@ function isGroupContents(opContents: any): opContents is IGroupedBatchMessageCon
|
|
|
28
27
|
return opContents?.type === OpGroupingManager.groupedBatchOp;
|
|
29
28
|
}
|
|
30
29
|
|
|
30
|
+
export function isGroupedBatch(op: ISequencedDocumentMessage): boolean {
|
|
31
|
+
return isGroupContents(op.contents);
|
|
32
|
+
}
|
|
33
|
+
|
|
31
34
|
export interface OpGroupingManagerConfig {
|
|
32
35
|
readonly groupedBatchingEnabled: boolean;
|
|
33
36
|
readonly opCountThreshold: number;
|
|
@@ -46,9 +49,7 @@ export class OpGroupingManager {
|
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
public groupBatch(batch: IBatch): IBatch {
|
|
49
|
-
|
|
50
|
-
return batch;
|
|
51
|
-
}
|
|
52
|
+
assert(this.shouldGroup(batch), "cannot group the provided batch");
|
|
52
53
|
|
|
53
54
|
if (batch.content.length >= 1000) {
|
|
54
55
|
this.logger.sendTelemetryEvent({
|
|
@@ -84,11 +85,9 @@ export class OpGroupingManager {
|
|
|
84
85
|
...batch,
|
|
85
86
|
content: [
|
|
86
87
|
{
|
|
87
|
-
localOpMetadata: undefined,
|
|
88
88
|
metadata: undefined,
|
|
89
89
|
referenceSequenceNumber: batch.content[0].referenceSequenceNumber,
|
|
90
90
|
contents: serializedContent,
|
|
91
|
-
type: OpGroupingManager.groupedBatchOp as ContainerMessageType,
|
|
92
91
|
},
|
|
93
92
|
],
|
|
94
93
|
};
|
|
@@ -96,13 +95,11 @@ export class OpGroupingManager {
|
|
|
96
95
|
}
|
|
97
96
|
|
|
98
97
|
public ungroupOp(op: ISequencedDocumentMessage): ISequencedDocumentMessage[] {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
98
|
+
assert(isGroupContents(op.contents), "can only ungroup a grouped batch");
|
|
99
|
+
const contents: IGroupedBatchMessageContents = op.contents;
|
|
102
100
|
|
|
103
|
-
const messages = op.contents.contents;
|
|
104
101
|
let fakeCsn = 1;
|
|
105
|
-
return
|
|
102
|
+
return contents.contents.map((subMessage) => ({
|
|
106
103
|
...op,
|
|
107
104
|
clientSequenceNumber: fakeCsn++,
|
|
108
105
|
contents: subMessage.contents,
|
|
@@ -3,18 +3,31 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { IBatchMessage } from "@fluidframework/container-definitions";
|
|
7
|
+
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
8
|
+
import { assert } from "@fluidframework/core-utils";
|
|
9
|
+
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
6
10
|
import {
|
|
7
|
-
createChildLogger,
|
|
8
11
|
DataCorruptionError,
|
|
12
|
+
createChildLogger,
|
|
9
13
|
extractSafePropertiesFromMessage,
|
|
10
14
|
} from "@fluidframework/telemetry-utils";
|
|
11
|
-
import { assert } from "@fluidframework/core-utils";
|
|
12
|
-
import { IBatchMessage } from "@fluidframework/container-definitions";
|
|
13
|
-
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
14
|
-
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
15
15
|
import { ContainerMessageType, ContainerRuntimeChunkedOpMessage } from "../messageTypes.js";
|
|
16
16
|
import { estimateSocketSize } from "./batchManager.js";
|
|
17
|
-
import { BatchMessage, IBatch, IChunkedOp
|
|
17
|
+
import { BatchMessage, IBatch, IChunkedOp } from "./definitions.js";
|
|
18
|
+
|
|
19
|
+
export function isChunkedMessage(message: ISequencedDocumentMessage): boolean {
|
|
20
|
+
return isChunkedContents(message.contents);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface IChunkedContents {
|
|
24
|
+
type: typeof ContainerMessageType.ChunkedOp;
|
|
25
|
+
contents: IChunkedOp;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isChunkedContents(contents: any): contents is IChunkedContents {
|
|
29
|
+
return contents?.type === ContainerMessageType.ChunkedOp;
|
|
30
|
+
}
|
|
18
31
|
|
|
19
32
|
/**
|
|
20
33
|
* Responsible for creating and reconstructing chunked messages.
|
|
@@ -45,44 +58,6 @@ export class OpSplitter {
|
|
|
45
58
|
return this.chunkMap;
|
|
46
59
|
}
|
|
47
60
|
|
|
48
|
-
public processRemoteMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {
|
|
49
|
-
if (message.type !== ContainerMessageType.ChunkedOp) {
|
|
50
|
-
return {
|
|
51
|
-
message,
|
|
52
|
-
state: "Skipped",
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)
|
|
57
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
58
|
-
const clientId = message.clientId as string;
|
|
59
|
-
const chunkedContent = message.contents as IChunkedOp;
|
|
60
|
-
this.addChunk(clientId, chunkedContent, message);
|
|
61
|
-
|
|
62
|
-
if (chunkedContent.chunkId < chunkedContent.totalChunks) {
|
|
63
|
-
// We are processing the op in chunks but haven't reached
|
|
64
|
-
// the last chunk yet in order to reconstruct the original op
|
|
65
|
-
return {
|
|
66
|
-
message,
|
|
67
|
-
state: "Accepted",
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
72
|
-
const serializedContent = this.chunkMap.get(clientId)!.join("");
|
|
73
|
-
this.clearPartialChunks(clientId);
|
|
74
|
-
|
|
75
|
-
const newMessage = { ...message };
|
|
76
|
-
newMessage.contents = serializedContent === "" ? undefined : JSON.parse(serializedContent);
|
|
77
|
-
newMessage.type = chunkedContent.originalType;
|
|
78
|
-
newMessage.metadata = chunkedContent.originalMetadata;
|
|
79
|
-
newMessage.compression = chunkedContent.originalCompression;
|
|
80
|
-
return {
|
|
81
|
-
message: newMessage,
|
|
82
|
-
state: "Processed",
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
61
|
public clearPartialChunks(clientId: string) {
|
|
87
62
|
if (this.chunkMap.has(clientId)) {
|
|
88
63
|
this.chunkMap.delete(clientId);
|
|
@@ -203,8 +178,53 @@ export class OpSplitter {
|
|
|
203
178
|
referenceSequenceNumber: batch.referenceSequenceNumber,
|
|
204
179
|
};
|
|
205
180
|
}
|
|
181
|
+
|
|
182
|
+
public processChunk(message: ISequencedDocumentMessage): ProcessChunkResult {
|
|
183
|
+
assert(isChunkedContents(message.contents), "message not of type ChunkedOp");
|
|
184
|
+
const contents: IChunkedContents = message.contents;
|
|
185
|
+
|
|
186
|
+
// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)
|
|
187
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
188
|
+
const clientId = message.clientId as string;
|
|
189
|
+
const chunkedContent = contents.contents;
|
|
190
|
+
this.addChunk(clientId, chunkedContent, message);
|
|
191
|
+
|
|
192
|
+
if (chunkedContent.chunkId < chunkedContent.totalChunks) {
|
|
193
|
+
// We are processing the op in chunks but haven't reached
|
|
194
|
+
// the last chunk yet in order to reconstruct the original op
|
|
195
|
+
return {
|
|
196
|
+
isFinalChunk: false,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
201
|
+
const serializedContent = this.chunkMap.get(clientId)!.join("");
|
|
202
|
+
this.clearPartialChunks(clientId);
|
|
203
|
+
|
|
204
|
+
const newMessage = { ...message };
|
|
205
|
+
newMessage.contents = serializedContent === "" ? undefined : JSON.parse(serializedContent);
|
|
206
|
+
// back-compat with 1.x builds
|
|
207
|
+
// This is only required / present for non-compressed, chunked ops
|
|
208
|
+
// For compressed ops, we have op grouping enabled, and type of each op is preserved within compressed content.
|
|
209
|
+
newMessage.type = (chunkedContent as any).originalType;
|
|
210
|
+
newMessage.metadata = chunkedContent.originalMetadata;
|
|
211
|
+
newMessage.compression = chunkedContent.originalCompression;
|
|
212
|
+
return {
|
|
213
|
+
message: newMessage,
|
|
214
|
+
isFinalChunk: true,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
206
217
|
}
|
|
207
218
|
|
|
219
|
+
type ProcessChunkResult =
|
|
220
|
+
| {
|
|
221
|
+
readonly isFinalChunk: false;
|
|
222
|
+
}
|
|
223
|
+
| {
|
|
224
|
+
readonly isFinalChunk: true;
|
|
225
|
+
readonly message: ISequencedDocumentMessage;
|
|
226
|
+
};
|
|
227
|
+
|
|
208
228
|
const chunkToBatchMessage = (
|
|
209
229
|
chunk: IChunkedOp,
|
|
210
230
|
referenceSequenceNumber: number,
|
|
@@ -216,9 +236,7 @@ const chunkToBatchMessage = (
|
|
|
216
236
|
};
|
|
217
237
|
return {
|
|
218
238
|
contents: JSON.stringify(payload),
|
|
219
|
-
type: payload.type,
|
|
220
239
|
metadata,
|
|
221
|
-
localOpMetadata: undefined,
|
|
222
240
|
referenceSequenceNumber,
|
|
223
241
|
};
|
|
224
242
|
};
|
|
@@ -253,7 +271,6 @@ export const splitOp = (
|
|
|
253
271
|
const chunk: IChunkedOp = {
|
|
254
272
|
chunkId,
|
|
255
273
|
contents: op.contents.substr(offset, chunkSizeInBytes),
|
|
256
|
-
originalType: op.type,
|
|
257
274
|
totalChunks: chunkCount,
|
|
258
275
|
};
|
|
259
276
|
|
|
@@ -263,6 +280,15 @@ export const splitOp = (
|
|
|
263
280
|
// last chunk, therefore it is the only one that needs it.
|
|
264
281
|
chunk.originalMetadata = op.metadata;
|
|
265
282
|
chunk.originalCompression = op.compression;
|
|
283
|
+
|
|
284
|
+
// back-compat with 1.x builds
|
|
285
|
+
// 2.x builds only do chunking for compressed ops.
|
|
286
|
+
// originalType is no longer used in such cases, as each op preserves its type within compressed payload.
|
|
287
|
+
// But, if 1.x builds see this op, and there is no type on the message, then it will ignore this message silently.
|
|
288
|
+
// This is really bad, as we will crash on later ops and it's very hard to debug these cases.
|
|
289
|
+
// If we put some known type here, then we will crash on it (as 1.x does not understand compression, and thus will not
|
|
290
|
+
// find info on the op like address of the channel to deliver the op)
|
|
291
|
+
(chunk as any).originalType = "component";
|
|
266
292
|
}
|
|
267
293
|
|
|
268
294
|
chunks.push(chunk);
|
|
@@ -3,18 +3,17 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { IBatchMessage, ICriticalContainerError } from "@fluidframework/container-definitions";
|
|
7
|
+
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
8
|
+
import { assert } from "@fluidframework/core-utils";
|
|
6
9
|
import {
|
|
7
|
-
createChildMonitoringContext,
|
|
8
10
|
GenericError,
|
|
9
11
|
MonitoringContext,
|
|
10
12
|
UsageError,
|
|
13
|
+
createChildMonitoringContext,
|
|
11
14
|
} from "@fluidframework/telemetry-utils";
|
|
12
|
-
import { assert } from "@fluidframework/core-utils";
|
|
13
|
-
import { IBatchMessage, ICriticalContainerError } from "@fluidframework/container-definitions";
|
|
14
|
-
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
15
15
|
import { ICompressionRuntimeOptions } from "../containerRuntime.js";
|
|
16
16
|
import { IPendingBatchMessage, PendingStateManager } from "../pendingStateManager.js";
|
|
17
|
-
import { ContainerMessageType } from "../messageTypes.js";
|
|
18
17
|
import {
|
|
19
18
|
BatchManager,
|
|
20
19
|
BatchSequenceNumbers,
|
|
@@ -187,20 +186,12 @@ export class Outbox {
|
|
|
187
186
|
}
|
|
188
187
|
|
|
189
188
|
public submit(message: BatchMessage) {
|
|
190
|
-
assert(
|
|
191
|
-
message.type !== ContainerMessageType.IdAllocation,
|
|
192
|
-
0x8f8 /* Allocation message submitted to mainBatch. */,
|
|
193
|
-
);
|
|
194
189
|
this.maybeFlushPartialBatch();
|
|
195
190
|
|
|
196
191
|
this.addMessageToBatchManager(this.mainBatch, message);
|
|
197
192
|
}
|
|
198
193
|
|
|
199
194
|
public submitAttach(message: BatchMessage) {
|
|
200
|
-
assert(
|
|
201
|
-
message.type === ContainerMessageType.Attach,
|
|
202
|
-
0x8f9 /* Non attach message submitted to attachFlowBatch. */,
|
|
203
|
-
);
|
|
204
195
|
this.maybeFlushPartialBatch();
|
|
205
196
|
|
|
206
197
|
if (
|
|
@@ -232,10 +223,6 @@ export class Outbox {
|
|
|
232
223
|
}
|
|
233
224
|
|
|
234
225
|
public submitBlobAttach(message: BatchMessage) {
|
|
235
|
-
assert(
|
|
236
|
-
message.type === ContainerMessageType.BlobAttach,
|
|
237
|
-
0x8fa /* Non blobAttach message submitted to blobAttachBatch. */,
|
|
238
|
-
);
|
|
239
226
|
this.maybeFlushPartialBatch();
|
|
240
227
|
|
|
241
228
|
this.addMessageToBatchManager(this.blobAttachBatch, message);
|
|
@@ -254,10 +241,6 @@ export class Outbox {
|
|
|
254
241
|
}
|
|
255
242
|
|
|
256
243
|
public submitIdAllocation(message: BatchMessage) {
|
|
257
|
-
assert(
|
|
258
|
-
message.type === ContainerMessageType.IdAllocation,
|
|
259
|
-
0x8fb /* Non allocation message submitted to idAllocationBatch. */,
|
|
260
|
-
);
|
|
261
244
|
this.maybeFlushPartialBatch();
|
|
262
245
|
|
|
263
246
|
if (
|
|
@@ -328,10 +311,9 @@ export class Outbox {
|
|
|
328
311
|
}
|
|
329
312
|
|
|
330
313
|
const rawBatch = batchManager.popBatch();
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
) {
|
|
314
|
+
const shouldGroup =
|
|
315
|
+
!disableGroupedBatching && this.params.groupingManager.shouldGroup(rawBatch);
|
|
316
|
+
if (rawBatch.hasReentrantOps === true && shouldGroup) {
|
|
335
317
|
assert(!this.rebasing, 0x6fa /* A rebased batch should never have reentrant ops */);
|
|
336
318
|
// If a batch contains reentrant ops (ops created as a result from processing another op)
|
|
337
319
|
// it needs to be rebased so that we can ensure consistent reference sequence numbers
|
|
@@ -344,7 +326,9 @@ export class Outbox {
|
|
|
344
326
|
// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.
|
|
345
327
|
// Because flush() is a task that executes async (on clean stack), we can get here in disconnected state.
|
|
346
328
|
if (this.params.shouldSend()) {
|
|
347
|
-
const processedBatch = this.compressBatch(
|
|
329
|
+
const processedBatch = this.compressBatch(
|
|
330
|
+
shouldGroup ? this.params.groupingManager.groupBatch(rawBatch) : rawBatch,
|
|
331
|
+
);
|
|
348
332
|
this.sendBatch(processedBatch);
|
|
349
333
|
}
|
|
350
334
|
|
|
@@ -390,7 +374,7 @@ export class Outbox {
|
|
|
390
374
|
return this.params.opReentrancy() && !this.rebasing;
|
|
391
375
|
}
|
|
392
376
|
|
|
393
|
-
private compressBatch(batch: IBatch
|
|
377
|
+
private compressBatch(batch: IBatch): IBatch {
|
|
394
378
|
if (
|
|
395
379
|
batch.content.length === 0 ||
|
|
396
380
|
this.params.config.compressionOptions === undefined ||
|
|
@@ -399,12 +383,10 @@ export class Outbox {
|
|
|
399
383
|
this.params.submitBatchFn === undefined
|
|
400
384
|
) {
|
|
401
385
|
// Nothing to do if the batch is empty or if compression is disabled or not supported, or if we don't need to compress
|
|
402
|
-
return
|
|
386
|
+
return batch;
|
|
403
387
|
}
|
|
404
388
|
|
|
405
|
-
const compressedBatch = this.params.compressor.compressBatch(
|
|
406
|
-
disableGroupedBatching ? batch : this.params.groupingManager.groupBatch(batch),
|
|
407
|
-
);
|
|
389
|
+
const compressedBatch = this.params.compressor.compressBatch(batch);
|
|
408
390
|
|
|
409
391
|
if (this.params.splitter.isBatchChunkingEnabled) {
|
|
410
392
|
return compressedBatch.contentSizeInBytes <= this.params.splitter.chunkSizeInBytes
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
type InboundSequencedRecentlyAddedContainerRuntimeMessage,
|
|
13
13
|
} from "../messageTypes.js";
|
|
14
14
|
import { OpDecompressor } from "./opDecompressor.js";
|
|
15
|
-
import { OpGroupingManager } from "./opGroupingManager.js";
|
|
16
|
-
import { OpSplitter } from "./opSplitter.js";
|
|
15
|
+
import { OpGroupingManager, isGroupedBatch } from "./opGroupingManager.js";
|
|
16
|
+
import { OpSplitter, isChunkedMessage } from "./opSplitter.js";
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Stateful class for processing incoming remote messages as the virtualization measures are unwrapped,
|
|
@@ -44,6 +44,14 @@ export class RemoteMessageProcessor {
|
|
|
44
44
|
* depends on this object instance.
|
|
45
45
|
* Note remoteMessageCopy.contents (and other object props) MUST not be modified,
|
|
46
46
|
* but may be overwritten (as is the case with contents).
|
|
47
|
+
*
|
|
48
|
+
* Incoming messages will always have compression, chunking, and grouped batching happen in a defined order and that order cannot be changed.
|
|
49
|
+
* When processing these messages, the order is:
|
|
50
|
+
* 1. If chunked, process the chunk and only continue if this is a final chunk
|
|
51
|
+
* 2. If compressed, decompress the message and store for further unrolling of the decompressed content
|
|
52
|
+
* 3. If grouped, ungroup the message
|
|
53
|
+
* For more details, see https://github.com/microsoft/FluidFramework/blob/main/packages/runtime/container-runtime/src/opLifecycle/README.md#inbound
|
|
54
|
+
*
|
|
47
55
|
* @returns the unchunked, decompressed, ungrouped, unpacked SequencedContainerRuntimeMessages encapsulated in the remote message.
|
|
48
56
|
* For ops that weren't virtualized (e.g. System ops that the ContainerRuntime will ultimately ignore),
|
|
49
57
|
* a singleton array [remoteMessageCopy] is returned
|
|
@@ -51,63 +59,38 @@ export class RemoteMessageProcessor {
|
|
|
51
59
|
public process(
|
|
52
60
|
remoteMessageCopy: ISequencedDocumentMessage,
|
|
53
61
|
): InboundSequencedContainerRuntimeMessageOrSystemMessage[] {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
for (let ungroupedMessage2 of this.opGroupingManager.ungroupOp(message)) {
|
|
63
|
-
// unpack and unchunk the ungrouped message in place
|
|
64
|
-
unpackRuntimeMessage(ungroupedMessage2);
|
|
65
|
-
const chunkProcessingResult =
|
|
66
|
-
this.opSplitter.processRemoteMessage(ungroupedMessage2);
|
|
67
|
-
ungroupedMessage2 = chunkProcessingResult.message;
|
|
68
|
-
|
|
69
|
-
// if the splitter is still rebuilding the original message, there is no need to continue processing
|
|
70
|
-
if (chunkProcessingResult.state === "Accepted") {
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// If the message is not chunked there is no need to continue processing
|
|
75
|
-
if (chunkProcessingResult.state !== "Processed") {
|
|
76
|
-
result.push(
|
|
77
|
-
ungroupedMessage2 as InboundSequencedContainerRuntimeMessageOrSystemMessage,
|
|
78
|
-
);
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Ungroup before and after decompression for back-compat (cleanup tracked by AB#4371)
|
|
83
|
-
for (const ungroupedMessageAfterChunking of this.opGroupingManager.ungroupOp(
|
|
84
|
-
ungroupedMessage2,
|
|
85
|
-
)) {
|
|
86
|
-
const decompressionAfterChunking = this.opDecompressor.processMessage(
|
|
87
|
-
ungroupedMessageAfterChunking,
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
for (const ungroupedMessageAfterChunking2 of this.opGroupingManager.ungroupOp(
|
|
91
|
-
decompressionAfterChunking.message,
|
|
92
|
-
)) {
|
|
93
|
-
if (decompressionAfterChunking.state === "Skipped") {
|
|
94
|
-
// After chunking, if the original message was not compressed,
|
|
95
|
-
// there is no need to continue processing
|
|
96
|
-
result.push(
|
|
97
|
-
ungroupedMessageAfterChunking2 as InboundSequencedContainerRuntimeMessageOrSystemMessage,
|
|
98
|
-
);
|
|
99
|
-
continue;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// The message needs to be unpacked after chunking + decompression
|
|
103
|
-
unpack(ungroupedMessageAfterChunking2);
|
|
104
|
-
result.push(ungroupedMessageAfterChunking2);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
62
|
+
let message = remoteMessageCopy;
|
|
63
|
+
ensureContentsDeserialized(message);
|
|
64
|
+
|
|
65
|
+
if (isChunkedMessage(message)) {
|
|
66
|
+
const chunkProcessingResult = this.opSplitter.processChunk(message);
|
|
67
|
+
// Only continue further if current chunk is the final chunk
|
|
68
|
+
if (!chunkProcessingResult.isFinalChunk) {
|
|
69
|
+
return [];
|
|
107
70
|
}
|
|
71
|
+
// This message will always be compressed
|
|
72
|
+
message = chunkProcessingResult.message;
|
|
108
73
|
}
|
|
109
74
|
|
|
110
|
-
|
|
75
|
+
if (this.opDecompressor.isCompressedMessage(message)) {
|
|
76
|
+
this.opDecompressor.decompressAndStore(message);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (this.opDecompressor.currentlyUnrolling) {
|
|
80
|
+
message = this.opDecompressor.unroll(message);
|
|
81
|
+
// Need to unpack after unrolling if not a groupedBatch
|
|
82
|
+
if (!isGroupedBatch(message)) {
|
|
83
|
+
unpack(message);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (isGroupedBatch(message)) {
|
|
88
|
+
return this.opGroupingManager.ungroupOp(message).map(unpack);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Do a final unpack of runtime messages in case the message was not grouped, compressed, or chunked
|
|
92
|
+
unpackRuntimeMessage(message);
|
|
93
|
+
return [message as InboundSequencedContainerRuntimeMessageOrSystemMessage];
|
|
111
94
|
}
|
|
112
95
|
}
|
|
113
96
|
|
|
@@ -128,9 +111,7 @@ function ensureContentsDeserialized(mutableMessage: ISequencedDocumentMessage):
|
|
|
128
111
|
* becomes a InboundSequencedContainerRuntimeMessage by the time the function returns
|
|
129
112
|
* (but there is no runtime validation of the 'type' or 'compatDetails' values).
|
|
130
113
|
*/
|
|
131
|
-
function unpack(
|
|
132
|
-
message: ISequencedDocumentMessage,
|
|
133
|
-
): asserts message is InboundSequencedContainerRuntimeMessage {
|
|
114
|
+
function unpack(message: ISequencedDocumentMessage): InboundSequencedContainerRuntimeMessage {
|
|
134
115
|
// We assume the contents is an InboundContainerRuntimeMessage (the message is "packed")
|
|
135
116
|
const contents = message.contents as InboundContainerRuntimeMessage;
|
|
136
117
|
|
|
@@ -143,6 +124,7 @@ function unpack(
|
|
|
143
124
|
(messageUnpacked as InboundSequencedRecentlyAddedContainerRuntimeMessage).compatDetails =
|
|
144
125
|
contents.compatDetails;
|
|
145
126
|
}
|
|
127
|
+
return messageUnpacked;
|
|
146
128
|
}
|
|
147
129
|
|
|
148
130
|
/**
|