@fluidframework/container-runtime 2.0.0-internal.3.0.2 → 2.0.0-internal.3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +19 -19
- package/.mocharc.js +2 -2
- package/api-extractor.json +2 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +2 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +15 -2
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +109 -37
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +11 -9
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +3 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +23 -11
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +225 -132
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +11 -9
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +27 -13
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +95 -56
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +7 -3
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +3 -1
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts +28 -4
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +122 -44
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +8 -3
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/{garbageCollection.d.ts → gc/garbageCollection.d.ts} +27 -203
- package/dist/gc/garbageCollection.d.ts.map +1 -0
- package/dist/{garbageCollection.js → gc/garbageCollection.js} +210 -400
- package/dist/gc/garbageCollection.js.map +1 -0
- package/dist/gc/gcDefinitions.d.ts +189 -0
- package/dist/gc/gcDefinitions.d.ts.map +1 -0
- package/dist/{garbageCollectionConstants.js → gc/gcDefinitions.js} +27 -2
- package/dist/gc/gcDefinitions.js.map +1 -0
- package/dist/gc/gcHelpers.d.ts +30 -0
- package/dist/gc/gcHelpers.d.ts.map +1 -0
- package/dist/gc/gcHelpers.js +65 -0
- package/dist/gc/gcHelpers.js.map +1 -0
- package/dist/gc/gcSummaryStateTracker.d.ts +86 -0
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -0
- package/dist/gc/gcSummaryStateTracker.js +246 -0
- package/dist/gc/gcSummaryStateTracker.js.map +1 -0
- package/{lib → dist/gc}/gcSweepReadyUsageDetection.d.ts +5 -5
- package/dist/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
- package/dist/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +15 -11
- package/dist/gc/gcSweepReadyUsageDetection.js.map +1 -0
- package/dist/gc/gcUnreferencedStateTracker.d.ts +34 -0
- package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
- package/dist/gc/gcUnreferencedStateTracker.js +94 -0
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -0
- package/dist/gc/index.d.ts +11 -0
- package/dist/gc/index.d.ts.map +1 -0
- package/dist/gc/index.js +40 -0
- package/dist/gc/index.js.map +1 -0
- package/dist/index.d.ts +2 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -9
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +2 -13
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +19 -41
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +4 -0
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +1 -0
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +5 -2
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +24 -13
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +19 -3
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +78 -45
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/opProperties.d.ts.map +1 -1
- package/dist/opProperties.js +1 -3
- package/dist/opProperties.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 +8 -2
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +21 -13
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +3 -2
- package/dist/scheduleManager.js.map +1 -1
- package/dist/serializedSnapshotStorage.d.ts +2 -2
- package/dist/serializedSnapshotStorage.d.ts.map +1 -1
- package/dist/serializedSnapshotStorage.js +5 -3
- package/dist/serializedSnapshotStorage.js.map +1 -1
- package/dist/summary/index.d.ts +17 -0
- package/dist/summary/index.d.ts.map +1 -0
- package/dist/summary/index.js +47 -0
- package/dist/summary/index.js.map +1 -0
- package/dist/summary/orderedClientElection.d.ts.map +1 -0
- package/dist/{orderedClientElection.js → summary/orderedClientElection.js} +10 -4
- package/dist/summary/orderedClientElection.js.map +1 -0
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -0
- package/{lib → dist/summary}/runningSummarizer.d.ts +19 -18
- package/dist/summary/runningSummarizer.d.ts.map +1 -0
- package/dist/{runningSummarizer.js → summary/runningSummarizer.js} +191 -76
- package/dist/summary/runningSummarizer.js.map +1 -0
- package/dist/{summarizer.d.ts → summary/summarizer.d.ts} +4 -6
- package/dist/summary/summarizer.d.ts.map +1 -0
- package/dist/{summarizer.js → summary/summarizer.js} +31 -71
- package/dist/summary/summarizer.js.map +1 -0
- package/dist/summary/summarizerClientElection.d.ts.map +1 -0
- package/dist/summary/summarizerClientElection.js.map +1 -0
- package/dist/summary/summarizerHandle.d.ts.map +1 -0
- package/dist/summary/summarizerHandle.js.map +1 -0
- package/{lib → dist/summary}/summarizerHeuristics.d.ts +1 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -0
- package/dist/{summarizerHeuristics.js → summary/summarizerHeuristics.js} +6 -9
- package/dist/summary/summarizerHeuristics.js.map +1 -0
- package/{lib → dist/summary}/summarizerTypes.d.ts +22 -22
- package/dist/summary/summarizerTypes.d.ts.map +1 -0
- package/dist/summary/summarizerTypes.js.map +1 -0
- package/dist/summary/summaryCollection.d.ts.map +1 -0
- package/dist/{summaryCollection.js → summary/summaryCollection.js} +18 -8
- package/dist/summary/summaryCollection.js.map +1 -0
- package/{lib → dist/summary}/summaryFormat.d.ts +1 -40
- package/dist/summary/summaryFormat.d.ts.map +1 -0
- package/dist/{summaryFormat.js → summary/summaryFormat.js} +19 -20
- package/dist/summary/summaryFormat.js.map +1 -0
- package/dist/summary/summaryGenerator.d.ts.map +1 -0
- package/dist/{summaryGenerator.js → summary/summaryGenerator.js} +33 -15
- package/dist/summary/summaryGenerator.js.map +1 -0
- package/dist/{summaryManager.d.ts → summary/summaryManager.d.ts} +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -0
- package/dist/{summaryManager.js → summary/summaryManager.js} +21 -9
- package/dist/summary/summaryManager.js.map +1 -0
- package/dist/throttler.d.ts +2 -2
- package/dist/throttler.d.ts.map +1 -1
- package/dist/throttler.js +4 -4
- package/dist/throttler.js.map +1 -1
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +15 -2
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +109 -37
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +11 -9
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +3 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +23 -11
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +201 -108
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +11 -9
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +27 -13
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +84 -45
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +7 -3
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +3 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts +28 -4
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +120 -42
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +9 -4
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/{garbageCollection.d.ts → gc/garbageCollection.d.ts} +27 -203
- package/lib/gc/garbageCollection.d.ts.map +1 -0
- package/lib/{garbageCollection.js → gc/garbageCollection.js} +190 -379
- package/lib/gc/garbageCollection.js.map +1 -0
- package/lib/gc/gcDefinitions.d.ts +189 -0
- package/lib/gc/gcDefinitions.d.ts.map +1 -0
- package/lib/{garbageCollectionConstants.js → gc/gcDefinitions.js} +26 -1
- package/lib/gc/gcDefinitions.js.map +1 -0
- package/lib/gc/gcHelpers.d.ts +30 -0
- package/lib/gc/gcHelpers.d.ts.map +1 -0
- package/lib/gc/gcHelpers.js +58 -0
- package/lib/gc/gcHelpers.js.map +1 -0
- package/lib/gc/gcSummaryStateTracker.d.ts +86 -0
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -0
- package/lib/gc/gcSummaryStateTracker.js +242 -0
- package/lib/gc/gcSummaryStateTracker.js.map +1 -0
- package/{dist → lib/gc}/gcSweepReadyUsageDetection.d.ts +5 -5
- package/lib/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
- package/lib/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +15 -11
- package/lib/gc/gcSweepReadyUsageDetection.js.map +1 -0
- package/lib/gc/gcUnreferencedStateTracker.d.ts +34 -0
- package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
- package/lib/gc/gcUnreferencedStateTracker.js +90 -0
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -0
- package/lib/gc/index.d.ts +11 -0
- package/lib/gc/index.d.ts.map +1 -0
- package/lib/gc/index.js +11 -0
- package/lib/gc/index.js.map +1 -0
- package/lib/index.d.ts +2 -5
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -4
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +2 -13
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +19 -41
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +4 -0
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +1 -0
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +5 -2
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +1 -1
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +25 -14
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +19 -3
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +79 -46
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/opProperties.d.ts.map +1 -1
- package/lib/opProperties.js +1 -3
- package/lib/opProperties.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 +8 -2
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +21 -13
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +3 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/serializedSnapshotStorage.d.ts +2 -2
- package/lib/serializedSnapshotStorage.d.ts.map +1 -1
- package/lib/serializedSnapshotStorage.js +5 -3
- package/lib/serializedSnapshotStorage.js.map +1 -1
- package/lib/summary/index.d.ts +17 -0
- package/lib/summary/index.d.ts.map +1 -0
- package/lib/summary/index.js +16 -0
- package/lib/summary/index.js.map +1 -0
- package/lib/summary/orderedClientElection.d.ts.map +1 -0
- package/lib/{orderedClientElection.js → summary/orderedClientElection.js} +10 -4
- package/lib/summary/orderedClientElection.js.map +1 -0
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -0
- package/{dist → lib/summary}/runningSummarizer.d.ts +19 -18
- package/lib/summary/runningSummarizer.d.ts.map +1 -0
- package/lib/{runningSummarizer.js → summary/runningSummarizer.js} +193 -78
- package/lib/summary/runningSummarizer.js.map +1 -0
- package/lib/{summarizer.d.ts → summary/summarizer.d.ts} +4 -6
- package/lib/summary/summarizer.d.ts.map +1 -0
- package/lib/{summarizer.js → summary/summarizer.js} +33 -73
- package/lib/summary/summarizer.js.map +1 -0
- package/lib/summary/summarizerClientElection.d.ts.map +1 -0
- package/lib/summary/summarizerClientElection.js.map +1 -0
- package/lib/summary/summarizerHandle.d.ts.map +1 -0
- package/lib/summary/summarizerHandle.js.map +1 -0
- package/{dist → lib/summary}/summarizerHeuristics.d.ts +1 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
- package/lib/{summarizerHeuristics.js → summary/summarizerHeuristics.js} +6 -9
- package/lib/summary/summarizerHeuristics.js.map +1 -0
- package/{dist → lib/summary}/summarizerTypes.d.ts +22 -22
- package/lib/summary/summarizerTypes.d.ts.map +1 -0
- package/lib/summary/summarizerTypes.js.map +1 -0
- package/lib/summary/summaryCollection.d.ts.map +1 -0
- package/lib/{summaryCollection.js → summary/summaryCollection.js} +18 -8
- package/lib/summary/summaryCollection.js.map +1 -0
- package/{dist → lib/summary}/summaryFormat.d.ts +1 -40
- package/lib/summary/summaryFormat.d.ts.map +1 -0
- package/lib/{summaryFormat.js → summary/summaryFormat.js} +20 -20
- package/lib/summary/summaryFormat.js.map +1 -0
- package/lib/summary/summaryGenerator.d.ts.map +1 -0
- package/lib/{summaryGenerator.js → summary/summaryGenerator.js} +33 -15
- package/lib/summary/summaryGenerator.js.map +1 -0
- package/lib/{summaryManager.d.ts → summary/summaryManager.d.ts} +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -0
- package/lib/{summaryManager.js → summary/summaryManager.js} +21 -9
- package/lib/summary/summaryManager.js.map +1 -0
- package/lib/throttler.d.ts +2 -2
- package/lib/throttler.d.ts.map +1 -1
- package/lib/throttler.js +4 -4
- package/lib/throttler.js.map +1 -1
- package/package.json +60 -51
- package/prettier.config.cjs +1 -1
- package/src/batchTracker.ts +54 -49
- package/src/blobManager.ts +825 -674
- package/src/connectionTelemetry.ts +280 -249
- package/src/containerHandleContext.ts +27 -29
- package/src/containerRuntime.ts +3249 -2978
- package/src/dataStore.ts +172 -159
- package/src/dataStoreContext.ts +1141 -1057
- package/src/dataStoreContexts.ts +178 -161
- package/src/dataStoreRegistry.ts +25 -20
- package/src/dataStores.ts +880 -731
- package/src/deltaScheduler.ts +158 -150
- package/{garbageCollection.md → src/gc/garbageCollection.md} +16 -3
- package/src/gc/garbageCollection.ts +1506 -0
- package/src/gc/gcDefinitions.ts +244 -0
- package/src/gc/gcHelpers.ts +86 -0
- package/src/gc/gcSummaryStateTracker.ts +339 -0
- package/src/gc/gcSweepReadyUsageDetection.ts +145 -0
- package/src/gc/gcUnreferencedStateTracker.ts +114 -0
- package/src/gc/index.ts +40 -0
- package/src/index.ts +67 -70
- package/src/opLifecycle/README.md +152 -0
- package/src/opLifecycle/batchManager.ts +101 -144
- package/src/opLifecycle/definitions.ts +33 -29
- package/src/opLifecycle/index.ts +5 -5
- package/src/opLifecycle/opCompressor.ts +55 -53
- package/src/opLifecycle/opDecompressor.ts +100 -81
- package/src/opLifecycle/opSplitter.ts +233 -188
- package/src/opLifecycle/outbox.ts +251 -195
- package/src/opLifecycle/remoteMessageProcessor.ts +62 -62
- package/src/opProperties.ts +11 -9
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +396 -338
- package/src/scheduleManager.ts +299 -269
- package/src/serializedSnapshotStorage.ts +126 -112
- package/src/summary/index.ts +99 -0
- package/src/summary/orderedClientElection.ts +564 -0
- package/src/summary/runWhileConnectedCoordinator.ts +113 -0
- package/src/summary/runningSummarizer.ts +788 -0
- package/src/summary/summarizer.ts +386 -0
- package/src/summary/summarizerClientElection.ts +139 -0
- package/src/{summarizerHandle.ts → summary/summarizerHandle.ts} +11 -9
- package/src/summary/summarizerHeuristics.ts +219 -0
- package/src/summary/summarizerTypes.ts +521 -0
- package/src/summary/summaryCollection.ts +450 -0
- package/src/summary/summaryFormat.ts +226 -0
- package/src/summary/summaryGenerator.ts +505 -0
- package/src/summary/summaryManager.ts +423 -0
- package/src/throttler.ts +131 -122
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +9 -13
- package/dist/garbageCollection.d.ts.map +0 -1
- package/dist/garbageCollection.js.map +0 -1
- package/dist/garbageCollectionConstants.d.ts +0 -25
- package/dist/garbageCollectionConstants.d.ts.map +0 -1
- package/dist/garbageCollectionConstants.js.map +0 -1
- package/dist/garbageCollectionTombstoneUtils.d.ts +0 -14
- package/dist/garbageCollectionTombstoneUtils.d.ts.map +0 -1
- package/dist/garbageCollectionTombstoneUtils.js +0 -23
- package/dist/garbageCollectionTombstoneUtils.js.map +0 -1
- package/dist/gcSweepReadyUsageDetection.d.ts.map +0 -1
- package/dist/gcSweepReadyUsageDetection.js.map +0 -1
- package/dist/orderedClientElection.d.ts.map +0 -1
- package/dist/orderedClientElection.js.map +0 -1
- package/dist/runWhileConnectedCoordinator.d.ts.map +0 -1
- package/dist/runWhileConnectedCoordinator.js.map +0 -1
- package/dist/runningSummarizer.d.ts.map +0 -1
- package/dist/runningSummarizer.js.map +0 -1
- package/dist/summarizer.d.ts.map +0 -1
- package/dist/summarizer.js.map +0 -1
- package/dist/summarizerClientElection.d.ts.map +0 -1
- package/dist/summarizerClientElection.js.map +0 -1
- package/dist/summarizerHandle.d.ts.map +0 -1
- package/dist/summarizerHandle.js.map +0 -1
- package/dist/summarizerHeuristics.d.ts.map +0 -1
- package/dist/summarizerHeuristics.js.map +0 -1
- package/dist/summarizerTypes.d.ts.map +0 -1
- package/dist/summarizerTypes.js.map +0 -1
- package/dist/summaryCollection.d.ts.map +0 -1
- package/dist/summaryCollection.js.map +0 -1
- package/dist/summaryFormat.d.ts.map +0 -1
- package/dist/summaryFormat.js.map +0 -1
- package/dist/summaryGenerator.d.ts.map +0 -1
- package/dist/summaryGenerator.js.map +0 -1
- package/dist/summaryManager.d.ts.map +0 -1
- package/dist/summaryManager.js.map +0 -1
- package/lib/garbageCollection.d.ts.map +0 -1
- package/lib/garbageCollection.js.map +0 -1
- package/lib/garbageCollectionConstants.d.ts +0 -25
- package/lib/garbageCollectionConstants.d.ts.map +0 -1
- package/lib/garbageCollectionConstants.js.map +0 -1
- package/lib/garbageCollectionTombstoneUtils.d.ts +0 -14
- package/lib/garbageCollectionTombstoneUtils.d.ts.map +0 -1
- package/lib/garbageCollectionTombstoneUtils.js +0 -19
- package/lib/garbageCollectionTombstoneUtils.js.map +0 -1
- package/lib/gcSweepReadyUsageDetection.d.ts.map +0 -1
- package/lib/gcSweepReadyUsageDetection.js.map +0 -1
- package/lib/orderedClientElection.d.ts.map +0 -1
- package/lib/orderedClientElection.js.map +0 -1
- package/lib/runWhileConnectedCoordinator.d.ts.map +0 -1
- package/lib/runWhileConnectedCoordinator.js.map +0 -1
- package/lib/runningSummarizer.d.ts.map +0 -1
- package/lib/runningSummarizer.js.map +0 -1
- package/lib/summarizer.d.ts.map +0 -1
- package/lib/summarizer.js.map +0 -1
- package/lib/summarizerClientElection.d.ts.map +0 -1
- package/lib/summarizerClientElection.js.map +0 -1
- package/lib/summarizerHandle.d.ts.map +0 -1
- package/lib/summarizerHandle.js.map +0 -1
- package/lib/summarizerHeuristics.d.ts.map +0 -1
- package/lib/summarizerHeuristics.js.map +0 -1
- package/lib/summarizerTypes.d.ts.map +0 -1
- package/lib/summarizerTypes.js.map +0 -1
- package/lib/summaryCollection.d.ts.map +0 -1
- package/lib/summaryCollection.js.map +0 -1
- package/lib/summaryFormat.d.ts.map +0 -1
- package/lib/summaryFormat.js.map +0 -1
- package/lib/summaryGenerator.d.ts.map +0 -1
- package/lib/summaryGenerator.js.map +0 -1
- package/lib/summaryManager.d.ts.map +0 -1
- package/lib/summaryManager.js.map +0 -1
- package/src/garbageCollection.ts +0 -1800
- package/src/garbageCollectionConstants.ts +0 -41
- package/src/garbageCollectionTombstoneUtils.ts +0 -28
- package/src/gcSweepReadyUsageDetection.ts +0 -139
- package/src/orderedClientElection.ts +0 -532
- package/src/runWhileConnectedCoordinator.ts +0 -106
- package/src/runningSummarizer.ts +0 -610
- package/src/summarizer.ts +0 -421
- package/src/summarizerClientElection.ts +0 -132
- package/src/summarizerHeuristics.ts +0 -222
- package/src/summarizerTypes.ts +0 -507
- package/src/summaryCollection.ts +0 -421
- package/src/summaryFormat.ts +0 -256
- package/src/summaryGenerator.ts +0 -450
- package/src/summaryManager.ts +0 -394
- /package/dist/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
- /package/dist/{runWhileConnectedCoordinator.d.ts → summary/runWhileConnectedCoordinator.d.ts} +0 -0
- /package/dist/{runWhileConnectedCoordinator.js → summary/runWhileConnectedCoordinator.js} +0 -0
- /package/dist/{summarizerClientElection.d.ts → summary/summarizerClientElection.d.ts} +0 -0
- /package/dist/{summarizerClientElection.js → summary/summarizerClientElection.js} +0 -0
- /package/dist/{summarizerHandle.d.ts → summary/summarizerHandle.d.ts} +0 -0
- /package/dist/{summarizerHandle.js → summary/summarizerHandle.js} +0 -0
- /package/dist/{summarizerTypes.js → summary/summarizerTypes.js} +0 -0
- /package/dist/{summaryCollection.d.ts → summary/summaryCollection.d.ts} +0 -0
- /package/dist/{summaryGenerator.d.ts → summary/summaryGenerator.d.ts} +0 -0
- /package/lib/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
- /package/lib/{runWhileConnectedCoordinator.d.ts → summary/runWhileConnectedCoordinator.d.ts} +0 -0
- /package/lib/{runWhileConnectedCoordinator.js → summary/runWhileConnectedCoordinator.js} +0 -0
- /package/lib/{summarizerClientElection.d.ts → summary/summarizerClientElection.d.ts} +0 -0
- /package/lib/{summarizerClientElection.js → summary/summarizerClientElection.js} +0 -0
- /package/lib/{summarizerHandle.d.ts → summary/summarizerHandle.d.ts} +0 -0
- /package/lib/{summarizerHandle.js → summary/summarizerHandle.js} +0 -0
- /package/lib/{summarizerTypes.js → summary/summarizerTypes.js} +0 -0
- /package/lib/{summaryCollection.d.ts → summary/summaryCollection.d.ts} +0 -0
- /package/lib/{summaryGenerator.d.ts → summary/summaryGenerator.d.ts} +0 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ITelemetryProperties } from "@fluidframework/common-definitions";
|
|
7
|
+
import { ICriticalContainerError } from "@fluidframework/container-definitions";
|
|
8
|
+
import {
|
|
9
|
+
IConfigProvider,
|
|
10
|
+
IFluidErrorBase,
|
|
11
|
+
LoggingError,
|
|
12
|
+
MonitoringContext,
|
|
13
|
+
} from "@fluidframework/telemetry-utils";
|
|
14
|
+
import { oneDayMs } from "./gcDefinitions";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Feature Gate Key -
|
|
18
|
+
* How many days between closing the container from this error (avoids locking user out of their file altogether)
|
|
19
|
+
*/
|
|
20
|
+
export const skipClosureForXDaysKey =
|
|
21
|
+
"Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection.SkipClosureForXDays";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* LocalStorage key (NOT via feature gate / monitoring context)
|
|
25
|
+
* A map from docId to info about the last time we closed due to this error
|
|
26
|
+
*/
|
|
27
|
+
export const closuresMapLocalStorageKey =
|
|
28
|
+
"Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection.Closures";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Feature gate key to enable closing the container if SweepReady objects are used.
|
|
32
|
+
* Value should contain keywords "interactiveClient" and/or "summarizer" to enable detection in each container type
|
|
33
|
+
*/
|
|
34
|
+
const sweepReadyUsageDetectionSetting = {
|
|
35
|
+
read(config: IConfigProvider) {
|
|
36
|
+
const sweepReadyUsageDetectionKey =
|
|
37
|
+
"Fluid.GarbageCollection.Dogfood.SweepReadyUsageDetection";
|
|
38
|
+
const value = config.getString(sweepReadyUsageDetectionKey);
|
|
39
|
+
if (value === undefined) {
|
|
40
|
+
return { interactiveClient: false, summarizer: false };
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
interactiveClient: value.includes("interactiveClient"),
|
|
44
|
+
summarizer: value.includes("summarizer"),
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Error class raised when a SweepReady object is used, indicating a bug in how
|
|
51
|
+
* references are managed in the container by the application, or a bug in how
|
|
52
|
+
* GC tracks those references.
|
|
53
|
+
*
|
|
54
|
+
* There's a chance for false positives when this error is raised by an Interactive Container,
|
|
55
|
+
* since only the Summarizer has the latest truth about unreferenced node tracking
|
|
56
|
+
*/
|
|
57
|
+
export class SweepReadyUsageError extends LoggingError implements IFluidErrorBase {
|
|
58
|
+
/** This errorType will be in temporary use (until Sweep is fully implemented) so don't add to any errorType type */
|
|
59
|
+
public errorType: string = "unreferencedObjectUsedAfterGarbageCollected";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* This class encapsulates the logic around what to do when a SweepReady object is used.
|
|
64
|
+
* There are several tactics we plan to use in Dogfood environments to aid diagnosis of these cases:
|
|
65
|
+
* - Closing the interactive container when either the interactive or summarizer client detects this kind of violation
|
|
66
|
+
* (via sweepReadyUsageDetectionSetting above)
|
|
67
|
+
* - Throttling the frequency of these crashes via a "Skip Closure Period" per container per device
|
|
68
|
+
* (via skipClosureForXDaysKey above. Uses localStorage and closuresMapLocalStorageKey to implement this behavior)
|
|
69
|
+
*/
|
|
70
|
+
export class SweepReadyUsageDetectionHandler {
|
|
71
|
+
private readonly localStorage: Pick<Storage, "getItem" | "setItem">;
|
|
72
|
+
|
|
73
|
+
constructor(
|
|
74
|
+
private readonly uniqueContainerKey: string,
|
|
75
|
+
private readonly mc: MonitoringContext,
|
|
76
|
+
private readonly closeFn: (error?: ICriticalContainerError) => void,
|
|
77
|
+
localStorageOverride?: Pick<Storage, "getItem" | "setItem">,
|
|
78
|
+
) {
|
|
79
|
+
const noopStorage = { getItem: () => null, setItem: () => {} };
|
|
80
|
+
// localStorage is not defined in Node environment, so fall back to noopStorage if needed.
|
|
81
|
+
this.localStorage = localStorageOverride ?? globalThis.localStorage ?? noopStorage;
|
|
82
|
+
|
|
83
|
+
if (this.localStorage === noopStorage) {
|
|
84
|
+
// This means the Skip Closure Period logic will not work.
|
|
85
|
+
this.mc.logger.sendTelemetryEvent({
|
|
86
|
+
eventName: "SweepReadyUsageDetectionHandlerNoopStorage",
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* If SweepReady Usage Detection is enabled, close the interactive container.
|
|
93
|
+
* If the SkipClosureForXDays setting is set, don't close the container more than once in that period.
|
|
94
|
+
*
|
|
95
|
+
* Once Sweep is fully implemented, this will be removed since the objects will be gone
|
|
96
|
+
* and errors will arise elsewhere in the runtime
|
|
97
|
+
*/
|
|
98
|
+
public usageDetectedInInteractiveClient(errorProps: ITelemetryProperties) {
|
|
99
|
+
if (!sweepReadyUsageDetectionSetting.read(this.mc.config).interactiveClient) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Default stance is we close every time - this reflects the severity of SweepReady Object Usage.
|
|
104
|
+
// However, we may choose to "throttle" the closures by setting the SkipClosureForXDays setting,
|
|
105
|
+
// which will only allow the container to close once during that period, to avoid locking users out.
|
|
106
|
+
let shouldClose: boolean = true;
|
|
107
|
+
let pastClosuresMap: Record<string, { lastCloseTime: number } | undefined> = {};
|
|
108
|
+
let lastCloseTime: number | undefined;
|
|
109
|
+
const skipClosureForXDays = this.mc.config.getNumber(skipClosureForXDaysKey);
|
|
110
|
+
if (skipClosureForXDays !== undefined) {
|
|
111
|
+
// Read pastClosuresMap from localStorage then extract the lastCloseTime from the map
|
|
112
|
+
try {
|
|
113
|
+
const rawValue = this.localStorage.getItem(closuresMapLocalStorageKey);
|
|
114
|
+
const parsedValue = rawValue === null ? {} : JSON.parse(rawValue);
|
|
115
|
+
if (typeof parsedValue === "object") {
|
|
116
|
+
pastClosuresMap = parsedValue;
|
|
117
|
+
}
|
|
118
|
+
} catch (e) {}
|
|
119
|
+
lastCloseTime = pastClosuresMap[this.uniqueContainerKey]?.lastCloseTime;
|
|
120
|
+
|
|
121
|
+
// Don't close if we did already within the Skip Closure Period
|
|
122
|
+
if (
|
|
123
|
+
lastCloseTime !== undefined &&
|
|
124
|
+
Date.now() < lastCloseTime + skipClosureForXDays * oneDayMs
|
|
125
|
+
) {
|
|
126
|
+
shouldClose = false;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const error = new SweepReadyUsageError("SweepReady object used in Non-Summarizer Client", {
|
|
131
|
+
errorDetails: JSON.stringify({ ...errorProps, lastCloseTime, skipClosureForXDays }),
|
|
132
|
+
});
|
|
133
|
+
if (shouldClose) {
|
|
134
|
+
// Update closures map in localStorage before closing
|
|
135
|
+
// Note there is a race condition between different tabs updating localStorage and overwriting
|
|
136
|
+
// each others' updates. If so, some tab will crash again. Just reload one at a time to get unstuck
|
|
137
|
+
pastClosuresMap[this.uniqueContainerKey] = { lastCloseTime: Date.now() };
|
|
138
|
+
this.localStorage.setItem(closuresMapLocalStorageKey, JSON.stringify(pastClosuresMap));
|
|
139
|
+
|
|
140
|
+
this.closeFn(error);
|
|
141
|
+
} else {
|
|
142
|
+
this.mc.logger.sendErrorEvent({ eventName: "SweepReadyObject_UsageAllowed" }, error);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { assert, Timer } from "@fluidframework/common-utils";
|
|
7
|
+
import { UnreferencedState } from "./gcDefinitions";
|
|
8
|
+
|
|
9
|
+
/** A wrapper around common-utils Timer that requires the timeout when calling start/restart */
|
|
10
|
+
class TimerWithNoDefaultTimeout extends Timer {
|
|
11
|
+
constructor(private readonly callback: () => void) {
|
|
12
|
+
// The default timeout/handlers will never be used since start/restart pass overrides below
|
|
13
|
+
super(0, () => {
|
|
14
|
+
throw new Error("DefaultHandler should not be used");
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
start(timeoutMs: number) {
|
|
19
|
+
super.start(timeoutMs, this.callback);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
restart(timeoutMs: number): void {
|
|
23
|
+
super.restart(timeoutMs, this.callback);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Helper class that tracks the state of an unreferenced node such as the time it was unreferenced and if it can
|
|
29
|
+
* be deleted by the sweep phase.
|
|
30
|
+
*/
|
|
31
|
+
export class UnreferencedStateTracker {
|
|
32
|
+
private _state: UnreferencedState = UnreferencedState.Active;
|
|
33
|
+
public get state(): UnreferencedState {
|
|
34
|
+
return this._state;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Timer to indicate when an unreferenced object is considered Inactive */
|
|
38
|
+
private readonly inactiveTimer: TimerWithNoDefaultTimeout;
|
|
39
|
+
/** Timer to indicate when an unreferenced object is Sweep-Ready */
|
|
40
|
+
private readonly sweepTimer: TimerWithNoDefaultTimeout;
|
|
41
|
+
|
|
42
|
+
constructor(
|
|
43
|
+
public readonly unreferencedTimestampMs: number,
|
|
44
|
+
/** The time after which node transitions to Inactive state. */
|
|
45
|
+
private readonly inactiveTimeoutMs: number,
|
|
46
|
+
/** The current reference timestamp used to track how long this node has been unreferenced for. */
|
|
47
|
+
currentReferenceTimestampMs: number,
|
|
48
|
+
/** The time after which node transitions to SweepReady state; undefined if session expiry is disabled. */
|
|
49
|
+
private readonly sweepTimeoutMs: number | undefined,
|
|
50
|
+
) {
|
|
51
|
+
if (this.sweepTimeoutMs !== undefined) {
|
|
52
|
+
assert(
|
|
53
|
+
this.inactiveTimeoutMs <= this.sweepTimeoutMs,
|
|
54
|
+
0x3b0 /* inactive timeout must not be greater than the sweep timeout */,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.sweepTimer = new TimerWithNoDefaultTimeout(() => {
|
|
59
|
+
this._state = UnreferencedState.SweepReady;
|
|
60
|
+
assert(
|
|
61
|
+
!this.inactiveTimer.hasTimer,
|
|
62
|
+
0x3b1 /* inactiveTimer still running after sweepTimer fired! */,
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
this.inactiveTimer = new TimerWithNoDefaultTimeout(() => {
|
|
67
|
+
this._state = UnreferencedState.Inactive;
|
|
68
|
+
|
|
69
|
+
// After the node becomes inactive, start the sweep timer after which the node will be ready for sweep.
|
|
70
|
+
if (this.sweepTimeoutMs !== undefined) {
|
|
71
|
+
this.sweepTimer.restart(this.sweepTimeoutMs - this.inactiveTimeoutMs);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
this.updateTracking(currentReferenceTimestampMs);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Updates the unreferenced state based on the provided timestamp. */
|
|
78
|
+
public updateTracking(currentReferenceTimestampMs: number) {
|
|
79
|
+
const unreferencedDurationMs = currentReferenceTimestampMs - this.unreferencedTimestampMs;
|
|
80
|
+
|
|
81
|
+
// If the node has been unreferenced for sweep timeout amount of time, update the state to SweepReady.
|
|
82
|
+
if (this.sweepTimeoutMs !== undefined && unreferencedDurationMs >= this.sweepTimeoutMs) {
|
|
83
|
+
this._state = UnreferencedState.SweepReady;
|
|
84
|
+
this.clearTimers();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// If the node has been unreferenced for inactive timeoutMs amount of time, update the state to inactive.
|
|
89
|
+
// Also, start a timer for the sweep timeout.
|
|
90
|
+
if (unreferencedDurationMs >= this.inactiveTimeoutMs) {
|
|
91
|
+
this._state = UnreferencedState.Inactive;
|
|
92
|
+
this.inactiveTimer.clear();
|
|
93
|
+
|
|
94
|
+
if (this.sweepTimeoutMs !== undefined) {
|
|
95
|
+
this.sweepTimer.restart(this.sweepTimeoutMs - unreferencedDurationMs);
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// The node is still active. Ensure the inactive timer is running with the proper remaining duration.
|
|
101
|
+
this.inactiveTimer.restart(this.inactiveTimeoutMs - unreferencedDurationMs);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private clearTimers() {
|
|
105
|
+
this.inactiveTimer.clear();
|
|
106
|
+
this.sweepTimer.clear();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Stop tracking this node. Reset the unreferenced timers and state, if any. */
|
|
110
|
+
public stopTracking() {
|
|
111
|
+
this.clearTimers();
|
|
112
|
+
this._state = UnreferencedState.Active;
|
|
113
|
+
}
|
|
114
|
+
}
|
package/src/gc/index.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { GarbageCollector } from "./garbageCollection";
|
|
7
|
+
export {
|
|
8
|
+
currentGCVersion,
|
|
9
|
+
defaultInactiveTimeoutMs,
|
|
10
|
+
defaultSessionExpiryDurationMs,
|
|
11
|
+
disableSweepLogKey,
|
|
12
|
+
GCNodeType,
|
|
13
|
+
gcTestModeKey,
|
|
14
|
+
gcTombstoneGenerationOptionName,
|
|
15
|
+
GCVersion,
|
|
16
|
+
gcVersionUpgradeToV2Key,
|
|
17
|
+
IGarbageCollectionRuntime,
|
|
18
|
+
IGarbageCollector,
|
|
19
|
+
IGarbageCollectorCreateParams,
|
|
20
|
+
IGCMetadata,
|
|
21
|
+
IGCStats,
|
|
22
|
+
oneDayMs,
|
|
23
|
+
runGCKey,
|
|
24
|
+
runSessionExpiryKey,
|
|
25
|
+
runSweepKey,
|
|
26
|
+
stableGCVersion,
|
|
27
|
+
sweepAttachmentBlobsKey,
|
|
28
|
+
sweepDatastoresKey,
|
|
29
|
+
throwOnTombstoneLoadKey,
|
|
30
|
+
throwOnTombstoneUsageKey,
|
|
31
|
+
UnreferencedState,
|
|
32
|
+
} from "./gcDefinitions";
|
|
33
|
+
export { sendGCUnexpectedUsageEvent, shouldAllowGcTombstoneEnforcement } from "./gcHelpers";
|
|
34
|
+
export { GCSummaryStateTracker } from "./gcSummaryStateTracker";
|
|
35
|
+
export {
|
|
36
|
+
skipClosureForXDaysKey,
|
|
37
|
+
closuresMapLocalStorageKey,
|
|
38
|
+
SweepReadyUsageDetectionHandler,
|
|
39
|
+
} from "./gcSweepReadyUsageDetection";
|
|
40
|
+
export { UnreferencedStateTracker } from "./gcUnreferencedStateTracker";
|
package/src/index.ts
CHANGED
|
@@ -4,79 +4,76 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
7
|
+
ContainerMessageType,
|
|
8
|
+
ContainerRuntimeMessage,
|
|
9
|
+
IGCRuntimeOptions,
|
|
10
|
+
ISummaryRuntimeOptions,
|
|
11
|
+
ISummaryBaseConfiguration,
|
|
12
|
+
ISummaryConfigurationHeuristics,
|
|
13
|
+
ISummaryConfigurationDisableSummarizer,
|
|
14
|
+
ISummaryConfigurationDisableHeuristics,
|
|
15
|
+
IContainerRuntimeOptions,
|
|
16
|
+
IRootSummaryTreeWithStats,
|
|
17
|
+
isRuntimeMessage,
|
|
18
|
+
RuntimeMessage,
|
|
19
|
+
agentSchedulerId,
|
|
20
|
+
ContainerRuntime,
|
|
21
|
+
RuntimeHeaders,
|
|
22
|
+
AllowTombstoneRequestHeaderKey,
|
|
23
|
+
TombstoneResponseHeaderKey,
|
|
24
|
+
ISummaryConfiguration,
|
|
25
|
+
DefaultSummaryConfiguration,
|
|
26
|
+
ICompressionRuntimeOptions,
|
|
27
|
+
CompressionAlgorithms,
|
|
28
28
|
} from "./containerRuntime";
|
|
29
29
|
export { FluidDataStoreRegistry } from "./dataStoreRegistry";
|
|
30
|
+
export { IGCStats } from "./gc";
|
|
30
31
|
export {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
IPendingLocalState,
|
|
36
|
-
IPendingMessage,
|
|
37
|
-
IPendingState,
|
|
32
|
+
IPendingFlush,
|
|
33
|
+
IPendingLocalState,
|
|
34
|
+
IPendingMessage,
|
|
35
|
+
IPendingState,
|
|
38
36
|
} from "./pendingStateManager";
|
|
39
|
-
export { Summarizer } from "./summarizer";
|
|
40
|
-
export {
|
|
41
|
-
EnqueueSummarizeResult,
|
|
42
|
-
IAckSummaryResult,
|
|
43
|
-
IBaseSummarizeResult,
|
|
44
|
-
IBroadcastSummaryResult,
|
|
45
|
-
ICancellationToken,
|
|
46
|
-
IConnectableRuntime,
|
|
47
|
-
IEnqueueSummarizeOptions,
|
|
48
|
-
IGenerateSummaryTreeResult,
|
|
49
|
-
IGeneratedSummaryStats,
|
|
50
|
-
INackSummaryResult,
|
|
51
|
-
IOnDemandSummarizeOptions,
|
|
52
|
-
IProvideSummarizer,
|
|
53
|
-
IRefreshSummaryAckOptions,
|
|
54
|
-
ISubmitSummaryOpResult,
|
|
55
|
-
ISubmitSummaryOptions,
|
|
56
|
-
ISummarizeOptions,
|
|
57
|
-
ISummarizeResults,
|
|
58
|
-
ISummarizer,
|
|
59
|
-
ISummarizerEvents,
|
|
60
|
-
ISummarizerInternalsProvider,
|
|
61
|
-
ISummarizerRuntime,
|
|
62
|
-
ISummarizingWarning,
|
|
63
|
-
ISummaryCancellationToken,
|
|
64
|
-
IUploadSummaryResult,
|
|
65
|
-
SubmitSummaryResult,
|
|
66
|
-
SummarizeResultPart,
|
|
67
|
-
SummarizerStopReason,
|
|
68
|
-
} from "./summarizerTypes";
|
|
69
37
|
export {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
38
|
+
IAckedSummary,
|
|
39
|
+
ISummarizer,
|
|
40
|
+
ISummarizeResults,
|
|
41
|
+
ISummaryCancellationToken,
|
|
42
|
+
neverCancelledSummaryToken,
|
|
43
|
+
Summarizer,
|
|
44
|
+
SummarizerStopReason,
|
|
45
|
+
SummaryCollection,
|
|
46
|
+
EnqueueSummarizeResult,
|
|
47
|
+
IAckSummaryResult,
|
|
48
|
+
IBaseSummarizeResult,
|
|
49
|
+
IBroadcastSummaryResult,
|
|
50
|
+
ICancellationToken,
|
|
51
|
+
IConnectableRuntime,
|
|
52
|
+
IEnqueueSummarizeOptions,
|
|
53
|
+
IGenerateSummaryTreeResult,
|
|
54
|
+
IGeneratedSummaryStats,
|
|
55
|
+
INackSummaryResult,
|
|
56
|
+
IOnDemandSummarizeOptions,
|
|
57
|
+
IProvideSummarizer,
|
|
58
|
+
IRefreshSummaryAckOptions,
|
|
59
|
+
ISubmitSummaryOpResult,
|
|
60
|
+
ISubmitSummaryOptions,
|
|
61
|
+
ISummarizeOptions,
|
|
62
|
+
ISummarizerEvents,
|
|
63
|
+
ISummarizerInternalsProvider,
|
|
64
|
+
ISummarizerRuntime,
|
|
65
|
+
ISummarizingWarning,
|
|
66
|
+
IUploadSummaryResult,
|
|
67
|
+
SubmitSummaryResult,
|
|
68
|
+
SummarizeResultPart,
|
|
69
|
+
IClientSummaryWatcher,
|
|
70
|
+
ISummary,
|
|
71
|
+
ISummaryCollectionOpEvents,
|
|
72
|
+
ISummaryAckMessage,
|
|
73
|
+
ISummaryNackMessage,
|
|
74
|
+
ISummaryOpMessage,
|
|
75
|
+
OpActionEventListener,
|
|
76
|
+
OpActionEventName,
|
|
77
|
+
ICancellableSummarizerController,
|
|
78
|
+
} from "./summary";
|
|
82
79
|
export { IChunkedOp, unpackRuntimeMessage } from "./opLifecycle";
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Configs and feature gates for solving the 1MB limit.
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
There is a current limitation regarding the size of the payload a Fluid client can send and receive. [The limit is 1MB per payload](https://github.com/microsoft/FluidFramework/issues/9023) and it is currently enforced explicitly with the `BatchTooLarge` error which closes the container.
|
|
6
|
+
|
|
7
|
+
There are two features which can be used to work around this size limit, batch compression and compressed batch chunking. This document describes how to enable/disable them, along with a brief description of how they work.
|
|
8
|
+
|
|
9
|
+
**The features are still considered experimental and for safety and back-compat reasons they are disabled by default.**
|
|
10
|
+
|
|
11
|
+
## Table of contents
|
|
12
|
+
|
|
13
|
+
- [Introduction](#introduction)
|
|
14
|
+
- [Enabling compression](#enabling-compression)
|
|
15
|
+
- [Enabling chunking for compression](#enabling-chunking-for-compression)
|
|
16
|
+
- [Disabling in case of emergency](#disabling-in-case-of-emergency)
|
|
17
|
+
- [Example configs](#example-configs)
|
|
18
|
+
- [How it works](#how-it-works)
|
|
19
|
+
|
|
20
|
+
## Enabling compression
|
|
21
|
+
|
|
22
|
+
**Compression targets payloads which exceed the max batch size (1MB) and it is disabled by default.** To enable compression, use the `IContainerRuntimeOptions.compressionOptions` property, of type `ICompressionRuntimeOptions`.
|
|
23
|
+
|
|
24
|
+
`ICompressionRuntimeOptions` has two properties:
|
|
25
|
+
|
|
26
|
+
- `minimumBatchSizeInBytes` – the minimum size of the batch for which compression should kick in. If the payload is too small, compression may not yield too many benefits. To target the original 1MB issue, a good value here would be to match the default maxBatchSizeInBytes (972800), however, experimentally, a good lower value could be at around 614400 bytes.
|
|
27
|
+
- `compressionAlgorithm` – currently, only `lz4` is supported.
|
|
28
|
+
|
|
29
|
+
## Enabling chunking for compression
|
|
30
|
+
|
|
31
|
+
**Op chunking for compression targets payloads which exceed the max batch size (1MB) after compression.** So, only payloads which are already compressed. By default, the feature is disabled.
|
|
32
|
+
|
|
33
|
+
To enable, use the `IContainerRuntimeOptions.chunkSizeInBytes` property, which represents the size of the chunked ops, when chunking is necessary. When chunking is performed, the large op is split into smaller ops (chunks). This config represents the size of the chunks. The value enables a trade-off between large chunks / few ops and small chunks / many ops. A good value for this would be at around 614400.
|
|
34
|
+
|
|
35
|
+
This config would govern chunking compressed batches only. We will not be enabling chunking across all types of ops/batches but **only when compression is enabled and when the batch is compressed**, and its payload size is more than `maxBatchSizeInBytes`. Therefore, for this feature to be working, it is required that compression is enabled using `IContainerRuntimeOptions.compressionOptions`.
|
|
36
|
+
|
|
37
|
+
It is recommended to also change the `maxBatchSizeInBytes` property in `IContainerRuntimeOptions`. By default, if unspecified it is 972800. We recommend a lower value such as `716800`, to account for any overhead on the server side. The reason for this is that chunking will only kick in after this configuration limit is exceeded. If the limit is too high, we might allow batches which are under 1MB but can increase in size due to overhead after they reach the server.
|
|
38
|
+
|
|
39
|
+
## Disabling in case of emergency
|
|
40
|
+
|
|
41
|
+
If the features are enabled using the configs, they can be disabled at runtime via feature gates as following:
|
|
42
|
+
|
|
43
|
+
- `Fluid.ContainerRuntime.DisableCompression` - if set to true, will disable compression (this has a side effect of also disabling chunking, as chunking is invoked only for compressed payloads).
|
|
44
|
+
- `Fluid.ContainerRuntime.DisableCompressionChunking` - if set to true, will disable chunking for compression.
|
|
45
|
+
|
|
46
|
+
## Example configs
|
|
47
|
+
|
|
48
|
+
Enable only compression:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
const runtimeOptions: IContainerRuntimeOptions = {
|
|
52
|
+
compressionOptions: {
|
|
53
|
+
minimumBatchSizeInBytes: 614400,
|
|
54
|
+
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
55
|
+
},
|
|
56
|
+
maxBatchSizeInBytes: 716800,
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Enable compression and chunking:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
const runtimeOptions: IContainerRuntimeOptions = {
|
|
64
|
+
compressionOptions: {
|
|
65
|
+
minimumBatchSizeInBytes: 614400,
|
|
66
|
+
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
67
|
+
},
|
|
68
|
+
chunkSizeInBytes: 614400,
|
|
69
|
+
maxBatchSizeInBytes: 716800,
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## How it works
|
|
74
|
+
|
|
75
|
+
Compression currently works as a runtime layer over the regular op sending/receiving pipeline.
|
|
76
|
+
|
|
77
|
+
If we have a batch with a size larger than the configured minimum required for compression (in the example let’s say it’s 850 bytes), as following:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
+-----------+-----------+-----------+-----------+
|
|
81
|
+
| Op 1 | Op 2 | Op 3 | Op 4 |
|
|
82
|
+
| SeqNum: 1 | SeqNum: 2 | SeqNum: 3 | SeqNum: 4 |
|
|
83
|
+
| Size: 100 | Size: 150 | Size: 200 | Size: 400 |
|
|
84
|
+
+-----------+-----------+-----------+-----------+
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The total size of the batch is 850 bytes. The client which needs to send the batch would compress the batch to a smaller size (200 bytes) and will send a new batch like the following:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
+--------------------+-----------+-----------+-----------+
|
|
91
|
+
| Op 1 | Op 2 | Op 3 | Op 4 |
|
|
92
|
+
| SeqNum: 1 | SeqNum: 2 | SeqNum: 3 | SeqNum: 4 |
|
|
93
|
+
| Size: 200 | Size: 0 | Size: 0 | Size: 0 |
|
|
94
|
+
| Compression: 'lz4' | | | |
|
|
95
|
+
+--------------------+-----------+-----------+-----------+
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The first op in the batch is the only one with content (which is opaque due to it being compressed), the rest of the ops serve only to reserve the sequence numbers so that the state machine which rebuilds the original batch on the receiving client can reconstruct the original batch.
|
|
99
|
+
|
|
100
|
+
When the batch is received by a client, it will detect the first op as being compressed, it will decompress it and store it in memory. For each empty op subsequently received, it will fetch the uncompressed content from memory and rebuild the original ops. The original ops are then processed by the runtime and applied accordingly.
|
|
101
|
+
So, compression virtualizes the batch.
|
|
102
|
+
|
|
103
|
+
After compression, the first op in the batch can exceed 1MB, therefore it would still be rejected. In this case, another layer of virtualization is added after compression (and before decompression, symmetrically on the receiving end).
|
|
104
|
+
|
|
105
|
+
The first op in the compressed batch can be chunked into smaller ops which can be sent outside the original batch. However, to conveniently maintain the batch semantics, the last chunk (the chunk which triggers rebuilding the original op) is the first op in the new batch.
|
|
106
|
+
|
|
107
|
+
To illustrate, let’s take the large batch below:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
+--------------------+-----------+-----------+-----------+
|
|
111
|
+
| Op 1 | Op 2 | Op 3 | Op 4 |
|
|
112
|
+
| SeqNum: 1 | SeqNum: 2 | SeqNum: 3 | SeqNum: 4 |
|
|
113
|
+
| Size: 900 | Size: 0 | Size: 0 | Size: 0 |
|
|
114
|
+
| Compression: 'lz4' | | | |
|
|
115
|
+
+--------------------+-----------+-----------+-----------+
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
This will produce the following batches:
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
+-----------+
|
|
122
|
+
| Chunk 1/3 |
|
|
123
|
+
| SeqNum: 1 |
|
|
124
|
+
| Size: 300 |
|
|
125
|
+
+-----------+
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
+-----------+
|
|
131
|
+
| Chunk 2/3 |
|
|
132
|
+
| SeqNum: 2 |
|
|
133
|
+
| Size: 300 |
|
|
134
|
+
+-----------+
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
+-----------+-----------+-----------+-----------+
|
|
140
|
+
| Chunk 3/3 | Op 2 | Op 3 | Op 4 |
|
|
141
|
+
| SeqNum: 3 | SeqNum: 4 | SeqNum: 5 | SeqNum: 6 |
|
|
142
|
+
| Size: 300 | Size: 0 | Size: 0 | Size: 0 |
|
|
143
|
+
+-----------+-----------+-----------+-----------+
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The first 2 chunks are sent in their own batches, while the last chunk is the first op in the last batch which contains the ops reserving the required sequence numbers.
|
|
147
|
+
|
|
148
|
+
Notice that the sequence numbers don’t matter here, as all ops will be based off the same reference sequence number, so the sequence number will be recalculated for all, without additional work.
|
|
149
|
+
|
|
150
|
+
Additionally, as compression preserves the original uncompressed batch layout in terms of the number of ops by using empty ops to reserve the sequence numbers, this ensures that the clients will always receive the exact count of ops to rebuild the uncompressed batch sequentially.
|
|
151
|
+
|
|
152
|
+
On the receiving end, the client will accumulate chunks 1 and 2 and keep them in memory. When chunk 3 is received, the original large, decompressed op will be rebuilt, and the runtime will then process the batch as if it is a compressed batch.
|