@fluidframework/container-runtime 2.0.0-internal.6.1.1 → 2.0.0-internal.6.3.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/CHANGELOG.md +39 -0
- package/README.md +4 -3
- package/dist/batchTracker.d.ts +1 -1
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +5 -4
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +4 -21
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +119 -185
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +13 -12
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +99 -16
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +380 -242
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +4 -5
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +2 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +40 -41
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts +1 -2
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +7 -8
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.js +2 -2
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +23 -25
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerProxyBase.d.ts +1 -1
- package/dist/deltaManagerProxyBase.js +2 -2
- package/dist/deltaManagerProxyBase.js.map +1 -1
- package/dist/deltaScheduler.js +6 -6
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/error.d.ts +14 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +21 -0
- package/dist/error.js.map +1 -0
- package/dist/gc/garbageCollection.d.ts +4 -6
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +26 -25
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +5 -3
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +4 -2
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.js +7 -7
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts +4 -7
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +15 -52
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +2 -0
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +4 -4
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +1 -1
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +1 -2
- package/dist/gc/index.js.map +1 -1
- package/dist/id-compressor/appendOnlySortedMap.d.ts +8 -30
- package/dist/id-compressor/appendOnlySortedMap.d.ts.map +1 -1
- package/dist/id-compressor/appendOnlySortedMap.js +26 -68
- package/dist/id-compressor/appendOnlySortedMap.js.map +1 -1
- package/dist/id-compressor/finalSpace.d.ts +29 -0
- package/dist/id-compressor/finalSpace.d.ts.map +1 -0
- package/dist/id-compressor/finalSpace.js +62 -0
- package/dist/id-compressor/finalSpace.js.map +1 -0
- package/dist/id-compressor/idCompressor.d.ts +25 -250
- package/dist/id-compressor/idCompressor.d.ts.map +1 -1
- package/dist/id-compressor/idCompressor.js +387 -1150
- package/dist/id-compressor/idCompressor.js.map +1 -1
- package/dist/id-compressor/identifiers.d.ts +32 -0
- package/dist/id-compressor/identifiers.d.ts.map +1 -0
- package/dist/id-compressor/identifiers.js +15 -0
- package/dist/id-compressor/identifiers.js.map +1 -0
- package/dist/id-compressor/index.d.ts +5 -6
- package/dist/id-compressor/index.d.ts.map +1 -1
- package/dist/id-compressor/index.js +20 -26
- package/dist/id-compressor/index.js.map +1 -1
- package/dist/id-compressor/persistanceUtilities.d.ts +22 -0
- package/dist/id-compressor/persistanceUtilities.d.ts.map +1 -0
- package/dist/id-compressor/persistanceUtilities.js +43 -0
- package/dist/id-compressor/persistanceUtilities.js.map +1 -0
- package/dist/id-compressor/sessionSpaceNormalizer.d.ts +46 -0
- package/dist/id-compressor/sessionSpaceNormalizer.d.ts.map +1 -0
- package/dist/id-compressor/sessionSpaceNormalizer.js +80 -0
- package/dist/id-compressor/sessionSpaceNormalizer.js.map +1 -0
- package/dist/id-compressor/sessions.d.ts +115 -0
- package/dist/id-compressor/sessions.d.ts.map +1 -0
- package/dist/id-compressor/sessions.js +305 -0
- package/dist/id-compressor/sessions.js.map +1 -0
- package/dist/id-compressor/utilities.d.ts +49 -0
- package/dist/id-compressor/utilities.d.ts.map +1 -0
- package/dist/id-compressor/utilities.js +166 -0
- package/dist/id-compressor/utilities.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.js +5 -5
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +11 -10
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +3 -3
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +14 -15
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +1 -0
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +16 -17
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +11 -5
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +12 -5
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +36 -23
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +23 -23
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/index.d.ts +3 -3
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js +2 -1
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +2 -3
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +8 -8
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js +3 -3
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +27 -4
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +246 -74
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +6 -5
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +73 -69
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +2 -2
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js +2 -2
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.js +2 -2
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/index.d.ts +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 +5 -14
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +32 -109
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +6 -30
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +0 -11
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +5 -88
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +38 -25
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +2 -3
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +9 -8
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.js +2 -2
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +10 -4
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +52 -48
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +7 -6
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +30 -22
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/batchTracker.d.ts +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +3 -2
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +4 -21
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +91 -157
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +2 -1
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +99 -16
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +332 -192
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +2 -3
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +2 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +3 -4
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts +1 -2
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +1 -2
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.js +1 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +2 -4
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerProxyBase.d.ts +1 -1
- package/lib/deltaManagerProxyBase.js +1 -1
- package/lib/deltaManagerProxyBase.js.map +1 -1
- package/lib/deltaScheduler.js +1 -1
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/error.d.ts +14 -0
- package/lib/error.d.ts.map +1 -0
- package/lib/error.js +17 -0
- package/lib/error.js.map +1 -0
- package/lib/gc/garbageCollection.d.ts +4 -6
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +26 -25
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +3 -1
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +4 -2
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.js +1 -1
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts +4 -7
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +16 -53
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +2 -0
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/lib/gc/index.d.ts +1 -1
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +1 -1
- package/lib/gc/index.js.map +1 -1
- package/lib/id-compressor/appendOnlySortedMap.d.ts +8 -30
- package/lib/id-compressor/appendOnlySortedMap.d.ts.map +1 -1
- package/lib/id-compressor/appendOnlySortedMap.js +25 -66
- package/lib/id-compressor/appendOnlySortedMap.js.map +1 -1
- package/lib/id-compressor/finalSpace.d.ts +29 -0
- package/lib/id-compressor/finalSpace.d.ts.map +1 -0
- package/lib/id-compressor/finalSpace.js +58 -0
- package/lib/id-compressor/finalSpace.js.map +1 -0
- package/lib/id-compressor/idCompressor.d.ts +25 -250
- package/lib/id-compressor/idCompressor.d.ts.map +1 -1
- package/lib/id-compressor/idCompressor.js +382 -1139
- package/lib/id-compressor/idCompressor.js.map +1 -1
- package/lib/id-compressor/identifiers.d.ts +32 -0
- package/lib/id-compressor/identifiers.d.ts.map +1 -0
- package/lib/id-compressor/identifiers.js +11 -0
- package/lib/id-compressor/identifiers.js.map +1 -0
- package/lib/id-compressor/index.d.ts +5 -6
- package/lib/id-compressor/index.d.ts.map +1 -1
- package/lib/id-compressor/index.js +5 -6
- package/lib/id-compressor/index.js.map +1 -1
- package/lib/id-compressor/persistanceUtilities.d.ts +22 -0
- package/lib/id-compressor/persistanceUtilities.d.ts.map +1 -0
- package/lib/id-compressor/persistanceUtilities.js +34 -0
- package/lib/id-compressor/persistanceUtilities.js.map +1 -0
- package/lib/id-compressor/sessionSpaceNormalizer.d.ts +46 -0
- package/lib/id-compressor/sessionSpaceNormalizer.d.ts.map +1 -0
- package/lib/id-compressor/sessionSpaceNormalizer.js +76 -0
- package/lib/id-compressor/sessionSpaceNormalizer.js.map +1 -0
- package/lib/id-compressor/sessions.d.ts +115 -0
- package/lib/id-compressor/sessions.d.ts.map +1 -0
- package/lib/id-compressor/sessions.js +290 -0
- package/lib/id-compressor/sessions.js.map +1 -0
- package/lib/id-compressor/utilities.d.ts +49 -0
- package/lib/id-compressor/utilities.d.ts.map +1 -0
- package/lib/id-compressor/utilities.js +148 -0
- package/lib/id-compressor/utilities.js.map +1 -0
- package/lib/index.d.ts +3 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.js +3 -3
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +2 -1
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +1 -1
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +2 -3
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +1 -0
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +7 -8
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +12 -6
- 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 +12 -5
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +21 -8
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +3 -3
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/index.d.ts +3 -3
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js +1 -1
- package/lib/summary/index.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +2 -3
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +3 -3
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +27 -4
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +240 -68
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +6 -5
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +69 -65
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts +2 -2
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.js +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/index.d.ts +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 +5 -14
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +16 -93
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +6 -30
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +0 -11
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +3 -86
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +38 -25
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +2 -3
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +2 -1
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.js +1 -1
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +10 -4
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +46 -42
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +7 -6
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +26 -18
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +30 -29
- package/src/batchTracker.ts +3 -2
- package/src/blobManager.ts +105 -185
- package/src/connectionTelemetry.ts +2 -1
- package/src/containerRuntime.ts +481 -267
- package/src/dataStore.ts +2 -3
- package/src/dataStoreContext.ts +5 -8
- package/src/dataStoreContexts.ts +2 -4
- package/src/dataStoreRegistry.ts +1 -1
- package/src/dataStores.ts +4 -7
- package/src/deltaManagerProxyBase.ts +1 -1
- package/src/deltaScheduler.ts +1 -1
- package/src/error.ts +18 -0
- package/src/gc/garbageCollection.ts +39 -41
- package/src/gc/gcConfigs.ts +4 -2
- package/src/gc/gcDefinitions.ts +4 -6
- package/src/gc/gcHelpers.ts +1 -1
- package/src/gc/gcSummaryStateTracker.ts +19 -65
- package/src/gc/gcTelemetry.ts +2 -0
- package/src/gc/gcUnreferencedStateTracker.ts +1 -1
- package/src/gc/index.ts +0 -1
- package/src/id-compressor/appendOnlySortedMap.ts +26 -87
- package/src/id-compressor/finalSpace.ts +67 -0
- package/src/id-compressor/idCompressor.ts +456 -1681
- package/src/id-compressor/identifiers.ts +42 -0
- package/src/id-compressor/index.ts +11 -20
- package/src/id-compressor/persistanceUtilities.ts +58 -0
- package/src/id-compressor/sessionSpaceNormalizer.ts +83 -0
- package/src/id-compressor/sessions.ts +405 -0
- package/src/id-compressor/utilities.ts +187 -0
- package/src/index.ts +7 -1
- package/src/opLifecycle/opCompressor.ts +3 -3
- package/src/opLifecycle/opDecompressor.ts +2 -1
- package/src/opLifecycle/opGroupingManager.ts +1 -1
- package/src/opLifecycle/opSplitter.ts +4 -4
- package/src/opLifecycle/outbox.ts +14 -11
- package/src/opLifecycle/remoteMessageProcessor.ts +19 -6
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +50 -29
- package/src/scheduleManager.ts +6 -4
- package/src/summary/index.ts +4 -3
- package/src/summary/orderedClientElection.ts +8 -5
- package/src/summary/runWhileConnectedCoordinator.ts +1 -1
- package/src/summary/runningSummarizer.ts +273 -97
- package/src/summary/summarizer.ts +23 -12
- package/src/summary/summarizerClientElection.ts +2 -2
- package/src/summary/summarizerHeuristics.ts +1 -1
- package/src/summary/summarizerNode/index.ts +1 -2
- package/src/summary/summarizerNode/summarizerNode.ts +23 -145
- package/src/summary/summarizerNode/summarizerNodeUtils.ts +7 -38
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +3 -123
- package/src/summary/summarizerTypes.ts +40 -25
- package/src/summary/summaryCollection.ts +3 -3
- package/src/summary/summaryFormat.ts +1 -1
- package/src/summary/summaryGenerator.ts +52 -55
- package/src/summary/summaryManager.ts +36 -13
- package/dist/id-compressor/idRange.d.ts +0 -11
- package/dist/id-compressor/idRange.d.ts.map +0 -1
- package/dist/id-compressor/idRange.js +0 -29
- package/dist/id-compressor/idRange.js.map +0 -1
- package/dist/id-compressor/numericUuid.d.ts +0 -59
- package/dist/id-compressor/numericUuid.d.ts.map +0 -1
- package/dist/id-compressor/numericUuid.js +0 -325
- package/dist/id-compressor/numericUuid.js.map +0 -1
- package/dist/id-compressor/sessionIdNormalizer.d.ts +0 -138
- package/dist/id-compressor/sessionIdNormalizer.d.ts.map +0 -1
- package/dist/id-compressor/sessionIdNormalizer.js +0 -483
- package/dist/id-compressor/sessionIdNormalizer.js.map +0 -1
- package/dist/id-compressor/utils.d.ts +0 -57
- package/dist/id-compressor/utils.d.ts.map +0 -1
- package/dist/id-compressor/utils.js +0 -90
- package/dist/id-compressor/utils.js.map +0 -1
- package/dist/id-compressor/uuidUtilities.d.ts +0 -28
- package/dist/id-compressor/uuidUtilities.d.ts.map +0 -1
- package/dist/id-compressor/uuidUtilities.js +0 -104
- package/dist/id-compressor/uuidUtilities.js.map +0 -1
- package/lib/id-compressor/idRange.d.ts +0 -11
- package/lib/id-compressor/idRange.d.ts.map +0 -1
- package/lib/id-compressor/idRange.js +0 -25
- package/lib/id-compressor/idRange.js.map +0 -1
- package/lib/id-compressor/numericUuid.d.ts +0 -59
- package/lib/id-compressor/numericUuid.d.ts.map +0 -1
- package/lib/id-compressor/numericUuid.js +0 -315
- package/lib/id-compressor/numericUuid.js.map +0 -1
- package/lib/id-compressor/sessionIdNormalizer.d.ts +0 -138
- package/lib/id-compressor/sessionIdNormalizer.d.ts.map +0 -1
- package/lib/id-compressor/sessionIdNormalizer.js +0 -479
- package/lib/id-compressor/sessionIdNormalizer.js.map +0 -1
- package/lib/id-compressor/utils.d.ts +0 -57
- package/lib/id-compressor/utils.d.ts.map +0 -1
- package/lib/id-compressor/utils.js +0 -79
- package/lib/id-compressor/utils.js.map +0 -1
- package/lib/id-compressor/uuidUtilities.d.ts +0 -28
- package/lib/id-compressor/uuidUtilities.d.ts.map +0 -1
- package/lib/id-compressor/uuidUtilities.js +0 -96
- package/lib/id-compressor/uuidUtilities.js.map +0 -1
- package/src/id-compressor/idRange.ts +0 -35
- package/src/id-compressor/numericUuid.ts +0 -383
- package/src/id-compressor/sessionIdNormalizer.ts +0 -609
- package/src/id-compressor/utils.ts +0 -114
- package/src/id-compressor/uuidUtilities.ts +0 -120
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
/* eslint-disable no-bitwise */
|
|
6
|
+
import { assert } from "@fluidframework/core-utils";
|
|
7
|
+
import { v4 } from "uuid";
|
|
8
|
+
const hexadecimalCharCodes = Array.from("09afAF").map((c) => c.charCodeAt(0));
|
|
9
|
+
function isHexadecimalCharacter(charCode) {
|
|
10
|
+
return ((charCode >= hexadecimalCharCodes[0] && charCode <= hexadecimalCharCodes[1]) ||
|
|
11
|
+
(charCode >= hexadecimalCharCodes[2] && charCode <= hexadecimalCharCodes[3]) ||
|
|
12
|
+
(charCode >= hexadecimalCharCodes[4] && charCode <= hexadecimalCharCodes[5]));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Generate a random session ID
|
|
16
|
+
*/
|
|
17
|
+
export function createSessionId() {
|
|
18
|
+
return assertIsStableId(v4());
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Asserts that the given string is a stable ID.
|
|
22
|
+
*/
|
|
23
|
+
export function assertIsStableId(stableId) {
|
|
24
|
+
assert(isStableId(stableId), 0x4a3 /* Expected a StableId */);
|
|
25
|
+
return stableId;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Asserts that the given string is a stable ID.
|
|
29
|
+
*/
|
|
30
|
+
export function assertIsSessionId(stableId) {
|
|
31
|
+
assertIsStableId(stableId);
|
|
32
|
+
return stableId;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generate a random stable ID
|
|
36
|
+
*/
|
|
37
|
+
export function generateStableId() {
|
|
38
|
+
return assertIsStableId(v4());
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Returns true iff the given string is a valid Version 4, variant 2 UUID
|
|
42
|
+
* 'xxxxxxxx-xxxx-4xxx-vxxx-xxxxxxxxxxxx'
|
|
43
|
+
*/
|
|
44
|
+
export function isStableId(str) {
|
|
45
|
+
if (str.length !== 36) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
for (let i = 0; i < str.length; i++) {
|
|
49
|
+
switch (i) {
|
|
50
|
+
case 8:
|
|
51
|
+
case 13:
|
|
52
|
+
case 18:
|
|
53
|
+
case 23:
|
|
54
|
+
if (str.charAt(i) !== "-") {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
58
|
+
case 14:
|
|
59
|
+
if (str.charAt(i) !== "4") {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case 19: {
|
|
64
|
+
const char = str.charAt(i);
|
|
65
|
+
if (char !== "8" && char !== "9" && char !== "a" && char !== "b") {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
default:
|
|
71
|
+
if (!isHexadecimalCharacter(str.charCodeAt(i))) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* A numeric comparator used for sorting in ascending order.
|
|
81
|
+
*
|
|
82
|
+
* Handles +/-0 like Map: -0 is equal to +0.
|
|
83
|
+
*/
|
|
84
|
+
export function compareFiniteNumbers(a, b) {
|
|
85
|
+
return a - b;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Compares strings lexically to form a strict partial ordering.
|
|
89
|
+
*/
|
|
90
|
+
export function compareStrings(a, b) {
|
|
91
|
+
return a > b ? 1 : a === b ? 0 : -1;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Compares bigints to form a strict partial ordering.
|
|
95
|
+
*/
|
|
96
|
+
export function compareBigints(a, b) {
|
|
97
|
+
return a > b ? 1 : a === b ? 0 : -1;
|
|
98
|
+
}
|
|
99
|
+
export function genCountFromLocalId(localId) {
|
|
100
|
+
return -localId;
|
|
101
|
+
}
|
|
102
|
+
export function localIdFromGenCount(genCount) {
|
|
103
|
+
return -genCount;
|
|
104
|
+
}
|
|
105
|
+
// xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
|
|
106
|
+
const versionMask = 0x4n << (19n * 4n); // Version 4
|
|
107
|
+
const variantMask = 0x8n << (15n * 4n); // Variant RFC4122 (1 0 x x)
|
|
108
|
+
const upperMask = 0xffffffffffffn << (20n * 4n);
|
|
109
|
+
// Upper mask when version/variant bits are removed
|
|
110
|
+
const strippedUpperMask = upperMask >> 6n;
|
|
111
|
+
const middieBittiesMask = 0xfffn << (16n * 4n);
|
|
112
|
+
// Middie mask when version/variant bits are removed
|
|
113
|
+
const strippedMiddieBittiesMask = middieBittiesMask >> 2n;
|
|
114
|
+
// Note: leading character should be 3 to mask at 0011
|
|
115
|
+
// The more-significant half of the N nibble is used to denote the variant (10xx)
|
|
116
|
+
const lowerMask = 0x3fffffffffffffffn;
|
|
117
|
+
export function numericUuidFromStableId(stableId) {
|
|
118
|
+
const uuidU128 = BigInt(`0x${stableId.replace(/-/g, "")}`);
|
|
119
|
+
const upperMasked = uuidU128 & upperMask;
|
|
120
|
+
const middieBittiesMasked = uuidU128 & middieBittiesMask;
|
|
121
|
+
const lowerMasked = uuidU128 & lowerMask;
|
|
122
|
+
const upperMaskedPlaced = upperMasked >> 6n;
|
|
123
|
+
const middieBittiesMaskedPlaced = middieBittiesMasked >> 2n;
|
|
124
|
+
const id = upperMaskedPlaced | middieBittiesMaskedPlaced | lowerMasked;
|
|
125
|
+
return id;
|
|
126
|
+
}
|
|
127
|
+
export function stableIdFromNumericUuid(numericUuid) {
|
|
128
|
+
// bitwise reverse transform
|
|
129
|
+
const upperMasked = (numericUuid & strippedUpperMask) << 6n;
|
|
130
|
+
const middieBittiesMasked = (numericUuid & strippedMiddieBittiesMask) << 2n;
|
|
131
|
+
const lowerMasked = numericUuid & lowerMask;
|
|
132
|
+
const uuidU128 = upperMasked | versionMask | middieBittiesMasked | variantMask | lowerMasked;
|
|
133
|
+
// Pad to 32 characters, inserting leading zeroes if needed
|
|
134
|
+
const uuidString = uuidU128.toString(16).padStart(32, "0");
|
|
135
|
+
return `${uuidString.substring(0, 8)}-${uuidString.substring(8, 12)}-${uuidString.substring(12, 16)}-${uuidString.substring(16, 20)}-${uuidString.substring(20, 32)}`;
|
|
136
|
+
}
|
|
137
|
+
export function offsetNumericUuid(numericUuid, offset) {
|
|
138
|
+
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
139
|
+
return (numericUuid + BigInt(offset));
|
|
140
|
+
}
|
|
141
|
+
export function subtractNumericUuids(a, b) {
|
|
142
|
+
return (a - b);
|
|
143
|
+
}
|
|
144
|
+
export function addNumericUuids(a, b) {
|
|
145
|
+
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
146
|
+
return (a + b);
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=utilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utilities.js","sourceRoot":"","sources":["../../src/id-compressor/utilities.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\n/* eslint-disable no-bitwise */\nimport { assert } from \"@fluidframework/core-utils\";\nimport { SessionId, StableId } from \"@fluidframework/runtime-definitions\";\nimport { v4 } from \"uuid\";\nimport { LocalCompressedId, NumericUuid } from \"./identifiers\";\n\nconst hexadecimalCharCodes = Array.from(\"09afAF\").map((c) => c.charCodeAt(0)) as [\n\tzero: number,\n\tnine: number,\n\ta: number,\n\tf: number,\n\tA: number,\n\tF: number,\n];\n\nfunction isHexadecimalCharacter(charCode: number): boolean {\n\treturn (\n\t\t(charCode >= hexadecimalCharCodes[0] && charCode <= hexadecimalCharCodes[1]) ||\n\t\t(charCode >= hexadecimalCharCodes[2] && charCode <= hexadecimalCharCodes[3]) ||\n\t\t(charCode >= hexadecimalCharCodes[4] && charCode <= hexadecimalCharCodes[5])\n\t);\n}\n\n/**\n * Generate a random session ID\n */\nexport function createSessionId(): SessionId {\n\treturn assertIsStableId(v4()) as SessionId;\n}\n\n/**\n * Asserts that the given string is a stable ID.\n */\nexport function assertIsStableId(stableId: string): StableId {\n\tassert(isStableId(stableId), 0x4a3 /* Expected a StableId */);\n\treturn stableId;\n}\n\n/**\n * Asserts that the given string is a stable ID.\n */\nexport function assertIsSessionId(stableId: string): SessionId {\n\tassertIsStableId(stableId);\n\treturn stableId as SessionId;\n}\n\n/**\n * Generate a random stable ID\n */\nexport function generateStableId(): StableId {\n\treturn assertIsStableId(v4());\n}\n\n/**\n * Returns true iff the given string is a valid Version 4, variant 2 UUID\n * 'xxxxxxxx-xxxx-4xxx-vxxx-xxxxxxxxxxxx'\n */\nexport function isStableId(str: string): str is StableId {\n\tif (str.length !== 36) {\n\t\treturn false;\n\t}\n\n\tfor (let i = 0; i < str.length; i++) {\n\t\tswitch (i) {\n\t\t\tcase 8:\n\t\t\tcase 13:\n\t\t\tcase 18:\n\t\t\tcase 23:\n\t\t\t\tif (str.charAt(i) !== \"-\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 14:\n\t\t\t\tif (str.charAt(i) !== \"4\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 19: {\n\t\t\t\tconst char = str.charAt(i);\n\t\t\t\tif (char !== \"8\" && char !== \"9\" && char !== \"a\" && char !== \"b\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tif (!isHexadecimalCharacter(str.charCodeAt(i))) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * A numeric comparator used for sorting in ascending order.\n *\n * Handles +/-0 like Map: -0 is equal to +0.\n */\nexport function compareFiniteNumbers<T extends number>(a: T, b: T): number {\n\treturn a - b;\n}\n\n/**\n * Compares strings lexically to form a strict partial ordering.\n */\nexport function compareStrings<T extends string>(a: T, b: T): number {\n\treturn a > b ? 1 : a === b ? 0 : -1;\n}\n\n/**\n * Compares bigints to form a strict partial ordering.\n */\nexport function compareBigints<T extends bigint>(a: T, b: T): number {\n\treturn a > b ? 1 : a === b ? 0 : -1;\n}\n\nexport function genCountFromLocalId(localId: LocalCompressedId): number {\n\treturn -localId;\n}\n\nexport function localIdFromGenCount(genCount: number): LocalCompressedId {\n\treturn -genCount as LocalCompressedId;\n}\n\n// xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx\nconst versionMask = 0x4n << (19n * 4n); // Version 4\nconst variantMask = 0x8n << (15n * 4n); // Variant RFC4122 (1 0 x x)\nconst upperMask = 0xffffffffffffn << (20n * 4n);\n// Upper mask when version/variant bits are removed\nconst strippedUpperMask = upperMask >> 6n;\nconst middieBittiesMask = 0xfffn << (16n * 4n);\n// Middie mask when version/variant bits are removed\nconst strippedMiddieBittiesMask = middieBittiesMask >> 2n;\n// Note: leading character should be 3 to mask at 0011\n// The more-significant half of the N nibble is used to denote the variant (10xx)\nconst lowerMask = 0x3fffffffffffffffn;\n\nexport function numericUuidFromStableId(stableId: StableId): NumericUuid {\n\tconst uuidU128 = BigInt(`0x${stableId.replace(/-/g, \"\")}`);\n\tconst upperMasked = uuidU128 & upperMask;\n\tconst middieBittiesMasked = uuidU128 & middieBittiesMask;\n\tconst lowerMasked = uuidU128 & lowerMask;\n\n\tconst upperMaskedPlaced = upperMasked >> 6n;\n\tconst middieBittiesMaskedPlaced = middieBittiesMasked >> 2n;\n\n\tconst id = upperMaskedPlaced | middieBittiesMaskedPlaced | lowerMasked;\n\treturn id as NumericUuid;\n}\n\nexport function stableIdFromNumericUuid(numericUuid: NumericUuid): StableId {\n\t// bitwise reverse transform\n\tconst upperMasked = (numericUuid & strippedUpperMask) << 6n;\n\tconst middieBittiesMasked = (numericUuid & strippedMiddieBittiesMask) << 2n;\n\tconst lowerMasked = numericUuid & lowerMask;\n\tconst uuidU128 = upperMasked | versionMask | middieBittiesMasked | variantMask | lowerMasked;\n\t// Pad to 32 characters, inserting leading zeroes if needed\n\tconst uuidString = uuidU128.toString(16).padStart(32, \"0\");\n\treturn `${uuidString.substring(0, 8)}-${uuidString.substring(8, 12)}-${uuidString.substring(\n\t\t12,\n\t\t16,\n\t)}-${uuidString.substring(16, 20)}-${uuidString.substring(20, 32)}` as StableId;\n}\n\nexport function offsetNumericUuid(numericUuid: NumericUuid, offset: number): NumericUuid {\n\t// eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n\treturn (numericUuid + BigInt(offset)) as NumericUuid;\n}\n\nexport function subtractNumericUuids(a: NumericUuid, b: NumericUuid): NumericUuid {\n\treturn (a - b) as NumericUuid;\n}\n\nexport function addNumericUuids(a: NumericUuid, b: NumericUuid): NumericUuid {\n\t// eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n\treturn (a + b) as NumericUuid;\n}\n"]}
|
package/lib/index.d.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export { ContainerMessageType, ContainerRuntimeMessage, ISummaryRuntimeOptions, ISummaryBaseConfiguration, ISummaryConfigurationHeuristics, ISummaryConfigurationDisableSummarizer, ISummaryConfigurationDisableHeuristics, IContainerRuntimeOptions, isRuntimeMessage, RuntimeMessage, agentSchedulerId, ContainerRuntime, RuntimeHeaders, AllowTombstoneRequestHeaderKey, TombstoneResponseHeaderKey, ISummaryConfiguration, DefaultSummaryConfiguration, ICompressionRuntimeOptions, CompressionAlgorithms, } from "./containerRuntime";
|
|
5
|
+
export { ContainerMessageType, ContainerRuntimeMessage, IContainerRuntimeMessageCompatDetails, CompatModeBehavior, ISummaryRuntimeOptions, ISummaryBaseConfiguration, ISummaryConfigurationHeuristics, ISummaryConfigurationDisableSummarizer, ISummaryConfigurationDisableHeuristics, IContainerRuntimeOptions, isRuntimeMessage, RuntimeMessage, agentSchedulerId, ContainerRuntime, RuntimeHeaders, AllowTombstoneRequestHeaderKey, AllowInactiveRequestHeaderKey, TombstoneResponseHeaderKey, InactiveResponseHeaderKey, ISummaryConfiguration, DefaultSummaryConfiguration, ICompressionRuntimeOptions, CompressionAlgorithms, } from "./containerRuntime";
|
|
6
6
|
export { FluidDataStoreRegistry } from "./dataStoreRegistry";
|
|
7
7
|
export { IGCRuntimeOptions, IGCStats } from "./gc";
|
|
8
|
-
export { IAckedSummary, ISummarizer, ISummarizeResults, ISummaryCancellationToken, neverCancelledSummaryToken, Summarizer, SummarizerStopReason, SummaryCollection, EnqueueSummarizeResult, IAckSummaryResult, IBaseSummarizeResult, IBroadcastSummaryResult, ICancellationToken, IConnectableRuntime, IEnqueueSummarizeOptions, IGenerateSummaryTreeResult, IGeneratedSummaryStats, INackSummaryResult, IOnDemandSummarizeOptions, IRefreshSummaryAckOptions, ISubmitSummaryOpResult, ISubmitSummaryOptions, ISummarizeOptions, ISummarizerEvents, ISummarizerInternalsProvider, ISummarizerRuntime, ISummarizingWarning, IUploadSummaryResult, SubmitSummaryResult, SummarizeResultPart, IClientSummaryWatcher, ISummary, ISummaryCollectionOpEvents, ISummaryAckMessage, ISummaryNackMessage, ISummaryOpMessage, OpActionEventListener, OpActionEventName, ICancellableSummarizerController, SubmitSummaryFailureData, SummaryStage, } from "./summary";
|
|
8
|
+
export { IAckedSummary, ISummarizer, ISummarizeResults, ISummaryCancellationToken, neverCancelledSummaryToken, Summarizer, SummarizerStopReason, SummaryCollection, EnqueueSummarizeResult, IAckSummaryResult, IBaseSummarizeResult, IBroadcastSummaryResult, ICancellationToken, IConnectableRuntime, IEnqueueSummarizeOptions, IGenerateSummaryTreeResult, IGeneratedSummaryStats, INackSummaryResult, IOnDemandSummarizeOptions, IRefreshSummaryAckOptions, ISubmitSummaryOpResult, ISubmitSummaryOptions, ISummarizeOptions, ISummarizerEvents, ISummarizerInternalsProvider, ISummarizerRuntime, ISummarizingWarning, IUploadSummaryResult, SubmitSummaryResult, SummarizeResultPart, IClientSummaryWatcher, ISummary, ISummaryCollectionOpEvents, ISummaryAckMessage, ISummaryNackMessage, ISummaryOpMessage, OpActionEventListener, OpActionEventName, ICancellableSummarizerController, SubmitSummaryFailureData, SummaryStage, IRetriableFailureResult, ISummarizeEventProps, } from "./summary";
|
|
9
|
+
export { isStableId, generateStableId, assertIsStableId } from "./id-compressor";
|
|
9
10
|
export { IChunkedOp, unpackRuntimeMessage } from "./opLifecycle";
|
|
10
|
-
export { generateStableId, isStableId, assertIsStableId } from "./id-compressor";
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,yBAAyB,EACzB,+BAA+B,EAC/B,sCAAsC,EACtC,sCAAsC,EACtC,wBAAwB,EACxB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,8BAA8B,EAC9B,0BAA0B,EAC1B,qBAAqB,EACrB,2BAA2B,EAC3B,0BAA0B,EAC1B,qBAAqB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACnD,OAAO,EACN,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,yBAAyB,EACzB,0BAA0B,EAC1B,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EACzB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,4BAA4B,EAC5B,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,QAAQ,EACR,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,gCAAgC,EAChC,wBAAwB,EACxB,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,oBAAoB,EACpB,uBAAuB,EACvB,qCAAqC,EACrC,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,EACzB,+BAA+B,EAC/B,sCAAsC,EACtC,sCAAsC,EACtC,wBAAwB,EACxB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,8BAA8B,EAC9B,6BAA6B,EAC7B,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,2BAA2B,EAC3B,0BAA0B,EAC1B,qBAAqB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACnD,OAAO,EACN,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,yBAAyB,EACzB,0BAA0B,EAC1B,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EACzB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,4BAA4B,EAC5B,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,QAAQ,EACR,0BAA0B,EAC1B,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,iBAAiB,EACjB,gCAAgC,EAChC,wBAAwB,EACxB,YAAY,EACZ,uBAAuB,EACvB,oBAAoB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export { ContainerMessageType, isRuntimeMessage, RuntimeMessage, agentSchedulerId, ContainerRuntime, RuntimeHeaders, AllowTombstoneRequestHeaderKey, TombstoneResponseHeaderKey, DefaultSummaryConfiguration, CompressionAlgorithms, } from "./containerRuntime";
|
|
5
|
+
export { ContainerMessageType, isRuntimeMessage, RuntimeMessage, agentSchedulerId, ContainerRuntime, RuntimeHeaders, AllowTombstoneRequestHeaderKey, AllowInactiveRequestHeaderKey, TombstoneResponseHeaderKey, InactiveResponseHeaderKey, DefaultSummaryConfiguration, CompressionAlgorithms, } from "./containerRuntime";
|
|
6
6
|
export { FluidDataStoreRegistry } from "./dataStoreRegistry";
|
|
7
7
|
export { neverCancelledSummaryToken, Summarizer, SummaryCollection, } from "./summary";
|
|
8
|
+
export { isStableId, generateStableId, assertIsStableId } from "./id-compressor";
|
|
8
9
|
export { unpackRuntimeMessage } from "./opLifecycle";
|
|
9
|
-
export { generateStableId, isStableId, assertIsStableId } from "./id-compressor";
|
|
10
10
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,oBAAoB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,oBAAoB,EAUpB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,8BAA8B,EAC9B,6BAA6B,EAC7B,0BAA0B,EAC1B,yBAAyB,EAEzB,2BAA2B,EAE3B,qBAAqB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,EAKN,0BAA0B,EAC1B,UAAU,EAEV,iBAAiB,GAoCjB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACjF,OAAO,EAAc,oBAAoB,EAAE,MAAM,eAAe,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n\tContainerMessageType,\n\tContainerRuntimeMessage,\n\tIContainerRuntimeMessageCompatDetails,\n\tCompatModeBehavior,\n\tISummaryRuntimeOptions,\n\tISummaryBaseConfiguration,\n\tISummaryConfigurationHeuristics,\n\tISummaryConfigurationDisableSummarizer,\n\tISummaryConfigurationDisableHeuristics,\n\tIContainerRuntimeOptions,\n\tisRuntimeMessage,\n\tRuntimeMessage,\n\tagentSchedulerId,\n\tContainerRuntime,\n\tRuntimeHeaders,\n\tAllowTombstoneRequestHeaderKey,\n\tAllowInactiveRequestHeaderKey,\n\tTombstoneResponseHeaderKey,\n\tInactiveResponseHeaderKey,\n\tISummaryConfiguration,\n\tDefaultSummaryConfiguration,\n\tICompressionRuntimeOptions,\n\tCompressionAlgorithms,\n} from \"./containerRuntime\";\nexport { FluidDataStoreRegistry } from \"./dataStoreRegistry\";\nexport { IGCRuntimeOptions, IGCStats } from \"./gc\";\nexport {\n\tIAckedSummary,\n\tISummarizer,\n\tISummarizeResults,\n\tISummaryCancellationToken,\n\tneverCancelledSummaryToken,\n\tSummarizer,\n\tSummarizerStopReason,\n\tSummaryCollection,\n\tEnqueueSummarizeResult,\n\tIAckSummaryResult,\n\tIBaseSummarizeResult,\n\tIBroadcastSummaryResult,\n\tICancellationToken,\n\tIConnectableRuntime,\n\tIEnqueueSummarizeOptions,\n\tIGenerateSummaryTreeResult,\n\tIGeneratedSummaryStats,\n\tINackSummaryResult,\n\tIOnDemandSummarizeOptions,\n\tIRefreshSummaryAckOptions,\n\tISubmitSummaryOpResult,\n\tISubmitSummaryOptions,\n\tISummarizeOptions,\n\tISummarizerEvents,\n\tISummarizerInternalsProvider,\n\tISummarizerRuntime,\n\tISummarizingWarning,\n\tIUploadSummaryResult,\n\tSubmitSummaryResult,\n\tSummarizeResultPart,\n\tIClientSummaryWatcher,\n\tISummary,\n\tISummaryCollectionOpEvents,\n\tISummaryAckMessage,\n\tISummaryNackMessage,\n\tISummaryOpMessage,\n\tOpActionEventListener,\n\tOpActionEventName,\n\tICancellableSummarizerController,\n\tSubmitSummaryFailureData,\n\tSummaryStage,\n\tIRetriableFailureResult,\n\tISummarizeEventProps,\n} from \"./summary\";\nexport { isStableId, generateStableId, assertIsStableId } from \"./id-compressor\";\nexport { IChunkedOp, unpackRuntimeMessage } from \"./opLifecycle\";\n"]}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { createChildLogger } from "@fluidframework/telemetry-utils";
|
|
6
|
-
import { assert
|
|
7
|
-
import {
|
|
5
|
+
import { createChildLogger, UsageError } from "@fluidframework/telemetry-utils";
|
|
6
|
+
import { assert } from "@fluidframework/core-utils";
|
|
7
|
+
import { IsoBuffer } from "@fluid-internal/client-utils";
|
|
8
8
|
import { compress } from "lz4js";
|
|
9
9
|
import { CompressionAlgorithms } from "../containerRuntime";
|
|
10
10
|
import { estimateSocketSize } from "./batchManager";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opCompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opCompressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"opCompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opCompressor.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 { createChildLogger, UsageError } from \"@fluidframework/telemetry-utils\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport { IsoBuffer } from \"@fluid-internal/client-utils\";\nimport { compress } from \"lz4js\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { CompressionAlgorithms } from \"../containerRuntime\";\nimport { estimateSocketSize } from \"./batchManager\";\nimport { IBatch, BatchMessage } from \"./definitions\";\n\n/**\n * Compresses batches of ops. It generates a single compressed op that contains\n * the contents of each op in the batch. It then submits empty ops for each original\n * op to reserve sequence numbers.\n */\nexport class OpCompressor {\n\tprivate readonly logger;\n\n\tconstructor(logger: ITelemetryBaseLogger) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpCompressor\" });\n\t}\n\n\tpublic compressBatch(batch: IBatch): IBatch {\n\t\tassert(\n\t\t\tbatch.contentSizeInBytes > 0 && batch.content.length > 0,\n\t\t\t0x5a4 /* Batch should not be empty */,\n\t\t);\n\n\t\tconst compressionStart = Date.now();\n\t\tconst contentsAsBuffer = new TextEncoder().encode(this.serializeBatch(batch));\n\t\tconst compressedContents = compress(contentsAsBuffer);\n\t\tconst compressedContent = IsoBuffer.from(compressedContents).toString(\"base64\");\n\t\tconst duration = Date.now() - compressionStart;\n\n\t\tconst messages: BatchMessage[] = [];\n\t\tmessages.push({\n\t\t\t...batch.content[0],\n\t\t\tcontents: JSON.stringify({ packedContents: compressedContent }),\n\t\t\tmetadata: batch.content[0].metadata,\n\t\t\tcompression: CompressionAlgorithms.lz4,\n\t\t});\n\n\t\t// Add empty placeholder messages to reserve the sequence numbers\n\t\tfor (const message of batch.content.slice(1)) {\n\t\t\tmessages.push({\n\t\t\t\ttype: message.type,\n\t\t\t\tlocalOpMetadata: message.localOpMetadata,\n\t\t\t\tmetadata: message.metadata,\n\t\t\t\treferenceSequenceNumber: message.referenceSequenceNumber,\n\t\t\t});\n\t\t}\n\n\t\tconst compressedBatch: IBatch = {\n\t\t\tcontentSizeInBytes: compressedContent.length,\n\t\t\tcontent: messages,\n\t\t\treferenceSequenceNumber: batch.referenceSequenceNumber,\n\t\t};\n\n\t\tif (batch.contentSizeInBytes > 200000) {\n\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\teventName: \"CompressedBatch\",\n\t\t\t\tduration,\n\t\t\t\tsizeBeforeCompression: batch.contentSizeInBytes,\n\t\t\t\tsizeAfterCompression: compressedBatch.contentSizeInBytes,\n\t\t\t\topCount: compressedBatch.content.length,\n\t\t\t\tsocketSize: estimateSocketSize(compressedBatch),\n\t\t\t});\n\t\t}\n\n\t\treturn compressedBatch;\n\t}\n\n\tprivate serializeBatch(batch: IBatch): string {\n\t\ttry {\n\t\t\treturn `[${batch.content.map((message) => message.contents).join(\",\")}]`;\n\t\t} catch (e: any) {\n\t\t\tif (e.message === \"Invalid string length\") {\n\t\t\t\t// This is how JSON.stringify signals that\n\t\t\t\t// the content size exceeds its capacity\n\t\t\t\tconst error = new UsageError(\"Payload too large\");\n\t\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"BatchTooLarge\",\n\t\t\t\t\t\tsize: batch.contentSizeInBytes,\n\t\t\t\t\t\tlength: batch.content.length,\n\t\t\t\t\t},\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tthrow e;\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opDecompressor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opDecompressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"opDecompressor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opDecompressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAIjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AASzD;;;;;;;GAOG;AACH,qBAAa,cAAc;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,mBAAmB,CAAkB;IAC7C,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAEZ,MAAM,EAAE,oBAAoB;IAIjC,cAAc,CAAC,OAAO,EAAE,yBAAyB,GAAG,wBAAwB;IAqGnF,OAAO,CAAC,YAAY;CA2CpB"}
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { decompress } from "lz4js";
|
|
6
|
-
import { assert
|
|
6
|
+
import { assert } from "@fluidframework/core-utils";
|
|
7
|
+
import { IsoBuffer, Uint8ArrayToString } from "@fluid-internal/client-utils";
|
|
7
8
|
import { createChildLogger } from "@fluidframework/telemetry-utils";
|
|
8
9
|
import { CompressionAlgorithms } from "../containerRuntime";
|
|
9
10
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opDecompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opDecompressor.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 { decompress } from \"lz4js\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { assert, IsoBuffer, Uint8ArrayToString } from \"@fluidframework/common-utils\";\nimport { createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { CompressionAlgorithms } from \"../containerRuntime\";\nimport { IBatchMetadata } from \"../metadata\";\nimport { IMessageProcessingResult } from \"./definitions\";\n\n/**\n * Compression makes assumptions about the shape of message contents. This interface codifies those assumptions, but does not validate them.\n */\ninterface IPackedContentsContents {\n\tpackedContents: string;\n}\n\n/**\n * State machine that \"unrolls\" contents of compressed batches of ops after decompressing them.\n * This class relies on some implicit contracts defined below:\n * 1. A compressed batch will have its first message with batch metadata set to true and compressed set to true\n * 2. Messages in the middle of a compressed batch will have neither batch metadata nor the compression property set\n * 3. The final message of a batch will have batch metadata set to false\n * 4. An individually compressed op will have undefined batch metadata and compression set to true\n */\nexport class OpDecompressor {\n\tprivate activeBatch = false;\n\tprivate rootMessageContents: any | undefined;\n\tprivate processedCount = 0;\n\tprivate readonly logger;\n\n\tconstructor(logger: ITelemetryBaseLogger) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpDecompressor\" });\n\t}\n\n\tpublic processMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {\n\t\tassert(\n\t\t\tmessage.compression === undefined || message.compression === CompressionAlgorithms.lz4,\n\t\t\t0x511 /* Only lz4 compression is supported */,\n\t\t);\n\n\t\tif (\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === true &&\n\t\t\tthis.isCompressed(message)\n\t\t) {\n\t\t\t// Beginning of a compressed batch\n\t\t\tassert(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);\n\t\t\tif (message.compression) {\n\t\t\t\t// lz4 is the only supported compression algorithm for now\n\t\t\t\tassert(\n\t\t\t\t\tmessage.compression === CompressionAlgorithms.lz4,\n\t\t\t\t\t0x4b9 /* lz4 is currently the only supported compression algorithm */,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.activeBatch = true;\n\n\t\t\tconst contents = IsoBuffer.from(\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\"base64\",\n\t\t\t);\n\t\t\tconst decompressedMessage = decompress(contents);\n\t\t\tconst intoString = Uint8ArrayToString(decompressedMessage);\n\t\t\tconst asObj = JSON.parse(intoString);\n\t\t\tthis.rootMessageContents = asObj;\n\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, this.rootMessageContents[this.processedCount++]),\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\tthis.rootMessageContents !== undefined &&\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === undefined &&\n\t\t\tthis.activeBatch\n\t\t) {\n\t\t\tassert(message.contents === undefined, 0x512 /* Expecting empty message */);\n\n\t\t\t// Continuation of compressed batch\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, this.rootMessageContents[this.processedCount++]),\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\tthis.rootMessageContents !== undefined &&\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === false\n\t\t) {\n\t\t\t// End of compressed batch\n\t\t\tconst returnMessage = newMessage(\n\t\t\t\tmessage,\n\t\t\t\tthis.rootMessageContents[this.processedCount++],\n\t\t\t);\n\n\t\t\tthis.activeBatch = false;\n\t\t\tthis.rootMessageContents = undefined;\n\t\t\tthis.processedCount = 0;\n\n\t\t\treturn {\n\t\t\t\tmessage: returnMessage,\n\t\t\t\tstate: \"Processed\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === undefined &&\n\t\t\tthis.isCompressed(message)\n\t\t) {\n\t\t\t// Single compressed message\n\t\t\tassert(\n\t\t\t\tthis.activeBatch === false,\n\t\t\t\t0x4ba /* shouldn't receive compressed message in middle of a batch */,\n\t\t\t);\n\n\t\t\tconst contents = IsoBuffer.from(\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\"base64\",\n\t\t\t);\n\t\t\tconst decompressedMessage = decompress(contents);\n\t\t\tconst intoString = new TextDecoder().decode(decompressedMessage);\n\t\t\tconst asObj = JSON.parse(intoString);\n\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, asObj[0]),\n\t\t\t\tstate: \"Processed\",\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tmessage,\n\t\t\tstate: \"Skipped\",\n\t\t};\n\t}\n\n\tprivate isCompressed(message: ISequencedDocumentMessage) {\n\t\tif (message.compression === CompressionAlgorithms.lz4) {\n\t\t\treturn true;\n\t\t}\n\n\t\t/**\n\t\t * Back-compat self healing mechanism for ADO:3538, as loaders from\n\t\t * version client_v2.0.0-internal.1.2.0 to client_v2.0.0-internal.2.2.0 do not\n\t\t * support adding the proper compression metadata to compressed messages submitted\n\t\t * by the runtime. Should be removed after the loader reaches sufficient saturation\n\t\t * for a version greater or equal than client_v2.0.0-internal.2.2.0.\n\t\t *\n\t\t * The condition holds true for compressed messages, regardless of metadata. We are ultimately\n\t\t * looking for a message with a single property `packedContents` inside `contents`, of type 'string'\n\t\t * with a base64 encoded value.\n\t\t */\n\t\ttry {\n\t\t\tif (\n\t\t\t\tmessage.contents !== null &&\n\t\t\t\ttypeof message.contents === \"object\" &&\n\t\t\t\tObject.keys(message.contents).length === 1 &&\n\t\t\t\ttypeof (message.contents as { packedContents?: unknown }).packedContents ===\n\t\t\t\t\t\"string\" &&\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents.length > 0 &&\n\t\t\t\tIsoBuffer.from(\n\t\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\t\"base64\",\n\t\t\t\t).toString(\"base64\") ===\n\t\t\t\t\t(message.contents as IPackedContentsContents).packedContents\n\t\t\t) {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"LegacyCompression\",\n\t\t\t\t\ttype: message.type,\n\t\t\t\t\tbatch: (message.metadata as IBatchMetadata | undefined)?.batch,\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn false;\n\t}\n}\n\n// We should not be mutating the input message nor its metadata\nconst newMessage = (\n\toriginalMessage: ISequencedDocumentMessage,\n\tcontents: any,\n): ISequencedDocumentMessage => ({\n\t...originalMessage,\n\tcontents,\n\tcompression: undefined,\n\t// TODO: It should already be the case that we're not modifying any metadata, not clear if/why this shallow clone should be required.\n\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n\tmetadata: { ...(originalMessage.metadata as any) },\n});\n"]}
|
|
1
|
+
{"version":3,"file":"opDecompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opDecompressor.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 { decompress } from \"lz4js\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport { IsoBuffer, Uint8ArrayToString } from \"@fluid-internal/client-utils\";\nimport { createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { CompressionAlgorithms } from \"../containerRuntime\";\nimport { IBatchMetadata } from \"../metadata\";\nimport { IMessageProcessingResult } from \"./definitions\";\n\n/**\n * Compression makes assumptions about the shape of message contents. This interface codifies those assumptions, but does not validate them.\n */\ninterface IPackedContentsContents {\n\tpackedContents: string;\n}\n\n/**\n * State machine that \"unrolls\" contents of compressed batches of ops after decompressing them.\n * This class relies on some implicit contracts defined below:\n * 1. A compressed batch will have its first message with batch metadata set to true and compressed set to true\n * 2. Messages in the middle of a compressed batch will have neither batch metadata nor the compression property set\n * 3. The final message of a batch will have batch metadata set to false\n * 4. An individually compressed op will have undefined batch metadata and compression set to true\n */\nexport class OpDecompressor {\n\tprivate activeBatch = false;\n\tprivate rootMessageContents: any | undefined;\n\tprivate processedCount = 0;\n\tprivate readonly logger;\n\n\tconstructor(logger: ITelemetryBaseLogger) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpDecompressor\" });\n\t}\n\n\tpublic processMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {\n\t\tassert(\n\t\t\tmessage.compression === undefined || message.compression === CompressionAlgorithms.lz4,\n\t\t\t0x511 /* Only lz4 compression is supported */,\n\t\t);\n\n\t\tif (\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === true &&\n\t\t\tthis.isCompressed(message)\n\t\t) {\n\t\t\t// Beginning of a compressed batch\n\t\t\tassert(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);\n\t\t\tif (message.compression) {\n\t\t\t\t// lz4 is the only supported compression algorithm for now\n\t\t\t\tassert(\n\t\t\t\t\tmessage.compression === CompressionAlgorithms.lz4,\n\t\t\t\t\t0x4b9 /* lz4 is currently the only supported compression algorithm */,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.activeBatch = true;\n\n\t\t\tconst contents = IsoBuffer.from(\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\"base64\",\n\t\t\t);\n\t\t\tconst decompressedMessage = decompress(contents);\n\t\t\tconst intoString = Uint8ArrayToString(decompressedMessage);\n\t\t\tconst asObj = JSON.parse(intoString);\n\t\t\tthis.rootMessageContents = asObj;\n\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, this.rootMessageContents[this.processedCount++]),\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\tthis.rootMessageContents !== undefined &&\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === undefined &&\n\t\t\tthis.activeBatch\n\t\t) {\n\t\t\tassert(message.contents === undefined, 0x512 /* Expecting empty message */);\n\n\t\t\t// Continuation of compressed batch\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, this.rootMessageContents[this.processedCount++]),\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\tthis.rootMessageContents !== undefined &&\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === false\n\t\t) {\n\t\t\t// End of compressed batch\n\t\t\tconst returnMessage = newMessage(\n\t\t\t\tmessage,\n\t\t\t\tthis.rootMessageContents[this.processedCount++],\n\t\t\t);\n\n\t\t\tthis.activeBatch = false;\n\t\t\tthis.rootMessageContents = undefined;\n\t\t\tthis.processedCount = 0;\n\n\t\t\treturn {\n\t\t\t\tmessage: returnMessage,\n\t\t\t\tstate: \"Processed\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\t(message.metadata as IBatchMetadata | undefined)?.batch === undefined &&\n\t\t\tthis.isCompressed(message)\n\t\t) {\n\t\t\t// Single compressed message\n\t\t\tassert(\n\t\t\t\tthis.activeBatch === false,\n\t\t\t\t0x4ba /* shouldn't receive compressed message in middle of a batch */,\n\t\t\t);\n\n\t\t\tconst contents = IsoBuffer.from(\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\"base64\",\n\t\t\t);\n\t\t\tconst decompressedMessage = decompress(contents);\n\t\t\tconst intoString = new TextDecoder().decode(decompressedMessage);\n\t\t\tconst asObj = JSON.parse(intoString);\n\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, asObj[0]),\n\t\t\t\tstate: \"Processed\",\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tmessage,\n\t\t\tstate: \"Skipped\",\n\t\t};\n\t}\n\n\tprivate isCompressed(message: ISequencedDocumentMessage) {\n\t\tif (message.compression === CompressionAlgorithms.lz4) {\n\t\t\treturn true;\n\t\t}\n\n\t\t/**\n\t\t * Back-compat self healing mechanism for ADO:3538, as loaders from\n\t\t * version client_v2.0.0-internal.1.2.0 to client_v2.0.0-internal.2.2.0 do not\n\t\t * support adding the proper compression metadata to compressed messages submitted\n\t\t * by the runtime. Should be removed after the loader reaches sufficient saturation\n\t\t * for a version greater or equal than client_v2.0.0-internal.2.2.0.\n\t\t *\n\t\t * The condition holds true for compressed messages, regardless of metadata. We are ultimately\n\t\t * looking for a message with a single property `packedContents` inside `contents`, of type 'string'\n\t\t * with a base64 encoded value.\n\t\t */\n\t\ttry {\n\t\t\tif (\n\t\t\t\tmessage.contents !== null &&\n\t\t\t\ttypeof message.contents === \"object\" &&\n\t\t\t\tObject.keys(message.contents).length === 1 &&\n\t\t\t\ttypeof (message.contents as { packedContents?: unknown }).packedContents ===\n\t\t\t\t\t\"string\" &&\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents.length > 0 &&\n\t\t\t\tIsoBuffer.from(\n\t\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\t\"base64\",\n\t\t\t\t).toString(\"base64\") ===\n\t\t\t\t\t(message.contents as IPackedContentsContents).packedContents\n\t\t\t) {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"LegacyCompression\",\n\t\t\t\t\ttype: message.type,\n\t\t\t\t\tbatch: (message.metadata as IBatchMetadata | undefined)?.batch,\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch (err) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn false;\n\t}\n}\n\n// We should not be mutating the input message nor its metadata\nconst newMessage = (\n\toriginalMessage: ISequencedDocumentMessage,\n\tcontents: any,\n): ISequencedDocumentMessage => ({\n\t...originalMessage,\n\tcontents,\n\tcompression: undefined,\n\t// TODO: It should already be the case that we're not modifying any metadata, not clear if/why this shallow clone should be required.\n\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n\tmetadata: { ...(originalMessage.metadata as any) },\n});\n"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { assert } from "@fluidframework/
|
|
5
|
+
import { assert } from "@fluidframework/core-utils";
|
|
6
6
|
export class OpGroupingManager {
|
|
7
7
|
constructor(groupedBatchingEnabled) {
|
|
8
8
|
this.groupedBatchingEnabled = groupedBatchingEnabled;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opGroupingManager.js","sourceRoot":"","sources":["../../src/opLifecycle/opGroupingManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"opGroupingManager.js","sourceRoot":"","sources":["../../src/opLifecycle/opGroupingManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAmBpD,MAAM,OAAO,iBAAiB;IAG7B,YAA6B,sBAA+B;QAA/B,2BAAsB,GAAtB,sBAAsB,CAAS;IAAG,CAAC;IAEzD,UAAU,CAAC,KAAa;QAC9B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,EAAE;YAC7D,OAAO,KAAK,CAAC;SACb;QAED,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE;YACpC,IAAI,OAAO,CAAC,QAAQ,EAAE;gBACrB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBAC3C,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,CAAC,oCAAoC,CAAC,CAAC;gBACpE,MAAM,CACL,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EACxC,KAAK,CAAC,4BAA4B,CAClC,CAAC;aACF;SACD;QAED,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC;YACxC,IAAI,EAAE,iBAAiB,CAAC,cAAc;YACtC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAkB,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC1D,QAAQ,EAAE,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;gBACnF,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,WAAW,EAAE,OAAO,CAAC,WAAW;aAChC,CAAC,CAAC;SACH,CAAC,CAAC;QAEH,MAAM,YAAY,GAAW;YAC5B,GAAG,KAAK;YACR,OAAO,EAAE;gBACR;oBACC,eAAe,EAAE,SAAS;oBAC1B,QAAQ,EAAE,SAAS;oBACnB,uBAAuB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,uBAAuB;oBACjE,QAAQ,EAAE,iBAAiB;oBAC3B,IAAI,EAAE,iBAAiB,CAAC,cAAsC;iBAC9D;aACD;SACD,CAAC;QACF,OAAO,YAAY,CAAC;IACrB,CAAC;IAEM,SAAS,CAAC,EAA6B;QAC7C,IACE,EAAE,CAAC,QAA2C,EAAE,IAAI;YACrD,iBAAiB,CAAC,cAAc,EAC/B;YACD,OAAO,CAAC,EAAE,CAAC,CAAC;SACZ;QAED,MAAM,QAAQ,GAAI,EAAE,CAAC,QAAyC,CAAC,QAAQ,CAAC;QACxE,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YACpC,GAAG,EAAE;YACL,oBAAoB,EAAE,OAAO,EAAE;YAC/B,QAAQ,EAAE,UAAU,CAAC,QAAQ;YAC7B,QAAQ,EAAE,UAAU,CAAC,QAAQ;YAC7B,WAAW,EAAE,UAAU,CAAC,WAAW;SACnC,CAAC,CAAC,CAAC;IACL,CAAC;;AA7De,gCAAc,GAAG,cAAc,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { ContainerMessageType } from \"..\";\nimport { IBatch } from \"./definitions\";\n\n/**\n * Grouping makes assumptions about the shape of message contents. This interface codifies those assumptions, but does not validate them.\n */\ninterface IGroupedBatchMessageContents {\n\ttype: typeof OpGroupingManager.groupedBatchOp;\n\tcontents: IGroupedMessage[];\n}\n\ninterface IGroupedMessage {\n\tcontents?: unknown;\n\tmetadata?: Record<string, unknown>;\n\tcompression?: string;\n}\n\nexport class OpGroupingManager {\n\tstatic readonly groupedBatchOp = \"groupedBatch\";\n\n\tconstructor(private readonly groupedBatchingEnabled: boolean) {}\n\n\tpublic groupBatch(batch: IBatch): IBatch {\n\t\tif (batch.content.length < 2 || !this.groupedBatchingEnabled) {\n\t\t\treturn batch;\n\t\t}\n\n\t\tfor (const message of batch.content) {\n\t\t\tif (message.metadata) {\n\t\t\t\tconst keys = Object.keys(message.metadata);\n\t\t\t\tassert(keys.length < 2, 0x5dd /* cannot group ops with metadata */);\n\t\t\t\tassert(\n\t\t\t\t\tkeys.length === 0 || keys[0] === \"batch\",\n\t\t\t\t\t0x5de /* unexpected op metadata */,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst serializedContent = JSON.stringify({\n\t\t\ttype: OpGroupingManager.groupedBatchOp,\n\t\t\tcontents: batch.content.map<IGroupedMessage>((message) => ({\n\t\t\t\tcontents: message.contents === undefined ? undefined : JSON.parse(message.contents),\n\t\t\t\tmetadata: message.metadata,\n\t\t\t\tcompression: message.compression,\n\t\t\t})),\n\t\t});\n\n\t\tconst groupedBatch: IBatch = {\n\t\t\t...batch,\n\t\t\tcontent: [\n\t\t\t\t{\n\t\t\t\t\tlocalOpMetadata: undefined,\n\t\t\t\t\tmetadata: undefined,\n\t\t\t\t\treferenceSequenceNumber: batch.content[0].referenceSequenceNumber,\n\t\t\t\t\tcontents: serializedContent,\n\t\t\t\t\ttype: OpGroupingManager.groupedBatchOp as ContainerMessageType,\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t\treturn groupedBatch;\n\t}\n\n\tpublic ungroupOp(op: ISequencedDocumentMessage): ISequencedDocumentMessage[] {\n\t\tif (\n\t\t\t(op.contents as { type?: unknown } | undefined)?.type !==\n\t\t\tOpGroupingManager.groupedBatchOp\n\t\t) {\n\t\t\treturn [op];\n\t\t}\n\n\t\tconst messages = (op.contents as IGroupedBatchMessageContents).contents;\n\t\tlet fakeCsn = 1;\n\t\treturn messages.map((subMessage) => ({\n\t\t\t...op,\n\t\t\tclientSequenceNumber: fakeCsn++,\n\t\t\tcontents: subMessage.contents,\n\t\t\tmetadata: subMessage.metadata,\n\t\t\tcompression: subMessage.compression,\n\t\t}));\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opSplitter.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"opSplitter.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAE3F;;GAEG;AACH,qBAAa,UAAU;IAOrB,OAAO,CAAC,QAAQ,CAAC,aAAa;aAGd,gBAAgB,EAAE,MAAM;IACxC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IATrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAGvB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,EACX,aAAa,EAC3B,CAAC,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,uBAAuB,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,GACtE,SAAS,EACI,gBAAgB,EAAE,MAAM,EACvB,mBAAmB,EAAE,MAAM,EAC5C,MAAM,EAAE,oBAAoB;IAM7B,IAAW,sBAAsB,IAAI,OAAO,CAE3C;IAED,IAAW,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAEjD;IAEM,oBAAoB,CAAC,OAAO,EAAE,yBAAyB,GAAG,wBAAwB;IAsClF,kBAAkB,CAAC,QAAQ,EAAE,MAAM;IAM1C,OAAO,CAAC,QAAQ;IA0BhB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACI,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAkEpD;AAoBD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,OAAO,OACf,YAAY,oBACE,MAAM,YACf,OAAO,KACd,UAAU,EAqCZ,CAAC"}
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { createChildLogger } from "@fluidframework/telemetry-utils";
|
|
6
|
-
import { assert } from "@fluidframework/
|
|
7
|
-
import { DataCorruptionError, extractSafePropertiesFromMessage, } from "@fluidframework/container-utils";
|
|
5
|
+
import { createChildLogger, DataCorruptionError, extractSafePropertiesFromMessage, } from "@fluidframework/telemetry-utils";
|
|
6
|
+
import { assert } from "@fluidframework/core-utils";
|
|
8
7
|
import { ContainerMessageType } from "../containerRuntime";
|
|
9
8
|
import { estimateSocketSize } from "./batchManager";
|
|
10
9
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opSplitter.js","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.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 { createChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IBatchMessage } from \"@fluidframework/container-definitions\";\nimport {\n\tDataCorruptionError,\n\textractSafePropertiesFromMessage,\n} from \"@fluidframework/container-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { ContainerMessageType, ContainerRuntimeMessage } from \"../containerRuntime\";\nimport { estimateSocketSize } from \"./batchManager\";\nimport { BatchMessage, IBatch, IChunkedOp, IMessageProcessingResult } from \"./definitions\";\n\n/**\n * Responsible for creating and reconstructing chunked messages.\n */\nexport class OpSplitter {\n\t// Local copy of incomplete received chunks.\n\tprivate readonly chunkMap: Map<string, string[]>;\n\tprivate readonly logger;\n\n\tconstructor(\n\t\tchunks: [string, string[]][],\n\t\tprivate readonly submitBatchFn:\n\t\t\t| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)\n\t\t\t| undefined,\n\t\tpublic readonly chunkSizeInBytes: number,\n\t\tprivate readonly maxBatchSizeInBytes: number,\n\t\tlogger: ITelemetryBaseLogger,\n\t) {\n\t\tthis.chunkMap = new Map<string, string[]>(chunks);\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpSplitter\" });\n\t}\n\n\tpublic get isBatchChunkingEnabled(): boolean {\n\t\treturn this.chunkSizeInBytes < Number.POSITIVE_INFINITY && this.submitBatchFn !== undefined;\n\t}\n\n\tpublic get chunks(): ReadonlyMap<string, string[]> {\n\t\treturn this.chunkMap;\n\t}\n\n\tpublic processRemoteMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {\n\t\tif (message.type !== ContainerMessageType.ChunkedOp) {\n\t\t\treturn {\n\t\t\t\tmessage,\n\t\t\t\tstate: \"Skipped\",\n\t\t\t};\n\t\t}\n\n\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\t\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n\t\tconst clientId = message.clientId as string;\n\t\tconst chunkedContent = message.contents as IChunkedOp;\n\t\tthis.addChunk(clientId, chunkedContent, message);\n\n\t\tif (chunkedContent.chunkId < chunkedContent.totalChunks) {\n\t\t\t// We are processing the op in chunks but haven't reached\n\t\t\t// the last chunk yet in order to reconstruct the original op\n\t\t\treturn {\n\t\t\t\tmessage,\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst serializedContent = this.chunkMap.get(clientId)!.join(\"\");\n\t\tthis.clearPartialChunks(clientId);\n\n\t\tconst newMessage = { ...message };\n\t\tnewMessage.contents = serializedContent === \"\" ? undefined : JSON.parse(serializedContent);\n\t\tnewMessage.type = chunkedContent.originalType;\n\t\tnewMessage.metadata = chunkedContent.originalMetadata;\n\t\tnewMessage.compression = chunkedContent.originalCompression;\n\t\treturn {\n\t\t\tmessage: newMessage,\n\t\t\tstate: \"Processed\",\n\t\t};\n\t}\n\n\tpublic clearPartialChunks(clientId: string) {\n\t\tif (this.chunkMap.has(clientId)) {\n\t\t\tthis.chunkMap.delete(clientId);\n\t\t}\n\t}\n\n\tprivate addChunk(\n\t\tclientId: string,\n\t\tchunkedContent: IChunkedOp,\n\t\toriginalMessage: ISequencedDocumentMessage,\n\t) {\n\t\tlet map = this.chunkMap.get(clientId);\n\t\tif (map === undefined) {\n\t\t\tmap = [];\n\t\t\tthis.chunkMap.set(clientId, map);\n\t\t}\n\n\t\tif (chunkedContent.chunkId !== map.length + 1) {\n\t\t\t// We are expecting the chunks to be processed sequentially, in the same order as they are sent.\n\t\t\t// Therefore, the chunkId of the incoming op needs to match the length of the array (1-based indexing)\n\t\t\t// holding the existing chunks for that particular clientId.\n\t\t\tthrow new DataCorruptionError(\"Chunk Id mismatch\", {\n\t\t\t\t...extractSafePropertiesFromMessage(originalMessage),\n\t\t\t\tchunkMapLength: map.length,\n\t\t\t\tchunkId: chunkedContent.chunkId,\n\t\t\t\ttotalChunks: chunkedContent.totalChunks,\n\t\t\t});\n\t\t}\n\n\t\tmap.push(chunkedContent.contents);\n\t}\n\n\t/**\n\t * Splits the first op of a compressed batch in chunks, sends the chunks separately and\n\t * returns a new batch composed of the last chunk and the rest of the ops in the original batch.\n\t *\n\t * A compressed batch is formed by one large op at the first position, followed by a series of placeholder ops\n\t * which are used in order to reserve the sequence numbers for when the first op gets unrolled into the original\n\t * uncompressed ops at ingestion in the runtime.\n\t *\n\t * If the first op is too large, it can be chunked (split into smaller op) which can be sent individually over the wire\n\t * and accumulate at ingestion, until the last op in the chunk is processed, when the original op is unrolled.\n\t *\n\t * This method will send the first N - 1 chunks separately and use the last chunk as the first message in the result batch\n\t * and then appends the original placeholder ops. This will ensure that the batch semantics of the original (non-compressed) batch\n\t * are preserved, as the original chunked op will be unrolled by the runtime when the first message in the batch is processed\n\t * (as it is the last chunk).\n\t *\n\t * To illustrate, if the input is `[largeOp, emptyOp, emptyOp]`, `largeOp` will be split into `[chunk1, chunk2, chunk3, chunk4]`.\n\t * `chunk1`, `chunk2` and `chunk3` will be sent individually and `[chunk4, emptyOp, emptyOp]` will be returned.\n\t *\n\t * @param batch - the compressed batch which needs to be processed\n\t * @returns A new adjusted batch which can be sent over the wire\n\t */\n\tpublic splitFirstBatchMessage(batch: IBatch): IBatch {\n\t\tassert(this.isBatchChunkingEnabled, 0x513 /* Chunking needs to be enabled */);\n\t\tassert(\n\t\t\tbatch.contentSizeInBytes > 0 && batch.content.length > 0,\n\t\t\t0x514 /* Batch needs to be non-empty */,\n\t\t);\n\t\tassert(\n\t\t\tbatch.referenceSequenceNumber !== undefined,\n\t\t\t0x58a /* Batch must have a reference sequence number if non-empty */,\n\t\t);\n\t\tassert(this.chunkSizeInBytes !== 0, 0x515 /* Chunk size needs to be non-zero */);\n\t\tassert(\n\t\t\tthis.chunkSizeInBytes < this.maxBatchSizeInBytes,\n\t\t\t0x516 /* Chunk size needs to be smaller than the max batch size */,\n\t\t);\n\n\t\tconst firstMessage = batch.content[0]; // we expect this to be the large compressed op, which needs to be split\n\t\tassert(\n\t\t\t(firstMessage.contents?.length ?? 0) >= this.chunkSizeInBytes,\n\t\t\t0x518 /* First message in the batch needs to be chunkable */,\n\t\t);\n\n\t\tconst restOfMessages = batch.content.slice(1); // we expect these to be empty ops, created to reserve sequence numbers\n\t\tconst socketSize = estimateSocketSize(batch);\n\t\tconst chunks = splitOp(\n\t\t\tfirstMessage,\n\t\t\tthis.chunkSizeInBytes,\n\t\t\t// If we estimate that the socket batch size will exceed the batch limit\n\t\t\t// we will inject an empty op to minimize the risk of the payload failing due to\n\t\t\t// the overhead from the trailing empty ops in the batch.\n\t\t\tsocketSize >= this.maxBatchSizeInBytes,\n\t\t);\n\n\t\tassert(this.submitBatchFn !== undefined, 0x519 /* We don't support old loaders */);\n\t\t// Send the first N-1 chunks immediately\n\t\tfor (const chunk of chunks.slice(0, -1)) {\n\t\t\tthis.submitBatchFn(\n\t\t\t\t[chunkToBatchMessage(chunk, batch.referenceSequenceNumber)],\n\t\t\t\tbatch.referenceSequenceNumber,\n\t\t\t);\n\t\t}\n\n\t\t// The last chunk will be part of the new batch and needs to\n\t\t// preserve the batch metadata of the original batch\n\t\tconst lastChunk = chunkToBatchMessage(\n\t\t\tchunks[chunks.length - 1],\n\t\t\tbatch.referenceSequenceNumber,\n\t\t\t{ batch: firstMessage.metadata?.batch },\n\t\t);\n\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\t// Used to be \"Chunked compressed batch\"\n\t\t\teventName: \"CompressedChunkedBatch\",\n\t\t\tlength: batch.content.length,\n\t\t\tsizeInBytes: batch.contentSizeInBytes,\n\t\t\tchunks: chunks.length,\n\t\t\tchunkSizeInBytes: this.chunkSizeInBytes,\n\t\t\tsocketSize,\n\t\t});\n\n\t\treturn {\n\t\t\tcontent: [lastChunk, ...restOfMessages],\n\t\t\tcontentSizeInBytes: lastChunk.contents?.length ?? 0,\n\t\t\treferenceSequenceNumber: batch.referenceSequenceNumber,\n\t\t};\n\t}\n}\n\nconst chunkToBatchMessage = (\n\tchunk: IChunkedOp,\n\treferenceSequenceNumber: number,\n\tmetadata: Record<string, unknown> | undefined = undefined,\n): BatchMessage => {\n\tconst payload: ContainerRuntimeMessage = {\n\t\ttype: ContainerMessageType.ChunkedOp,\n\t\tcontents: chunk,\n\t};\n\treturn {\n\t\tcontents: JSON.stringify(payload),\n\t\ttype: payload.type,\n\t\tmetadata,\n\t\tlocalOpMetadata: undefined,\n\t\treferenceSequenceNumber,\n\t};\n};\n\n/**\n * Splits an op into smaller ops (chunks), based on the size of the op and the `chunkSizeInBytes` parameter.\n *\n * The last op of the result will be bundled with empty ops in the same batch. There is a risk of the batch payload\n * exceeding the 1MB limit due to the overhead from the empty ops. If the last op is large, the risk is even higher.\n * To minimize the odds, an extra empty op can be added to the result using the `extraOp` parameter.\n *\n * @param op - the op to be split\n * @param chunkSizeInBytes - how large should the chunks be\n * @param extraOp - should an extra empty op be added to the result\n * @returns an array of chunked ops\n */\nexport const splitOp = (\n\top: BatchMessage,\n\tchunkSizeInBytes: number,\n\textraOp: boolean = false,\n): IChunkedOp[] => {\n\tconst chunks: IChunkedOp[] = [];\n\tassert(\n\t\top.contents !== undefined && op.contents !== null,\n\t\t0x51a /* We should have something to chunk */,\n\t);\n\n\tconst contentLength = op.contents.length;\n\tconst chunkCount = Math.floor((contentLength - 1) / chunkSizeInBytes) + 1 + (extraOp ? 1 : 0);\n\tlet offset = 0;\n\tfor (let chunkId = 1; chunkId <= chunkCount; chunkId++) {\n\t\tconst chunk: IChunkedOp = {\n\t\t\tchunkId,\n\t\t\tcontents: op.contents.substr(offset, chunkSizeInBytes),\n\t\t\toriginalType: op.type,\n\t\t\ttotalChunks: chunkCount,\n\t\t};\n\n\t\tif (chunkId === chunkCount) {\n\t\t\t// We don't need to port these to all the chunks,\n\t\t\t// as we rebuild the original op when we process the\n\t\t\t// last chunk, therefore it is the only one that needs it.\n\t\t\tchunk.originalMetadata = op.metadata;\n\t\t\tchunk.originalCompression = op.compression;\n\t\t}\n\n\t\tchunks.push(chunk);\n\t\toffset += chunkSizeInBytes;\n\t\tassert(\n\t\t\tchunkId >= chunkCount - 1 || offset <= contentLength,\n\t\t\t0x58b /* Content offset within bounds */,\n\t\t);\n\t}\n\n\tassert(offset >= contentLength, 0x58c /* Content offset equal or larger than content length */);\n\tassert(chunks.length === chunkCount, 0x5a5 /* Expected number of chunks */);\n\treturn chunks;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"opSplitter.js","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.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 {\n\tcreateChildLogger,\n\tDataCorruptionError,\n\textractSafePropertiesFromMessage,\n} from \"@fluidframework/telemetry-utils\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport { IBatchMessage } from \"@fluidframework/container-definitions\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { ContainerMessageType, ContainerRuntimeMessage } from \"../containerRuntime\";\nimport { estimateSocketSize } from \"./batchManager\";\nimport { BatchMessage, IBatch, IChunkedOp, IMessageProcessingResult } from \"./definitions\";\n\n/**\n * Responsible for creating and reconstructing chunked messages.\n */\nexport class OpSplitter {\n\t// Local copy of incomplete received chunks.\n\tprivate readonly chunkMap: Map<string, string[]>;\n\tprivate readonly logger;\n\n\tconstructor(\n\t\tchunks: [string, string[]][],\n\t\tprivate readonly submitBatchFn:\n\t\t\t| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)\n\t\t\t| undefined,\n\t\tpublic readonly chunkSizeInBytes: number,\n\t\tprivate readonly maxBatchSizeInBytes: number,\n\t\tlogger: ITelemetryBaseLogger,\n\t) {\n\t\tthis.chunkMap = new Map<string, string[]>(chunks);\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpSplitter\" });\n\t}\n\n\tpublic get isBatchChunkingEnabled(): boolean {\n\t\treturn this.chunkSizeInBytes < Number.POSITIVE_INFINITY && this.submitBatchFn !== undefined;\n\t}\n\n\tpublic get chunks(): ReadonlyMap<string, string[]> {\n\t\treturn this.chunkMap;\n\t}\n\n\tpublic processRemoteMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {\n\t\tif (message.type !== ContainerMessageType.ChunkedOp) {\n\t\t\treturn {\n\t\t\t\tmessage,\n\t\t\t\tstate: \"Skipped\",\n\t\t\t};\n\t\t}\n\n\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\t\t// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n\t\tconst clientId = message.clientId as string;\n\t\tconst chunkedContent = message.contents as IChunkedOp;\n\t\tthis.addChunk(clientId, chunkedContent, message);\n\n\t\tif (chunkedContent.chunkId < chunkedContent.totalChunks) {\n\t\t\t// We are processing the op in chunks but haven't reached\n\t\t\t// the last chunk yet in order to reconstruct the original op\n\t\t\treturn {\n\t\t\t\tmessage,\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst serializedContent = this.chunkMap.get(clientId)!.join(\"\");\n\t\tthis.clearPartialChunks(clientId);\n\n\t\tconst newMessage = { ...message };\n\t\tnewMessage.contents = serializedContent === \"\" ? undefined : JSON.parse(serializedContent);\n\t\tnewMessage.type = chunkedContent.originalType;\n\t\tnewMessage.metadata = chunkedContent.originalMetadata;\n\t\tnewMessage.compression = chunkedContent.originalCompression;\n\t\treturn {\n\t\t\tmessage: newMessage,\n\t\t\tstate: \"Processed\",\n\t\t};\n\t}\n\n\tpublic clearPartialChunks(clientId: string) {\n\t\tif (this.chunkMap.has(clientId)) {\n\t\t\tthis.chunkMap.delete(clientId);\n\t\t}\n\t}\n\n\tprivate addChunk(\n\t\tclientId: string,\n\t\tchunkedContent: IChunkedOp,\n\t\toriginalMessage: ISequencedDocumentMessage,\n\t) {\n\t\tlet map = this.chunkMap.get(clientId);\n\t\tif (map === undefined) {\n\t\t\tmap = [];\n\t\t\tthis.chunkMap.set(clientId, map);\n\t\t}\n\n\t\tif (chunkedContent.chunkId !== map.length + 1) {\n\t\t\t// We are expecting the chunks to be processed sequentially, in the same order as they are sent.\n\t\t\t// Therefore, the chunkId of the incoming op needs to match the length of the array (1-based indexing)\n\t\t\t// holding the existing chunks for that particular clientId.\n\t\t\tthrow new DataCorruptionError(\"Chunk Id mismatch\", {\n\t\t\t\t...extractSafePropertiesFromMessage(originalMessage),\n\t\t\t\tchunkMapLength: map.length,\n\t\t\t\tchunkId: chunkedContent.chunkId,\n\t\t\t\ttotalChunks: chunkedContent.totalChunks,\n\t\t\t});\n\t\t}\n\n\t\tmap.push(chunkedContent.contents);\n\t}\n\n\t/**\n\t * Splits the first op of a compressed batch in chunks, sends the chunks separately and\n\t * returns a new batch composed of the last chunk and the rest of the ops in the original batch.\n\t *\n\t * A compressed batch is formed by one large op at the first position, followed by a series of placeholder ops\n\t * which are used in order to reserve the sequence numbers for when the first op gets unrolled into the original\n\t * uncompressed ops at ingestion in the runtime.\n\t *\n\t * If the first op is too large, it can be chunked (split into smaller op) which can be sent individually over the wire\n\t * and accumulate at ingestion, until the last op in the chunk is processed, when the original op is unrolled.\n\t *\n\t * This method will send the first N - 1 chunks separately and use the last chunk as the first message in the result batch\n\t * and then appends the original placeholder ops. This will ensure that the batch semantics of the original (non-compressed) batch\n\t * are preserved, as the original chunked op will be unrolled by the runtime when the first message in the batch is processed\n\t * (as it is the last chunk).\n\t *\n\t * To illustrate, if the input is `[largeOp, emptyOp, emptyOp]`, `largeOp` will be split into `[chunk1, chunk2, chunk3, chunk4]`.\n\t * `chunk1`, `chunk2` and `chunk3` will be sent individually and `[chunk4, emptyOp, emptyOp]` will be returned.\n\t *\n\t * @param batch - the compressed batch which needs to be processed\n\t * @returns A new adjusted batch which can be sent over the wire\n\t */\n\tpublic splitFirstBatchMessage(batch: IBatch): IBatch {\n\t\tassert(this.isBatchChunkingEnabled, 0x513 /* Chunking needs to be enabled */);\n\t\tassert(\n\t\t\tbatch.contentSizeInBytes > 0 && batch.content.length > 0,\n\t\t\t0x514 /* Batch needs to be non-empty */,\n\t\t);\n\t\tassert(\n\t\t\tbatch.referenceSequenceNumber !== undefined,\n\t\t\t0x58a /* Batch must have a reference sequence number if non-empty */,\n\t\t);\n\t\tassert(this.chunkSizeInBytes !== 0, 0x515 /* Chunk size needs to be non-zero */);\n\t\tassert(\n\t\t\tthis.chunkSizeInBytes < this.maxBatchSizeInBytes,\n\t\t\t0x516 /* Chunk size needs to be smaller than the max batch size */,\n\t\t);\n\n\t\tconst firstMessage = batch.content[0]; // we expect this to be the large compressed op, which needs to be split\n\t\tassert(\n\t\t\t(firstMessage.contents?.length ?? 0) >= this.chunkSizeInBytes,\n\t\t\t0x518 /* First message in the batch needs to be chunkable */,\n\t\t);\n\n\t\tconst restOfMessages = batch.content.slice(1); // we expect these to be empty ops, created to reserve sequence numbers\n\t\tconst socketSize = estimateSocketSize(batch);\n\t\tconst chunks = splitOp(\n\t\t\tfirstMessage,\n\t\t\tthis.chunkSizeInBytes,\n\t\t\t// If we estimate that the socket batch size will exceed the batch limit\n\t\t\t// we will inject an empty op to minimize the risk of the payload failing due to\n\t\t\t// the overhead from the trailing empty ops in the batch.\n\t\t\tsocketSize >= this.maxBatchSizeInBytes,\n\t\t);\n\n\t\tassert(this.submitBatchFn !== undefined, 0x519 /* We don't support old loaders */);\n\t\t// Send the first N-1 chunks immediately\n\t\tfor (const chunk of chunks.slice(0, -1)) {\n\t\t\tthis.submitBatchFn(\n\t\t\t\t[chunkToBatchMessage(chunk, batch.referenceSequenceNumber)],\n\t\t\t\tbatch.referenceSequenceNumber,\n\t\t\t);\n\t\t}\n\n\t\t// The last chunk will be part of the new batch and needs to\n\t\t// preserve the batch metadata of the original batch\n\t\tconst lastChunk = chunkToBatchMessage(\n\t\t\tchunks[chunks.length - 1],\n\t\t\tbatch.referenceSequenceNumber,\n\t\t\t{ batch: firstMessage.metadata?.batch },\n\t\t);\n\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\t// Used to be \"Chunked compressed batch\"\n\t\t\teventName: \"CompressedChunkedBatch\",\n\t\t\tlength: batch.content.length,\n\t\t\tsizeInBytes: batch.contentSizeInBytes,\n\t\t\tchunks: chunks.length,\n\t\t\tchunkSizeInBytes: this.chunkSizeInBytes,\n\t\t\tsocketSize,\n\t\t});\n\n\t\treturn {\n\t\t\tcontent: [lastChunk, ...restOfMessages],\n\t\t\tcontentSizeInBytes: lastChunk.contents?.length ?? 0,\n\t\t\treferenceSequenceNumber: batch.referenceSequenceNumber,\n\t\t};\n\t}\n}\n\nconst chunkToBatchMessage = (\n\tchunk: IChunkedOp,\n\treferenceSequenceNumber: number,\n\tmetadata: Record<string, unknown> | undefined = undefined,\n): BatchMessage => {\n\tconst payload: ContainerRuntimeMessage = {\n\t\ttype: ContainerMessageType.ChunkedOp,\n\t\tcontents: chunk,\n\t};\n\treturn {\n\t\tcontents: JSON.stringify(payload),\n\t\ttype: payload.type,\n\t\tmetadata,\n\t\tlocalOpMetadata: undefined,\n\t\treferenceSequenceNumber,\n\t};\n};\n\n/**\n * Splits an op into smaller ops (chunks), based on the size of the op and the `chunkSizeInBytes` parameter.\n *\n * The last op of the result will be bundled with empty ops in the same batch. There is a risk of the batch payload\n * exceeding the 1MB limit due to the overhead from the empty ops. If the last op is large, the risk is even higher.\n * To minimize the odds, an extra empty op can be added to the result using the `extraOp` parameter.\n *\n * @param op - the op to be split\n * @param chunkSizeInBytes - how large should the chunks be\n * @param extraOp - should an extra empty op be added to the result\n * @returns an array of chunked ops\n */\nexport const splitOp = (\n\top: BatchMessage,\n\tchunkSizeInBytes: number,\n\textraOp: boolean = false,\n): IChunkedOp[] => {\n\tconst chunks: IChunkedOp[] = [];\n\tassert(\n\t\top.contents !== undefined && op.contents !== null,\n\t\t0x51a /* We should have something to chunk */,\n\t);\n\n\tconst contentLength = op.contents.length;\n\tconst chunkCount = Math.floor((contentLength - 1) / chunkSizeInBytes) + 1 + (extraOp ? 1 : 0);\n\tlet offset = 0;\n\tfor (let chunkId = 1; chunkId <= chunkCount; chunkId++) {\n\t\tconst chunk: IChunkedOp = {\n\t\t\tchunkId,\n\t\t\tcontents: op.contents.substr(offset, chunkSizeInBytes),\n\t\t\toriginalType: op.type,\n\t\t\ttotalChunks: chunkCount,\n\t\t};\n\n\t\tif (chunkId === chunkCount) {\n\t\t\t// We don't need to port these to all the chunks,\n\t\t\t// as we rebuild the original op when we process the\n\t\t\t// last chunk, therefore it is the only one that needs it.\n\t\t\tchunk.originalMetadata = op.metadata;\n\t\t\tchunk.originalCompression = op.compression;\n\t\t}\n\n\t\tchunks.push(chunk);\n\t\toffset += chunkSizeInBytes;\n\t\tassert(\n\t\t\tchunkId >= chunkCount - 1 || offset <= contentLength,\n\t\t\t0x58b /* Content offset within bounds */,\n\t\t);\n\t}\n\n\tassert(offset >= contentLength, 0x58c /* Content offset equal or larger than content length */);\n\tassert(chunks.length === chunkCount, 0x5a5 /* Expected number of chunks */);\n\treturn chunks;\n};\n"]}
|
|
@@ -62,6 +62,7 @@ export declare class Outbox {
|
|
|
62
62
|
private readonly maxMismatchedOpsToReport;
|
|
63
63
|
private mismatchedOpsReported;
|
|
64
64
|
constructor(params: IOutboxParameters);
|
|
65
|
+
get messageCount(): number;
|
|
65
66
|
get isEmpty(): boolean;
|
|
66
67
|
/**
|
|
67
68
|
* If we detect that the reference sequence number of the incoming message does not match
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { createChildMonitoringContext } from "@fluidframework/telemetry-utils";
|
|
6
|
-
import { assert } from "@fluidframework/
|
|
7
|
-
import { GenericError, UsageError } from "@fluidframework/container-utils";
|
|
5
|
+
import { createChildMonitoringContext, GenericError, UsageError, } from "@fluidframework/telemetry-utils";
|
|
6
|
+
import { assert } from "@fluidframework/core-utils";
|
|
8
7
|
import { BatchManager, estimateSocketSize, sequenceNumbersMatch, } from "./batchManager";
|
|
9
8
|
/**
|
|
10
9
|
* Temporarily increase the stack limit while executing the provided action.
|
|
@@ -20,8 +19,7 @@ import { BatchManager, estimateSocketSize, sequenceNumbersMatch, } from "./batch
|
|
|
20
19
|
export function getLongStack(action, length = 50) {
|
|
21
20
|
const errorObj = Error;
|
|
22
21
|
if ((Object.getOwnPropertyDescriptor(errorObj, "stackTraceLimit") ||
|
|
23
|
-
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(errorObj), "stackTraceLimit")
|
|
24
|
-
{}).writable !== true) {
|
|
22
|
+
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(errorObj), "stackTraceLimit"))?.writable !== true) {
|
|
25
23
|
return action();
|
|
26
24
|
}
|
|
27
25
|
const originalStackTraceLimit = errorObj.stackTraceLimit;
|
|
@@ -57,10 +55,11 @@ export class Outbox {
|
|
|
57
55
|
this.mainBatch = new BatchManager({ hardLimit });
|
|
58
56
|
this.blobAttachBatch = new BatchManager({ hardLimit });
|
|
59
57
|
}
|
|
58
|
+
get messageCount() {
|
|
59
|
+
return this.attachFlowBatch.length + this.mainBatch.length + this.blobAttachBatch.length;
|
|
60
|
+
}
|
|
60
61
|
get isEmpty() {
|
|
61
|
-
return
|
|
62
|
-
this.mainBatch.length === 0 &&
|
|
63
|
-
this.blobAttachBatch.length === 0);
|
|
62
|
+
return this.messageCount === 0;
|
|
64
63
|
}
|
|
65
64
|
/**
|
|
66
65
|
* If we detect that the reference sequence number of the incoming message does not match
|