@fluidframework/container-runtime 2.12.0 → 2.20.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 +36 -0
- package/CHANGELOG.md +50 -0
- package/api-report/container-runtime.legacy.alpha.api.md +9 -203
- package/container-runtime.test-files.tar +0 -0
- package/dist/batchTracker.d.ts.map +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 +16 -2
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/blobManager/blobManagerSnapSum.d.ts.map +1 -1
- 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 +22 -12
- package/dist/channelCollection.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +6 -2
- 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 +74 -65
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +53 -37
- 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 +2 -1
- 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 +31 -18
- 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 +6 -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 +12 -5
- 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 +2 -1
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +210 -70
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +39 -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 +6 -2
- package/dist/gc/gcHelpers.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.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 +6 -2
- 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/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 +9 -3
- package/dist/opLifecycle/duplicateBatchDetector.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +3 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +12 -8
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +0 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +5 -4
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +2 -1
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +6 -1
- 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.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 -6
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +43 -5
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/summary/documentSchema.d.ts.map +1 -1
- package/dist/summary/documentSchema.js +2 -0
- 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 +93 -31
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +15 -5
- package/dist/summary/orderedClientElection.js.map +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 +17 -6
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +12 -4
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +9 -5
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +9 -3
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- 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 +12 -4
- package/dist/summary/summarizerHeuristics.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 +15 -5
- 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 +12 -4
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +12 -4
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +246 -135
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +1 -4
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +24 -8
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- 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 +3 -1
- 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 +12 -4
- 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.map +1 -1
- 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 +16 -2
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/blobManager/blobManagerSnapSum.d.ts.map +1 -1
- 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 +22 -12
- package/lib/channelCollection.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +6 -2
- 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 +74 -65
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +53 -37
- 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 +2 -1
- 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 +31 -18
- 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 +6 -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 +95 -89
- 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 +12 -5
- 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 +1 -1
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +210 -70
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js +39 -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 +6 -2
- package/lib/gc/gcHelpers.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.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 +6 -2
- 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/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 +9 -3
- package/lib/opLifecycle/duplicateBatchDetector.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +1 -1
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +3 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +13 -9
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +0 -1
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +6 -5
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +2 -1
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +6 -1
- 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.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 -6
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +41 -4
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/summary/documentSchema.d.ts.map +1 -1
- package/lib/summary/documentSchema.js +2 -0
- 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 +93 -31
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +15 -5
- package/lib/summary/orderedClientElection.js.map +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 +17 -6
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +12 -4
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +9 -5
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +9 -3
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- 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 +12 -4
- package/lib/summary/summarizerHeuristics.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 +15 -5
- 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 +12 -4
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +12 -4
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +246 -135
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +1 -4
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +24 -8
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- 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 +3 -1
- 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 +12 -4
- 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 +44 -31
- package/src/batchTracker.ts +31 -33
- package/src/blobManager/blobManager.ts +38 -19
- package/src/blobManager/blobManagerSnapSum.ts +1 -1
- package/src/channelCollection.ts +44 -37
- package/src/connectionTelemetry.ts +31 -13
- package/src/containerHandleContext.ts +2 -2
- package/src/containerRuntime.ts +198 -140
- package/src/dataStore.ts +11 -6
- package/src/dataStoreContext.ts +80 -59
- package/src/dataStoreContexts.ts +16 -12
- package/src/dataStoreRegistry.ts +1 -1
- package/src/deltaManagerProxies.ts +5 -5
- package/src/deltaScheduler.ts +19 -13
- package/src/gc/garbageCollection.ts +41 -18
- package/src/gc/gcConfigs.ts +4 -4
- package/src/gc/gcDefinitions.ts +212 -70
- package/src/gc/gcHelpers.ts +11 -5
- package/src/gc/gcSummaryDefinitions.ts +18 -6
- package/src/gc/gcSummaryStateTracker.ts +4 -2
- package/src/gc/gcTelemetry.ts +47 -19
- package/src/gc/gcUnreferencedStateTracker.ts +40 -16
- package/src/gc/index.ts +1 -0
- package/src/{scheduleManager.ts → inboundBatchAggregator.ts} +54 -121
- package/src/index.ts +0 -3
- package/src/messageTypes.ts +14 -5
- package/src/metadata.ts +12 -4
- package/src/opLifecycle/batchManager.ts +12 -6
- package/src/opLifecycle/duplicateBatchDetector.ts +10 -4
- package/src/opLifecycle/opCompressor.ts +8 -4
- package/src/opLifecycle/opDecompressor.ts +20 -11
- package/src/opLifecycle/opGroupingManager.ts +12 -8
- package/src/opLifecycle/opSplitter.ts +11 -8
- package/src/opLifecycle/outbox.ts +22 -13
- package/src/opLifecycle/remoteMessageProcessor.ts +10 -4
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +71 -15
- package/src/summary/documentSchema.ts +30 -18
- package/src/summary/index.ts +0 -3
- package/src/summary/orderedClientElection.ts +100 -38
- package/src/summary/runWhileConnectedCoordinator.ts +6 -3
- package/src/summary/runningSummarizer.ts +38 -19
- package/src/summary/summarizer.ts +29 -16
- package/src/summary/summarizerClientElection.ts +2 -2
- package/src/summary/summarizerHeuristics.ts +22 -11
- package/src/summary/summarizerNode/summarizerNode.ts +22 -12
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +48 -16
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +21 -11
- package/src/summary/summarizerTypes.ts +246 -139
- package/src/summary/summaryCollection.ts +24 -25
- package/src/summary/summaryFormat.ts +24 -8
- package/src/summary/summaryGenerator.ts +14 -8
- package/src/summary/summaryManager.ts +28 -18
- package/src/throttler.ts +23 -11
- package/dist/scheduleManager.d.ts +0 -28
- package/dist/scheduleManager.d.ts.map +0 -1
- package/dist/scheduleManager.js +0 -235
- 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 -231
- package/lib/scheduleManager.js.map +0 -1
|
@@ -13,13 +13,19 @@ import { type BatchStartInfo } from "./remoteMessageProcessor.js";
|
|
|
13
13
|
* This class tracks recent batchIds we've seen, and checks incoming batches for duplicates.
|
|
14
14
|
*/
|
|
15
15
|
export class DuplicateBatchDetector {
|
|
16
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* All batchIds we've seen recently enough (based on MSN) that we need to watch for duplicates
|
|
18
|
+
*/
|
|
17
19
|
private readonly batchIdsAll = new Set<string>();
|
|
18
20
|
|
|
19
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* We map from sequenceNumber to batchId to find which ones we can stop tracking as MSN advances
|
|
23
|
+
*/
|
|
20
24
|
private readonly batchIdsBySeqNum = new Map<number, string>();
|
|
21
25
|
|
|
22
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Initialize from snapshot data if provided - otherwise initialize empty
|
|
28
|
+
*/
|
|
23
29
|
constructor(batchIdsFromSnapshot: [number, string][] | undefined) {
|
|
24
30
|
if (batchIdsFromSnapshot) {
|
|
25
31
|
this.batchIdsBySeqNum = new Map(batchIdsFromSnapshot);
|
|
@@ -78,7 +84,7 @@ export class DuplicateBatchDetector {
|
|
|
78
84
|
* Batches that started before the MSN are not at risk for a sequenced duplicate to arrive,
|
|
79
85
|
* since the batch start has been processed by all clients, and local batches are deduped and the forked client would close.
|
|
80
86
|
*/
|
|
81
|
-
private clearOldBatchIds(msn: number) {
|
|
87
|
+
private clearOldBatchIds(msn: number): void {
|
|
82
88
|
this.batchIdsBySeqNum.forEach((batchId, sequenceNumber) => {
|
|
83
89
|
if (sequenceNumber < msn) {
|
|
84
90
|
this.batchIdsBySeqNum.delete(sequenceNumber);
|
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
import { IsoBuffer } from "@fluid-internal/client-utils";
|
|
7
7
|
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
8
8
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
UsageError,
|
|
11
|
+
createChildLogger,
|
|
12
|
+
type ITelemetryLoggerExt,
|
|
13
|
+
} from "@fluidframework/telemetry-utils/internal";
|
|
10
14
|
import { compress } from "lz4js";
|
|
11
15
|
|
|
12
16
|
import { CompressionAlgorithms } from "../containerRuntime.js";
|
|
@@ -20,7 +24,7 @@ import { BatchMessage, IBatch } from "./definitions.js";
|
|
|
20
24
|
* op to reserve sequence numbers.
|
|
21
25
|
*/
|
|
22
26
|
export class OpCompressor {
|
|
23
|
-
private readonly logger;
|
|
27
|
+
private readonly logger: ITelemetryLoggerExt;
|
|
24
28
|
|
|
25
29
|
constructor(logger: ITelemetryBaseLogger) {
|
|
26
30
|
this.logger = createChildLogger({ logger, namespace: "OpCompressor" });
|
|
@@ -89,8 +93,8 @@ export class OpCompressor {
|
|
|
89
93
|
try {
|
|
90
94
|
// Yields a valid JSON array, since each message.contents is already serialized to JSON
|
|
91
95
|
return `[${batch.messages.map(({ contents }) => contents).join(",")}]`;
|
|
92
|
-
} catch (e:
|
|
93
|
-
if (e.message === "Invalid string length") {
|
|
96
|
+
} catch (e: unknown) {
|
|
97
|
+
if ((e as Partial<Error>).message === "Invalid string length") {
|
|
94
98
|
// This is how JSON.stringify signals that
|
|
95
99
|
// the content size exceeds its capacity
|
|
96
100
|
const error = new UsageError("Payload too large");
|
|
@@ -7,7 +7,10 @@ import { IsoBuffer, Uint8ArrayToString } from "@fluid-internal/client-utils";
|
|
|
7
7
|
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
8
8
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
9
9
|
import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
createChildLogger,
|
|
12
|
+
type ITelemetryLoggerExt,
|
|
13
|
+
} from "@fluidframework/telemetry-utils/internal";
|
|
11
14
|
import { decompress } from "lz4js";
|
|
12
15
|
|
|
13
16
|
import { CompressionAlgorithms } from "../containerRuntime.js";
|
|
@@ -30,9 +33,11 @@ interface IPackedContentsContents {
|
|
|
30
33
|
*/
|
|
31
34
|
export class OpDecompressor {
|
|
32
35
|
private activeBatch = false;
|
|
36
|
+
// TODO: better typing
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
33
38
|
private rootMessageContents: any | undefined;
|
|
34
39
|
private processedCount = 0;
|
|
35
|
-
private readonly logger;
|
|
40
|
+
private readonly logger: ITelemetryLoggerExt;
|
|
36
41
|
|
|
37
42
|
constructor(logger: ITelemetryBaseLogger) {
|
|
38
43
|
this.logger = createChildLogger({ logger, namespace: "OpDecompressor" });
|
|
@@ -81,11 +86,13 @@ export class OpDecompressor {
|
|
|
81
86
|
return false;
|
|
82
87
|
}
|
|
83
88
|
|
|
84
|
-
public get currentlyUnrolling() {
|
|
89
|
+
public get currentlyUnrolling(): boolean {
|
|
85
90
|
return this.activeBatch;
|
|
86
91
|
}
|
|
87
92
|
|
|
88
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* Is the decompressed and stored batch only comprised of a single message
|
|
95
|
+
*/
|
|
89
96
|
private isSingleMessageBatch = false;
|
|
90
97
|
|
|
91
98
|
/**
|
|
@@ -118,8 +125,8 @@ export class OpDecompressor {
|
|
|
118
125
|
);
|
|
119
126
|
const decompressedMessage = decompress(contents);
|
|
120
127
|
const intoString = Uint8ArrayToString(decompressedMessage);
|
|
121
|
-
|
|
122
|
-
this.rootMessageContents =
|
|
128
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
129
|
+
this.rootMessageContents = JSON.parse(intoString);
|
|
123
130
|
}
|
|
124
131
|
|
|
125
132
|
/**
|
|
@@ -130,6 +137,7 @@ export class OpDecompressor {
|
|
|
130
137
|
assert(this.currentlyUnrolling, 0x942 /* not currently unrolling */);
|
|
131
138
|
assert(this.rootMessageContents !== undefined, 0x943 /* missing rootMessageContents */);
|
|
132
139
|
assert(
|
|
140
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
133
141
|
this.rootMessageContents.length > this.processedCount,
|
|
134
142
|
0x944 /* no more content to unroll */,
|
|
135
143
|
);
|
|
@@ -138,6 +146,7 @@ export class OpDecompressor {
|
|
|
138
146
|
|
|
139
147
|
if (batchMetadata === false || this.isSingleMessageBatch) {
|
|
140
148
|
// End of compressed batch
|
|
149
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
141
150
|
const returnMessage = newMessage(message, this.rootMessageContents[this.processedCount]);
|
|
142
151
|
|
|
143
152
|
this.activeBatch = false;
|
|
@@ -148,6 +157,7 @@ export class OpDecompressor {
|
|
|
148
157
|
return returnMessage;
|
|
149
158
|
} else if (batchMetadata === true) {
|
|
150
159
|
// Start of compressed batch
|
|
160
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
151
161
|
return newMessage(message, this.rootMessageContents[this.processedCount++]);
|
|
152
162
|
}
|
|
153
163
|
|
|
@@ -155,6 +165,7 @@ export class OpDecompressor {
|
|
|
155
165
|
assert(message.contents === undefined, 0x512 /* Expecting empty message */);
|
|
156
166
|
|
|
157
167
|
// Continuation of compressed batch
|
|
168
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
158
169
|
return newMessage(message, this.rootMessageContents[this.processedCount++]);
|
|
159
170
|
}
|
|
160
171
|
}
|
|
@@ -162,15 +173,13 @@ export class OpDecompressor {
|
|
|
162
173
|
// We should not be mutating the input message nor its metadata
|
|
163
174
|
const newMessage = (
|
|
164
175
|
originalMessage: ISequencedDocumentMessage,
|
|
165
|
-
contents:
|
|
176
|
+
contents: unknown,
|
|
166
177
|
): ISequencedDocumentMessage => ({
|
|
167
178
|
...originalMessage,
|
|
168
179
|
contents,
|
|
169
180
|
compression: undefined,
|
|
170
181
|
// TODO: It should already be the case that we're not modifying any metadata, not clear if/why this shallow clone should be required.
|
|
171
|
-
|
|
182
|
+
|
|
172
183
|
metadata:
|
|
173
|
-
originalMessage.metadata === undefined
|
|
174
|
-
? undefined
|
|
175
|
-
: { ...(originalMessage.metadata as any) },
|
|
184
|
+
originalMessage.metadata === undefined ? undefined : { ...originalMessage.metadata },
|
|
176
185
|
});
|
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
7
7
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
8
8
|
import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
createChildLogger,
|
|
11
|
+
type ITelemetryLoggerExt,
|
|
12
|
+
} from "@fluidframework/telemetry-utils/internal";
|
|
10
13
|
|
|
11
14
|
import { IBatch, type BatchMessage } from "./definitions.js";
|
|
12
15
|
|
|
@@ -24,8 +27,11 @@ interface IGroupedMessage {
|
|
|
24
27
|
compression?: string;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
function isGroupContents(opContents:
|
|
28
|
-
return
|
|
30
|
+
function isGroupContents(opContents: unknown): opContents is IGroupedBatchMessageContents {
|
|
31
|
+
return (
|
|
32
|
+
(opContents as Partial<IGroupedBatchMessageContents>)?.type ===
|
|
33
|
+
OpGroupingManager.groupedBatchOp
|
|
34
|
+
);
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
export function isGroupedBatch(op: ISequencedDocumentMessage): boolean {
|
|
@@ -35,12 +41,11 @@ export function isGroupedBatch(op: ISequencedDocumentMessage): boolean {
|
|
|
35
41
|
export interface OpGroupingManagerConfig {
|
|
36
42
|
readonly groupedBatchingEnabled: boolean;
|
|
37
43
|
readonly opCountThreshold: number;
|
|
38
|
-
readonly reentrantBatchGroupingEnabled: boolean;
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
export class OpGroupingManager {
|
|
42
47
|
static readonly groupedBatchOp = "groupedBatch";
|
|
43
|
-
private readonly logger;
|
|
48
|
+
private readonly logger: ITelemetryLoggerExt;
|
|
44
49
|
|
|
45
50
|
constructor(
|
|
46
51
|
private readonly config: OpGroupingManagerConfig,
|
|
@@ -156,9 +161,8 @@ export class OpGroupingManager {
|
|
|
156
161
|
this.config.groupedBatchingEnabled &&
|
|
157
162
|
// The number of ops in the batch must surpass the configured threshold
|
|
158
163
|
// or be empty (to allow for empty batches to be grouped)
|
|
159
|
-
(batch.messages.length === 0 || batch.messages.length >= this.config.opCountThreshold)
|
|
160
|
-
// Support for reentrant batches
|
|
161
|
-
(this.config.reentrantBatchGroupingEnabled || batch.hasReentrantOps !== true)
|
|
164
|
+
(batch.messages.length === 0 || batch.messages.length >= this.config.opCountThreshold)
|
|
165
|
+
// Support for reentrant batches will be on by default
|
|
162
166
|
);
|
|
163
167
|
}
|
|
164
168
|
}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
DataCorruptionError,
|
|
12
12
|
createChildLogger,
|
|
13
13
|
extractSafePropertiesFromMessage,
|
|
14
|
+
type ITelemetryLoggerExt,
|
|
14
15
|
} from "@fluidframework/telemetry-utils/internal";
|
|
15
16
|
|
|
16
17
|
import { ContainerMessageType, ContainerRuntimeChunkedOpMessage } from "../messageTypes.js";
|
|
@@ -23,12 +24,12 @@ export function isChunkedMessage(message: ISequencedDocumentMessage): boolean {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
interface IChunkedContents {
|
|
26
|
-
type: typeof ContainerMessageType.ChunkedOp;
|
|
27
|
-
contents: IChunkedOp;
|
|
27
|
+
readonly type: typeof ContainerMessageType.ChunkedOp;
|
|
28
|
+
readonly contents: IChunkedOp;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
function isChunkedContents(contents:
|
|
31
|
-
return contents?.type === ContainerMessageType.ChunkedOp;
|
|
31
|
+
function isChunkedContents(contents: unknown): contents is IChunkedContents {
|
|
32
|
+
return (contents as Partial<IChunkedContents>)?.type === ContainerMessageType.ChunkedOp;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
/**
|
|
@@ -37,7 +38,7 @@ function isChunkedContents(contents: any): contents is IChunkedContents {
|
|
|
37
38
|
export class OpSplitter {
|
|
38
39
|
// Local copy of incomplete received chunks.
|
|
39
40
|
private readonly chunkMap: Map<string, string[]>;
|
|
40
|
-
private readonly logger;
|
|
41
|
+
private readonly logger: ITelemetryLoggerExt;
|
|
41
42
|
|
|
42
43
|
constructor(
|
|
43
44
|
chunks: [string, string[]][],
|
|
@@ -62,7 +63,7 @@ export class OpSplitter {
|
|
|
62
63
|
return this.chunkMap;
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
public clearPartialChunks(clientId: string) {
|
|
66
|
+
public clearPartialChunks(clientId: string): void {
|
|
66
67
|
if (this.chunkMap.has(clientId)) {
|
|
67
68
|
this.chunkMap.delete(clientId);
|
|
68
69
|
}
|
|
@@ -72,7 +73,7 @@ export class OpSplitter {
|
|
|
72
73
|
clientId: string,
|
|
73
74
|
chunkedContent: IChunkedOp,
|
|
74
75
|
originalMessage: ISequencedDocumentMessage,
|
|
75
|
-
) {
|
|
76
|
+
): void {
|
|
76
77
|
let map = this.chunkMap.get(clientId);
|
|
77
78
|
if (map === undefined) {
|
|
78
79
|
map = [];
|
|
@@ -190,7 +191,7 @@ export class OpSplitter {
|
|
|
190
191
|
const contents: IChunkedContents = message.contents;
|
|
191
192
|
|
|
192
193
|
// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)
|
|
193
|
-
|
|
194
|
+
|
|
194
195
|
const clientId = message.clientId as string;
|
|
195
196
|
const chunkedContent = contents.contents;
|
|
196
197
|
this.addChunk(clientId, chunkedContent, message);
|
|
@@ -215,6 +216,7 @@ export class OpSplitter {
|
|
|
215
216
|
// back-compat with 1.x builds
|
|
216
217
|
// This is only required / present for non-compressed, chunked ops
|
|
217
218
|
// For compressed ops, we have op grouping enabled, and type of each op is preserved within compressed content.
|
|
219
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
|
|
218
220
|
completeMessage.type = (chunkedContent as any).originalType;
|
|
219
221
|
completeMessage.metadata = chunkedContent.originalMetadata;
|
|
220
222
|
completeMessage.compression = chunkedContent.originalCompression;
|
|
@@ -298,6 +300,7 @@ export const splitOp = (
|
|
|
298
300
|
// This is really bad, as we will crash on later ops and it's very hard to debug these cases.
|
|
299
301
|
// If we put some known type here, then we will crash on it (as 1.x does not understand compression, and thus will not
|
|
300
302
|
// find info on the op like address of the channel to deliver the op)
|
|
303
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
|
|
301
304
|
(chunk as any).originalType = "component";
|
|
302
305
|
}
|
|
303
306
|
|
|
@@ -77,6 +77,8 @@ export function serializeOpContents(contents: OutboundContainerRuntimeMessage):
|
|
|
77
77
|
* @returns the result of the action provided
|
|
78
78
|
*/
|
|
79
79
|
export function getLongStack<T>(action: () => T, length: number = 50): T {
|
|
80
|
+
// TODO: better typing here
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
|
|
80
82
|
const errorObj = Error as any;
|
|
81
83
|
if (
|
|
82
84
|
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
|
|
@@ -90,11 +92,14 @@ export function getLongStack<T>(action: () => T, length: number = 50): T {
|
|
|
90
92
|
return action();
|
|
91
93
|
}
|
|
92
94
|
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
|
|
93
96
|
const originalStackTraceLimit = errorObj.stackTraceLimit;
|
|
94
97
|
try {
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
95
99
|
errorObj.stackTraceLimit = length;
|
|
96
100
|
return action();
|
|
97
101
|
} finally {
|
|
102
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
|
|
98
103
|
errorObj.stackTraceLimit = originalStackTraceLimit;
|
|
99
104
|
}
|
|
100
105
|
}
|
|
@@ -171,7 +176,7 @@ export class Outbox {
|
|
|
171
176
|
* last message processed by the ContainerRuntime. In the absence of op reentrancy, this
|
|
172
177
|
* pair will remain stable during a single JS turn during which the batch is being built up.
|
|
173
178
|
*/
|
|
174
|
-
private maybeFlushPartialBatch() {
|
|
179
|
+
private maybeFlushPartialBatch(): void {
|
|
175
180
|
const mainBatchSeqNums = this.mainBatch.sequenceNumbers;
|
|
176
181
|
const blobAttachSeqNums = this.blobAttachBatch.sequenceNumbers;
|
|
177
182
|
const idAllocSeqNums = this.idAllocationBatch.sequenceNumbers;
|
|
@@ -214,13 +219,13 @@ export class Outbox {
|
|
|
214
219
|
}
|
|
215
220
|
}
|
|
216
221
|
|
|
217
|
-
public submit(message: BatchMessage) {
|
|
222
|
+
public submit(message: BatchMessage): void {
|
|
218
223
|
this.maybeFlushPartialBatch();
|
|
219
224
|
|
|
220
225
|
this.addMessageToBatchManager(this.mainBatch, message);
|
|
221
226
|
}
|
|
222
227
|
|
|
223
|
-
public submitBlobAttach(message: BatchMessage) {
|
|
228
|
+
public submitBlobAttach(message: BatchMessage): void {
|
|
224
229
|
this.maybeFlushPartialBatch();
|
|
225
230
|
|
|
226
231
|
this.addMessageToBatchManager(this.blobAttachBatch, message);
|
|
@@ -238,13 +243,13 @@ export class Outbox {
|
|
|
238
243
|
}
|
|
239
244
|
}
|
|
240
245
|
|
|
241
|
-
public submitIdAllocation(message: BatchMessage) {
|
|
246
|
+
public submitIdAllocation(message: BatchMessage): void {
|
|
242
247
|
this.maybeFlushPartialBatch();
|
|
243
248
|
|
|
244
249
|
this.addMessageToBatchManager(this.idAllocationBatch, message);
|
|
245
250
|
}
|
|
246
251
|
|
|
247
|
-
private addMessageToBatchManager(batchManager: BatchManager, message: BatchMessage) {
|
|
252
|
+
private addMessageToBatchManager(batchManager: BatchManager, message: BatchMessage): void {
|
|
248
253
|
if (
|
|
249
254
|
!batchManager.push(
|
|
250
255
|
message,
|
|
@@ -267,7 +272,7 @@ export class Outbox {
|
|
|
267
272
|
* @param resubmittingBatchId - If defined, indicates this is a resubmission of a batch
|
|
268
273
|
* with the given Batch ID, which must be preserved
|
|
269
274
|
*/
|
|
270
|
-
public flush(resubmittingBatchId?: BatchId) {
|
|
275
|
+
public flush(resubmittingBatchId?: BatchId): void {
|
|
271
276
|
if (this.isContextReentrant()) {
|
|
272
277
|
const error = new UsageError("Flushing is not supported inside DDS event handlers");
|
|
273
278
|
this.params.closeContainer(error);
|
|
@@ -277,7 +282,7 @@ export class Outbox {
|
|
|
277
282
|
this.flushAll(resubmittingBatchId);
|
|
278
283
|
}
|
|
279
284
|
|
|
280
|
-
private flushAll(resubmittingBatchId?: BatchId) {
|
|
285
|
+
private flushAll(resubmittingBatchId?: BatchId): void {
|
|
281
286
|
// If we're resubmitting and all batches are empty, we need to flush an empty batch.
|
|
282
287
|
// Note that we currently resubmit one batch at a time, so on resubmit, 2 of the 3 batches will *always* be empty.
|
|
283
288
|
// It's theoretically possible that we don't *need* to resubmit this empty batch, and in those cases, it'll safely be ignored
|
|
@@ -304,7 +309,7 @@ export class Outbox {
|
|
|
304
309
|
);
|
|
305
310
|
}
|
|
306
311
|
|
|
307
|
-
private flushEmptyBatch(resubmittingBatchId: BatchId) {
|
|
312
|
+
private flushEmptyBatch(resubmittingBatchId: BatchId): void {
|
|
308
313
|
const referenceSequenceNumber =
|
|
309
314
|
this.params.getCurrentSequenceNumbers().referenceSequenceNumber;
|
|
310
315
|
assert(
|
|
@@ -330,7 +335,7 @@ export class Outbox {
|
|
|
330
335
|
batchManager: BatchManager,
|
|
331
336
|
disableGroupedBatching: boolean = false,
|
|
332
337
|
resubmittingBatchId?: BatchId,
|
|
333
|
-
) {
|
|
338
|
+
): void {
|
|
334
339
|
if (batchManager.empty) {
|
|
335
340
|
return;
|
|
336
341
|
}
|
|
@@ -375,7 +380,7 @@ export class Outbox {
|
|
|
375
380
|
*
|
|
376
381
|
* @param rawBatch - the batch to be rebased
|
|
377
382
|
*/
|
|
378
|
-
private rebase(rawBatch: IBatch, batchManager: BatchManager) {
|
|
383
|
+
private rebase(rawBatch: IBatch, batchManager: BatchManager): void {
|
|
379
384
|
assert(!this.rebasing, 0x6fb /* Reentrancy */);
|
|
380
385
|
assert(batchManager.options.canRebase, 0x9a7 /* BatchManager does not support rebase */);
|
|
381
386
|
|
|
@@ -459,7 +464,7 @@ export class Outbox {
|
|
|
459
464
|
* @param batch - batch to be sent
|
|
460
465
|
* @returns the clientSequenceNumber of the start of the batch, or undefined if nothing was sent
|
|
461
466
|
*/
|
|
462
|
-
private sendBatch(batch: IBatch) {
|
|
467
|
+
private sendBatch(batch: IBatch): number | undefined {
|
|
463
468
|
const length = batch.messages.length;
|
|
464
469
|
if (length === 0) {
|
|
465
470
|
return undefined; // Nothing submitted
|
|
@@ -505,9 +510,13 @@ export class Outbox {
|
|
|
505
510
|
}
|
|
506
511
|
|
|
507
512
|
/**
|
|
508
|
-
*
|
|
513
|
+
* Gets a checkpoint object per batch that facilitates iterating over the batch messages when rolling back.
|
|
509
514
|
*/
|
|
510
|
-
public getBatchCheckpoints() {
|
|
515
|
+
public getBatchCheckpoints(): {
|
|
516
|
+
mainBatch: IBatchCheckpoint;
|
|
517
|
+
idAllocationBatch: IBatchCheckpoint;
|
|
518
|
+
blobAttachBatch: IBatchCheckpoint;
|
|
519
|
+
} {
|
|
511
520
|
// This variable is declared with a specific type so that we have a standard import of the IBatchCheckpoint type.
|
|
512
521
|
// When the type is inferred, the generated .d.ts uses a dynamic import which doesn't resolve.
|
|
513
522
|
const mainBatch: IBatchCheckpoint = this.mainBatch.checkpoint();
|
|
@@ -22,11 +22,17 @@ import { OpSplitter, isChunkedMessage } from "./opSplitter.js";
|
|
|
22
22
|
// eslint-disable-next-line unused-imports/no-unused-imports -- Used by "@link" comment annotation below
|
|
23
23
|
import { serializeOpContents } from "./outbox.js";
|
|
24
24
|
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Info about the batch we learn when we process the first message
|
|
27
|
+
*/
|
|
26
28
|
export interface BatchStartInfo {
|
|
27
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* Batch ID, if present
|
|
31
|
+
*/
|
|
28
32
|
readonly batchId: string | undefined;
|
|
29
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* clientId that sent this batch. Used to compute Batch ID if needed
|
|
35
|
+
*/
|
|
30
36
|
readonly clientId: string;
|
|
31
37
|
/**
|
|
32
38
|
* Client Sequence Number of the Grouped Batch message, or the first message in the ungrouped batch.
|
|
@@ -101,7 +107,7 @@ export class RemoteMessageProcessor {
|
|
|
101
107
|
return this.opSplitter.chunks;
|
|
102
108
|
}
|
|
103
109
|
|
|
104
|
-
public clearPartialMessagesFor(clientId: string) {
|
|
110
|
+
public clearPartialMessagesFor(clientId: string): void {
|
|
105
111
|
this.opSplitter.clearPartialChunks(clientId);
|
|
106
112
|
}
|
|
107
113
|
|
package/src/packageVersion.ts
CHANGED
|
@@ -56,16 +56,22 @@ export interface IPendingMessage {
|
|
|
56
56
|
* Or, -1 if it was never submitted (and clientId will be a random uuid)
|
|
57
57
|
*/
|
|
58
58
|
batchStartCsn: number;
|
|
59
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* length of the batch (how many runtime messages here)
|
|
61
|
+
*/
|
|
60
62
|
length: number;
|
|
61
|
-
/**
|
|
63
|
+
/**
|
|
64
|
+
* If true, don't compare batchID of incoming batches to this. e.g. ID Allocation Batch IDs should be ignored
|
|
65
|
+
*/
|
|
62
66
|
ignoreBatchId?: boolean;
|
|
63
67
|
};
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
type Patch<T, U> = U & Omit<T, keyof U>;
|
|
67
71
|
|
|
68
|
-
/**
|
|
72
|
+
/**
|
|
73
|
+
* First version of the type (pre-dates batchInfo)
|
|
74
|
+
*/
|
|
69
75
|
type IPendingMessageV0 = Patch<IPendingMessage, { batchInfo?: undefined }>;
|
|
70
76
|
|
|
71
77
|
/**
|
|
@@ -82,7 +88,9 @@ export interface IPendingLocalState {
|
|
|
82
88
|
pendingStates: IPendingMessage[];
|
|
83
89
|
}
|
|
84
90
|
|
|
85
|
-
/**
|
|
91
|
+
/**
|
|
92
|
+
* Info needed to replay/resubmit a pending message
|
|
93
|
+
*/
|
|
86
94
|
export type PendingMessageResubmitData = Pick<
|
|
87
95
|
IPendingMessage,
|
|
88
96
|
"content" | "localOpMetadata" | "opMetadata"
|
|
@@ -98,7 +106,9 @@ export interface IRuntimeStateHandler {
|
|
|
98
106
|
}
|
|
99
107
|
|
|
100
108
|
function isEmptyBatchPendingMessage(message: IPendingMessageFromStash): boolean {
|
|
109
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
101
110
|
const content = JSON.parse(message.content);
|
|
111
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
102
112
|
return content.type === "groupedBatch" && content.contents?.length === 0;
|
|
103
113
|
}
|
|
104
114
|
|
|
@@ -131,6 +141,28 @@ function scrubAndStringify(
|
|
|
131
141
|
return JSON.stringify(scrubbed);
|
|
132
142
|
}
|
|
133
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Finds and returns the index where the strings diverge, and the character at that index in each string (or undefined if not applicable)
|
|
146
|
+
*/
|
|
147
|
+
export function findFirstCharacterMismatched(
|
|
148
|
+
a: string,
|
|
149
|
+
b: string,
|
|
150
|
+
): [index: number, charA?: string, charB?: string] {
|
|
151
|
+
const minLength = Math.min(a.length, b.length);
|
|
152
|
+
for (let i = 0; i < minLength; i++) {
|
|
153
|
+
if (a[i] !== b[i]) {
|
|
154
|
+
return [i, a[i], b[i]];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Since we didn't return in the loop, the shorter string must be a prefix of the other.
|
|
159
|
+
// If they're the same length, return -1 to indicate they're identical.
|
|
160
|
+
// Otherwise, the next character of the longer one is where they differ. No need to return that next character.
|
|
161
|
+
return a.length === b.length
|
|
162
|
+
? [-1, undefined, undefined]
|
|
163
|
+
: [minLength, a[minLength], b[minLength]];
|
|
164
|
+
}
|
|
165
|
+
|
|
134
166
|
function withoutLocalOpMetadata(message: IPendingMessage): IPendingMessage {
|
|
135
167
|
return {
|
|
136
168
|
...message,
|
|
@@ -148,9 +180,13 @@ function withoutLocalOpMetadata(message: IPendingMessage): IPendingMessage {
|
|
|
148
180
|
* It verifies that all the ops are acked, are received in the right order and batch information is correct.
|
|
149
181
|
*/
|
|
150
182
|
export class PendingStateManager implements IDisposable {
|
|
151
|
-
/**
|
|
183
|
+
/**
|
|
184
|
+
* Messages that will need to be resubmitted if not ack'd before the next reconnection
|
|
185
|
+
*/
|
|
152
186
|
private readonly pendingMessages = new Deque<IPendingMessage>();
|
|
153
|
-
/**
|
|
187
|
+
/**
|
|
188
|
+
* Messages stashed from a previous container, now being rehydrated. Need to be resubmitted.
|
|
189
|
+
*/
|
|
154
190
|
private readonly initialMessages = new Deque<IPendingMessageFromStash>();
|
|
155
191
|
|
|
156
192
|
/**
|
|
@@ -163,7 +199,9 @@ export class PendingStateManager implements IDisposable {
|
|
|
163
199
|
this.pendingMessages.clear();
|
|
164
200
|
});
|
|
165
201
|
|
|
166
|
-
/**
|
|
202
|
+
/**
|
|
203
|
+
* Used to ensure we don't replay ops on the same connection twice
|
|
204
|
+
*/
|
|
167
205
|
private clientIdFromLastReplay: string | undefined;
|
|
168
206
|
|
|
169
207
|
/**
|
|
@@ -232,10 +270,10 @@ export class PendingStateManager implements IDisposable {
|
|
|
232
270
|
}
|
|
233
271
|
}
|
|
234
272
|
|
|
235
|
-
public get disposed() {
|
|
273
|
+
public get disposed(): boolean {
|
|
236
274
|
return this.disposeOnce.evaluated;
|
|
237
275
|
}
|
|
238
|
-
public readonly dispose = () => this.disposeOnce.value;
|
|
276
|
+
public readonly dispose = (): void => this.disposeOnce.value;
|
|
239
277
|
|
|
240
278
|
/**
|
|
241
279
|
* The given batch has been flushed, and needs to be tracked locally until the corresponding
|
|
@@ -249,7 +287,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
249
287
|
batch: BatchMessage[],
|
|
250
288
|
clientSequenceNumber: number | undefined,
|
|
251
289
|
ignoreBatchId?: boolean,
|
|
252
|
-
) {
|
|
290
|
+
): void {
|
|
253
291
|
// clientId and batchStartCsn are used for generating the batchId so we can detect container forks
|
|
254
292
|
// where this batch was submitted by two different clients rehydrating from the same local state.
|
|
255
293
|
// In the typical case where the batch was actually sent, use the clientId and clientSequenceNumber.
|
|
@@ -288,7 +326,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
288
326
|
* Applies stashed ops at their reference sequence number so they are ready to be ACKed or resubmitted
|
|
289
327
|
* @param seqNum - Sequence number at which to apply ops. Will apply all ops if seqNum is undefined.
|
|
290
328
|
*/
|
|
291
|
-
public async applyStashedOpsAt(seqNum?: number) {
|
|
329
|
+
public async applyStashedOpsAt(seqNum?: number): Promise<void> {
|
|
292
330
|
// apply stashed ops at sequence number
|
|
293
331
|
while (!this.initialMessages.isEmpty()) {
|
|
294
332
|
if (seqNum !== undefined) {
|
|
@@ -459,7 +497,17 @@ export class PendingStateManager implements IDisposable {
|
|
|
459
497
|
const messageContent = buildPendingMessageContent(message);
|
|
460
498
|
|
|
461
499
|
// Stringified content should match
|
|
500
|
+
// If it doesn't, collect as much info about the difference as possible (privacy-wise) and log it
|
|
462
501
|
if (pendingMessage.content !== messageContent) {
|
|
502
|
+
const [pendingLength, incomingLength] = [
|
|
503
|
+
pendingMessage.content.length,
|
|
504
|
+
messageContent.length,
|
|
505
|
+
];
|
|
506
|
+
const [mismatchStartIndex, pendingChar, incomingChar] = findFirstCharacterMismatched(
|
|
507
|
+
pendingMessage.content,
|
|
508
|
+
messageContent,
|
|
509
|
+
);
|
|
510
|
+
|
|
463
511
|
const pendingContentObj = JSON.parse(
|
|
464
512
|
pendingMessage.content,
|
|
465
513
|
) as LocalContainerRuntimeMessage;
|
|
@@ -467,6 +515,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
467
515
|
messageContent,
|
|
468
516
|
) as InboundContainerRuntimeMessage;
|
|
469
517
|
|
|
518
|
+
// Compare inner contents object, since that both should be { type, contents }
|
|
470
519
|
const contentsMatch =
|
|
471
520
|
pendingContentObj.contents === incomingContentObj.contents ||
|
|
472
521
|
(pendingContentObj.contents !== undefined &&
|
|
@@ -480,6 +529,11 @@ export class PendingStateManager implements IDisposable {
|
|
|
480
529
|
pendingContentScrubbed: scrubAndStringify(pendingContentObj),
|
|
481
530
|
incomingContentScrubbed: scrubAndStringify(incomingContentObj),
|
|
482
531
|
contentsMatch,
|
|
532
|
+
pendingLength,
|
|
533
|
+
incomingLength,
|
|
534
|
+
mismatchStartIndex,
|
|
535
|
+
pendingChar,
|
|
536
|
+
incomingChar,
|
|
483
537
|
},
|
|
484
538
|
});
|
|
485
539
|
|
|
@@ -497,7 +551,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
497
551
|
/**
|
|
498
552
|
* Check if the incoming batch matches the batch info for the next pending message.
|
|
499
553
|
*/
|
|
500
|
-
private onLocalBatchBegin(batchStart: BatchStartInfo, batchLength?: number) {
|
|
554
|
+
private onLocalBatchBegin(batchStart: BatchStartInfo, batchLength?: number): void {
|
|
501
555
|
// Get the next message from the pending queue. Verify a message exists.
|
|
502
556
|
const pendingMessage = this.pendingMessages.peekFront();
|
|
503
557
|
assert(
|
|
@@ -556,7 +610,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
556
610
|
* states in its queue. This includes triggering resubmission of unacked ops.
|
|
557
611
|
* ! Note: successfully resubmitting an op that has been successfully sequenced is not possible due to checks in the ConnectionStateHandler (Loader layer)
|
|
558
612
|
*/
|
|
559
|
-
public replayPendingStates() {
|
|
613
|
+
public replayPendingStates(): void {
|
|
560
614
|
assert(
|
|
561
615
|
this.stateHandler.connected(),
|
|
562
616
|
0x172 /* "The connection state is not consistent with the runtime" */,
|
|
@@ -600,7 +654,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
600
654
|
/**
|
|
601
655
|
* We must preserve the distinct batches on resubmit.
|
|
602
656
|
* Note: It is not possible for the PendingStateManager to receive a partially acked batch. It will
|
|
603
|
-
* either receive the whole batch ack or nothing at all.
|
|
657
|
+
* either receive the whole batch ack or nothing at all. See {@link InboundBatchAggregator} for how this works.
|
|
604
658
|
*/
|
|
605
659
|
if (batchMetadataFlag === undefined) {
|
|
606
660
|
// Single-message batch
|
|
@@ -667,7 +721,9 @@ export class PendingStateManager implements IDisposable {
|
|
|
667
721
|
}
|
|
668
722
|
}
|
|
669
723
|
|
|
670
|
-
/**
|
|
724
|
+
/**
|
|
725
|
+
* For back-compat if trying to apply stashed ops that pre-date batchInfo
|
|
726
|
+
*/
|
|
671
727
|
function patchbatchInfo(
|
|
672
728
|
message: IPendingMessageFromStash,
|
|
673
729
|
): asserts message is IPendingMessage {
|