@fluidframework/container-runtime 2.13.0 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +71 -5
- package/CHANGELOG.md +84 -0
- package/api-report/container-runtime.legacy.alpha.api.md +38 -232
- package/dist/batchTracker.d.ts +1 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager/blobManager.d.ts +5 -1
- package/dist/blobManager/blobManager.d.ts.map +1 -1
- package/dist/blobManager/blobManager.js +30 -13
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/blobManager/blobManagerSnapSum.d.ts +1 -0
- package/dist/blobManager/blobManagerSnapSum.d.ts.map +1 -1
- package/dist/blobManager/blobManagerSnapSum.js +7 -5
- package/dist/blobManager/blobManagerSnapSum.js.map +1 -1
- package/dist/channelCollection.d.ts +23 -12
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +85 -53
- 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 +10 -6
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerHandleContext.d.ts +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +87 -94
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +312 -226
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts +7 -3
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +8 -4
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +41 -25
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +47 -29
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +6 -2
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +7 -2
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts +1 -1
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/deltaManagerProxies.d.ts +1 -17
- package/dist/deltaManagerProxies.d.ts.map +1 -1
- package/dist/deltaManagerProxies.js.map +1 -1
- package/dist/deltaScheduler.d.ts +9 -6
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +95 -89
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +21 -7
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +48 -19
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +11 -0
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +5 -2
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +218 -70
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +40 -13
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +6 -2
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +14 -7
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
- package/dist/gc/gcSummaryDefinitions.d.ts +18 -6
- package/dist/gc/gcSummaryDefinitions.d.ts.map +1 -1
- package/dist/gc/gcSummaryDefinitions.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +2 -1
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +33 -11
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +35 -17
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.d.ts +42 -13
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +27 -9
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +1 -0
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +3 -1
- package/dist/gc/index.js.map +1 -1
- package/dist/inboundBatchAggregator.d.ts +34 -0
- package/dist/inboundBatchAggregator.d.ts.map +1 -0
- package/dist/inboundBatchAggregator.js +185 -0
- package/dist/inboundBatchAggregator.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/layerCompatState.d.ts +19 -0
- package/dist/layerCompatState.d.ts.map +1 -0
- package/dist/layerCompatState.js +64 -0
- package/dist/layerCompatState.js.map +1 -0
- package/dist/legacy.d.ts +0 -4
- package/dist/messageTypes.d.ts +14 -5
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/metadata.d.ts +12 -4
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +6 -2
- package/dist/metadata.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +9 -3
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +3 -1
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/duplicateBatchDetector.d.ts +9 -3
- package/dist/opLifecycle/duplicateBatchDetector.d.ts.map +1 -1
- package/dist/opLifecycle/duplicateBatchDetector.js +11 -5
- package/dist/opLifecycle/duplicateBatchDetector.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts +3 -2
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +13 -19
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +6 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +16 -8
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +1 -2
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +9 -6
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +13 -10
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +16 -11
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +4 -4
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +17 -16
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +9 -3
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +3 -1
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/package.json +2 -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 +22 -11
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +24 -15
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +7 -0
- package/dist/summary/documentSchema.d.ts.map +1 -1
- package/dist/summary/documentSchema.js +8 -4
- package/dist/summary/documentSchema.js.map +1 -1
- package/dist/summary/index.d.ts +1 -1
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +94 -31
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +28 -16
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -0
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js +7 -2
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +17 -6
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +48 -19
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +10 -5
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +26 -11
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js +1 -0
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.d.ts +6 -2
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js +13 -5
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/index.d.ts.map +1 -1
- package/dist/summary/summarizerNode/index.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +24 -8
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +45 -36
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +48 -16
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js +3 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +13 -5
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +15 -7
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +253 -135
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +3 -4
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +10 -8
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +28 -9
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js +3 -2
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +9 -3
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +22 -9
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +8 -4
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +20 -9
- package/dist/summary/summaryManager.js.map +1 -1
- package/dist/throttler.d.ts +26 -10
- package/dist/throttler.d.ts.map +1 -1
- package/dist/throttler.js +12 -4
- package/dist/throttler.js.map +1 -1
- package/lib/batchTracker.d.ts +1 -2
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -2
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager/blobManager.d.ts +5 -1
- package/lib/blobManager/blobManager.d.ts.map +1 -1
- package/lib/blobManager/blobManager.js +30 -13
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/blobManager/blobManagerSnapSum.d.ts +1 -0
- package/lib/blobManager/blobManagerSnapSum.d.ts.map +1 -1
- package/lib/blobManager/blobManagerSnapSum.js +7 -5
- package/lib/blobManager/blobManagerSnapSum.js.map +1 -1
- package/lib/channelCollection.d.ts +23 -12
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +88 -54
- 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 +11 -7
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerHandleContext.d.ts +1 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +87 -94
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +319 -228
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts +7 -3
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +8 -4
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +41 -25
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +47 -29
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts +6 -2
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +7 -2
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/deltaManagerProxies.d.ts +1 -17
- package/lib/deltaManagerProxies.d.ts.map +1 -1
- package/lib/deltaManagerProxies.js.map +1 -1
- package/lib/deltaScheduler.d.ts +9 -6
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +96 -90
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +21 -7
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +51 -20
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts +11 -0
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +4 -2
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +218 -70
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js +40 -13
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +6 -2
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +14 -7
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -1
- package/lib/gc/gcSummaryDefinitions.d.ts +18 -6
- package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -1
- package/lib/gc/gcSummaryDefinitions.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +2 -1
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +33 -11
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +38 -18
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.d.ts +42 -13
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js +27 -9
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/lib/gc/index.d.ts +1 -0
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +1 -0
- package/lib/gc/index.js.map +1 -1
- package/lib/inboundBatchAggregator.d.ts +34 -0
- package/lib/inboundBatchAggregator.d.ts.map +1 -0
- package/lib/inboundBatchAggregator.js +181 -0
- package/lib/inboundBatchAggregator.js.map +1 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/layerCompatState.d.ts +19 -0
- package/lib/layerCompatState.d.ts.map +1 -0
- package/lib/layerCompatState.js +60 -0
- package/lib/layerCompatState.js.map +1 -0
- package/lib/legacy.d.ts +0 -4
- package/lib/messageTypes.d.ts +14 -5
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js.map +1 -1
- package/lib/metadata.d.ts +12 -4
- package/lib/metadata.d.ts.map +1 -1
- package/lib/metadata.js +6 -2
- package/lib/metadata.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +9 -3
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +3 -1
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/duplicateBatchDetector.d.ts +9 -3
- package/lib/opLifecycle/duplicateBatchDetector.d.ts.map +1 -1
- package/lib/opLifecycle/duplicateBatchDetector.js +11 -5
- package/lib/opLifecycle/duplicateBatchDetector.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts +3 -2
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +14 -20
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +6 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +17 -9
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +1 -2
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +10 -7
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +13 -10
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +16 -11
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +4 -4
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +17 -16
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +9 -3
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +3 -1
- 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 +22 -11
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +25 -16
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +7 -0
- package/lib/summary/documentSchema.d.ts.map +1 -1
- package/lib/summary/documentSchema.js +8 -4
- package/lib/summary/documentSchema.js.map +1 -1
- package/lib/summary/index.d.ts +1 -1
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +94 -31
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +28 -16
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts +1 -0
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js +7 -2
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +17 -6
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +48 -19
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +10 -5
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +26 -11
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js +1 -0
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.d.ts +6 -2
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summary/summarizerHeuristics.js +13 -5
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/index.d.ts.map +1 -1
- package/lib/summary/summarizerNode/index.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +24 -8
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +45 -36
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +48 -16
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js +3 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +13 -5
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +15 -7
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +253 -135
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +3 -4
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +10 -8
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +28 -9
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js +2 -2
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +9 -3
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +22 -9
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +8 -4
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +20 -9
- package/lib/summary/summaryManager.js.map +1 -1
- package/lib/throttler.d.ts +26 -10
- package/lib/throttler.d.ts.map +1 -1
- package/lib/throttler.js +12 -4
- package/lib/throttler.js.map +1 -1
- package/package.json +22 -31
- package/src/batchTracker.ts +34 -36
- package/src/blobManager/blobManager.ts +54 -33
- package/src/blobManager/blobManagerSnapSum.ts +10 -10
- package/src/channelCollection.ts +108 -82
- package/src/connectionTelemetry.ts +43 -19
- package/src/containerHandleContext.ts +2 -2
- package/src/containerRuntime.ts +492 -364
- package/src/dataStore.ts +17 -9
- package/src/dataStoreContext.ts +94 -73
- package/src/dataStoreContexts.ts +17 -12
- package/src/dataStoreRegistry.ts +1 -1
- package/src/deltaManagerProxies.ts +5 -5
- package/src/deltaScheduler.ts +24 -18
- package/src/gc/garbageCollection.ts +89 -40
- package/src/gc/gcConfigs.ts +13 -5
- package/src/gc/gcDefinitions.ts +224 -70
- package/src/gc/gcHelpers.ts +22 -11
- package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
- package/src/gc/gcSummaryDefinitions.ts +18 -6
- package/src/gc/gcSummaryStateTracker.ts +7 -3
- package/src/gc/gcTelemetry.ts +73 -30
- package/src/gc/gcUnreferencedStateTracker.ts +40 -16
- package/src/gc/index.ts +1 -0
- package/src/{scheduleManager.ts → inboundBatchAggregator.ts} +55 -122
- package/src/index.ts +0 -3
- package/src/layerCompatState.ts +75 -0
- package/src/messageTypes.ts +16 -5
- package/src/metadata.ts +12 -4
- package/src/opLifecycle/README.md +43 -34
- package/src/opLifecycle/batchManager.ts +12 -6
- package/src/opLifecycle/duplicateBatchDetector.ts +12 -6
- package/src/opLifecycle/opCompressor.ts +22 -25
- package/src/opLifecycle/opDecompressor.ts +23 -11
- package/src/opLifecycle/opGroupingManager.ts +16 -11
- package/src/opLifecycle/opSplitter.ts +24 -18
- package/src/opLifecycle/outbox.ts +35 -33
- package/src/opLifecycle/remoteMessageProcessor.ts +13 -5
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +49 -26
- package/src/summary/documentSchema.ts +41 -22
- package/src/summary/index.ts +0 -3
- package/src/summary/orderedClientElection.ts +114 -49
- package/src/summary/runWhileConnectedCoordinator.ts +12 -3
- package/src/summary/runningSummarizer.ts +79 -36
- package/src/summary/summarizer.ts +51 -25
- package/src/summary/summarizerClientElection.ts +4 -2
- package/src/summary/summarizerHeuristics.ts +23 -12
- package/src/summary/summarizerNode/index.ts +1 -0
- package/src/summary/summarizerNode/summarizerNode.ts +54 -43
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +48 -16
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +25 -15
- package/src/summary/summarizerTypes.ts +253 -139
- package/src/summary/summaryCollection.ts +41 -31
- package/src/summary/summaryFormat.ts +34 -13
- package/src/summary/summaryGenerator.ts +39 -18
- package/src/summary/summaryManager.ts +36 -24
- package/src/throttler.ts +23 -11
- package/container-runtime.test-files.tar +0 -0
- package/dist/scheduleManager.d.ts +0 -28
- package/dist/scheduleManager.d.ts.map +0 -1
- package/dist/scheduleManager.js +0 -233
- package/dist/scheduleManager.js.map +0 -1
- package/lib/scheduleManager.d.ts +0 -28
- package/lib/scheduleManager.d.ts.map +0 -1
- package/lib/scheduleManager.js +0 -229
- package/lib/scheduleManager.js.map +0 -1
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
|
|
25
25
|
import { IThrottler } from "../throttler.js";
|
|
26
26
|
|
|
27
|
+
// eslint-disable-next-line import/no-deprecated
|
|
27
28
|
import { Summarizer } from "./summarizer.js";
|
|
28
29
|
import { ISummarizerClientElection } from "./summarizerClientElection.js";
|
|
29
30
|
import {
|
|
@@ -102,11 +103,11 @@ export class SummaryManager
|
|
|
102
103
|
private summarizer?: ISummarizer;
|
|
103
104
|
private _disposed = false;
|
|
104
105
|
|
|
105
|
-
public get disposed() {
|
|
106
|
+
public get disposed(): boolean {
|
|
106
107
|
return this._disposed;
|
|
107
108
|
}
|
|
108
109
|
|
|
109
|
-
public get currentState() {
|
|
110
|
+
public get currentState(): SummaryManagerState {
|
|
110
111
|
return this.state;
|
|
111
112
|
}
|
|
112
113
|
|
|
@@ -118,8 +119,10 @@ export class SummaryManager
|
|
|
118
119
|
"opsSinceLastAck" | "addOpListener" | "removeOpListener"
|
|
119
120
|
>,
|
|
120
121
|
parentLogger: ITelemetryBaseLogger,
|
|
121
|
-
/**
|
|
122
|
-
*
|
|
122
|
+
/**
|
|
123
|
+
* Creates summarizer by asking interactive container to spawn summarizing container and
|
|
124
|
+
* get back its Summarizer instance.
|
|
125
|
+
*/
|
|
123
126
|
private readonly createSummarizerFn: () => Promise<ISummarizer>,
|
|
124
127
|
private readonly startThrottler: IThrottler,
|
|
125
128
|
{
|
|
@@ -154,7 +157,7 @@ export class SummaryManager
|
|
|
154
157
|
this.refreshSummarizer();
|
|
155
158
|
}
|
|
156
159
|
|
|
157
|
-
private readonly handleConnected = (clientId: string) => {
|
|
160
|
+
private readonly handleConnected = (clientId: string): void => {
|
|
158
161
|
this.latestClientId = clientId;
|
|
159
162
|
// If we have a summarizer, it should have been either cancelled on disconnected by now.
|
|
160
163
|
// But because of lastSummary process, it can still hang around, so there is not much we can
|
|
@@ -162,11 +165,13 @@ export class SummaryManager
|
|
|
162
165
|
this.refreshSummarizer();
|
|
163
166
|
};
|
|
164
167
|
|
|
165
|
-
private readonly handleDisconnected = () => {
|
|
168
|
+
private readonly handleDisconnected = (): void => {
|
|
166
169
|
this.refreshSummarizer();
|
|
167
170
|
};
|
|
168
171
|
|
|
169
|
-
private static readonly isStartingOrRunning = (
|
|
172
|
+
private static readonly isStartingOrRunning = (
|
|
173
|
+
state: SummaryManagerState,
|
|
174
|
+
): state is SummaryManagerState.Starting | SummaryManagerState.Running =>
|
|
170
175
|
state === SummaryManagerState.Starting || state === SummaryManagerState.Running;
|
|
171
176
|
|
|
172
177
|
private getShouldSummarizeState(): ShouldSummarizeState {
|
|
@@ -199,7 +204,7 @@ export class SummaryManager
|
|
|
199
204
|
return { shouldSummarize: true };
|
|
200
205
|
}
|
|
201
206
|
|
|
202
|
-
private readonly refreshSummarizer = () => {
|
|
207
|
+
private readonly refreshSummarizer = (): void => {
|
|
203
208
|
// Transition states depending on shouldSummarize, which is a calculated property
|
|
204
209
|
// that is only true if this client is connected and is the elected summarizer.
|
|
205
210
|
const shouldSummarizeState = this.getShouldSummarizeState();
|
|
@@ -232,7 +237,7 @@ export class SummaryManager
|
|
|
232
237
|
}
|
|
233
238
|
};
|
|
234
239
|
|
|
235
|
-
private startSummarization() {
|
|
240
|
+
private startSummarization(): void {
|
|
236
241
|
assert(this.state === SummaryManagerState.Off, 0x261 /* "Expected: off" */);
|
|
237
242
|
this.state = SummaryManagerState.Starting;
|
|
238
243
|
|
|
@@ -280,6 +285,7 @@ export class SummaryManager
|
|
|
280
285
|
// which would happen when we have a high enough number of unsummarized ops.
|
|
281
286
|
if (
|
|
282
287
|
startWithInitialDelay ||
|
|
288
|
+
// eslint-disable-next-line import/no-deprecated
|
|
283
289
|
!Summarizer.stopReasonCanRunLastSummary(shouldSummarizeState.stopReason)
|
|
284
290
|
) {
|
|
285
291
|
this.state = SummaryManagerState.Starting;
|
|
@@ -328,6 +334,7 @@ export class SummaryManager
|
|
|
328
334
|
// If failure happened on container load, we may not yet realized that socket disconnected, so check
|
|
329
335
|
// offlineError.
|
|
330
336
|
const category =
|
|
337
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
331
338
|
error?.errorType === DriverErrorTypes.offlineError ? "generic" : "error";
|
|
332
339
|
this.logger.sendTelemetryEvent(
|
|
333
340
|
{
|
|
@@ -352,7 +359,7 @@ export class SummaryManager
|
|
|
352
359
|
});
|
|
353
360
|
}
|
|
354
361
|
|
|
355
|
-
private stop(reason: SummarizerStopReason) {
|
|
362
|
+
private stop(reason: SummarizerStopReason): void {
|
|
356
363
|
if (!SummaryManager.isStartingOrRunning(this.state)) {
|
|
357
364
|
return;
|
|
358
365
|
}
|
|
@@ -401,10 +408,10 @@ export class SummaryManager
|
|
|
401
408
|
}
|
|
402
409
|
|
|
403
410
|
if (delayMs > 0) {
|
|
404
|
-
let timer;
|
|
405
|
-
let resolveOpPromiseFn;
|
|
411
|
+
let timer: number | undefined;
|
|
412
|
+
let resolveOpPromiseFn: (value: void | PromiseLike<void>) => void;
|
|
406
413
|
// Create a listener that will break the delay if we've exceeded the initial delay ops count.
|
|
407
|
-
const opsListenerFn = () => {
|
|
414
|
+
const opsListenerFn = (): void => {
|
|
408
415
|
if (this.summaryCollection.opsSinceLastAck >= this.opsToBypassInitialDelay) {
|
|
409
416
|
clearTimeout(timer);
|
|
410
417
|
resolveOpPromiseFn();
|
|
@@ -427,7 +434,7 @@ export class SummaryManager
|
|
|
427
434
|
|
|
428
435
|
public summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults {
|
|
429
436
|
if (this.summarizer === undefined) {
|
|
430
|
-
throw Error("No running summarizer client");
|
|
437
|
+
throw new Error("No running summarizer client");
|
|
431
438
|
// TODO: could spawn a summarizer client temporarily.
|
|
432
439
|
}
|
|
433
440
|
return this.summarizer.summarizeOnDemand(options);
|
|
@@ -435,13 +442,13 @@ export class SummaryManager
|
|
|
435
442
|
|
|
436
443
|
public enqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult {
|
|
437
444
|
if (this.summarizer === undefined) {
|
|
438
|
-
throw Error("No running summarizer client");
|
|
445
|
+
throw new Error("No running summarizer client");
|
|
439
446
|
// TODO: could spawn a summarizer client temporarily.
|
|
440
447
|
}
|
|
441
448
|
return this.summarizer.enqueueSummarize(options);
|
|
442
449
|
}
|
|
443
450
|
|
|
444
|
-
public dispose() {
|
|
451
|
+
public dispose(): void {
|
|
445
452
|
this.clientElection.off("electedSummarizerChanged", this.refreshSummarizer);
|
|
446
453
|
this.connectedState.off("connected", this.handleConnected);
|
|
447
454
|
this.connectedState.off("disconnected", this.handleDisconnected);
|
|
@@ -449,26 +456,31 @@ export class SummaryManager
|
|
|
449
456
|
this._disposed = true;
|
|
450
457
|
}
|
|
451
458
|
|
|
452
|
-
private readonly forwardedEvents = new Map<
|
|
459
|
+
private readonly forwardedEvents = new Map<string, () => void>();
|
|
453
460
|
|
|
454
|
-
private setupForwardedEvents() {
|
|
455
|
-
[
|
|
461
|
+
private setupForwardedEvents(): void {
|
|
462
|
+
for (const event of [
|
|
456
463
|
"summarize",
|
|
457
464
|
"summarizeAllAttemptsFailed",
|
|
458
465
|
"summarizerStop",
|
|
459
466
|
"summarizerStart",
|
|
460
467
|
"summarizerStartupFailed",
|
|
461
|
-
]
|
|
462
|
-
const listener = (...args:
|
|
468
|
+
]) {
|
|
469
|
+
const listener = (...args: unknown[]): void => {
|
|
463
470
|
this.emit(event, ...args);
|
|
464
471
|
};
|
|
472
|
+
// TODO: better typing here
|
|
473
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
|
|
465
474
|
this.summarizer?.on(event as any, listener);
|
|
466
475
|
this.forwardedEvents.set(event, listener);
|
|
467
|
-
}
|
|
476
|
+
}
|
|
468
477
|
}
|
|
469
478
|
|
|
470
|
-
private cleanupForwardedEvents() {
|
|
471
|
-
|
|
479
|
+
private cleanupForwardedEvents(): void {
|
|
480
|
+
for (const [event, listener] of this.forwardedEvents.entries()) {
|
|
481
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
|
|
482
|
+
this.summarizer?.off(event as any, listener);
|
|
483
|
+
}
|
|
472
484
|
this.forwardedEvents.clear();
|
|
473
485
|
}
|
|
474
486
|
}
|
package/src/throttler.ts
CHANGED
|
@@ -16,9 +16,13 @@ export interface IThrottler {
|
|
|
16
16
|
*/
|
|
17
17
|
readonly numAttempts: number;
|
|
18
18
|
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Width of sliding delay window in milliseconds.
|
|
21
|
+
*/
|
|
20
22
|
readonly delayWindowMs: number;
|
|
21
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Maximum delay allowed in milliseconds.
|
|
25
|
+
*/
|
|
22
26
|
readonly maxDelayMs: number;
|
|
23
27
|
/**
|
|
24
28
|
* Delay function used to calculate what the delay should be.
|
|
@@ -35,7 +39,7 @@ export interface IThrottler {
|
|
|
35
39
|
export class Throttler implements IThrottler {
|
|
36
40
|
private startTimes: number[] = [];
|
|
37
41
|
|
|
38
|
-
public get numAttempts() {
|
|
42
|
+
public get numAttempts(): number {
|
|
39
43
|
return this.startTimes.length;
|
|
40
44
|
}
|
|
41
45
|
|
|
@@ -51,16 +55,20 @@ export class Throttler implements IThrottler {
|
|
|
51
55
|
* Latest attempt time after compensating for the delay time itself
|
|
52
56
|
* by adding the delay time to the actual time.
|
|
53
57
|
*/
|
|
54
|
-
public get latestAttemptTime() {
|
|
58
|
+
public get latestAttemptTime(): number | undefined {
|
|
55
59
|
return this.startTimes.length > 0
|
|
56
60
|
? this.startTimes[this.startTimes.length - 1]
|
|
57
61
|
: undefined;
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
constructor(
|
|
61
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* Width of sliding delay window in milliseconds.
|
|
67
|
+
*/
|
|
62
68
|
public readonly delayWindowMs: number,
|
|
63
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* Maximum delay allowed in milliseconds.
|
|
71
|
+
*/
|
|
64
72
|
public readonly maxDelayMs: number,
|
|
65
73
|
/**
|
|
66
74
|
* Delay function used to calculate what the delay should be.
|
|
@@ -70,7 +78,7 @@ export class Throttler implements IThrottler {
|
|
|
70
78
|
public readonly delayFn: (numAttempts: number) => number,
|
|
71
79
|
) {}
|
|
72
80
|
|
|
73
|
-
public getDelay() {
|
|
81
|
+
public getDelay(): number {
|
|
74
82
|
const now = Date.now();
|
|
75
83
|
|
|
76
84
|
const latestAttemptTime = this.latestAttemptTime;
|
|
@@ -131,7 +139,9 @@ export const formExponentialFn =
|
|
|
131
139
|
: coefficient * Math.pow(multiplier, numAttempts) + offset,
|
|
132
140
|
);
|
|
133
141
|
|
|
134
|
-
/**
|
|
142
|
+
/**
|
|
143
|
+
* f(n) = C x (B^(n+A)) + F = (C x B^A) x B^n + F
|
|
144
|
+
*/
|
|
135
145
|
export const formExponentialFnWithAttemptOffset = (
|
|
136
146
|
attemptOffset: number,
|
|
137
147
|
{
|
|
@@ -140,7 +150,7 @@ export const formExponentialFnWithAttemptOffset = (
|
|
|
140
150
|
offset = 0,
|
|
141
151
|
initialDelay = undefined as number | undefined,
|
|
142
152
|
} = {},
|
|
143
|
-
) =>
|
|
153
|
+
): IThrottler["delayFn"] =>
|
|
144
154
|
formExponentialFn({
|
|
145
155
|
multiplier,
|
|
146
156
|
coefficient: coefficient * Math.pow(multiplier, attemptOffset),
|
|
@@ -160,11 +170,13 @@ export const formLinearFn =
|
|
|
160
170
|
(numAttempts) =>
|
|
161
171
|
Math.max(0, coefficient * numAttempts + offset);
|
|
162
172
|
|
|
163
|
-
/**
|
|
173
|
+
/**
|
|
174
|
+
* f(n) = C x (n+A) + F = C x n + (C x A + F)
|
|
175
|
+
*/
|
|
164
176
|
export const formLinearFnWithAttemptOffset = (
|
|
165
177
|
attemptOffset: number,
|
|
166
178
|
{ coefficient = 1, offset = 0 } = {},
|
|
167
|
-
) =>
|
|
179
|
+
): IThrottler["delayFn"] =>
|
|
168
180
|
formLinearFn({
|
|
169
181
|
coefficient,
|
|
170
182
|
offset: coefficient * attemptOffset + offset,
|
|
Binary file
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import type { EventEmitter } from "@fluid-internal/client-utils";
|
|
6
|
-
import { IDeltaManagerFull } from "@fluidframework/container-definitions/internal";
|
|
7
|
-
import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
|
|
8
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
|
|
9
|
-
/**
|
|
10
|
-
* This class has the following responsibilities:
|
|
11
|
-
*
|
|
12
|
-
* 1. It tracks batches as we process ops and raises "batchBegin" and "batchEnd" events.
|
|
13
|
-
* As part of it, it validates batch correctness (i.e. no system ops in the middle of batch)
|
|
14
|
-
*
|
|
15
|
-
* 2. It creates instance of ScheduleManagerCore that ensures we never start processing ops from batch
|
|
16
|
-
* unless all ops of the batch are in.
|
|
17
|
-
*/
|
|
18
|
-
export declare class ScheduleManager {
|
|
19
|
-
private readonly deltaManager;
|
|
20
|
-
private readonly emitter;
|
|
21
|
-
readonly getClientId: () => string | undefined;
|
|
22
|
-
private readonly logger;
|
|
23
|
-
private readonly deltaScheduler;
|
|
24
|
-
constructor(deltaManager: IDeltaManagerFull, emitter: EventEmitter, getClientId: () => string | undefined, logger: ITelemetryLoggerExt);
|
|
25
|
-
batchBegin(message: ISequencedDocumentMessage): void;
|
|
26
|
-
batchEnd(error: any | undefined, message: ISequencedDocumentMessage): void;
|
|
27
|
-
}
|
|
28
|
-
//# sourceMappingURL=scheduleManager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scheduleManager.d.ts","sourceRoot":"","sources":["../src/scheduleManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gDAAgD,CAAC;AAEnF,OAAO,EAEN,yBAAyB,EACzB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EACN,mBAAmB,EAKnB,MAAM,0CAA0C,CAAC;AAYlD;;;;;;;;GAQG;AACH,qBAAa,eAAe;IAI1B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,MAAM,GAAG,SAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM;IANxB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;gBAG9B,YAAY,EAAE,iBAAiB,EAC/B,OAAO,EAAE,YAAY,EAC7B,WAAW,EAAE,MAAM,MAAM,GAAG,SAAS,EAC7B,MAAM,EAAE,mBAAmB;IAStC,UAAU,CAAC,OAAO,EAAE,yBAAyB;IAK7C,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,SAAS,EAAE,OAAO,EAAE,yBAAyB;CAI1E"}
|
package/dist/scheduleManager.js
DELETED
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*!
|
|
3
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
-
* Licensed under the MIT License.
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.ScheduleManager = void 0;
|
|
8
|
-
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
9
|
-
const internal_1 = require("@fluidframework/core-utils/internal");
|
|
10
|
-
const internal_2 = require("@fluidframework/driver-utils/internal");
|
|
11
|
-
const internal_3 = require("@fluidframework/telemetry-utils/internal");
|
|
12
|
-
const deltaScheduler_js_1 = require("./deltaScheduler.js");
|
|
13
|
-
const packageVersion_js_1 = require("./packageVersion.js");
|
|
14
|
-
/**
|
|
15
|
-
* This class has the following responsibilities:
|
|
16
|
-
*
|
|
17
|
-
* 1. It tracks batches as we process ops and raises "batchBegin" and "batchEnd" events.
|
|
18
|
-
* As part of it, it validates batch correctness (i.e. no system ops in the middle of batch)
|
|
19
|
-
*
|
|
20
|
-
* 2. It creates instance of ScheduleManagerCore that ensures we never start processing ops from batch
|
|
21
|
-
* unless all ops of the batch are in.
|
|
22
|
-
*/
|
|
23
|
-
class ScheduleManager {
|
|
24
|
-
constructor(deltaManager, emitter, getClientId, logger) {
|
|
25
|
-
this.deltaManager = deltaManager;
|
|
26
|
-
this.emitter = emitter;
|
|
27
|
-
this.getClientId = getClientId;
|
|
28
|
-
this.logger = logger;
|
|
29
|
-
this.deltaScheduler = new deltaScheduler_js_1.DeltaScheduler(this.deltaManager, (0, internal_3.createChildLogger)({ logger: this.logger, namespace: "DeltaScheduler" }));
|
|
30
|
-
void new ScheduleManagerCore(deltaManager, getClientId, logger);
|
|
31
|
-
}
|
|
32
|
-
batchBegin(message) {
|
|
33
|
-
this.emitter.emit("batchBegin", message);
|
|
34
|
-
this.deltaScheduler.batchBegin(message);
|
|
35
|
-
}
|
|
36
|
-
batchEnd(error, message) {
|
|
37
|
-
this.emitter.emit("batchEnd", error, message);
|
|
38
|
-
this.deltaScheduler.batchEnd(message);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
exports.ScheduleManager = ScheduleManager;
|
|
42
|
-
/**
|
|
43
|
-
* This class controls pausing and resuming of inbound queue to ensure that we never
|
|
44
|
-
* start processing ops in a batch IF we do not have all ops in the batch.
|
|
45
|
-
*/
|
|
46
|
-
class ScheduleManagerCore {
|
|
47
|
-
constructor(deltaManager, getClientId, logger) {
|
|
48
|
-
this.deltaManager = deltaManager;
|
|
49
|
-
this.getClientId = getClientId;
|
|
50
|
-
this.logger = logger;
|
|
51
|
-
this.localPaused = false;
|
|
52
|
-
this.timePaused = 0;
|
|
53
|
-
this.batchCount = 0;
|
|
54
|
-
// Listen for delta manager sends and add batch metadata to messages
|
|
55
|
-
this.deltaManager.on("prepareSend", (messages) => {
|
|
56
|
-
if (messages.length === 0) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
// First message will have the batch flag set to true if doing a batched send
|
|
60
|
-
const firstMessageMetadata = messages[0].metadata;
|
|
61
|
-
if (!firstMessageMetadata?.batch) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
// If the batch contains only a single op, clear the batch flag.
|
|
65
|
-
if (messages.length === 1) {
|
|
66
|
-
delete firstMessageMetadata.batch;
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
// Set the batch flag to false on the last message to indicate the end of the send batch
|
|
70
|
-
const lastMessage = messages[messages.length - 1];
|
|
71
|
-
// TODO: It's not clear if this shallow clone is required, as opposed to just setting "batch" to false.
|
|
72
|
-
lastMessage.metadata = { ...lastMessage.metadata, batch: false };
|
|
73
|
-
});
|
|
74
|
-
// Listen for updates and peek at the inbound
|
|
75
|
-
this.deltaManager.inbound.on("push", (message) => {
|
|
76
|
-
this.trackPending(message);
|
|
77
|
-
});
|
|
78
|
-
// Start with baseline - empty inbound queue.
|
|
79
|
-
(0, internal_1.assert)(!this.localPaused, 0x293 /* "initial state" */);
|
|
80
|
-
const allPending = this.deltaManager.inbound.toArray();
|
|
81
|
-
for (const pending of allPending) {
|
|
82
|
-
this.trackPending(pending);
|
|
83
|
-
}
|
|
84
|
-
// We are intentionally directly listening to the "op" to inspect system ops as well.
|
|
85
|
-
// If we do not observe system ops, we are likely to hit 0x296 assert when system ops
|
|
86
|
-
// precedes start of incomplete batch.
|
|
87
|
-
this.deltaManager.on("op", (message) => this.afterOpProcessing(message));
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* The only public function in this class - called when we processed an op,
|
|
91
|
-
* to make decision if op processing should be paused or not after that.
|
|
92
|
-
*/
|
|
93
|
-
afterOpProcessing(message) {
|
|
94
|
-
(0, internal_1.assert)(!this.localPaused, 0x294 /* "can't have op processing paused if we are processing an op" */);
|
|
95
|
-
// If the inbound queue is ever empty, nothing to do!
|
|
96
|
-
if (this.deltaManager.inbound.length === 0) {
|
|
97
|
-
(0, internal_1.assert)(this.pauseSequenceNumber === undefined, 0x295 /* "there should be no pending batch if we have no ops" */);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
// The queue is
|
|
101
|
-
// 1. paused only when the next message to be processed is the beginning of a batch. Done in two places:
|
|
102
|
-
// - here (processing ops until reaching start of incomplete batch)
|
|
103
|
-
// - in trackPending(), when queue was empty and start of batch showed up.
|
|
104
|
-
// 2. resumed when batch end comes in (in trackPending())
|
|
105
|
-
// do we have incomplete batch to worry about?
|
|
106
|
-
if (this.pauseSequenceNumber !== undefined) {
|
|
107
|
-
if (message.sequenceNumber >= this.pauseSequenceNumber) {
|
|
108
|
-
throw internal_3.DataProcessingError.create(
|
|
109
|
-
// Former assert 0x296
|
|
110
|
-
"Incomplete batch", "ScheduleManager", message, {
|
|
111
|
-
type: message.type,
|
|
112
|
-
contentType: typeof message.contents,
|
|
113
|
-
batch: message.metadata?.batch,
|
|
114
|
-
compression: message.compression,
|
|
115
|
-
pauseSeqNum: this.pauseSequenceNumber,
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
// If the next op is the start of incomplete batch, then we can't process it until it's fully in - pause!
|
|
119
|
-
if (message.sequenceNumber + 1 === this.pauseSequenceNumber) {
|
|
120
|
-
this.pauseQueue();
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
pauseQueue() {
|
|
125
|
-
(0, internal_1.assert)(!this.localPaused, 0x297 /* "always called from resumed state" */);
|
|
126
|
-
this.localPaused = true;
|
|
127
|
-
this.timePaused = client_utils_1.performance.now();
|
|
128
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
129
|
-
this.deltaManager.inbound.pause();
|
|
130
|
-
}
|
|
131
|
-
resumeQueue(startBatch, messageEndBatch) {
|
|
132
|
-
const endBatch = messageEndBatch.sequenceNumber;
|
|
133
|
-
const duration = this.localPaused ? client_utils_1.performance.now() - this.timePaused : undefined;
|
|
134
|
-
this.batchCount++;
|
|
135
|
-
if (this.batchCount % 1000 === 1) {
|
|
136
|
-
this.logger.sendTelemetryEvent({
|
|
137
|
-
eventName: "BatchStats",
|
|
138
|
-
sequenceNumber: endBatch,
|
|
139
|
-
length: endBatch - startBatch + 1,
|
|
140
|
-
msnDistance: endBatch - messageEndBatch.minimumSequenceNumber,
|
|
141
|
-
duration,
|
|
142
|
-
batchCount: this.batchCount,
|
|
143
|
-
interrupted: this.localPaused,
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
// Return early if no change in value
|
|
147
|
-
if (!this.localPaused) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
this.localPaused = false;
|
|
151
|
-
this.deltaManager.inbound.resume();
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Called for each incoming op (i.e. inbound "push" notification)
|
|
155
|
-
*/
|
|
156
|
-
trackPending(message) {
|
|
157
|
-
(0, internal_1.assert)(this.deltaManager.inbound.length !== 0, 0x298 /* "we have something in the queue that generates this event" */);
|
|
158
|
-
(0, internal_1.assert)((this.currentBatchClientId === undefined) === (this.pauseSequenceNumber === undefined), 0x299 /* "non-synchronized state" */);
|
|
159
|
-
const metadata = message.metadata;
|
|
160
|
-
// batchMetadata will be true for the message that starts a batch, false for the one that ends it, and
|
|
161
|
-
// undefined for all other messages.
|
|
162
|
-
const batchMetadata = metadata?.batch;
|
|
163
|
-
// Protocol messages are never part of a runtime batch of messages
|
|
164
|
-
if (!(0, internal_2.isRuntimeMessage)(message)) {
|
|
165
|
-
// Protocol messages should never show up in the middle of the batch!
|
|
166
|
-
if (this.currentBatchClientId !== undefined) {
|
|
167
|
-
throw internal_3.DataProcessingError.create("Received a system message during batch processing", // Formerly known as assert 0x29a
|
|
168
|
-
"trackPending", message, {
|
|
169
|
-
runtimeVersion: packageVersion_js_1.pkgVersion,
|
|
170
|
-
batchClientId:
|
|
171
|
-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
172
|
-
this.currentBatchClientId === null ? "null" : this.currentBatchClientId,
|
|
173
|
-
pauseSequenceNumber: this.pauseSequenceNumber,
|
|
174
|
-
localBatch: this.currentBatchClientId === this.getClientId(),
|
|
175
|
-
messageType: message.type,
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
(0, internal_1.assert)(batchMetadata === undefined, 0x29b /* "system op in a batch?" */);
|
|
179
|
-
(0, internal_1.assert)(!this.localPaused, 0x29c /* "we should be processing ops when there is no active batch" */);
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
if (this.currentBatchClientId === undefined && batchMetadata === undefined) {
|
|
183
|
-
(0, internal_1.assert)(!this.localPaused, 0x29d /* "we should be processing ops when there is no active batch" */);
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
// If we got here, the message is part of a batch. Either starting, in progress, or ending.
|
|
187
|
-
// If this is not the start of the batch, error out if the message was sent by a client other than the one that
|
|
188
|
-
// started the current batch (it should not be possible for ops from other clients to get interleaved with a batch).
|
|
189
|
-
if (this.currentBatchClientId !== undefined &&
|
|
190
|
-
this.currentBatchClientId !== message.clientId) {
|
|
191
|
-
throw new internal_3.DataCorruptionError("OpBatchIncomplete", {
|
|
192
|
-
runtimeVersion: packageVersion_js_1.pkgVersion,
|
|
193
|
-
batchClientId:
|
|
194
|
-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
195
|
-
this.currentBatchClientId === null ? "null" : this.currentBatchClientId,
|
|
196
|
-
pauseSequenceNumber: this.pauseSequenceNumber,
|
|
197
|
-
localBatch: this.currentBatchClientId === this.getClientId(),
|
|
198
|
-
localMessage: message.clientId === this.getClientId(),
|
|
199
|
-
...(0, internal_3.extractSafePropertiesFromMessage)(message),
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
// The queue is
|
|
203
|
-
// 1. paused only when the next message to be processed is the beginning of a batch. Done in two places:
|
|
204
|
-
// - in afterOpProcessing() - processing ops until reaching start of incomplete batch
|
|
205
|
-
// - here, when queue was empty and start of batch showed up (batchMetadata === true below).
|
|
206
|
-
// 2. resumed when batch end comes in (batchMetadata === false below)
|
|
207
|
-
if (batchMetadata) {
|
|
208
|
-
(0, internal_1.assert)(this.currentBatchClientId === undefined, 0x29e /* "there can't be active batch" */);
|
|
209
|
-
(0, internal_1.assert)(!this.localPaused, 0x29f /* "we should be processing ops when there is no active batch" */);
|
|
210
|
-
this.pauseSequenceNumber = message.sequenceNumber;
|
|
211
|
-
// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)
|
|
212
|
-
this.currentBatchClientId = message.clientId;
|
|
213
|
-
// Start of the batch
|
|
214
|
-
// Only pause processing if queue has no other ops!
|
|
215
|
-
// If there are any other ops in the queue, processing will be stopped when they are processed!
|
|
216
|
-
if (this.deltaManager.inbound.length === 1) {
|
|
217
|
-
this.pauseQueue();
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
else if (batchMetadata === false) {
|
|
221
|
-
(0, internal_1.assert)(this.pauseSequenceNumber !== undefined, 0x2a0 /* "batch presence was validated above" */);
|
|
222
|
-
// Batch is complete, we can process it!
|
|
223
|
-
this.resumeQueue(this.pauseSequenceNumber, message);
|
|
224
|
-
this.pauseSequenceNumber = undefined;
|
|
225
|
-
this.currentBatchClientId = undefined;
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
// Continuation of current batch. Do nothing
|
|
229
|
-
(0, internal_1.assert)(this.currentBatchClientId !== undefined, 0x2a1 /* "logic error" */);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
//# sourceMappingURL=scheduleManager.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scheduleManager.js","sourceRoot":"","sources":["../src/scheduleManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { EventEmitter } from \"@fluid-internal/client-utils\";\nimport { performance } from \"@fluid-internal/client-utils\";\nimport { IDeltaManagerFull } from \"@fluidframework/container-definitions/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tIDocumentMessage,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { isRuntimeMessage } from \"@fluidframework/driver-utils/internal\";\nimport {\n\tITelemetryLoggerExt,\n\tDataCorruptionError,\n\tDataProcessingError,\n\tcreateChildLogger,\n\textractSafePropertiesFromMessage,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { DeltaScheduler } from \"./deltaScheduler.js\";\nimport { IBatchMetadata } from \"./metadata.js\";\nimport { pkgVersion } from \"./packageVersion.js\";\n\ntype IRuntimeMessageMetadata =\n\t| undefined\n\t| {\n\t\t\tbatch?: boolean;\n\t };\n\n/**\n * This class has the following responsibilities:\n *\n * 1. It tracks batches as we process ops and raises \"batchBegin\" and \"batchEnd\" events.\n * As part of it, it validates batch correctness (i.e. no system ops in the middle of batch)\n *\n * 2. It creates instance of ScheduleManagerCore that ensures we never start processing ops from batch\n * unless all ops of the batch are in.\n */\nexport class ScheduleManager {\n\tprivate readonly deltaScheduler: DeltaScheduler;\n\n\tconstructor(\n\t\tprivate readonly deltaManager: IDeltaManagerFull,\n\t\tprivate readonly emitter: EventEmitter,\n\t\treadonly getClientId: () => string | undefined,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {\n\t\tthis.deltaScheduler = new DeltaScheduler(\n\t\t\tthis.deltaManager,\n\t\t\tcreateChildLogger({ logger: this.logger, namespace: \"DeltaScheduler\" }),\n\t\t);\n\t\tvoid new ScheduleManagerCore(deltaManager, getClientId, logger);\n\t}\n\n\tpublic batchBegin(message: ISequencedDocumentMessage) {\n\t\tthis.emitter.emit(\"batchBegin\", message);\n\t\tthis.deltaScheduler.batchBegin(message);\n\t}\n\n\tpublic batchEnd(error: any | undefined, message: ISequencedDocumentMessage) {\n\t\tthis.emitter.emit(\"batchEnd\", error, message);\n\t\tthis.deltaScheduler.batchEnd(message);\n\t}\n}\n\n/**\n * This class controls pausing and resuming of inbound queue to ensure that we never\n * start processing ops in a batch IF we do not have all ops in the batch.\n */\nclass ScheduleManagerCore {\n\tprivate pauseSequenceNumber: number | undefined;\n\tprivate currentBatchClientId: string | undefined;\n\tprivate localPaused = false;\n\tprivate timePaused = 0;\n\tprivate batchCount = 0;\n\n\tconstructor(\n\t\tprivate readonly deltaManager: IDeltaManagerFull,\n\t\tprivate readonly getClientId: () => string | undefined,\n\t\tprivate readonly logger: ITelemetryLoggerExt,\n\t) {\n\t\t// Listen for delta manager sends and add batch metadata to messages\n\t\tthis.deltaManager.on(\"prepareSend\", (messages: IDocumentMessage[]) => {\n\t\t\tif (messages.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// First message will have the batch flag set to true if doing a batched send\n\t\t\tconst firstMessageMetadata = messages[0].metadata as IRuntimeMessageMetadata;\n\t\t\tif (!firstMessageMetadata?.batch) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If the batch contains only a single op, clear the batch flag.\n\t\t\tif (messages.length === 1) {\n\t\t\t\tdelete firstMessageMetadata.batch;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the batch flag to false on the last message to indicate the end of the send batch\n\t\t\tconst lastMessage = messages[messages.length - 1];\n\t\t\t// TODO: It's not clear if this shallow clone is required, as opposed to just setting \"batch\" to false.\n\n\t\t\tlastMessage.metadata = { ...(lastMessage.metadata as any), batch: false };\n\t\t});\n\n\t\t// Listen for updates and peek at the inbound\n\t\tthis.deltaManager.inbound.on(\"push\", (message: ISequencedDocumentMessage) => {\n\t\t\tthis.trackPending(message);\n\t\t});\n\n\t\t// Start with baseline - empty inbound queue.\n\t\tassert(!this.localPaused, 0x293 /* \"initial state\" */);\n\n\t\tconst allPending = this.deltaManager.inbound.toArray();\n\t\tfor (const pending of allPending) {\n\t\t\tthis.trackPending(pending);\n\t\t}\n\n\t\t// We are intentionally directly listening to the \"op\" to inspect system ops as well.\n\t\t// If we do not observe system ops, we are likely to hit 0x296 assert when system ops\n\t\t// precedes start of incomplete batch.\n\t\tthis.deltaManager.on(\"op\", (message) => this.afterOpProcessing(message));\n\t}\n\n\t/**\n\t * The only public function in this class - called when we processed an op,\n\t * to make decision if op processing should be paused or not after that.\n\t */\n\tpublic afterOpProcessing(message: ISequencedDocumentMessage) {\n\t\tassert(\n\t\t\t!this.localPaused,\n\t\t\t0x294 /* \"can't have op processing paused if we are processing an op\" */,\n\t\t);\n\n\t\t// If the inbound queue is ever empty, nothing to do!\n\t\tif (this.deltaManager.inbound.length === 0) {\n\t\t\tassert(\n\t\t\t\tthis.pauseSequenceNumber === undefined,\n\t\t\t\t0x295 /* \"there should be no pending batch if we have no ops\" */,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// The queue is\n\t\t// 1. paused only when the next message to be processed is the beginning of a batch. Done in two places:\n\t\t// - here (processing ops until reaching start of incomplete batch)\n\t\t// - in trackPending(), when queue was empty and start of batch showed up.\n\t\t// 2. resumed when batch end comes in (in trackPending())\n\n\t\t// do we have incomplete batch to worry about?\n\t\tif (this.pauseSequenceNumber !== undefined) {\n\t\t\tif (message.sequenceNumber >= this.pauseSequenceNumber) {\n\t\t\t\tthrow DataProcessingError.create(\n\t\t\t\t\t// Former assert 0x296\n\t\t\t\t\t\"Incomplete batch\",\n\t\t\t\t\t\"ScheduleManager\",\n\t\t\t\t\tmessage,\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: message.type,\n\t\t\t\t\t\tcontentType: typeof message.contents,\n\t\t\t\t\t\tbatch: (message.metadata as IBatchMetadata | undefined)?.batch,\n\t\t\t\t\t\tcompression: message.compression,\n\t\t\t\t\t\tpauseSeqNum: this.pauseSequenceNumber,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// If the next op is the start of incomplete batch, then we can't process it until it's fully in - pause!\n\t\t\tif (message.sequenceNumber + 1 === this.pauseSequenceNumber) {\n\t\t\t\tthis.pauseQueue();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate pauseQueue() {\n\t\tassert(!this.localPaused, 0x297 /* \"always called from resumed state\" */);\n\t\tthis.localPaused = true;\n\t\tthis.timePaused = performance.now();\n\t\t// eslint-disable-next-line @typescript-eslint/no-floating-promises\n\t\tthis.deltaManager.inbound.pause();\n\t}\n\n\tprivate resumeQueue(startBatch: number, messageEndBatch: ISequencedDocumentMessage) {\n\t\tconst endBatch = messageEndBatch.sequenceNumber;\n\t\tconst duration = this.localPaused ? performance.now() - this.timePaused : undefined;\n\n\t\tthis.batchCount++;\n\t\tif (this.batchCount % 1000 === 1) {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"BatchStats\",\n\t\t\t\tsequenceNumber: endBatch,\n\t\t\t\tlength: endBatch - startBatch + 1,\n\t\t\t\tmsnDistance: endBatch - messageEndBatch.minimumSequenceNumber,\n\t\t\t\tduration,\n\t\t\t\tbatchCount: this.batchCount,\n\t\t\t\tinterrupted: this.localPaused,\n\t\t\t});\n\t\t}\n\n\t\t// Return early if no change in value\n\t\tif (!this.localPaused) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.localPaused = false;\n\n\t\tthis.deltaManager.inbound.resume();\n\t}\n\n\t/**\n\t * Called for each incoming op (i.e. inbound \"push\" notification)\n\t */\n\tprivate trackPending(message: ISequencedDocumentMessage) {\n\t\tassert(\n\t\t\tthis.deltaManager.inbound.length !== 0,\n\t\t\t0x298 /* \"we have something in the queue that generates this event\" */,\n\t\t);\n\n\t\tassert(\n\t\t\t(this.currentBatchClientId === undefined) === (this.pauseSequenceNumber === undefined),\n\t\t\t0x299 /* \"non-synchronized state\" */,\n\t\t);\n\n\t\tconst metadata = message.metadata as IRuntimeMessageMetadata;\n\t\t// batchMetadata will be true for the message that starts a batch, false for the one that ends it, and\n\t\t// undefined for all other messages.\n\t\tconst batchMetadata = metadata?.batch;\n\n\t\t// Protocol messages are never part of a runtime batch of messages\n\t\tif (!isRuntimeMessage(message)) {\n\t\t\t// Protocol messages should never show up in the middle of the batch!\n\t\t\tif (this.currentBatchClientId !== undefined) {\n\t\t\t\tthrow DataProcessingError.create(\n\t\t\t\t\t\"Received a system message during batch processing\", // Formerly known as assert 0x29a\n\t\t\t\t\t\"trackPending\",\n\t\t\t\t\tmessage,\n\t\t\t\t\t{\n\t\t\t\t\t\truntimeVersion: pkgVersion,\n\t\t\t\t\t\tbatchClientId:\n\t\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n\t\t\t\t\t\t\tthis.currentBatchClientId === null ? \"null\" : this.currentBatchClientId,\n\t\t\t\t\t\tpauseSequenceNumber: this.pauseSequenceNumber,\n\t\t\t\t\t\tlocalBatch: this.currentBatchClientId === this.getClientId(),\n\t\t\t\t\t\tmessageType: message.type,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tassert(batchMetadata === undefined, 0x29b /* \"system op in a batch?\" */);\n\t\t\tassert(\n\t\t\t\t!this.localPaused,\n\t\t\t\t0x29c /* \"we should be processing ops when there is no active batch\" */,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.currentBatchClientId === undefined && batchMetadata === undefined) {\n\t\t\tassert(\n\t\t\t\t!this.localPaused,\n\t\t\t\t0x29d /* \"we should be processing ops when there is no active batch\" */,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// If we got here, the message is part of a batch. Either starting, in progress, or ending.\n\n\t\t// If this is not the start of the batch, error out if the message was sent by a client other than the one that\n\t\t// started the current batch (it should not be possible for ops from other clients to get interleaved with a batch).\n\t\tif (\n\t\t\tthis.currentBatchClientId !== undefined &&\n\t\t\tthis.currentBatchClientId !== message.clientId\n\t\t) {\n\t\t\tthrow new DataCorruptionError(\"OpBatchIncomplete\", {\n\t\t\t\truntimeVersion: pkgVersion,\n\t\t\t\tbatchClientId:\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n\t\t\t\t\tthis.currentBatchClientId === null ? \"null\" : this.currentBatchClientId,\n\t\t\t\tpauseSequenceNumber: this.pauseSequenceNumber,\n\t\t\t\tlocalBatch: this.currentBatchClientId === this.getClientId(),\n\t\t\t\tlocalMessage: message.clientId === this.getClientId(),\n\t\t\t\t...extractSafePropertiesFromMessage(message),\n\t\t\t});\n\t\t}\n\n\t\t// The queue is\n\t\t// 1. paused only when the next message to be processed is the beginning of a batch. Done in two places:\n\t\t// - in afterOpProcessing() - processing ops until reaching start of incomplete batch\n\t\t// - here, when queue was empty and start of batch showed up (batchMetadata === true below).\n\t\t// 2. resumed when batch end comes in (batchMetadata === false below)\n\n\t\tif (batchMetadata) {\n\t\t\tassert(\n\t\t\t\tthis.currentBatchClientId === undefined,\n\t\t\t\t0x29e /* \"there can't be active batch\" */,\n\t\t\t);\n\t\t\tassert(\n\t\t\t\t!this.localPaused,\n\t\t\t\t0x29f /* \"we should be processing ops when there is no active batch\" */,\n\t\t\t);\n\t\t\tthis.pauseSequenceNumber = message.sequenceNumber;\n\t\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\n\t\t\tthis.currentBatchClientId = message.clientId as string;\n\t\t\t// Start of the batch\n\t\t\t// Only pause processing if queue has no other ops!\n\t\t\t// If there are any other ops in the queue, processing will be stopped when they are processed!\n\t\t\tif (this.deltaManager.inbound.length === 1) {\n\t\t\t\tthis.pauseQueue();\n\t\t\t}\n\t\t} else if (batchMetadata === false) {\n\t\t\tassert(\n\t\t\t\tthis.pauseSequenceNumber !== undefined,\n\t\t\t\t0x2a0 /* \"batch presence was validated above\" */,\n\t\t\t);\n\t\t\t// Batch is complete, we can process it!\n\t\t\tthis.resumeQueue(this.pauseSequenceNumber, message);\n\t\t\tthis.pauseSequenceNumber = undefined;\n\t\t\tthis.currentBatchClientId = undefined;\n\t\t} else {\n\t\t\t// Continuation of current batch. Do nothing\n\t\t\tassert(this.currentBatchClientId !== undefined, 0x2a1 /* \"logic error\" */);\n\t\t}\n\t}\n}\n"]}
|
package/lib/scheduleManager.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import type { EventEmitter } from "@fluid-internal/client-utils";
|
|
6
|
-
import { IDeltaManagerFull } from "@fluidframework/container-definitions/internal";
|
|
7
|
-
import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
|
|
8
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
|
|
9
|
-
/**
|
|
10
|
-
* This class has the following responsibilities:
|
|
11
|
-
*
|
|
12
|
-
* 1. It tracks batches as we process ops and raises "batchBegin" and "batchEnd" events.
|
|
13
|
-
* As part of it, it validates batch correctness (i.e. no system ops in the middle of batch)
|
|
14
|
-
*
|
|
15
|
-
* 2. It creates instance of ScheduleManagerCore that ensures we never start processing ops from batch
|
|
16
|
-
* unless all ops of the batch are in.
|
|
17
|
-
*/
|
|
18
|
-
export declare class ScheduleManager {
|
|
19
|
-
private readonly deltaManager;
|
|
20
|
-
private readonly emitter;
|
|
21
|
-
readonly getClientId: () => string | undefined;
|
|
22
|
-
private readonly logger;
|
|
23
|
-
private readonly deltaScheduler;
|
|
24
|
-
constructor(deltaManager: IDeltaManagerFull, emitter: EventEmitter, getClientId: () => string | undefined, logger: ITelemetryLoggerExt);
|
|
25
|
-
batchBegin(message: ISequencedDocumentMessage): void;
|
|
26
|
-
batchEnd(error: any | undefined, message: ISequencedDocumentMessage): void;
|
|
27
|
-
}
|
|
28
|
-
//# sourceMappingURL=scheduleManager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scheduleManager.d.ts","sourceRoot":"","sources":["../src/scheduleManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAEjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gDAAgD,CAAC;AAEnF,OAAO,EAEN,yBAAyB,EACzB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EACN,mBAAmB,EAKnB,MAAM,0CAA0C,CAAC;AAYlD;;;;;;;;GAQG;AACH,qBAAa,eAAe;IAI1B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,MAAM,GAAG,SAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM;IANxB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;gBAG9B,YAAY,EAAE,iBAAiB,EAC/B,OAAO,EAAE,YAAY,EAC7B,WAAW,EAAE,MAAM,MAAM,GAAG,SAAS,EAC7B,MAAM,EAAE,mBAAmB;IAStC,UAAU,CAAC,OAAO,EAAE,yBAAyB;IAK7C,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,SAAS,EAAE,OAAO,EAAE,yBAAyB;CAI1E"}
|