@fluidframework/container-runtime 2.0.0-internal.3.1.0 → 2.0.0-internal.3.2.1
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/dist/blobManager.d.ts +6 -0
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +31 -6
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +17 -15
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +158 -121
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +21 -12
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +76 -50
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +9 -10
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +42 -49
- package/dist/dataStores.js.map +1 -1
- package/dist/{garbageCollection.d.ts → gc/garbageCollection.d.ts} +5 -200
- package/dist/gc/garbageCollection.d.ts.map +1 -0
- package/dist/{garbageCollection.js → gc/garbageCollection.js} +77 -353
- 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} +24 -2
- package/dist/gc/gcDefinitions.js.map +1 -0
- package/{lib/garbageCollectionHelpers.d.ts → dist/gc/gcHelpers.d.ts} +5 -1
- package/dist/gc/gcHelpers.d.ts.map +1 -0
- package/dist/{garbageCollectionHelpers.js → gc/gcHelpers.js} +27 -7
- 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/dist/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
- package/dist/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +2 -2
- 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 +7 -36
- 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/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +1 -0
- package/dist/opLifecycle/opCompressor.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 +20 -12
- 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 +59 -28
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +1 -2
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +14 -9
- package/dist/pendingStateManager.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/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} +158 -56
- package/dist/summary/runningSummarizer.js.map +1 -0
- package/dist/{summarizer.d.ts → summary/summarizer.d.ts} +2 -4
- package/dist/summary/summarizer.d.ts.map +1 -0
- package/dist/{summarizer.js → summary/summarizer.js} +1 -61
- 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/dist/{summarizerHeuristics.d.ts → summary/summarizerHeuristics.d.ts} +1 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -0
- package/dist/summary/summarizerHeuristics.js.map +1 -0
- package/{lib → dist/summary}/summarizerTypes.d.ts +1 -1
- 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/summary/summaryCollection.js.map +1 -0
- package/{lib → dist/summary}/summaryFormat.d.ts +1 -43
- package/dist/summary/summaryFormat.d.ts.map +1 -0
- package/dist/{summaryFormat.js → summary/summaryFormat.js} +1 -10
- package/dist/summary/summaryFormat.js.map +1 -0
- package/dist/summary/summaryGenerator.d.ts.map +1 -0
- package/dist/{summaryGenerator.js → summary/summaryGenerator.js} +1 -2
- 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/summary/summaryManager.js.map +1 -0
- package/lib/blobManager.d.ts +6 -0
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +28 -3
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +17 -15
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +127 -90
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +21 -12
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +64 -38
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +9 -10
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +33 -40
- package/lib/dataStores.js.map +1 -1
- package/lib/{garbageCollection.d.ts → gc/garbageCollection.d.ts} +5 -200
- package/lib/gc/garbageCollection.d.ts.map +1 -0
- package/lib/{garbageCollection.js → gc/garbageCollection.js} +44 -319
- 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} +23 -1
- package/lib/gc/gcDefinitions.js.map +1 -0
- package/{dist/garbageCollectionHelpers.d.ts → lib/gc/gcHelpers.d.ts} +5 -1
- package/lib/gc/gcHelpers.d.ts.map +1 -0
- package/lib/{garbageCollectionHelpers.js → gc/gcHelpers.js} +20 -2
- 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/lib/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
- package/lib/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +1 -1
- 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 +7 -36
- 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/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +1 -0
- package/lib/opLifecycle/opCompressor.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 +20 -12
- 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 +60 -29
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +1 -2
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +14 -9
- package/lib/pendingStateManager.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/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} +159 -57
- package/lib/summary/runningSummarizer.js.map +1 -0
- package/lib/{summarizer.d.ts → summary/summarizer.d.ts} +2 -4
- package/lib/summary/summarizer.d.ts.map +1 -0
- package/lib/{summarizer.js → summary/summarizer.js} +3 -63
- 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/lib/{summarizerHeuristics.d.ts → summary/summarizerHeuristics.d.ts} +1 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
- package/lib/summary/summarizerHeuristics.js.map +1 -0
- package/{dist → lib/summary}/summarizerTypes.d.ts +1 -1
- 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/summary/summaryCollection.js.map +1 -0
- package/{dist → lib/summary}/summaryFormat.d.ts +1 -43
- package/lib/summary/summaryFormat.d.ts.map +1 -0
- package/lib/{summaryFormat.js → summary/summaryFormat.js} +0 -8
- package/lib/summary/summaryFormat.js.map +1 -0
- package/lib/summary/summaryGenerator.d.ts.map +1 -0
- package/lib/{summaryGenerator.js → summary/summaryGenerator.js} +1 -2
- 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/summary/summaryManager.js.map +1 -0
- package/package.json +125 -122
- package/src/blobManager.ts +33 -3
- package/src/containerRuntime.ts +178 -106
- package/src/dataStoreContext.ts +90 -49
- package/src/dataStores.ts +44 -51
- package/{garbageCollection.md → src/gc/garbageCollection.md} +2 -2
- package/src/{garbageCollection.ts → gc/garbageCollection.ts} +90 -560
- package/src/gc/gcDefinitions.ts +244 -0
- package/src/{garbageCollectionHelpers.ts → gc/gcHelpers.ts} +26 -1
- package/src/gc/gcSummaryStateTracker.ts +339 -0
- package/src/{gcSweepReadyUsageDetection.ts → gc/gcSweepReadyUsageDetection.ts} +1 -1
- package/src/gc/gcUnreferencedStateTracker.ts +114 -0
- package/src/gc/index.ts +40 -0
- package/src/index.ts +10 -14
- package/src/opLifecycle/batchManager.ts +7 -54
- package/src/opLifecycle/definitions.ts +4 -0
- package/src/opLifecycle/opCompressor.ts +1 -0
- package/src/opLifecycle/opSplitter.ts +33 -14
- package/src/opLifecycle/outbox.ts +84 -38
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +26 -14
- package/src/summary/index.ts +99 -0
- package/src/{runningSummarizer.ts → summary/runningSummarizer.ts} +279 -139
- package/src/{summarizer.ts → summary/summarizer.ts} +5 -76
- package/src/{summarizerHeuristics.ts → summary/summarizerHeuristics.ts} +1 -1
- package/src/{summarizerTypes.ts → summary/summarizerTypes.ts} +1 -1
- package/src/{summaryFormat.ts → summary/summaryFormat.ts} +1 -53
- package/src/{summaryGenerator.ts → summary/summaryGenerator.ts} +9 -9
- package/src/{summaryManager.ts → summary/summaryManager.ts} +1 -1
- package/dist/garbageCollection.d.ts.map +0 -1
- package/dist/garbageCollection.js.map +0 -1
- package/dist/garbageCollectionConstants.d.ts +0 -26
- package/dist/garbageCollectionConstants.d.ts.map +0 -1
- package/dist/garbageCollectionConstants.js.map +0 -1
- package/dist/garbageCollectionHelpers.d.ts.map +0 -1
- package/dist/garbageCollectionHelpers.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 -26
- package/lib/garbageCollectionConstants.d.ts.map +0 -1
- package/lib/garbageCollectionConstants.js.map +0 -1
- package/lib/garbageCollectionHelpers.d.ts.map +0 -1
- package/lib/garbageCollectionHelpers.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/garbageCollectionConstants.ts +0 -44
- /package/dist/{gcSweepReadyUsageDetection.d.ts → gc/gcSweepReadyUsageDetection.d.ts} +0 -0
- /package/dist/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
- /package/dist/{orderedClientElection.js → summary/orderedClientElection.js} +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/{summarizerHeuristics.js → summary/summarizerHeuristics.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/{summaryCollection.js → summary/summaryCollection.js} +0 -0
- /package/dist/{summaryGenerator.d.ts → summary/summaryGenerator.d.ts} +0 -0
- /package/dist/{summaryManager.js → summary/summaryManager.js} +0 -0
- /package/lib/{gcSweepReadyUsageDetection.d.ts → gc/gcSweepReadyUsageDetection.d.ts} +0 -0
- /package/lib/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
- /package/lib/{orderedClientElection.js → summary/orderedClientElection.js} +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/{summarizerHeuristics.js → summary/summarizerHeuristics.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/{summaryCollection.js → summary/summaryCollection.js} +0 -0
- /package/lib/{summaryGenerator.d.ts → summary/summaryGenerator.d.ts} +0 -0
- /package/lib/{summaryManager.js → summary/summaryManager.js} +0 -0
- /package/src/{orderedClientElection.ts → summary/orderedClientElection.ts} +0 -0
- /package/src/{runWhileConnectedCoordinator.ts → summary/runWhileConnectedCoordinator.ts} +0 -0
- /package/src/{summarizerClientElection.ts → summary/summarizerClientElection.ts} +0 -0
- /package/src/{summarizerHandle.ts → summary/summarizerHandle.ts} +0 -0
- /package/src/{summaryCollection.ts → summary/summaryCollection.ts} +0 -0
|
@@ -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
|
@@ -27,15 +27,22 @@ export {
|
|
|
27
27
|
CompressionAlgorithms,
|
|
28
28
|
} from "./containerRuntime";
|
|
29
29
|
export { FluidDataStoreRegistry } from "./dataStoreRegistry";
|
|
30
|
-
export { IGCStats } from "./
|
|
30
|
+
export { IGCStats } from "./gc";
|
|
31
31
|
export {
|
|
32
32
|
IPendingFlush,
|
|
33
33
|
IPendingLocalState,
|
|
34
34
|
IPendingMessage,
|
|
35
35
|
IPendingState,
|
|
36
36
|
} from "./pendingStateManager";
|
|
37
|
-
export { Summarizer } from "./summarizer";
|
|
38
37
|
export {
|
|
38
|
+
IAckedSummary,
|
|
39
|
+
ISummarizer,
|
|
40
|
+
ISummarizeResults,
|
|
41
|
+
ISummaryCancellationToken,
|
|
42
|
+
neverCancelledSummaryToken,
|
|
43
|
+
Summarizer,
|
|
44
|
+
SummarizerStopReason,
|
|
45
|
+
SummaryCollection,
|
|
39
46
|
EnqueueSummarizeResult,
|
|
40
47
|
IAckSummaryResult,
|
|
41
48
|
IBaseSummarizeResult,
|
|
@@ -52,20 +59,13 @@ export {
|
|
|
52
59
|
ISubmitSummaryOpResult,
|
|
53
60
|
ISubmitSummaryOptions,
|
|
54
61
|
ISummarizeOptions,
|
|
55
|
-
ISummarizeResults,
|
|
56
|
-
ISummarizer,
|
|
57
62
|
ISummarizerEvents,
|
|
58
63
|
ISummarizerInternalsProvider,
|
|
59
64
|
ISummarizerRuntime,
|
|
60
65
|
ISummarizingWarning,
|
|
61
|
-
ISummaryCancellationToken,
|
|
62
66
|
IUploadSummaryResult,
|
|
63
67
|
SubmitSummaryResult,
|
|
64
68
|
SummarizeResultPart,
|
|
65
|
-
SummarizerStopReason,
|
|
66
|
-
} from "./summarizerTypes";
|
|
67
|
-
export {
|
|
68
|
-
IAckedSummary,
|
|
69
69
|
IClientSummaryWatcher,
|
|
70
70
|
ISummary,
|
|
71
71
|
ISummaryCollectionOpEvents,
|
|
@@ -74,10 +74,6 @@ export {
|
|
|
74
74
|
ISummaryOpMessage,
|
|
75
75
|
OpActionEventListener,
|
|
76
76
|
OpActionEventName,
|
|
77
|
-
SummaryCollection,
|
|
78
|
-
} from "./summaryCollection";
|
|
79
|
-
export {
|
|
80
77
|
ICancellableSummarizerController,
|
|
81
|
-
|
|
82
|
-
} from "./runWhileConnectedCoordinator";
|
|
78
|
+
} from "./summary";
|
|
83
79
|
export { IChunkedOp, unpackRuntimeMessage } from "./opLifecycle";
|
|
@@ -3,14 +3,10 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
7
|
-
import { UsageError } from "@fluidframework/driver-utils";
|
|
8
|
-
import { ChildLogger } from "@fluidframework/telemetry-utils";
|
|
9
6
|
import { ICompressionRuntimeOptions } from "../containerRuntime";
|
|
10
7
|
import { BatchMessage, IBatch, IBatchCheckpoint } from "./definitions";
|
|
11
8
|
|
|
12
9
|
export interface IBatchManagerOptions {
|
|
13
|
-
readonly enableOpReentryCheck?: boolean;
|
|
14
10
|
readonly hardLimit: number;
|
|
15
11
|
readonly softLimit?: number;
|
|
16
12
|
readonly compressionOptions?: ICompressionRuntimeOptions;
|
|
@@ -20,17 +16,8 @@ export interface IBatchManagerOptions {
|
|
|
20
16
|
* Helper class that manages partial batch & rollback.
|
|
21
17
|
*/
|
|
22
18
|
export class BatchManager {
|
|
23
|
-
private readonly logger;
|
|
24
19
|
private pendingBatch: BatchMessage[] = [];
|
|
25
20
|
private batchContentSize = 0;
|
|
26
|
-
/**
|
|
27
|
-
* Track the number of ops which were detected to have a mismatched
|
|
28
|
-
* reference sequence number, in order to self-throttle the telemetry events.
|
|
29
|
-
*
|
|
30
|
-
* This should be removed as part of ADO:2322
|
|
31
|
-
*/
|
|
32
|
-
private readonly maxMismatchedOpsToReport = 5;
|
|
33
|
-
private mismatchedOpsReported = 0;
|
|
34
21
|
|
|
35
22
|
public get length() {
|
|
36
23
|
return this.pendingBatch.length;
|
|
@@ -39,13 +26,15 @@ export class BatchManager {
|
|
|
39
26
|
return this.batchContentSize;
|
|
40
27
|
}
|
|
41
28
|
|
|
42
|
-
|
|
43
|
-
this.
|
|
29
|
+
public get referenceSequenceNumber(): number | undefined {
|
|
30
|
+
return this.pendingBatch.length === 0
|
|
31
|
+
? undefined
|
|
32
|
+
: this.pendingBatch[this.pendingBatch.length - 1].referenceSequenceNumber;
|
|
44
33
|
}
|
|
45
34
|
|
|
46
|
-
public
|
|
47
|
-
this.checkReferenceSequenceNumber(message);
|
|
35
|
+
constructor(public readonly options: IBatchManagerOptions) {}
|
|
48
36
|
|
|
37
|
+
public push(message: BatchMessage): boolean {
|
|
49
38
|
const contentSize = this.batchContentSize + (message.contents?.length ?? 0);
|
|
50
39
|
const opCount = this.pendingBatch.length;
|
|
51
40
|
|
|
@@ -86,6 +75,7 @@ export class BatchManager {
|
|
|
86
75
|
const batch: IBatch = {
|
|
87
76
|
content: this.pendingBatch,
|
|
88
77
|
contentSizeInBytes: this.batchContentSize,
|
|
78
|
+
referenceSequenceNumber: this.referenceSequenceNumber,
|
|
89
79
|
};
|
|
90
80
|
|
|
91
81
|
this.pendingBatch = [];
|
|
@@ -112,43 +102,6 @@ export class BatchManager {
|
|
|
112
102
|
},
|
|
113
103
|
};
|
|
114
104
|
}
|
|
115
|
-
|
|
116
|
-
private checkReferenceSequenceNumber(message: BatchMessage) {
|
|
117
|
-
if (
|
|
118
|
-
this.pendingBatch.length === 0 ||
|
|
119
|
-
message.referenceSequenceNumber === this.pendingBatch[0].referenceSequenceNumber
|
|
120
|
-
) {
|
|
121
|
-
// The reference sequence numbers are stable
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const telemetryProperties = {
|
|
126
|
-
referenceSequenceNumber: this.pendingBatch[0].referenceSequenceNumber,
|
|
127
|
-
messageReferenceSequenceNumber: message.referenceSequenceNumber,
|
|
128
|
-
type: message.deserializedContent.type,
|
|
129
|
-
length: this.pendingBatch.length,
|
|
130
|
-
enableOpReentryCheck: this.options.enableOpReentryCheck === true,
|
|
131
|
-
};
|
|
132
|
-
const error = new UsageError("Submission of an out of order message");
|
|
133
|
-
const eventName = "ReferenceSequenceNumberMismatch";
|
|
134
|
-
|
|
135
|
-
if (this.options.enableOpReentryCheck === true) {
|
|
136
|
-
this.logger.sendErrorEvent({ eventName, ...telemetryProperties }, error);
|
|
137
|
-
throw error;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {
|
|
141
|
-
this.logger.sendErrorEvent(
|
|
142
|
-
{
|
|
143
|
-
eventName,
|
|
144
|
-
...telemetryProperties,
|
|
145
|
-
ops: this.mismatchedOpsReported,
|
|
146
|
-
maxOps: this.maxMismatchedOpsToReport,
|
|
147
|
-
},
|
|
148
|
-
error,
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
105
|
}
|
|
153
106
|
|
|
154
107
|
const addBatchMetadata = (batch: IBatch): IBatch => {
|
|
@@ -30,6 +30,10 @@ export interface IBatch {
|
|
|
30
30
|
* All the messages in the batch
|
|
31
31
|
*/
|
|
32
32
|
readonly content: BatchMessage[];
|
|
33
|
+
/**
|
|
34
|
+
* The reference sequence number for the batch
|
|
35
|
+
*/
|
|
36
|
+
readonly referenceSequenceNumber: number | undefined;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
export interface IBatchCheckpoint {
|
|
@@ -25,7 +25,9 @@ export class OpSplitter {
|
|
|
25
25
|
|
|
26
26
|
constructor(
|
|
27
27
|
chunks: [string, string[]][],
|
|
28
|
-
private readonly submitBatchFn:
|
|
28
|
+
private readonly submitBatchFn:
|
|
29
|
+
| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)
|
|
30
|
+
| undefined,
|
|
29
31
|
private readonly chunkSizeInBytes: number,
|
|
30
32
|
private readonly maxBatchSizeInBytes: number,
|
|
31
33
|
logger: ITelemetryLogger,
|
|
@@ -138,6 +140,10 @@ export class OpSplitter {
|
|
|
138
140
|
batch.contentSizeInBytes > 0 && batch.content.length > 0,
|
|
139
141
|
0x514 /* Batch needs to be non-empty */,
|
|
140
142
|
);
|
|
143
|
+
assert(
|
|
144
|
+
batch.referenceSequenceNumber !== undefined,
|
|
145
|
+
0x58a /* Batch must have a reference sequence number if non-empty */,
|
|
146
|
+
);
|
|
141
147
|
assert(this.chunkSizeInBytes !== 0, 0x515 /* Chunk size needs to be non-zero */);
|
|
142
148
|
assert(
|
|
143
149
|
this.chunkSizeInBytes < this.maxBatchSizeInBytes,
|
|
@@ -160,14 +166,17 @@ export class OpSplitter {
|
|
|
160
166
|
assert(this.submitBatchFn !== undefined, 0x519 /* We don't support old loaders */);
|
|
161
167
|
// Send the first N-1 chunks immediately
|
|
162
168
|
for (const chunk of chunks.slice(0, -1)) {
|
|
163
|
-
this.submitBatchFn(
|
|
169
|
+
this.submitBatchFn(
|
|
170
|
+
[chunkToBatchMessage(chunk, batch.referenceSequenceNumber)],
|
|
171
|
+
batch.referenceSequenceNumber,
|
|
172
|
+
);
|
|
164
173
|
}
|
|
165
174
|
|
|
166
175
|
// The last chunk will be part of the new batch and needs to
|
|
167
176
|
// preserve the batch metadata of the original batch
|
|
168
177
|
const lastChunk = chunkToBatchMessage(
|
|
169
178
|
chunks[chunks.length - 1],
|
|
170
|
-
|
|
179
|
+
batch.referenceSequenceNumber,
|
|
171
180
|
{ batch: firstMessage.metadata?.batch },
|
|
172
181
|
);
|
|
173
182
|
|
|
@@ -182,6 +191,7 @@ export class OpSplitter {
|
|
|
182
191
|
return {
|
|
183
192
|
content: [lastChunk, ...restOfMessages],
|
|
184
193
|
contentSizeInBytes: lastChunk.contents?.length ?? 0,
|
|
194
|
+
referenceSequenceNumber: batch.referenceSequenceNumber,
|
|
185
195
|
};
|
|
186
196
|
}
|
|
187
197
|
}
|
|
@@ -212,27 +222,36 @@ export const splitOp = (op: BatchMessage, chunkSizeInBytes: number): IChunkedOp[
|
|
|
212
222
|
);
|
|
213
223
|
|
|
214
224
|
const contentLength = op.contents.length;
|
|
215
|
-
const
|
|
225
|
+
const chunkCount = Math.floor((contentLength - 1) / chunkSizeInBytes) + 2;
|
|
216
226
|
let offset = 0;
|
|
217
|
-
for (let i = 1; i
|
|
227
|
+
for (let i = 1; i < chunkCount; i++) {
|
|
218
228
|
const chunk: IChunkedOp = {
|
|
219
229
|
chunkId: i,
|
|
220
230
|
contents: op.contents.substr(offset, chunkSizeInBytes),
|
|
221
231
|
originalType: op.deserializedContent.type,
|
|
222
|
-
totalChunks:
|
|
232
|
+
totalChunks: chunkCount,
|
|
223
233
|
};
|
|
224
234
|
|
|
225
|
-
if (i === chunkN) {
|
|
226
|
-
// We don't need to port these to all the chunks,
|
|
227
|
-
// as we rebuild the original op when we process the
|
|
228
|
-
// last chunk, therefore it is the only one that needs it.
|
|
229
|
-
chunk.originalMetadata = op.metadata;
|
|
230
|
-
chunk.originalCompression = op.compression;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
235
|
chunks.push(chunk);
|
|
234
236
|
offset += chunkSizeInBytes;
|
|
237
|
+
assert(
|
|
238
|
+
i === chunkCount - 1 || offset <= contentLength,
|
|
239
|
+
0x58b /* Content offset within bounds */,
|
|
240
|
+
);
|
|
235
241
|
}
|
|
236
242
|
|
|
243
|
+
assert(offset >= contentLength, 0x58c /* Content offset equal or larger than content length */);
|
|
244
|
+
// The last chunk has empty contents, to minimize the risk of the
|
|
245
|
+
// resulting payload exceeding 1MB due to the overhead from the empty ops
|
|
246
|
+
// which will be bundled with this op.
|
|
247
|
+
chunks.push({
|
|
248
|
+
chunkId: chunkCount,
|
|
249
|
+
contents: "",
|
|
250
|
+
originalType: op.deserializedContent.type,
|
|
251
|
+
totalChunks: chunkCount,
|
|
252
|
+
originalMetadata: op.metadata,
|
|
253
|
+
originalCompression: op.compression,
|
|
254
|
+
});
|
|
255
|
+
|
|
237
256
|
return chunks;
|
|
238
257
|
};
|
|
@@ -6,8 +6,13 @@
|
|
|
6
6
|
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
7
7
|
import { assert } from "@fluidframework/common-utils";
|
|
8
8
|
import { IContainerContext } from "@fluidframework/container-definitions";
|
|
9
|
-
import { GenericError } from "@fluidframework/container-utils";
|
|
9
|
+
import { GenericError, UsageError } from "@fluidframework/container-utils";
|
|
10
10
|
import { MessageType } from "@fluidframework/protocol-definitions";
|
|
11
|
+
import {
|
|
12
|
+
ChildLogger,
|
|
13
|
+
loggerToMonitoringContext,
|
|
14
|
+
MonitoringContext,
|
|
15
|
+
} from "@fluidframework/telemetry-utils";
|
|
11
16
|
import { ICompressionRuntimeOptions } from "../containerRuntime";
|
|
12
17
|
import { PendingStateManager } from "../pendingStateManager";
|
|
13
18
|
import { BatchManager } from "./batchManager";
|
|
@@ -19,7 +24,7 @@ export interface IOutboxConfig {
|
|
|
19
24
|
readonly compressionOptions: ICompressionRuntimeOptions;
|
|
20
25
|
// The maximum size of a batch that we can send over the wire.
|
|
21
26
|
readonly maxBatchSizeInBytes: number;
|
|
22
|
-
readonly
|
|
27
|
+
readonly disablePartialFlush: boolean;
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
export interface IOutboxParameters {
|
|
@@ -33,11 +38,22 @@ export interface IOutboxParameters {
|
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
export class Outbox {
|
|
41
|
+
private readonly mc: MonitoringContext;
|
|
36
42
|
private readonly attachFlowBatch: BatchManager;
|
|
37
43
|
private readonly mainBatch: BatchManager;
|
|
38
|
-
private readonly defaultAttachFlowSoftLimitInBytes =
|
|
44
|
+
private readonly defaultAttachFlowSoftLimitInBytes = 320 * 1024;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Track the number of ops which were detected to have a mismatched
|
|
48
|
+
* reference sequence number, in order to self-throttle the telemetry events.
|
|
49
|
+
*
|
|
50
|
+
* This should be removed as part of ADO:2322
|
|
51
|
+
*/
|
|
52
|
+
private readonly maxMismatchedOpsToReport = 3;
|
|
53
|
+
private mismatchedOpsReported = 0;
|
|
39
54
|
|
|
40
55
|
constructor(private readonly params: IOutboxParameters) {
|
|
56
|
+
this.mc = loggerToMonitoringContext(ChildLogger.create(params.logger, "Outbox"));
|
|
41
57
|
const isCompressionEnabled =
|
|
42
58
|
this.params.config.compressionOptions.minimumBatchSizeInBytes !==
|
|
43
59
|
Number.POSITIVE_INFINITY;
|
|
@@ -45,28 +61,63 @@ export class Outbox {
|
|
|
45
61
|
const hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;
|
|
46
62
|
const softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;
|
|
47
63
|
|
|
48
|
-
this.attachFlowBatch = new BatchManager(
|
|
49
|
-
|
|
50
|
-
hardLimit,
|
|
51
|
-
softLimit,
|
|
52
|
-
enableOpReentryCheck: params.config.enableOpReentryCheck,
|
|
53
|
-
},
|
|
54
|
-
params.logger,
|
|
55
|
-
);
|
|
56
|
-
this.mainBatch = new BatchManager(
|
|
57
|
-
{
|
|
58
|
-
hardLimit,
|
|
59
|
-
enableOpReentryCheck: params.config.enableOpReentryCheck,
|
|
60
|
-
},
|
|
61
|
-
params.logger,
|
|
62
|
-
);
|
|
64
|
+
this.attachFlowBatch = new BatchManager({ hardLimit, softLimit });
|
|
65
|
+
this.mainBatch = new BatchManager({ hardLimit });
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
public get isEmpty(): boolean {
|
|
66
69
|
return this.attachFlowBatch.length === 0 && this.mainBatch.length === 0;
|
|
67
70
|
}
|
|
68
71
|
|
|
72
|
+
/**
|
|
73
|
+
* If we detect that the reference sequence number of the incoming message does not match
|
|
74
|
+
* what was already in the batch managers, this means that batching has been interrupted so
|
|
75
|
+
* we will flush the accumulated messages to account for that and create a new batch with the new
|
|
76
|
+
* message as the first message.
|
|
77
|
+
*
|
|
78
|
+
* @param message - the incoming message
|
|
79
|
+
*/
|
|
80
|
+
private maybeFlushPartialBatch(message: BatchMessage) {
|
|
81
|
+
const mainBatchReference = this.mainBatch.referenceSequenceNumber;
|
|
82
|
+
const attachFlowBatchReference = this.attachFlowBatch.referenceSequenceNumber;
|
|
83
|
+
assert(
|
|
84
|
+
this.params.config.disablePartialFlush ||
|
|
85
|
+
mainBatchReference === undefined ||
|
|
86
|
+
attachFlowBatchReference === undefined ||
|
|
87
|
+
mainBatchReference === attachFlowBatchReference,
|
|
88
|
+
0x58d /* Reference sequence numbers from both batches must be in sync */,
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
if (
|
|
92
|
+
(mainBatchReference === undefined ||
|
|
93
|
+
mainBatchReference === message.referenceSequenceNumber) &&
|
|
94
|
+
(attachFlowBatchReference === undefined ||
|
|
95
|
+
attachFlowBatchReference === message.referenceSequenceNumber)
|
|
96
|
+
) {
|
|
97
|
+
// The reference sequence numbers are stable, there is nothing to do
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {
|
|
102
|
+
this.mc.logger.sendErrorEvent(
|
|
103
|
+
{
|
|
104
|
+
eventName: "ReferenceSequenceNumberMismatch",
|
|
105
|
+
mainReferenceSequenceNumber: mainBatchReference,
|
|
106
|
+
attachReferenceSequenceNumber: attachFlowBatchReference,
|
|
107
|
+
messageReferenceSequenceNumber: message.referenceSequenceNumber,
|
|
108
|
+
},
|
|
109
|
+
new UsageError("Submission of an out of order message"),
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!this.params.config.disablePartialFlush) {
|
|
114
|
+
this.flush();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
69
118
|
public submit(message: BatchMessage) {
|
|
119
|
+
this.maybeFlushPartialBatch(message);
|
|
120
|
+
|
|
70
121
|
if (!this.mainBatch.push(message)) {
|
|
71
122
|
throw new GenericError("BatchTooLarge", /* error */ undefined, {
|
|
72
123
|
opSize: message.contents?.length ?? 0,
|
|
@@ -78,6 +129,8 @@ export class Outbox {
|
|
|
78
129
|
}
|
|
79
130
|
|
|
80
131
|
public submitAttach(message: BatchMessage) {
|
|
132
|
+
this.maybeFlushPartialBatch(message);
|
|
133
|
+
|
|
81
134
|
if (!this.attachFlowBatch.push(message)) {
|
|
82
135
|
// BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged
|
|
83
136
|
// when queue is not empty.
|
|
@@ -113,9 +166,9 @@ export class Outbox {
|
|
|
113
166
|
|
|
114
167
|
private flushInternal(rawBatch: IBatch) {
|
|
115
168
|
const processedBatch = this.compressBatch(rawBatch);
|
|
116
|
-
|
|
169
|
+
this.sendBatch(processedBatch);
|
|
117
170
|
|
|
118
|
-
this.persistBatch(
|
|
171
|
+
this.persistBatch(rawBatch.content);
|
|
119
172
|
}
|
|
120
173
|
|
|
121
174
|
private compressBatch(batch: IBatch): IBatch {
|
|
@@ -153,17 +206,14 @@ export class Outbox {
|
|
|
153
206
|
* Sends the batch object to the container context to be sent over the wire.
|
|
154
207
|
*
|
|
155
208
|
* @param batch - batch to be sent
|
|
156
|
-
* @returns the client sequence number of the last batched op which was sent and
|
|
157
|
-
* -1 if there are no ops or the container cannot send ops.
|
|
158
209
|
*/
|
|
159
|
-
private sendBatch(batch: IBatch)
|
|
160
|
-
let clientSequenceNumber: number = -1;
|
|
210
|
+
private sendBatch(batch: IBatch) {
|
|
161
211
|
const length = batch.content.length;
|
|
162
212
|
|
|
163
213
|
// Did we disconnect in the middle of turn-based batch?
|
|
164
214
|
// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.
|
|
165
215
|
if (length === 0 || !this.params.shouldSend()) {
|
|
166
|
-
return
|
|
216
|
+
return;
|
|
167
217
|
}
|
|
168
218
|
|
|
169
219
|
if (this.params.containerContext.submitBatchFn === undefined) {
|
|
@@ -175,7 +225,7 @@ export class Outbox {
|
|
|
175
225
|
delete message.metadata.compressed;
|
|
176
226
|
}
|
|
177
227
|
|
|
178
|
-
|
|
228
|
+
this.params.containerContext.submitFn(
|
|
179
229
|
MessageType.Operation,
|
|
180
230
|
message.deserializedContent,
|
|
181
231
|
true, // batch
|
|
@@ -185,37 +235,33 @@ export class Outbox {
|
|
|
185
235
|
|
|
186
236
|
this.params.containerContext.deltaManager.flush();
|
|
187
237
|
} else {
|
|
188
|
-
|
|
189
|
-
|
|
238
|
+
assert(
|
|
239
|
+
batch.referenceSequenceNumber !== undefined,
|
|
240
|
+
0x58e /* Batch must not be empty */,
|
|
241
|
+
);
|
|
242
|
+
this.params.containerContext.submitBatchFn(
|
|
190
243
|
batch.content.map((message) => ({
|
|
191
244
|
contents: message.contents,
|
|
192
245
|
metadata: message.metadata,
|
|
193
246
|
compression: message.compression,
|
|
247
|
+
referenceSequenceNumber: message.referenceSequenceNumber,
|
|
194
248
|
})),
|
|
249
|
+
batch.referenceSequenceNumber,
|
|
195
250
|
);
|
|
196
251
|
}
|
|
197
|
-
|
|
198
|
-
// Convert from clientSequenceNumber of last message in the batch to clientSequenceNumber of first message.
|
|
199
|
-
clientSequenceNumber -= length - 1;
|
|
200
|
-
assert(clientSequenceNumber >= 0, 0x3d0 /* clientSequenceNumber can't be negative */);
|
|
201
|
-
return clientSequenceNumber;
|
|
202
252
|
}
|
|
203
253
|
|
|
204
|
-
private persistBatch(
|
|
205
|
-
let clientSequenceNumber = initialClientSequenceNumber;
|
|
254
|
+
private persistBatch(batch: BatchMessage[]) {
|
|
206
255
|
// Let the PendingStateManager know that a message was submitted.
|
|
207
256
|
// In future, need to shift toward keeping batch as a whole!
|
|
208
257
|
for (const message of batch) {
|
|
209
258
|
this.params.pendingStateManager.onSubmitMessage(
|
|
210
259
|
message.deserializedContent.type,
|
|
211
|
-
clientSequenceNumber,
|
|
212
260
|
message.referenceSequenceNumber,
|
|
213
261
|
message.deserializedContent.contents,
|
|
214
262
|
message.localOpMetadata,
|
|
215
263
|
message.metadata,
|
|
216
264
|
);
|
|
217
|
-
|
|
218
|
-
clientSequenceNumber++;
|
|
219
265
|
}
|
|
220
266
|
}
|
|
221
267
|
|
package/src/packageVersion.ts
CHANGED