@fluidframework/container-runtime 2.20.0 → 2.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +36 -6
- package/.mocharc.cjs +3 -0
- package/CHANGELOG.md +42 -0
- package/README.md +1 -0
- package/api-report/container-runtime.legacy.alpha.api.md +31 -31
- package/dist/batchTracker.d.ts +1 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +1 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager/blobManager.d.ts +0 -3
- package/dist/blobManager/blobManager.d.ts.map +1 -1
- package/dist/blobManager/blobManager.js +25 -19
- package/dist/blobManager/blobManager.js.map +1 -1
- package/dist/blobManager/blobManagerSnapSum.d.ts +1 -0
- package/dist/blobManager/blobManagerSnapSum.d.ts.map +1 -1
- package/dist/blobManager/blobManagerSnapSum.js +7 -5
- package/dist/blobManager/blobManagerSnapSum.js.map +1 -1
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +63 -41
- package/dist/channelCollection.js.map +1 -1
- package/dist/connectionTelemetry.d.ts +2 -2
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +4 -4
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +14 -30
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +265 -196
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +6 -3
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +16 -11
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +1 -0
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +5 -5
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +36 -14
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +2 -0
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +8 -0
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +1 -0
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +8 -5
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/dist/gc/gcSummaryStateTracker.js +2 -1
- package/dist/gc/gcSummaryStateTracker.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +29 -15
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/inboundBatchAggregator.js +3 -3
- package/dist/inboundBatchAggregator.js.map +1 -1
- package/dist/layerCompatState.d.ts +19 -0
- package/dist/layerCompatState.d.ts.map +1 -0
- package/dist/layerCompatState.js +64 -0
- package/dist/layerCompatState.js.map +1 -0
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/duplicateBatchDetector.js +2 -2
- package/dist/opLifecycle/duplicateBatchDetector.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts +3 -2
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +13 -19
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts +3 -0
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +4 -1
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +5 -3
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts +13 -10
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +14 -11
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +3 -3
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +11 -15
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +3 -1
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +3 -4
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +11 -10
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/summary/documentSchema.d.ts +7 -0
- package/dist/summary/documentSchema.d.ts.map +1 -1
- package/dist/summary/documentSchema.js +6 -4
- package/dist/summary/documentSchema.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +1 -0
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +13 -11
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -0
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js +7 -2
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +2 -2
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +38 -17
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +1 -0
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +18 -9
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js +1 -0
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.js +1 -1
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/index.d.ts.map +1 -1
- package/dist/summary/summarizerNode/index.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +30 -31
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +3 -3
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +7 -0
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +3 -4
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +9 -6
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +4 -1
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js +3 -2
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +19 -8
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +12 -9
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/batchTracker.d.ts +1 -2
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -2
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager/blobManager.d.ts +0 -3
- package/lib/blobManager/blobManager.d.ts.map +1 -1
- package/lib/blobManager/blobManager.js +26 -20
- package/lib/blobManager/blobManager.js.map +1 -1
- package/lib/blobManager/blobManagerSnapSum.d.ts +1 -0
- package/lib/blobManager/blobManagerSnapSum.d.ts.map +1 -1
- package/lib/blobManager/blobManagerSnapSum.js +7 -5
- package/lib/blobManager/blobManagerSnapSum.js.map +1 -1
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +66 -42
- package/lib/channelCollection.js.map +1 -1
- package/lib/connectionTelemetry.d.ts +2 -2
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +5 -5
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +14 -30
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +272 -198
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +6 -3
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +16 -11
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +1 -0
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +6 -6
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +39 -15
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +2 -0
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +8 -0
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js +1 -0
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +8 -5
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
- package/lib/gc/gcSummaryStateTracker.js +2 -1
- package/lib/gc/gcSummaryStateTracker.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +32 -16
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/inboundBatchAggregator.js +4 -4
- package/lib/inboundBatchAggregator.js.map +1 -1
- package/lib/layerCompatState.d.ts +19 -0
- package/lib/layerCompatState.d.ts.map +1 -0
- package/lib/layerCompatState.js +60 -0
- package/lib/layerCompatState.js.map +1 -0
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js.map +1 -1
- package/lib/opLifecycle/duplicateBatchDetector.js +2 -2
- package/lib/opLifecycle/duplicateBatchDetector.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts +3 -2
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +13 -19
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts +3 -0
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +4 -1
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +5 -3
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts +13 -10
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +14 -11
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +3 -3
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +11 -15
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +3 -1
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +3 -4
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +12 -11
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/summary/documentSchema.d.ts +7 -0
- package/lib/summary/documentSchema.d.ts.map +1 -1
- package/lib/summary/documentSchema.js +6 -4
- package/lib/summary/documentSchema.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +1 -0
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +13 -11
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts +1 -0
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js +7 -2
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +2 -2
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +38 -17
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +1 -0
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +18 -9
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js +1 -0
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.js +1 -1
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/index.d.ts.map +1 -1
- package/lib/summary/summarizerNode/index.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +30 -31
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +3 -3
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +7 -0
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +3 -4
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +9 -6
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +4 -1
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js +2 -2
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +19 -8
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +12 -9
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +24 -46
- package/src/batchTracker.ts +3 -3
- package/src/blobManager/blobManager.ts +27 -28
- package/src/blobManager/blobManagerSnapSum.ts +8 -8
- package/src/channelCollection.ts +63 -44
- package/src/connectionTelemetry.ts +12 -6
- package/src/containerRuntime.ts +306 -236
- package/src/dataStore.ts +6 -3
- package/src/dataStoreContext.ts +16 -16
- package/src/dataStoreContexts.ts +1 -0
- package/src/deltaScheduler.ts +6 -6
- package/src/gc/garbageCollection.ts +47 -20
- package/src/gc/gcConfigs.ts +9 -1
- package/src/gc/gcDefinitions.ts +12 -0
- package/src/gc/gcHelpers.ts +9 -4
- package/src/gc/gcSummaryStateTracker.ts +3 -1
- package/src/gc/gcTelemetry.ts +26 -11
- package/src/inboundBatchAggregator.ts +4 -4
- package/src/layerCompatState.ts +75 -0
- package/src/messageTypes.ts +2 -0
- package/src/opLifecycle/README.md +43 -34
- package/src/opLifecycle/duplicateBatchDetector.ts +2 -2
- package/src/opLifecycle/opCompressor.ts +16 -23
- package/src/opLifecycle/opDecompressor.ts +4 -1
- package/src/opLifecycle/opGroupingManager.ts +5 -4
- package/src/opLifecycle/opSplitter.ts +14 -11
- package/src/opLifecycle/outbox.ts +13 -20
- package/src/opLifecycle/remoteMessageProcessor.ts +3 -1
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +15 -10
- package/src/summary/documentSchema.ts +11 -4
- package/src/summary/orderedClientElection.ts +14 -11
- package/src/summary/runWhileConnectedCoordinator.ts +6 -0
- package/src/summary/runningSummarizer.ts +43 -19
- package/src/summary/summarizer.ts +24 -11
- package/src/summary/summarizerClientElection.ts +2 -0
- package/src/summary/summarizerHeuristics.ts +1 -1
- package/src/summary/summarizerNode/index.ts +1 -0
- package/src/summary/summarizerNode/summarizerNode.ts +32 -31
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +4 -4
- package/src/summary/summarizerTypes.ts +7 -0
- package/src/summary/summaryCollection.ts +19 -8
- package/src/summary/summaryFormat.ts +10 -5
- package/src/summary/summaryGenerator.ts +25 -10
- package/src/summary/summaryManager.ts +14 -12
- package/container-runtime.test-files.tar +0 -0
package/src/containerRuntime.ts
CHANGED
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
Trace,
|
|
8
|
+
TypedEventEmitter,
|
|
9
|
+
type ILayerCompatDetails,
|
|
10
|
+
type IProvideLayerCompatDetails,
|
|
11
|
+
} from "@fluid-internal/client-utils";
|
|
7
12
|
import {
|
|
8
13
|
AttachState,
|
|
9
14
|
IAudience,
|
|
@@ -12,7 +17,6 @@ import {
|
|
|
12
17
|
type IAudienceEvents,
|
|
13
18
|
} from "@fluidframework/container-definitions";
|
|
14
19
|
import {
|
|
15
|
-
IBatchMessage,
|
|
16
20
|
IContainerContext,
|
|
17
21
|
IGetPendingLocalStateProps,
|
|
18
22
|
ILoader,
|
|
@@ -34,6 +38,7 @@ import {
|
|
|
34
38
|
ITelemetryBaseLogger,
|
|
35
39
|
} from "@fluidframework/core-interfaces";
|
|
36
40
|
import {
|
|
41
|
+
type IErrorBase,
|
|
37
42
|
IFluidHandleContext,
|
|
38
43
|
type IFluidHandleInternal,
|
|
39
44
|
IProvideFluidHandleContext,
|
|
@@ -142,6 +147,7 @@ import {
|
|
|
142
147
|
blobsTreeName,
|
|
143
148
|
isBlobPath,
|
|
144
149
|
loadBlobManagerLoadInfo,
|
|
150
|
+
// eslint-disable-next-line import/no-deprecated
|
|
145
151
|
type IBlobManagerLoadInfo,
|
|
146
152
|
} from "./blobManager/index.js";
|
|
147
153
|
import {
|
|
@@ -159,15 +165,18 @@ import {
|
|
|
159
165
|
} from "./deltaManagerProxies.js";
|
|
160
166
|
import { DeltaScheduler } from "./deltaScheduler.js";
|
|
161
167
|
import {
|
|
168
|
+
// eslint-disable-next-line import/no-deprecated
|
|
162
169
|
GCNodeType,
|
|
163
170
|
GarbageCollector,
|
|
164
171
|
IGCRuntimeOptions,
|
|
172
|
+
// eslint-disable-next-line import/no-deprecated
|
|
165
173
|
IGCStats,
|
|
166
174
|
IGarbageCollector,
|
|
167
175
|
gcGenerationOptionName,
|
|
168
176
|
type GarbageCollectionMessage,
|
|
169
177
|
} from "./gc/index.js";
|
|
170
178
|
import { InboundBatchAggregator } from "./inboundBatchAggregator.js";
|
|
179
|
+
import { RuntimeCompatDetails, validateLoaderCompatibility } from "./layerCompatState.js";
|
|
171
180
|
import {
|
|
172
181
|
ContainerMessageType,
|
|
173
182
|
type ContainerRuntimeDocumentSchemaMessage,
|
|
@@ -202,26 +211,38 @@ import {
|
|
|
202
211
|
PendingStateManager,
|
|
203
212
|
} from "./pendingStateManager.js";
|
|
204
213
|
import {
|
|
214
|
+
// eslint-disable-next-line import/no-deprecated
|
|
205
215
|
DocumentsSchemaController,
|
|
206
216
|
EnqueueSummarizeResult,
|
|
207
217
|
IBaseSummarizeResult,
|
|
218
|
+
// eslint-disable-next-line import/no-deprecated
|
|
208
219
|
IConnectableRuntime,
|
|
220
|
+
// eslint-disable-next-line import/no-deprecated
|
|
209
221
|
IContainerRuntimeMetadata,
|
|
222
|
+
// eslint-disable-next-line import/no-deprecated
|
|
210
223
|
ICreateContainerMetadata,
|
|
224
|
+
// eslint-disable-next-line import/no-deprecated
|
|
211
225
|
type IDocumentSchemaChangeMessage,
|
|
226
|
+
// eslint-disable-next-line import/no-deprecated
|
|
212
227
|
type IDocumentSchemaCurrent,
|
|
213
228
|
IEnqueueSummarizeOptions,
|
|
214
229
|
IGenerateSummaryTreeResult,
|
|
215
230
|
IGeneratedSummaryStats,
|
|
216
231
|
IOnDemandSummarizeOptions,
|
|
232
|
+
// eslint-disable-next-line import/no-deprecated
|
|
217
233
|
IRefreshSummaryAckOptions,
|
|
218
234
|
IRootSummarizerNodeWithGC,
|
|
235
|
+
// eslint-disable-next-line import/no-deprecated
|
|
219
236
|
ISerializedElection,
|
|
237
|
+
// eslint-disable-next-line import/no-deprecated
|
|
220
238
|
ISubmitSummaryOptions,
|
|
221
239
|
ISummarizeResults,
|
|
222
240
|
ISummarizer,
|
|
241
|
+
// eslint-disable-next-line import/no-deprecated
|
|
223
242
|
ISummarizerInternalsProvider,
|
|
243
|
+
// eslint-disable-next-line import/no-deprecated
|
|
224
244
|
ISummarizerRuntime,
|
|
245
|
+
// eslint-disable-next-line import/no-deprecated
|
|
225
246
|
ISummaryMetadataMessage,
|
|
226
247
|
IdCompressorMode,
|
|
227
248
|
OrderedClientCollection,
|
|
@@ -229,6 +250,7 @@ import {
|
|
|
229
250
|
RetriableSummaryError,
|
|
230
251
|
RunWhileConnectedCoordinator,
|
|
231
252
|
SubmitSummaryResult,
|
|
253
|
+
// eslint-disable-next-line import/no-deprecated
|
|
232
254
|
Summarizer,
|
|
233
255
|
SummarizerClientElection,
|
|
234
256
|
SummaryCollection,
|
|
@@ -244,6 +266,7 @@ import {
|
|
|
244
266
|
rootHasIsolatedChannels,
|
|
245
267
|
summarizerClientType,
|
|
246
268
|
wrapSummaryInChannelsTree,
|
|
269
|
+
// eslint-disable-next-line import/no-deprecated
|
|
247
270
|
type IDocumentSchemaFeatures,
|
|
248
271
|
} from "./summary/index.js";
|
|
249
272
|
import { Throttler, formExponentialFn } from "./throttler.js";
|
|
@@ -389,6 +412,12 @@ export type ISummaryConfiguration =
|
|
|
389
412
|
| ISummaryConfigurationDisableHeuristics
|
|
390
413
|
| ISummaryConfigurationHeuristics;
|
|
391
414
|
|
|
415
|
+
export function isSummariesDisabled(
|
|
416
|
+
config: ISummaryConfiguration,
|
|
417
|
+
): config is ISummaryConfigurationDisableSummarizer {
|
|
418
|
+
return config.state === "disabled";
|
|
419
|
+
}
|
|
420
|
+
|
|
392
421
|
/**
|
|
393
422
|
* @legacy
|
|
394
423
|
* @alpha
|
|
@@ -414,7 +443,7 @@ export const DefaultSummaryConfiguration: ISummaryConfiguration = {
|
|
|
414
443
|
|
|
415
444
|
nonRuntimeOpWeight: 0.1,
|
|
416
445
|
|
|
417
|
-
runtimeOpWeight: 1
|
|
446
|
+
runtimeOpWeight: 1,
|
|
418
447
|
|
|
419
448
|
nonRuntimeHeuristicThreshold: 20,
|
|
420
449
|
};
|
|
@@ -560,6 +589,7 @@ export interface IContainerRuntimeOptionsInternal extends IContainerRuntimeOptio
|
|
|
560
589
|
* Error responses when requesting a deleted object will have this header set to true
|
|
561
590
|
* @legacy
|
|
562
591
|
* @alpha
|
|
592
|
+
* @deprecated This type will be moved to internal in 2.30. External usage is not necessary or supported.
|
|
563
593
|
*/
|
|
564
594
|
export const DeletedResponseHeaderKey = "wasDeleted";
|
|
565
595
|
/**
|
|
@@ -611,7 +641,7 @@ export enum CompressionAlgorithms {
|
|
|
611
641
|
* @alpha
|
|
612
642
|
*/
|
|
613
643
|
export const disabledCompressionConfig: ICompressionRuntimeOptions = {
|
|
614
|
-
minimumBatchSizeInBytes:
|
|
644
|
+
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
615
645
|
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
616
646
|
};
|
|
617
647
|
|
|
@@ -713,7 +743,9 @@ export function getDeviceSpec(): {
|
|
|
713
743
|
hardwareConcurrency: navigator.hardwareConcurrency,
|
|
714
744
|
};
|
|
715
745
|
}
|
|
716
|
-
} catch {
|
|
746
|
+
} catch {
|
|
747
|
+
// Eat the error
|
|
748
|
+
}
|
|
717
749
|
return {};
|
|
718
750
|
}
|
|
719
751
|
|
|
@@ -774,19 +806,18 @@ async function createSummarizer(loader: ILoader, url: string): Promise<ISummariz
|
|
|
774
806
|
|
|
775
807
|
// Older containers may not have the "getEntryPoint" API
|
|
776
808
|
// ! This check will need to stay until LTS of loader moves past 2.0.0-internal.7.0.0
|
|
777
|
-
if (resolvedContainer.getEntryPoint
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-assignment
|
|
781
|
-
const response = await (resolvedContainer as any).request({
|
|
809
|
+
if (resolvedContainer.getEntryPoint === undefined) {
|
|
810
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any
|
|
811
|
+
const response = (await (resolvedContainer as any).request({
|
|
782
812
|
url: `/${summarizerRequestUrl}`,
|
|
783
|
-
});
|
|
784
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
813
|
+
})) as IResponse;
|
|
785
814
|
if (response.status !== 200 || response.mimeType !== "fluid/object") {
|
|
786
815
|
throw responseToException(response, request);
|
|
787
816
|
}
|
|
788
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-
|
|
817
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
789
818
|
fluidObject = response.value;
|
|
819
|
+
} else {
|
|
820
|
+
fluidObject = await resolvedContainer.getEntryPoint();
|
|
790
821
|
}
|
|
791
822
|
|
|
792
823
|
if (fluidObject?.ISummarizer === undefined) {
|
|
@@ -802,7 +833,9 @@ async function createSummarizer(loader: ILoader, url: string): Promise<ISummariz
|
|
|
802
833
|
* Please see addMetadataToSummary() as well
|
|
803
834
|
*/
|
|
804
835
|
function lastMessageFromMetadata(
|
|
836
|
+
// eslint-disable-next-line import/no-deprecated
|
|
805
837
|
metadata: IContainerRuntimeMetadata | undefined,
|
|
838
|
+
// eslint-disable-next-line import/no-deprecated
|
|
806
839
|
): ISummaryMetadataMessage | undefined {
|
|
807
840
|
return metadata?.documentSchema?.runtime?.explicitSchemaControl
|
|
808
841
|
? metadata?.lastMessage
|
|
@@ -822,6 +855,7 @@ export let getSingleUseLegacyLogCallback = (logger: ITelemetryLoggerExt, type: s
|
|
|
822
855
|
});
|
|
823
856
|
|
|
824
857
|
// Now that we've logged, prevent future logging (globally).
|
|
858
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
825
859
|
getSingleUseLegacyLogCallback = () => () => {};
|
|
826
860
|
};
|
|
827
861
|
};
|
|
@@ -877,6 +911,10 @@ export async function loadContainerRuntime(
|
|
|
877
911
|
return ContainerRuntime.loadRuntime(params);
|
|
878
912
|
}
|
|
879
913
|
|
|
914
|
+
const defaultMaxConsecutiveReconnects = 7;
|
|
915
|
+
|
|
916
|
+
const defaultTelemetrySignalSampleCount = 100;
|
|
917
|
+
|
|
880
918
|
/**
|
|
881
919
|
* Represents the runtime of the container. Contains helper functions/state of the container.
|
|
882
920
|
* It will define the store level mappings.
|
|
@@ -888,9 +926,12 @@ export class ContainerRuntime
|
|
|
888
926
|
implements
|
|
889
927
|
IContainerRuntime,
|
|
890
928
|
IRuntime,
|
|
929
|
+
// eslint-disable-next-line import/no-deprecated
|
|
891
930
|
ISummarizerRuntime,
|
|
931
|
+
// eslint-disable-next-line import/no-deprecated
|
|
892
932
|
ISummarizerInternalsProvider,
|
|
893
|
-
IProvideFluidHandleContext
|
|
933
|
+
IProvideFluidHandleContext,
|
|
934
|
+
IProvideLayerCompatDetails
|
|
894
935
|
{
|
|
895
936
|
/**
|
|
896
937
|
* Load the stores from a snapshot and returns the runtime.
|
|
@@ -991,7 +1032,9 @@ export class ContainerRuntime
|
|
|
991
1032
|
tryFetchBlob<ReturnType<DuplicateBatchDetector["getRecentBatchInfoForSummary"]>>(
|
|
992
1033
|
recentBatchInfoBlobName,
|
|
993
1034
|
),
|
|
1035
|
+
// eslint-disable-next-line import/no-deprecated
|
|
994
1036
|
tryFetchBlob<IContainerRuntimeMetadata>(metadataBlobName),
|
|
1037
|
+
// eslint-disable-next-line import/no-deprecated
|
|
995
1038
|
tryFetchBlob<ISerializedElection>(electedSummarizerBlobName),
|
|
996
1039
|
tryFetchBlob<[string, string][]>(aliasBlobName),
|
|
997
1040
|
tryFetchBlob<SerializedIdCompressorWithNoSession>(idCompressorBlobName),
|
|
@@ -1008,6 +1051,7 @@ export class ContainerRuntime
|
|
|
1008
1051
|
// When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
|
|
1009
1052
|
if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
|
|
1010
1053
|
// Unless bypass is explicitly set, then take action when sequence numbers mismatch.
|
|
1054
|
+
// eslint-disable-next-line unicorn/no-lonely-if -- Separate if statements make flow easier to parse
|
|
1011
1055
|
if (
|
|
1012
1056
|
loadSequenceNumberVerification !== "bypass" &&
|
|
1013
1057
|
runtimeSequenceNumber !== protocolSequenceNumber
|
|
@@ -1036,15 +1080,18 @@ export class ContainerRuntime
|
|
|
1036
1080
|
|
|
1037
1081
|
let desiredIdCompressorMode: IdCompressorMode;
|
|
1038
1082
|
switch (mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled")) {
|
|
1039
|
-
case true:
|
|
1083
|
+
case true: {
|
|
1040
1084
|
desiredIdCompressorMode = "on";
|
|
1041
1085
|
break;
|
|
1042
|
-
|
|
1086
|
+
}
|
|
1087
|
+
case false: {
|
|
1043
1088
|
desiredIdCompressorMode = undefined;
|
|
1044
1089
|
break;
|
|
1045
|
-
|
|
1090
|
+
}
|
|
1091
|
+
default: {
|
|
1046
1092
|
desiredIdCompressorMode = enableRuntimeIdCompressor;
|
|
1047
1093
|
break;
|
|
1094
|
+
}
|
|
1048
1095
|
}
|
|
1049
1096
|
|
|
1050
1097
|
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
@@ -1108,21 +1155,22 @@ export class ContainerRuntime
|
|
|
1108
1155
|
pendingLocalState.pendingIdCompressorState,
|
|
1109
1156
|
compressorLogger,
|
|
1110
1157
|
);
|
|
1111
|
-
} else if (serializedIdCompressor
|
|
1158
|
+
} else if (serializedIdCompressor === undefined) {
|
|
1159
|
+
return createIdCompressor(compressorLogger);
|
|
1160
|
+
} else {
|
|
1112
1161
|
return deserializeIdCompressor(
|
|
1113
1162
|
serializedIdCompressor,
|
|
1114
1163
|
createSessionId(),
|
|
1115
1164
|
compressorLogger,
|
|
1116
1165
|
);
|
|
1117
|
-
} else {
|
|
1118
|
-
return createIdCompressor(compressorLogger);
|
|
1119
1166
|
}
|
|
1120
1167
|
};
|
|
1121
1168
|
|
|
1122
1169
|
const compressionLz4 =
|
|
1123
|
-
compressionOptions.minimumBatchSizeInBytes !==
|
|
1170
|
+
compressionOptions.minimumBatchSizeInBytes !== Number.POSITIVE_INFINITY &&
|
|
1124
1171
|
compressionOptions.compressionAlgorithm === "lz4";
|
|
1125
1172
|
|
|
1173
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1126
1174
|
const documentSchemaController = new DocumentsSchemaController(
|
|
1127
1175
|
existing,
|
|
1128
1176
|
protocolSequenceNumber,
|
|
@@ -1190,7 +1238,7 @@ export class ContainerRuntime
|
|
|
1190
1238
|
runtime.setConnectionStateCore(true, runtime.delayConnectClientId);
|
|
1191
1239
|
}
|
|
1192
1240
|
},
|
|
1193
|
-
(error) => runtime.closeFn(error),
|
|
1241
|
+
(error: IErrorBase) => runtime.closeFn(error),
|
|
1194
1242
|
);
|
|
1195
1243
|
|
|
1196
1244
|
// Apply stashed ops with a reference sequence number equal to the sequence number of the snapshot,
|
|
@@ -1221,18 +1269,6 @@ export class ContainerRuntime
|
|
|
1221
1269
|
return this;
|
|
1222
1270
|
}
|
|
1223
1271
|
|
|
1224
|
-
private readonly submitFn: (
|
|
1225
|
-
type: MessageType,
|
|
1226
|
-
contents: unknown,
|
|
1227
|
-
batch: boolean,
|
|
1228
|
-
appData?: unknown,
|
|
1229
|
-
) => number;
|
|
1230
|
-
/**
|
|
1231
|
-
* Although current IContainerContext guarantees submitBatchFn, it is not available on older loaders.
|
|
1232
|
-
*/
|
|
1233
|
-
private readonly submitBatchFn:
|
|
1234
|
-
| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)
|
|
1235
|
-
| undefined;
|
|
1236
1272
|
private readonly submitSummaryFn: (
|
|
1237
1273
|
summaryOp: ISummaryContent,
|
|
1238
1274
|
referenceSequenceNumber?: number,
|
|
@@ -1272,9 +1308,11 @@ export class ContainerRuntime
|
|
|
1272
1308
|
* this op roundtrips, compression will be On. Client can't send compressed ops until it's change in schema.
|
|
1273
1309
|
*/
|
|
1274
1310
|
public get sessionSchema(): {
|
|
1311
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1275
1312
|
[P in keyof IDocumentSchemaFeatures]?: IDocumentSchemaFeatures[P] extends boolean
|
|
1276
1313
|
? true
|
|
1277
|
-
:
|
|
1314
|
+
: // eslint-disable-next-line import/no-deprecated
|
|
1315
|
+
IDocumentSchemaFeatures[P];
|
|
1278
1316
|
} {
|
|
1279
1317
|
return this.documentsSchemaController.sessionSchema.runtime;
|
|
1280
1318
|
}
|
|
@@ -1291,9 +1329,6 @@ export class ContainerRuntime
|
|
|
1291
1329
|
// In such case we have to process all ops, including those marked with savedOp === true.
|
|
1292
1330
|
private readonly skipSavedCompressorOps: boolean;
|
|
1293
1331
|
|
|
1294
|
-
public get idCompressorMode(): IdCompressorMode {
|
|
1295
|
-
return this.sessionSchema.idCompressorMode;
|
|
1296
|
-
}
|
|
1297
1332
|
/**
|
|
1298
1333
|
* {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.idCompressor}
|
|
1299
1334
|
*/
|
|
@@ -1302,7 +1337,7 @@ export class ContainerRuntime
|
|
|
1302
1337
|
// If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
|
|
1303
1338
|
// That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
|
|
1304
1339
|
// to reason over such things as session ID space.
|
|
1305
|
-
if (this.idCompressorMode === "on") {
|
|
1340
|
+
if (this.sessionSchema.idCompressorMode === "on") {
|
|
1306
1341
|
assert(this._idCompressor !== undefined, 0x8ea /* compressor should have been loaded */);
|
|
1307
1342
|
return this._idCompressor;
|
|
1308
1343
|
}
|
|
@@ -1310,7 +1345,7 @@ export class ContainerRuntime
|
|
|
1310
1345
|
|
|
1311
1346
|
/**
|
|
1312
1347
|
* True if we have ID compressor loading in-flight (async operation). Useful only for
|
|
1313
|
-
* this.idCompressorMode === "delayed" mode
|
|
1348
|
+
* this.sessionSchema.idCompressorMode === "delayed" mode
|
|
1314
1349
|
*/
|
|
1315
1350
|
protected _loadIdCompressor: Promise<void> | undefined;
|
|
1316
1351
|
|
|
@@ -1354,14 +1389,10 @@ export class ContainerRuntime
|
|
|
1354
1389
|
* do not create it (see SummarizerClientElection.clientDetailsPermitElection() for details)
|
|
1355
1390
|
*/
|
|
1356
1391
|
private readonly summaryManager?: SummaryManager;
|
|
1357
|
-
private readonly summaryCollection: SummaryCollection;
|
|
1358
1392
|
|
|
1359
1393
|
private readonly summarizerNode: IRootSummarizerNodeWithGC;
|
|
1360
1394
|
|
|
1361
|
-
private readonly logger: ITelemetryLoggerExt;
|
|
1362
|
-
|
|
1363
1395
|
private readonly maxConsecutiveReconnects: number;
|
|
1364
|
-
private readonly defaultMaxConsecutiveReconnects = 7;
|
|
1365
1396
|
|
|
1366
1397
|
private _orderSequentiallyCalls: number = 0;
|
|
1367
1398
|
private readonly _flushMode: FlushMode;
|
|
@@ -1415,10 +1446,8 @@ export class ContainerRuntime
|
|
|
1415
1446
|
|
|
1416
1447
|
private dirtyContainer: boolean;
|
|
1417
1448
|
private emitDirtyDocumentEvent = true;
|
|
1418
|
-
private readonly disableAttachReorder: boolean | undefined;
|
|
1419
1449
|
private readonly useDeltaManagerOpsProxy: boolean;
|
|
1420
1450
|
private readonly closeSummarizerDelayMs: number;
|
|
1421
|
-
private readonly defaultTelemetrySignalSampleCount = 100;
|
|
1422
1451
|
private readonly _signalTracking: IPerfSignalReport = {
|
|
1423
1452
|
totalSignalsSentInLatencyWindow: 0,
|
|
1424
1453
|
signalsLost: 0,
|
|
@@ -1436,6 +1465,7 @@ export class ContainerRuntime
|
|
|
1436
1465
|
* It is the main entry point for summary work.
|
|
1437
1466
|
* It is created only by summarizing container (i.e. one with clientType === "summarizer")
|
|
1438
1467
|
*/
|
|
1468
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1439
1469
|
private readonly _summarizer?: Summarizer;
|
|
1440
1470
|
private readonly deltaScheduler: DeltaScheduler;
|
|
1441
1471
|
private readonly inboundBatchAggregator: InboundBatchAggregator;
|
|
@@ -1451,37 +1481,12 @@ export class ContainerRuntime
|
|
|
1451
1481
|
/**
|
|
1452
1482
|
* The last message processed at the time of the last summary.
|
|
1453
1483
|
*/
|
|
1484
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1454
1485
|
private messageAtLastSummary: ISummaryMetadataMessage | undefined;
|
|
1455
1486
|
|
|
1456
|
-
private get summarizer(): Summarizer {
|
|
1457
|
-
assert(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
|
|
1458
|
-
return this._summarizer;
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
1487
|
private readonly summariesDisabled: boolean;
|
|
1462
|
-
private isSummariesDisabled(): boolean {
|
|
1463
|
-
return this.summaryConfiguration.state === "disabled";
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
|
-
private readonly maxOpsSinceLastSummary: number;
|
|
1467
|
-
private getMaxOpsSinceLastSummary(): number {
|
|
1468
|
-
return this.summaryConfiguration.state !== "disabled"
|
|
1469
|
-
? this.summaryConfiguration.maxOpsSinceLastSummary
|
|
1470
|
-
: 0;
|
|
1471
|
-
}
|
|
1472
|
-
|
|
1473
|
-
private readonly initialSummarizerDelayMs: number;
|
|
1474
|
-
private getInitialSummarizerDelayMs(): number {
|
|
1475
|
-
// back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
|
|
1476
|
-
// to ISummaryConfiguration in 0.60.
|
|
1477
|
-
if (this.runtimeOptions.summaryOptions.initialSummarizerDelayMs !== undefined) {
|
|
1478
|
-
return this.runtimeOptions.summaryOptions.initialSummarizerDelayMs;
|
|
1479
|
-
}
|
|
1480
|
-
return this.summaryConfiguration.state !== "disabled"
|
|
1481
|
-
? this.summaryConfiguration.initialSummarizerDelayMs
|
|
1482
|
-
: 0;
|
|
1483
|
-
}
|
|
1484
1488
|
|
|
1489
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1485
1490
|
private readonly createContainerMetadata: ICreateContainerMetadata;
|
|
1486
1491
|
/**
|
|
1487
1492
|
* The summary number of the next summary that will be generated for this container. This is incremented every time
|
|
@@ -1513,11 +1518,6 @@ export class ContainerRuntime
|
|
|
1513
1518
|
*/
|
|
1514
1519
|
private readonly telemetryDocumentId: string;
|
|
1515
1520
|
|
|
1516
|
-
/**
|
|
1517
|
-
* Whether this client is the summarizer client itself (type is summarizerClientType)
|
|
1518
|
-
*/
|
|
1519
|
-
private readonly isSummarizerClient: boolean;
|
|
1520
|
-
|
|
1521
1521
|
/**
|
|
1522
1522
|
* The id of the version used to initially load this runtime, or undefined if it's newly created.
|
|
1523
1523
|
*/
|
|
@@ -1538,27 +1538,30 @@ export class ContainerRuntime
|
|
|
1538
1538
|
expiry: { policy: "absolute", durationMs: 60000 },
|
|
1539
1539
|
});
|
|
1540
1540
|
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
private readonly runtimeOptions: Readonly<Required<IContainerRuntimeOptionsInternal>>;
|
|
1541
|
+
public get ILayerCompatDetails(): ILayerCompatDetails {
|
|
1542
|
+
return RuntimeCompatDetails;
|
|
1543
|
+
}
|
|
1545
1544
|
|
|
1546
1545
|
/***/
|
|
1547
1546
|
protected constructor(
|
|
1548
1547
|
context: IContainerContext,
|
|
1549
1548
|
private readonly registry: IFluidDataStoreRegistry,
|
|
1549
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1550
1550
|
private readonly metadata: IContainerRuntimeMetadata | undefined,
|
|
1551
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1551
1552
|
electedSummarizerData: ISerializedElection | undefined,
|
|
1552
1553
|
chunks: [string, string[]][],
|
|
1553
1554
|
dataStoreAliasMap: [string, string][],
|
|
1554
|
-
|
|
1555
|
+
baseRuntimeOptions: Readonly<Required<IContainerRuntimeOptions>>,
|
|
1555
1556
|
private readonly containerScope: FluidObject,
|
|
1556
1557
|
// Create a custom ITelemetryBaseLogger to output telemetry events.
|
|
1557
1558
|
public readonly baseLogger: ITelemetryBaseLogger,
|
|
1558
1559
|
existing: boolean,
|
|
1560
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1559
1561
|
blobManagerSnapshot: IBlobManagerLoadInfo,
|
|
1560
1562
|
private readonly _storage: IDocumentStorageService,
|
|
1561
1563
|
private readonly createIdCompressor: () => Promise<IIdCompressor & IIdCompressorCore>,
|
|
1564
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1562
1565
|
private readonly documentsSchemaController: DocumentsSchemaController,
|
|
1563
1566
|
featureGatesForTelemetry: Record<string, boolean | number | undefined>,
|
|
1564
1567
|
provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>,
|
|
@@ -1566,11 +1569,12 @@ export class ContainerRuntime
|
|
|
1566
1569
|
request: IRequest,
|
|
1567
1570
|
runtime: IContainerRuntime,
|
|
1568
1571
|
) => Promise<IResponse>,
|
|
1569
|
-
|
|
1572
|
+
// eslint-disable-next-line unicorn/no-object-as-default-parameter
|
|
1573
|
+
summaryConfiguration: ISummaryConfiguration = {
|
|
1570
1574
|
// the defaults
|
|
1571
1575
|
...DefaultSummaryConfiguration,
|
|
1572
1576
|
// the runtime configuration overrides
|
|
1573
|
-
...
|
|
1577
|
+
...baseRuntimeOptions.summaryOptions?.summaryConfigOverrides,
|
|
1574
1578
|
},
|
|
1575
1579
|
recentBatchInfo?: [number, string][],
|
|
1576
1580
|
) {
|
|
@@ -1596,14 +1600,19 @@ export class ContainerRuntime
|
|
|
1596
1600
|
snapshotWithContents,
|
|
1597
1601
|
} = context;
|
|
1598
1602
|
|
|
1603
|
+
// In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
|
|
1604
|
+
this.disposeFn = disposeFn ?? closeFn;
|
|
1605
|
+
|
|
1606
|
+
const maybeLoaderCompatDetails = context as FluidObject<ILayerCompatDetails>;
|
|
1607
|
+
validateLoaderCompatibility(maybeLoaderCompatDetails.ILayerCompatDetails, this.disposeFn);
|
|
1608
|
+
|
|
1599
1609
|
// Backfill in defaults for the internal runtimeOptions, since they may not be present on the provided runtimeOptions object
|
|
1600
|
-
|
|
1610
|
+
const runtimeOptions = {
|
|
1601
1611
|
flushMode: defaultFlushMode,
|
|
1602
|
-
...
|
|
1612
|
+
...baseRuntimeOptions,
|
|
1603
1613
|
};
|
|
1604
|
-
this.logger = createChildLogger({ logger: this.baseLogger });
|
|
1605
1614
|
this.mc = createChildMonitoringContext({
|
|
1606
|
-
logger: this.
|
|
1615
|
+
logger: this.baseLogger,
|
|
1607
1616
|
namespace: "ContainerRuntime",
|
|
1608
1617
|
});
|
|
1609
1618
|
|
|
@@ -1623,20 +1632,24 @@ export class ContainerRuntime
|
|
|
1623
1632
|
|
|
1624
1633
|
// Here we could wrap/intercept on these functions to block/modify outgoing messages if needed.
|
|
1625
1634
|
// This makes ContainerRuntime the final gatekeeper for outgoing messages.
|
|
1626
|
-
this
|
|
1627
|
-
this.
|
|
1628
|
-
|
|
1635
|
+
// back-compat: ADO #1385: Make this call unconditional in the future
|
|
1636
|
+
this.submitSummaryFn =
|
|
1637
|
+
submitSummaryFn ??
|
|
1638
|
+
((summaryOp, refseq) => submitFn(MessageType.Summarize, summaryOp, false));
|
|
1629
1639
|
this.submitSignalFn = submitSignalFn;
|
|
1630
1640
|
|
|
1631
1641
|
// TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
|
|
1632
1642
|
// Values are generally expected to be set from the runtime side.
|
|
1633
1643
|
this.options = options ?? {};
|
|
1634
1644
|
this.clientDetails = clientDetails;
|
|
1635
|
-
|
|
1645
|
+
const isSummarizerClient = this.clientDetails.type === summarizerClientType;
|
|
1636
1646
|
this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
|
|
1647
|
+
// eslint-disable-next-line unicorn/consistent-destructuring
|
|
1637
1648
|
this._getClientId = () => context.clientId;
|
|
1649
|
+
// eslint-disable-next-line unicorn/consistent-destructuring
|
|
1638
1650
|
this._getAttachState = () => context.attachState;
|
|
1639
1651
|
this.getAbsoluteUrl = async (relativeUrl: string) => {
|
|
1652
|
+
// eslint-disable-next-line unicorn/consistent-destructuring
|
|
1640
1653
|
if (context.getAbsoluteUrl === undefined) {
|
|
1641
1654
|
throw new Error("Driver does not implement getAbsoluteUrl");
|
|
1642
1655
|
}
|
|
@@ -1650,10 +1663,8 @@ export class ContainerRuntime
|
|
|
1650
1663
|
this.on("dirty", () => context.updateDirtyContainerState(true));
|
|
1651
1664
|
this.on("saved", () => context.updateDirtyContainerState(false));
|
|
1652
1665
|
|
|
1653
|
-
// In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
|
|
1654
|
-
this.disposeFn = disposeFn ?? closeFn;
|
|
1655
1666
|
// In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
|
|
1656
|
-
this.closeFn =
|
|
1667
|
+
this.closeFn = isSummarizerClient ? this.disposeFn : closeFn;
|
|
1657
1668
|
|
|
1658
1669
|
let loadSummaryNumber: number;
|
|
1659
1670
|
// Get the container creation metadata. For new container, we initialize these. For existing containers,
|
|
@@ -1686,28 +1697,22 @@ export class ContainerRuntime
|
|
|
1686
1697
|
metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
|
|
1687
1698
|
inputs: JSON.stringify({
|
|
1688
1699
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
1689
|
-
gcOptions_gcGeneration:
|
|
1700
|
+
gcOptions_gcGeneration: runtimeOptions.gcOptions[gcGenerationOptionName],
|
|
1690
1701
|
}),
|
|
1691
1702
|
});
|
|
1692
1703
|
|
|
1693
1704
|
this.telemetryDocumentId = metadata?.telemetryDocumentId ?? uuid();
|
|
1694
1705
|
|
|
1695
|
-
this.disableAttachReorder = this.mc.config.getBoolean(
|
|
1696
|
-
"Fluid.ContainerRuntime.disableAttachOpReorder",
|
|
1697
|
-
);
|
|
1698
|
-
|
|
1699
1706
|
const opGroupingManager = new OpGroupingManager(
|
|
1700
1707
|
{
|
|
1701
1708
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
1702
|
-
opCountThreshold:
|
|
1703
|
-
this.mc.config.getNumber("Fluid.ContainerRuntime.GroupedBatchingOpCount") ?? 2,
|
|
1704
1709
|
},
|
|
1705
1710
|
this.mc.logger,
|
|
1706
1711
|
);
|
|
1707
1712
|
|
|
1708
1713
|
const opSplitter = new OpSplitter(
|
|
1709
1714
|
chunks,
|
|
1710
|
-
|
|
1715
|
+
submitBatchFn,
|
|
1711
1716
|
runtimeOptions.chunkSizeInBytes,
|
|
1712
1717
|
runtimeOptions.maxBatchSizeInBytes,
|
|
1713
1718
|
this.mc.logger,
|
|
@@ -1730,7 +1735,7 @@ export class ContainerRuntime
|
|
|
1730
1735
|
isAttached: () => this.attachState !== AttachState.Detached,
|
|
1731
1736
|
},
|
|
1732
1737
|
pendingRuntimeState?.pending,
|
|
1733
|
-
this.
|
|
1738
|
+
this.baseLogger,
|
|
1734
1739
|
);
|
|
1735
1740
|
|
|
1736
1741
|
let outerDeltaManager: IDeltaManagerFull;
|
|
@@ -1756,28 +1761,42 @@ export class ContainerRuntime
|
|
|
1756
1761
|
|
|
1757
1762
|
this.handleContext = new ContainerFluidHandleContext("", this);
|
|
1758
1763
|
|
|
1759
|
-
if (
|
|
1760
|
-
this.validateSummaryHeuristicConfiguration(
|
|
1764
|
+
if (summaryConfiguration.state === "enabled") {
|
|
1765
|
+
this.validateSummaryHeuristicConfiguration(summaryConfiguration);
|
|
1761
1766
|
}
|
|
1762
1767
|
|
|
1763
|
-
this.summariesDisabled =
|
|
1764
|
-
|
|
1765
|
-
|
|
1768
|
+
this.summariesDisabled = isSummariesDisabled(summaryConfiguration);
|
|
1769
|
+
const { maxOpsSinceLastSummary = 0, initialSummarizerDelayMs = 0 } = isSummariesDisabled(
|
|
1770
|
+
summaryConfiguration,
|
|
1771
|
+
)
|
|
1772
|
+
? {}
|
|
1773
|
+
: {
|
|
1774
|
+
...summaryConfiguration,
|
|
1775
|
+
initialSummarizerDelayMs:
|
|
1776
|
+
// back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
|
|
1777
|
+
// to ISummaryConfiguration in 0.60.
|
|
1778
|
+
runtimeOptions.summaryOptions.initialSummarizerDelayMs ??
|
|
1779
|
+
summaryConfiguration.initialSummarizerDelayMs,
|
|
1780
|
+
};
|
|
1766
1781
|
|
|
1767
1782
|
this.maxConsecutiveReconnects =
|
|
1768
|
-
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
|
|
1769
|
-
|
|
1770
|
-
|
|
1783
|
+
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ?? defaultMaxConsecutiveReconnects;
|
|
1784
|
+
|
|
1785
|
+
// If the context has ILayerCompatDetails, it supports referenceSequenceNumbers since that features
|
|
1786
|
+
// predates ILayerCompatDetails.
|
|
1787
|
+
const referenceSequenceNumbersSupported =
|
|
1788
|
+
maybeLoaderCompatDetails.ILayerCompatDetails === undefined
|
|
1789
|
+
? supportedFeatures?.get("referenceSequenceNumbers") === true
|
|
1790
|
+
: true;
|
|
1771
1791
|
if (
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
supportedFeatures?.get("referenceSequenceNumbers") !== true
|
|
1792
|
+
runtimeOptions.flushMode === (FlushModeExperimental.Async as unknown as FlushMode) &&
|
|
1793
|
+
!referenceSequenceNumbersSupported
|
|
1775
1794
|
) {
|
|
1776
1795
|
// The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
|
|
1777
1796
|
this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
|
|
1778
1797
|
this._flushMode = FlushMode.TurnBased;
|
|
1779
1798
|
} else {
|
|
1780
|
-
this._flushMode =
|
|
1799
|
+
this._flushMode = runtimeOptions.flushMode;
|
|
1781
1800
|
}
|
|
1782
1801
|
this.offlineEnabled =
|
|
1783
1802
|
this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ?? false;
|
|
@@ -1795,6 +1814,7 @@ export class ContainerRuntime
|
|
|
1795
1814
|
this.duplicateBatchDetector = new DuplicateBatchDetector(recentBatchInfo);
|
|
1796
1815
|
}
|
|
1797
1816
|
|
|
1817
|
+
// eslint-disable-next-line unicorn/consistent-destructuring
|
|
1798
1818
|
if (context.attachState === AttachState.Attached) {
|
|
1799
1819
|
const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
|
|
1800
1820
|
if (
|
|
@@ -1810,13 +1830,13 @@ export class ContainerRuntime
|
|
|
1810
1830
|
|
|
1811
1831
|
this.garbageCollector = GarbageCollector.create({
|
|
1812
1832
|
runtime: this,
|
|
1813
|
-
gcOptions:
|
|
1833
|
+
gcOptions: runtimeOptions.gcOptions,
|
|
1814
1834
|
baseSnapshot,
|
|
1815
1835
|
baseLogger: this.mc.logger,
|
|
1816
1836
|
existing,
|
|
1817
1837
|
metadata,
|
|
1818
1838
|
createContainerMetadata: this.createContainerMetadata,
|
|
1819
|
-
isSummarizerClient
|
|
1839
|
+
isSummarizerClient,
|
|
1820
1840
|
getNodePackagePath: async (nodePath: string) => this.getGCNodePackagePath(nodePath),
|
|
1821
1841
|
getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
|
|
1822
1842
|
readAndParseBlob: async <T>(id: string) => readAndParse<T>(this.storage, id),
|
|
@@ -1833,7 +1853,7 @@ export class ContainerRuntime
|
|
|
1833
1853
|
? undefined
|
|
1834
1854
|
: loadedFromSequenceNumber;
|
|
1835
1855
|
this.summarizerNode = createRootSummarizerNodeWithGC(
|
|
1836
|
-
createChildLogger({ logger: this.
|
|
1856
|
+
createChildLogger({ logger: this.baseLogger, namespace: "SummarizerNode" }),
|
|
1837
1857
|
// Summarize function to call when summarize is called. Summarizer node always tracks summary state.
|
|
1838
1858
|
async (fullTree: boolean, trackState: boolean, telemetryContext?: ITelemetryContext) =>
|
|
1839
1859
|
this.summarizeInternal(fullTree, trackState, telemetryContext),
|
|
@@ -1922,31 +1942,30 @@ export class ContainerRuntime
|
|
|
1922
1942
|
isBlobDeleted: (blobPath: string) => this.garbageCollector.isNodeDeleted(blobPath),
|
|
1923
1943
|
runtime: this,
|
|
1924
1944
|
stashedBlobs: pendingRuntimeState?.pendingAttachmentBlobs,
|
|
1925
|
-
closeContainer: (error?: ICriticalContainerError) => this.closeFn(error),
|
|
1926
1945
|
});
|
|
1927
1946
|
|
|
1928
1947
|
this.deltaScheduler = new DeltaScheduler(
|
|
1929
1948
|
this.innerDeltaManager,
|
|
1930
1949
|
this,
|
|
1931
|
-
createChildLogger({ logger: this.
|
|
1950
|
+
createChildLogger({ logger: this.baseLogger, namespace: "DeltaScheduler" }),
|
|
1932
1951
|
);
|
|
1933
1952
|
|
|
1934
1953
|
this.inboundBatchAggregator = new InboundBatchAggregator(
|
|
1935
1954
|
this.innerDeltaManager,
|
|
1936
1955
|
() => this.clientId,
|
|
1937
|
-
createChildLogger({ logger: this.
|
|
1956
|
+
createChildLogger({ logger: this.baseLogger, namespace: "InboundBatchAggregator" }),
|
|
1938
1957
|
);
|
|
1939
1958
|
|
|
1940
1959
|
const disablePartialFlush = this.mc.config.getBoolean(
|
|
1941
1960
|
"Fluid.ContainerRuntime.DisablePartialFlush",
|
|
1942
1961
|
);
|
|
1943
1962
|
|
|
1944
|
-
const legacySendBatchFn = makeLegacySendBatchFn(
|
|
1963
|
+
const legacySendBatchFn = makeLegacySendBatchFn(submitFn, this.innerDeltaManager);
|
|
1945
1964
|
|
|
1946
1965
|
this.outbox = new Outbox({
|
|
1947
1966
|
shouldSend: () => this.canSendOps(),
|
|
1948
1967
|
pendingStateManager: this.pendingStateManager,
|
|
1949
|
-
submitBatchFn
|
|
1968
|
+
submitBatchFn,
|
|
1950
1969
|
legacySendBatchFn,
|
|
1951
1970
|
compressor: new OpCompressor(this.mc.logger),
|
|
1952
1971
|
splitter: opSplitter,
|
|
@@ -2003,7 +2022,7 @@ export class ContainerRuntime
|
|
|
2003
2022
|
);
|
|
2004
2023
|
this.closeSummarizerDelayMs =
|
|
2005
2024
|
closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
|
|
2006
|
-
|
|
2025
|
+
const summaryCollection = new SummaryCollection(this.deltaManager, this.baseLogger);
|
|
2007
2026
|
|
|
2008
2027
|
this.dirtyContainer =
|
|
2009
2028
|
this.attachState !== AttachState.Attached || this.hasPendingMessages();
|
|
@@ -2013,7 +2032,7 @@ export class ContainerRuntime
|
|
|
2013
2032
|
this.mc.logger.sendTelemetryEvent({ eventName: "SummariesDisabled" });
|
|
2014
2033
|
} else {
|
|
2015
2034
|
const orderedClientLogger = createChildLogger({
|
|
2016
|
-
logger: this.
|
|
2035
|
+
logger: this.baseLogger,
|
|
2017
2036
|
namespace: "OrderedClientElection",
|
|
2018
2037
|
});
|
|
2019
2038
|
const orderedClientCollection = new OrderedClientCollection(
|
|
@@ -2033,18 +2052,20 @@ export class ContainerRuntime
|
|
|
2033
2052
|
|
|
2034
2053
|
this.summarizerClientElection = new SummarizerClientElection(
|
|
2035
2054
|
orderedClientLogger,
|
|
2036
|
-
|
|
2055
|
+
summaryCollection,
|
|
2037
2056
|
orderedClientElectionForSummarizer,
|
|
2038
|
-
|
|
2057
|
+
maxOpsSinceLastSummary,
|
|
2039
2058
|
);
|
|
2040
2059
|
|
|
2041
|
-
if (
|
|
2060
|
+
if (isSummarizerClient) {
|
|
2061
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2042
2062
|
this._summarizer = new Summarizer(
|
|
2043
2063
|
this /* ISummarizerRuntime */,
|
|
2044
|
-
() =>
|
|
2064
|
+
() => summaryConfiguration,
|
|
2045
2065
|
this /* ISummarizerInternalsProvider */,
|
|
2046
2066
|
this.handleContext,
|
|
2047
|
-
|
|
2067
|
+
summaryCollection,
|
|
2068
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2048
2069
|
async (runtime: IConnectableRuntime) =>
|
|
2049
2070
|
RunWhileConnectedCoordinator.create(
|
|
2050
2071
|
runtime,
|
|
@@ -2057,31 +2078,31 @@ export class ContainerRuntime
|
|
|
2057
2078
|
// Only create a SummaryManager and SummarizerClientElection
|
|
2058
2079
|
// if summaries are enabled and we are not the summarizer client.
|
|
2059
2080
|
const defaultAction = (): void => {
|
|
2060
|
-
if (
|
|
2081
|
+
if (summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
|
|
2061
2082
|
this.mc.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
|
|
2062
2083
|
// unregister default to no log on every op after falling behind
|
|
2063
2084
|
// and register summary ack handler to re-register this handler
|
|
2064
2085
|
// after successful summary
|
|
2065
|
-
|
|
2086
|
+
summaryCollection.once(MessageType.SummaryAck, () => {
|
|
2066
2087
|
this.mc.logger.sendTelemetryEvent({
|
|
2067
2088
|
eventName: "SummaryStatus:CaughtUp",
|
|
2068
2089
|
});
|
|
2069
2090
|
// we've caught up, so re-register the default action to monitor for
|
|
2070
2091
|
// falling behind, and unregister ourself
|
|
2071
|
-
|
|
2092
|
+
summaryCollection.on("default", defaultAction);
|
|
2072
2093
|
});
|
|
2073
|
-
|
|
2094
|
+
summaryCollection.off("default", defaultAction);
|
|
2074
2095
|
}
|
|
2075
2096
|
};
|
|
2076
2097
|
|
|
2077
|
-
|
|
2098
|
+
summaryCollection.on("default", defaultAction);
|
|
2078
2099
|
|
|
2079
2100
|
// Create the SummaryManager and mark the initial state
|
|
2080
2101
|
this.summaryManager = new SummaryManager(
|
|
2081
2102
|
this.summarizerClientElection,
|
|
2082
2103
|
this, // IConnectedState
|
|
2083
|
-
|
|
2084
|
-
this.
|
|
2104
|
+
summaryCollection,
|
|
2105
|
+
this.baseLogger,
|
|
2085
2106
|
this.formCreateSummarizerFn(loader),
|
|
2086
2107
|
new Throttler(
|
|
2087
2108
|
60 * 1000, // 60 sec delay window
|
|
@@ -2090,28 +2111,29 @@ export class ContainerRuntime
|
|
|
2090
2111
|
formExponentialFn({ coefficient: 20, initialDelay: 0 }),
|
|
2091
2112
|
),
|
|
2092
2113
|
{
|
|
2093
|
-
initialDelayMs:
|
|
2114
|
+
initialDelayMs: initialSummarizerDelayMs,
|
|
2094
2115
|
},
|
|
2095
2116
|
);
|
|
2096
2117
|
// Forward events from SummaryManager
|
|
2097
|
-
[
|
|
2118
|
+
for (const eventName of [
|
|
2098
2119
|
"summarize",
|
|
2099
2120
|
"summarizeAllAttemptsFailed",
|
|
2100
2121
|
"summarizerStop",
|
|
2101
2122
|
"summarizerStart",
|
|
2102
2123
|
"summarizerStartupFailed",
|
|
2103
|
-
]
|
|
2104
|
-
this.summaryManager?.on(eventName, (...args:
|
|
2124
|
+
]) {
|
|
2125
|
+
this.summaryManager?.on(eventName, (...args: unknown[]) => {
|
|
2105
2126
|
this.emit(eventName, ...args);
|
|
2106
2127
|
});
|
|
2107
|
-
}
|
|
2128
|
+
}
|
|
2108
2129
|
|
|
2109
2130
|
this.summaryManager.start();
|
|
2110
2131
|
}
|
|
2111
2132
|
}
|
|
2112
2133
|
|
|
2113
2134
|
// logging hardware telemetry
|
|
2114
|
-
this.
|
|
2135
|
+
this.baseLogger.send({
|
|
2136
|
+
category: "generic",
|
|
2115
2137
|
eventName: "DeviceSpec",
|
|
2116
2138
|
...getDeviceSpec(),
|
|
2117
2139
|
});
|
|
@@ -2124,13 +2146,12 @@ export class ContainerRuntime
|
|
|
2124
2146
|
summaryFormatVersion: metadata?.summaryFormatVersion,
|
|
2125
2147
|
disableIsolatedChannels: metadata?.disableIsolatedChannels,
|
|
2126
2148
|
gcVersion: metadata?.gcFeature,
|
|
2127
|
-
options: JSON.stringify(
|
|
2149
|
+
options: JSON.stringify(baseRuntimeOptions),
|
|
2128
2150
|
idCompressorModeMetadata: metadata?.documentSchema?.runtime?.idCompressorMode,
|
|
2129
|
-
idCompressorMode: this.idCompressorMode,
|
|
2151
|
+
idCompressorMode: this.sessionSchema.idCompressorMode,
|
|
2130
2152
|
sessionRuntimeSchema: JSON.stringify(this.sessionSchema),
|
|
2131
2153
|
featureGates: JSON.stringify({
|
|
2132
2154
|
...featureGatesForTelemetry,
|
|
2133
|
-
disableAttachReorder: this.disableAttachReorder,
|
|
2134
2155
|
disablePartialFlush,
|
|
2135
2156
|
closeSummarizerDelayOverride,
|
|
2136
2157
|
}),
|
|
@@ -2139,15 +2160,11 @@ export class ContainerRuntime
|
|
|
2139
2160
|
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
2140
2161
|
});
|
|
2141
2162
|
|
|
2142
|
-
ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.
|
|
2143
|
-
BindBatchTracker(this, this.
|
|
2163
|
+
ReportOpPerfTelemetry(this.clientId, this._deltaManager, this, this.baseLogger);
|
|
2164
|
+
BindBatchTracker(this, this.baseLogger);
|
|
2144
2165
|
|
|
2145
2166
|
this.entryPoint = new LazyPromise(async () => {
|
|
2146
|
-
if (this.
|
|
2147
|
-
assert(
|
|
2148
|
-
this._summarizer !== undefined,
|
|
2149
|
-
0x5bf /* Summarizer object is undefined in a summarizer client */,
|
|
2150
|
-
);
|
|
2167
|
+
if (this._summarizer !== undefined) {
|
|
2151
2168
|
return this._summarizer;
|
|
2152
2169
|
}
|
|
2153
2170
|
return provideEntryPoint(this);
|
|
@@ -2158,8 +2175,9 @@ export class ContainerRuntime
|
|
|
2158
2175
|
this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
|
|
2159
2176
|
}
|
|
2160
2177
|
|
|
2178
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2161
2179
|
public onSchemaChange(schema: IDocumentSchemaCurrent): void {
|
|
2162
|
-
this.logger.sendTelemetryEvent({
|
|
2180
|
+
this.mc.logger.sendTelemetryEvent({
|
|
2163
2181
|
eventName: "SchemaChangeAccept",
|
|
2164
2182
|
sessionRuntimeSchema: JSON.stringify(schema),
|
|
2165
2183
|
});
|
|
@@ -2216,8 +2234,8 @@ export class ContainerRuntime
|
|
|
2216
2234
|
*/
|
|
2217
2235
|
private async initializeBaseState(): Promise<void> {
|
|
2218
2236
|
if (
|
|
2219
|
-
this.idCompressorMode === "on" ||
|
|
2220
|
-
(this.idCompressorMode === "delayed" && this.connected)
|
|
2237
|
+
this.sessionSchema.idCompressorMode === "on" ||
|
|
2238
|
+
(this.sessionSchema.idCompressorMode === "delayed" && this.connected)
|
|
2221
2239
|
) {
|
|
2222
2240
|
this._idCompressor = await this.createIdCompressor();
|
|
2223
2241
|
// This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
|
|
@@ -2276,7 +2294,7 @@ export class ContainerRuntime
|
|
|
2276
2294
|
// be in same loading group. So, once we have fetched the snapshot for that loading group on
|
|
2277
2295
|
// any request, then cache that as same group could be requested in future too.
|
|
2278
2296
|
const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(
|
|
2279
|
-
sortedLoadingGroupIds.join(),
|
|
2297
|
+
sortedLoadingGroupIds.join(","),
|
|
2280
2298
|
async () => {
|
|
2281
2299
|
assert(
|
|
2282
2300
|
this.storage.getSnapshot !== undefined,
|
|
@@ -2291,7 +2309,7 @@ export class ContainerRuntime
|
|
|
2291
2309
|
},
|
|
2292
2310
|
);
|
|
2293
2311
|
|
|
2294
|
-
this.logger.sendTelemetryEvent({
|
|
2312
|
+
this.mc.logger.sendTelemetryEvent({
|
|
2295
2313
|
eventName: "GroupIdSnapshotFetched",
|
|
2296
2314
|
details: JSON.stringify({
|
|
2297
2315
|
fromCache: loadedFromCache,
|
|
@@ -2332,7 +2350,7 @@ export class ContainerRuntime
|
|
|
2332
2350
|
// another snapshot from which the summarizer loaded and it is behind, then just give up as
|
|
2333
2351
|
// the summarizer state is not up to date.
|
|
2334
2352
|
// This should be a recoverable scenario and shouldn't happen as we should process the ack first.
|
|
2335
|
-
if (this.
|
|
2353
|
+
if (this._summarizer !== undefined) {
|
|
2336
2354
|
throw new Error("Summarizer client behind, loaded newer snapshot with loadingGroupId");
|
|
2337
2355
|
}
|
|
2338
2356
|
|
|
@@ -2403,7 +2421,7 @@ export class ContainerRuntime
|
|
|
2403
2421
|
return {
|
|
2404
2422
|
status: 200,
|
|
2405
2423
|
mimeType: "fluid/object",
|
|
2406
|
-
value: this.
|
|
2424
|
+
value: this._summarizer,
|
|
2407
2425
|
};
|
|
2408
2426
|
}
|
|
2409
2427
|
return create404Response(request);
|
|
@@ -2481,6 +2499,7 @@ export class ContainerRuntime
|
|
|
2481
2499
|
// Is document schema explicit control on?
|
|
2482
2500
|
const explicitSchemaControl = documentSchema?.runtime.explicitSchemaControl;
|
|
2483
2501
|
|
|
2502
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2484
2503
|
const metadata: IContainerRuntimeMetadata = {
|
|
2485
2504
|
...this.createContainerMetadata,
|
|
2486
2505
|
// Increment the summary number for the next summary that will be generated.
|
|
@@ -2494,7 +2513,8 @@ export class ContainerRuntime
|
|
|
2494
2513
|
// last message's sequence number.
|
|
2495
2514
|
// See also lastMessageFromMetadata()
|
|
2496
2515
|
message: explicitSchemaControl
|
|
2497
|
-
?
|
|
2516
|
+
? // eslint-disable-next-line import/no-deprecated
|
|
2517
|
+
({ sequenceNumber: -1 } as unknown as ISummaryMetadataMessage)
|
|
2498
2518
|
: message,
|
|
2499
2519
|
lastMessage: explicitSchemaControl ? message : undefined,
|
|
2500
2520
|
documentSchema,
|
|
@@ -2639,9 +2659,10 @@ export class ContainerRuntime
|
|
|
2639
2659
|
switch (opContents.type) {
|
|
2640
2660
|
case ContainerMessageType.FluidDataStoreOp:
|
|
2641
2661
|
case ContainerMessageType.Attach:
|
|
2642
|
-
case ContainerMessageType.Alias:
|
|
2662
|
+
case ContainerMessageType.Alias: {
|
|
2643
2663
|
return this.channelCollection.applyStashedOp(opContents);
|
|
2644
|
-
|
|
2664
|
+
}
|
|
2665
|
+
case ContainerMessageType.IdAllocation: {
|
|
2645
2666
|
// IDs allocation ops in stashed state are ignored because the tip state of the compressor
|
|
2646
2667
|
// is serialized into the pending state. This is done because generation of new IDs during
|
|
2647
2668
|
// stashed op application (or, later, resubmit) must generate new IDs and if the compressor
|
|
@@ -2652,19 +2673,24 @@ export class ContainerRuntime
|
|
|
2652
2673
|
// before applying the rest of the stashed ops. This would accomplish the same thing but with
|
|
2653
2674
|
// better performance in future incremental stashed state creation.
|
|
2654
2675
|
assert(
|
|
2655
|
-
this.idCompressorMode !== undefined,
|
|
2676
|
+
this.sessionSchema.idCompressorMode !== undefined,
|
|
2656
2677
|
0x8f1 /* ID compressor should be in use */,
|
|
2657
2678
|
);
|
|
2658
2679
|
return;
|
|
2659
|
-
|
|
2680
|
+
}
|
|
2681
|
+
case ContainerMessageType.DocumentSchemaChange: {
|
|
2660
2682
|
return;
|
|
2661
|
-
|
|
2683
|
+
}
|
|
2684
|
+
case ContainerMessageType.BlobAttach: {
|
|
2662
2685
|
return;
|
|
2663
|
-
|
|
2686
|
+
}
|
|
2687
|
+
case ContainerMessageType.Rejoin: {
|
|
2664
2688
|
throw new Error("rejoin not expected here");
|
|
2665
|
-
|
|
2689
|
+
}
|
|
2690
|
+
case ContainerMessageType.GC: {
|
|
2666
2691
|
// GC op is only sent in summarizer which should never have stashed ops.
|
|
2667
2692
|
throw new LoggingError("GC op not expected to be stashed in summarizer");
|
|
2693
|
+
}
|
|
2668
2694
|
default: {
|
|
2669
2695
|
const error = getUnknownMessageTypeError(
|
|
2670
2696
|
opContents.type,
|
|
@@ -2679,7 +2705,7 @@ export class ContainerRuntime
|
|
|
2679
2705
|
private async loadIdCompressor(): Promise<void | undefined> {
|
|
2680
2706
|
if (
|
|
2681
2707
|
this._idCompressor === undefined &&
|
|
2682
|
-
this.idCompressorMode !== undefined &&
|
|
2708
|
+
this.sessionSchema.idCompressorMode !== undefined &&
|
|
2683
2709
|
this._loadIdCompressor === undefined
|
|
2684
2710
|
) {
|
|
2685
2711
|
this._loadIdCompressor = this.createIdCompressor()
|
|
@@ -2694,7 +2720,7 @@ export class ContainerRuntime
|
|
|
2694
2720
|
this._idCompressor = compressor;
|
|
2695
2721
|
})
|
|
2696
2722
|
.catch((error) => {
|
|
2697
|
-
this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
2723
|
+
this.mc.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
2698
2724
|
throw error;
|
|
2699
2725
|
});
|
|
2700
2726
|
}
|
|
@@ -2710,7 +2736,7 @@ export class ContainerRuntime
|
|
|
2710
2736
|
0x978 /* this.clientId does not match Audience */,
|
|
2711
2737
|
);
|
|
2712
2738
|
|
|
2713
|
-
if (connected && this.idCompressorMode === "delayed") {
|
|
2739
|
+
if (connected && this.sessionSchema.idCompressorMode === "delayed") {
|
|
2714
2740
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
2715
2741
|
this.loadIdCompressor();
|
|
2716
2742
|
}
|
|
@@ -2832,7 +2858,7 @@ export class ContainerRuntime
|
|
|
2832
2858
|
// or something different, like a system message.
|
|
2833
2859
|
const hasModernRuntimeMessageEnvelope = messageCopy.type === MessageType.Operation;
|
|
2834
2860
|
const savedOp = (messageCopy.metadata as ISavedOpMetadata)?.savedOp;
|
|
2835
|
-
const logLegacyCase = getSingleUseLegacyLogCallback(this.logger, messageCopy.type);
|
|
2861
|
+
const logLegacyCase = getSingleUseLegacyLogCallback(this.mc.logger, messageCopy.type);
|
|
2836
2862
|
|
|
2837
2863
|
let runtimeBatch: boolean =
|
|
2838
2864
|
hasModernRuntimeMessageEnvelope || isUnpackedRuntimeMessage(messageCopy);
|
|
@@ -2987,11 +3013,11 @@ export class ContainerRuntime
|
|
|
2987
3013
|
let error: unknown;
|
|
2988
3014
|
try {
|
|
2989
3015
|
if (!runtimeBatch) {
|
|
2990
|
-
|
|
3016
|
+
for (const { message } of messagesWithMetadata) {
|
|
2991
3017
|
this.ensureNoDataModelChanges(() => {
|
|
2992
3018
|
this.observeNonRuntimeMessage(message);
|
|
2993
3019
|
});
|
|
2994
|
-
}
|
|
3020
|
+
}
|
|
2995
3021
|
return;
|
|
2996
3022
|
}
|
|
2997
3023
|
|
|
@@ -3076,8 +3102,8 @@ export class ContainerRuntime
|
|
|
3076
3102
|
for (const { message } of messagesWithMetadata) {
|
|
3077
3103
|
this.emit("op", message, true /* runtimeMessage */);
|
|
3078
3104
|
}
|
|
3079
|
-
} catch (
|
|
3080
|
-
error =
|
|
3105
|
+
} catch (error_) {
|
|
3106
|
+
error = error_;
|
|
3081
3107
|
throw error;
|
|
3082
3108
|
} finally {
|
|
3083
3109
|
if (locationInBatch.batchEnd) {
|
|
@@ -3148,38 +3174,46 @@ export class ContainerRuntime
|
|
|
3148
3174
|
switch (message.type) {
|
|
3149
3175
|
case ContainerMessageType.FluidDataStoreOp:
|
|
3150
3176
|
case ContainerMessageType.Attach:
|
|
3151
|
-
case ContainerMessageType.Alias:
|
|
3177
|
+
case ContainerMessageType.Alias: {
|
|
3152
3178
|
// Remove the metadata from the message before sending it to the channel collection. The metadata
|
|
3153
3179
|
// is added by the container runtime and is not part of the message that the channel collection and
|
|
3154
3180
|
// layers below it expect.
|
|
3155
3181
|
this.channelCollection.processMessages({ envelope: message, messagesContent, local });
|
|
3156
3182
|
break;
|
|
3157
|
-
|
|
3183
|
+
}
|
|
3184
|
+
case ContainerMessageType.BlobAttach: {
|
|
3158
3185
|
this.blobManager.processBlobAttachMessage(message, local);
|
|
3159
3186
|
break;
|
|
3160
|
-
|
|
3187
|
+
}
|
|
3188
|
+
case ContainerMessageType.IdAllocation: {
|
|
3161
3189
|
this.processIdCompressorMessages(contents as IdCreationRange[], savedOp);
|
|
3162
3190
|
break;
|
|
3163
|
-
|
|
3191
|
+
}
|
|
3192
|
+
case ContainerMessageType.GC: {
|
|
3164
3193
|
this.garbageCollector.processMessages(
|
|
3165
3194
|
contents as GarbageCollectionMessage[],
|
|
3166
3195
|
message.timestamp,
|
|
3167
3196
|
local,
|
|
3168
3197
|
);
|
|
3169
3198
|
break;
|
|
3170
|
-
|
|
3199
|
+
}
|
|
3200
|
+
case ContainerMessageType.ChunkedOp: {
|
|
3171
3201
|
// From observability POV, we should not expose the rest of the system (including "op" events on object) to these messages.
|
|
3172
3202
|
// Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
|
|
3173
3203
|
assert(false, 0x93d /* should not even get here */);
|
|
3174
|
-
|
|
3204
|
+
}
|
|
3205
|
+
case ContainerMessageType.Rejoin: {
|
|
3175
3206
|
break;
|
|
3176
|
-
|
|
3207
|
+
}
|
|
3208
|
+
case ContainerMessageType.DocumentSchemaChange: {
|
|
3177
3209
|
this.documentsSchemaController.processDocumentSchemaMessages(
|
|
3210
|
+
// eslint-disable-next-line import/no-deprecated
|
|
3178
3211
|
contents as IDocumentSchemaChangeMessage[],
|
|
3179
3212
|
local,
|
|
3180
3213
|
message.sequenceNumber,
|
|
3181
3214
|
);
|
|
3182
3215
|
break;
|
|
3216
|
+
}
|
|
3183
3217
|
default: {
|
|
3184
3218
|
const error = getUnknownMessageTypeError(
|
|
3185
3219
|
message.type,
|
|
@@ -3206,7 +3240,7 @@ export class ContainerRuntime
|
|
|
3206
3240
|
// put it in a pending queue and delay finalization.
|
|
3207
3241
|
if (this._idCompressor === undefined) {
|
|
3208
3242
|
assert(
|
|
3209
|
-
this.idCompressorMode !== undefined,
|
|
3243
|
+
this.sessionSchema.idCompressorMode !== undefined,
|
|
3210
3244
|
0x93c /* id compressor should be enabled */,
|
|
3211
3245
|
);
|
|
3212
3246
|
this.pendingIdCompressorOps.push(range);
|
|
@@ -3246,7 +3280,11 @@ export class ContainerRuntime
|
|
|
3246
3280
|
* Updates signal telemetry including emitting telemetry events.
|
|
3247
3281
|
*/
|
|
3248
3282
|
private processSignalForTelemetry(envelope: ISignalEnvelope): void {
|
|
3249
|
-
const {
|
|
3283
|
+
const {
|
|
3284
|
+
clientBroadcastSignalSequenceNumber,
|
|
3285
|
+
contents: envelopeContents,
|
|
3286
|
+
address: envelopeAddress,
|
|
3287
|
+
} = envelope;
|
|
3250
3288
|
if (clientBroadcastSignalSequenceNumber === undefined) {
|
|
3251
3289
|
return;
|
|
3252
3290
|
}
|
|
@@ -3291,8 +3329,8 @@ export class ContainerRuntime
|
|
|
3291
3329
|
};
|
|
3292
3330
|
// Only log `contents.type` when address is for container to avoid
|
|
3293
3331
|
// chance that contents type is customer data.
|
|
3294
|
-
if (
|
|
3295
|
-
details.contentsType =
|
|
3332
|
+
if (envelopeAddress === undefined) {
|
|
3333
|
+
details.contentsType = envelopeContents.type; // Type of signal that was received out of order.
|
|
3296
3334
|
}
|
|
3297
3335
|
this.mc.logger.sendTelemetryEvent({
|
|
3298
3336
|
eventName: "SignalOutOfOrder",
|
|
@@ -3388,8 +3426,8 @@ export class ContainerRuntime
|
|
|
3388
3426
|
checkpoint.rollback((message: BatchMessage) =>
|
|
3389
3427
|
this.rollback(message.contents, message.localOpMetadata),
|
|
3390
3428
|
);
|
|
3391
|
-
} catch (
|
|
3392
|
-
const error2 = wrapError(
|
|
3429
|
+
} catch (error_) {
|
|
3430
|
+
const error2 = wrapError(error_, (message) => {
|
|
3393
3431
|
return DataProcessingError.create(
|
|
3394
3432
|
`RollbackError: ${message}`,
|
|
3395
3433
|
"checkpointRollback",
|
|
@@ -3549,8 +3587,9 @@ export class ContainerRuntime
|
|
|
3549
3587
|
case ContainerMessageType.GC: {
|
|
3550
3588
|
return false;
|
|
3551
3589
|
}
|
|
3552
|
-
default:
|
|
3590
|
+
default: {
|
|
3553
3591
|
break;
|
|
3592
|
+
}
|
|
3554
3593
|
}
|
|
3555
3594
|
return true;
|
|
3556
3595
|
}
|
|
@@ -3593,7 +3632,7 @@ export class ContainerRuntime
|
|
|
3593
3632
|
|
|
3594
3633
|
// We should not track the round trip of a new signal in the case we are already tracking one.
|
|
3595
3634
|
if (
|
|
3596
|
-
clientBroadcastSignalSequenceNumber %
|
|
3635
|
+
clientBroadcastSignalSequenceNumber % defaultTelemetrySignalSampleCount === 1 &&
|
|
3597
3636
|
this._signalTracking.roundTripSignalSequenceNumber === undefined
|
|
3598
3637
|
) {
|
|
3599
3638
|
this._signalTracking.signalTimestamp = Date.now();
|
|
@@ -3687,6 +3726,12 @@ export class ContainerRuntime
|
|
|
3687
3726
|
|
|
3688
3727
|
public readonly getAbsoluteUrl: (relativeUrl: string) => Promise<string | undefined>;
|
|
3689
3728
|
|
|
3729
|
+
/**
|
|
3730
|
+
* Builds the Summary tree including all the channels and the container state.
|
|
3731
|
+
*
|
|
3732
|
+
* @remarks - Unfortunately, this function is accessed in a non-typesafe way by a legacy first-party partner,
|
|
3733
|
+
* so until we can provide a proper API for their scenario, we need to ensure this function doesn't change.
|
|
3734
|
+
*/
|
|
3690
3735
|
private async summarizeInternal(
|
|
3691
3736
|
fullTree: boolean,
|
|
3692
3737
|
trackState: boolean,
|
|
@@ -3834,8 +3879,10 @@ export class ContainerRuntime
|
|
|
3834
3879
|
const { dataStoreRoutes, blobManagerRoutes } =
|
|
3835
3880
|
this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
|
|
3836
3881
|
|
|
3837
|
-
|
|
3838
|
-
|
|
3882
|
+
return [
|
|
3883
|
+
...this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes),
|
|
3884
|
+
...this.blobManager.deleteSweepReadyNodes(blobManagerRoutes),
|
|
3885
|
+
];
|
|
3839
3886
|
}
|
|
3840
3887
|
|
|
3841
3888
|
/**
|
|
@@ -3864,10 +3911,13 @@ export class ContainerRuntime
|
|
|
3864
3911
|
* Returns the type of the GC node. Currently, there are nodes that belong to the root ("/"), data stores or
|
|
3865
3912
|
* blob manager.
|
|
3866
3913
|
*/
|
|
3914
|
+
// eslint-disable-next-line import/no-deprecated
|
|
3867
3915
|
public getNodeType(nodePath: string): GCNodeType {
|
|
3868
3916
|
if (isBlobPath(nodePath)) {
|
|
3917
|
+
// eslint-disable-next-line import/no-deprecated
|
|
3869
3918
|
return GCNodeType.Blob;
|
|
3870
3919
|
}
|
|
3920
|
+
// eslint-disable-next-line import/no-deprecated
|
|
3871
3921
|
return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
|
|
3872
3922
|
}
|
|
3873
3923
|
|
|
@@ -3883,13 +3933,19 @@ export class ContainerRuntime
|
|
|
3883
3933
|
}
|
|
3884
3934
|
|
|
3885
3935
|
switch (this.getNodeType(nodePath)) {
|
|
3886
|
-
|
|
3936
|
+
// eslint-disable-next-line import/no-deprecated
|
|
3937
|
+
case GCNodeType.Blob: {
|
|
3887
3938
|
return [blobManagerBasePath];
|
|
3939
|
+
}
|
|
3940
|
+
// eslint-disable-next-line import/no-deprecated
|
|
3888
3941
|
case GCNodeType.DataStore:
|
|
3889
|
-
|
|
3942
|
+
// eslint-disable-next-line import/no-deprecated
|
|
3943
|
+
case GCNodeType.SubDataStore: {
|
|
3890
3944
|
return this.channelCollection.getDataStorePackagePath(nodePath);
|
|
3891
|
-
|
|
3945
|
+
}
|
|
3946
|
+
default: {
|
|
3892
3947
|
assert(false, 0x2de /* "Package path requested for unsupported node type." */);
|
|
3948
|
+
}
|
|
3893
3949
|
}
|
|
3894
3950
|
}
|
|
3895
3951
|
|
|
@@ -3935,6 +3991,7 @@ export class ContainerRuntime
|
|
|
3935
3991
|
fullGC?: boolean;
|
|
3936
3992
|
},
|
|
3937
3993
|
telemetryContext?: ITelemetryContext,
|
|
3994
|
+
// eslint-disable-next-line import/no-deprecated
|
|
3938
3995
|
): Promise<IGCStats | undefined> {
|
|
3939
3996
|
return this.garbageCollector.collectGarbage(options, telemetryContext);
|
|
3940
3997
|
}
|
|
@@ -3977,8 +4034,10 @@ export class ContainerRuntime
|
|
|
3977
4034
|
* op processing, updating SummarizerNode state tracking, and garbage collection.
|
|
3978
4035
|
* @param options - options controlling how the summary is generated or submitted
|
|
3979
4036
|
*/
|
|
4037
|
+
// eslint-disable-next-line import/no-deprecated
|
|
3980
4038
|
public async submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult> {
|
|
3981
4039
|
const {
|
|
4040
|
+
cancellationToken,
|
|
3982
4041
|
fullTree = false,
|
|
3983
4042
|
finalAttempt = false,
|
|
3984
4043
|
summaryLogger,
|
|
@@ -4098,7 +4157,7 @@ export class ContainerRuntime
|
|
|
4098
4157
|
eventName: "LatestSummaryRefSeqNumMismatch",
|
|
4099
4158
|
details: {
|
|
4100
4159
|
...startSummaryResult,
|
|
4101
|
-
mismatchNumbers:
|
|
4160
|
+
mismatchNumbers: [...startSummaryResult.mismatchNumbers],
|
|
4102
4161
|
},
|
|
4103
4162
|
});
|
|
4104
4163
|
|
|
@@ -4122,7 +4181,7 @@ export class ContainerRuntime
|
|
|
4122
4181
|
// summarizer to reconnect in the future.
|
|
4123
4182
|
// Also checking for cancellation is a must as summary process may be abandoned for other reasons,
|
|
4124
4183
|
// like loss of connectivity for main (interactive) client.
|
|
4125
|
-
if (
|
|
4184
|
+
if (cancellationToken.cancelled) {
|
|
4126
4185
|
return { continue: false, error: "disconnected" };
|
|
4127
4186
|
}
|
|
4128
4187
|
// That said, we rely on submitSystemMessage() that today only works in connected state.
|
|
@@ -4263,10 +4322,7 @@ export class ContainerRuntime
|
|
|
4263
4322
|
|
|
4264
4323
|
let handle: string;
|
|
4265
4324
|
try {
|
|
4266
|
-
handle = await this.storage.uploadSummaryWithContext(
|
|
4267
|
-
summarizeResult.summary,
|
|
4268
|
-
summaryContext,
|
|
4269
|
-
);
|
|
4325
|
+
handle = await this.storage.uploadSummaryWithContext(summaryTree, summaryContext);
|
|
4270
4326
|
} catch (error) {
|
|
4271
4327
|
return {
|
|
4272
4328
|
stage: "generate",
|
|
@@ -4416,14 +4472,14 @@ export class ContainerRuntime
|
|
|
4416
4472
|
}
|
|
4417
4473
|
|
|
4418
4474
|
private updateDocumentDirtyState(dirty: boolean): void {
|
|
4419
|
-
if (this.attachState
|
|
4420
|
-
assert(dirty, 0x3d2 /* Non-attached container is dirty */);
|
|
4421
|
-
} else {
|
|
4475
|
+
if (this.attachState === AttachState.Attached) {
|
|
4422
4476
|
// Other way is not true = see this.isContainerMessageDirtyable()
|
|
4423
4477
|
assert(
|
|
4424
4478
|
!dirty || this.hasPendingMessages(),
|
|
4425
4479
|
0x3d3 /* if doc is dirty, there has to be pending ops */,
|
|
4426
4480
|
);
|
|
4481
|
+
} else {
|
|
4482
|
+
assert(dirty, 0x3d2 /* Non-attached container is dirty */);
|
|
4427
4483
|
}
|
|
4428
4484
|
|
|
4429
4485
|
if (this.dirtyContainer === dirty) {
|
|
@@ -4520,7 +4576,7 @@ export class ContainerRuntime
|
|
|
4520
4576
|
// on this callback to do actual sending.
|
|
4521
4577
|
const schemaChangeMessage = this.documentsSchemaController.maybeSendSchemaMessage();
|
|
4522
4578
|
if (schemaChangeMessage) {
|
|
4523
|
-
this.logger.sendTelemetryEvent({
|
|
4579
|
+
this.mc.logger.sendTelemetryEvent({
|
|
4524
4580
|
eventName: "SchemaChangeProposal",
|
|
4525
4581
|
refSeq: schemaChangeMessage.refSeq,
|
|
4526
4582
|
version: schemaChangeMessage.version,
|
|
@@ -4574,6 +4630,9 @@ export class ContainerRuntime
|
|
|
4574
4630
|
}
|
|
4575
4631
|
|
|
4576
4632
|
this.flushTaskExists = true;
|
|
4633
|
+
|
|
4634
|
+
// TODO: hoist this out of the function scope to save unnecessary allocations
|
|
4635
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping -- Separate `flush` method already exists in outer scope
|
|
4577
4636
|
const flush = (): void => {
|
|
4578
4637
|
this.flushTaskExists = false;
|
|
4579
4638
|
try {
|
|
@@ -4584,27 +4643,30 @@ export class ContainerRuntime
|
|
|
4584
4643
|
};
|
|
4585
4644
|
|
|
4586
4645
|
switch (this.flushMode) {
|
|
4587
|
-
case FlushMode.TurnBased:
|
|
4646
|
+
case FlushMode.TurnBased: {
|
|
4588
4647
|
// When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
|
|
4589
4648
|
// batch at the end of the turn
|
|
4590
4649
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
4591
4650
|
Promise.resolve().then(flush);
|
|
4592
4651
|
break;
|
|
4652
|
+
}
|
|
4593
4653
|
|
|
4594
4654
|
// FlushModeExperimental is experimental and not exposed directly in the runtime APIs
|
|
4595
|
-
case FlushModeExperimental.Async as unknown as FlushMode:
|
|
4655
|
+
case FlushModeExperimental.Async as unknown as FlushMode: {
|
|
4596
4656
|
// When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
|
|
4597
4657
|
// batch when all micro-tasks are complete.
|
|
4598
4658
|
// Compared to TurnBased, this flush mode will capture more ops into the same batch.
|
|
4599
4659
|
setTimeout(flush, 0);
|
|
4600
4660
|
break;
|
|
4661
|
+
}
|
|
4601
4662
|
|
|
4602
|
-
default:
|
|
4663
|
+
default: {
|
|
4603
4664
|
assert(
|
|
4604
4665
|
this._orderSequentiallyCalls > 0,
|
|
4605
4666
|
0x587 /* Unreachable unless running under orderSequentially */,
|
|
4606
4667
|
);
|
|
4607
4668
|
break;
|
|
4669
|
+
}
|
|
4608
4670
|
}
|
|
4609
4671
|
}
|
|
4610
4672
|
|
|
@@ -4621,10 +4683,7 @@ export class ContainerRuntime
|
|
|
4621
4683
|
// System message should not be sent in the middle of the batch.
|
|
4622
4684
|
assert(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
|
|
4623
4685
|
|
|
4624
|
-
|
|
4625
|
-
return this.submitSummaryFn !== undefined
|
|
4626
|
-
? this.submitSummaryFn(contents, referenceSequenceNumber)
|
|
4627
|
-
: this.submitFn(MessageType.Summarize, contents, false);
|
|
4686
|
+
return this.submitSummaryFn(contents, referenceSequenceNumber);
|
|
4628
4687
|
}
|
|
4629
4688
|
|
|
4630
4689
|
/**
|
|
@@ -4674,17 +4733,18 @@ export class ContainerRuntime
|
|
|
4674
4733
|
opMetadata: Record<string, unknown> | undefined,
|
|
4675
4734
|
): void {
|
|
4676
4735
|
assert(
|
|
4677
|
-
|
|
4736
|
+
this._summarizer === undefined,
|
|
4678
4737
|
0x8f2 /* Summarizer never reconnects so should never resubmit */,
|
|
4679
4738
|
);
|
|
4680
4739
|
switch (message.type) {
|
|
4681
4740
|
case ContainerMessageType.FluidDataStoreOp:
|
|
4682
4741
|
case ContainerMessageType.Attach:
|
|
4683
|
-
case ContainerMessageType.Alias:
|
|
4742
|
+
case ContainerMessageType.Alias: {
|
|
4684
4743
|
// For Operations, call resubmitDataStoreOp which will find the right store
|
|
4685
4744
|
// and trigger resubmission on it.
|
|
4686
4745
|
this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
|
|
4687
4746
|
break;
|
|
4747
|
+
}
|
|
4688
4748
|
case ContainerMessageType.IdAllocation: {
|
|
4689
4749
|
// Allocation ops are never resubmitted/rebased. This is because they require special handling to
|
|
4690
4750
|
// avoid being submitted out of order. For example, if the pending state manager contained
|
|
@@ -4695,20 +4755,24 @@ export class ContainerRuntime
|
|
|
4695
4755
|
// all pending IDs. The resubmitted allocation ops are then ignored here.
|
|
4696
4756
|
break;
|
|
4697
4757
|
}
|
|
4698
|
-
case ContainerMessageType.BlobAttach:
|
|
4758
|
+
case ContainerMessageType.BlobAttach: {
|
|
4699
4759
|
this.blobManager.reSubmit(opMetadata);
|
|
4700
4760
|
break;
|
|
4701
|
-
|
|
4761
|
+
}
|
|
4762
|
+
case ContainerMessageType.Rejoin: {
|
|
4702
4763
|
this.submit(message);
|
|
4703
4764
|
break;
|
|
4704
|
-
|
|
4765
|
+
}
|
|
4766
|
+
case ContainerMessageType.GC: {
|
|
4705
4767
|
this.submit(message);
|
|
4706
4768
|
break;
|
|
4707
|
-
|
|
4769
|
+
}
|
|
4770
|
+
case ContainerMessageType.DocumentSchemaChange: {
|
|
4708
4771
|
// There is no need to resend this message. Document schema controller will properly resend it again (if needed)
|
|
4709
4772
|
// on a first occasion (any ops sent after reconnect). There is a good chance, though, that it will not want to
|
|
4710
4773
|
// send any ops, as some other client already changed schema.
|
|
4711
4774
|
break;
|
|
4775
|
+
}
|
|
4712
4776
|
default: {
|
|
4713
4777
|
const error = getUnknownMessageTypeError(message.type, "reSubmitCore" /* codePath */);
|
|
4714
4778
|
this.closeFn(error);
|
|
@@ -4721,19 +4785,22 @@ export class ContainerRuntime
|
|
|
4721
4785
|
// Need to parse from string for back-compat
|
|
4722
4786
|
const { type, contents } = this.parseLocalOpContent(content);
|
|
4723
4787
|
switch (type) {
|
|
4724
|
-
case ContainerMessageType.FluidDataStoreOp:
|
|
4788
|
+
case ContainerMessageType.FluidDataStoreOp: {
|
|
4725
4789
|
// For operations, call rollbackDataStoreOp which will find the right store
|
|
4726
4790
|
// and trigger rollback on it.
|
|
4727
4791
|
this.channelCollection.rollback(type, contents, localOpMetadata);
|
|
4728
4792
|
break;
|
|
4729
|
-
|
|
4793
|
+
}
|
|
4794
|
+
default: {
|
|
4730
4795
|
throw new Error(`Can't rollback ${type}`);
|
|
4796
|
+
}
|
|
4731
4797
|
}
|
|
4732
4798
|
}
|
|
4733
4799
|
|
|
4734
4800
|
/**
|
|
4735
4801
|
* Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck
|
|
4736
4802
|
*/
|
|
4803
|
+
// eslint-disable-next-line import/no-deprecated
|
|
4737
4804
|
public async refreshLatestSummaryAck(options: IRefreshSummaryAckOptions): Promise<void> {
|
|
4738
4805
|
const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
|
|
4739
4806
|
// proposalHandle is always passed from RunningSummarizer.
|
|
@@ -4780,6 +4847,9 @@ export class ContainerRuntime
|
|
|
4780
4847
|
};
|
|
4781
4848
|
}
|
|
4782
4849
|
|
|
4850
|
+
private readonly readAndParseBlob = async <T>(id: string): Promise<T> =>
|
|
4851
|
+
readAndParse<T>(this.storage, id);
|
|
4852
|
+
|
|
4783
4853
|
/**
|
|
4784
4854
|
* Fetches the latest snapshot from storage. If the fetched snapshot is same or newer than the one for which ack
|
|
4785
4855
|
* was received, close this client. Fetching the snapshot will update the cache for this client so if it's
|
|
@@ -4840,6 +4910,7 @@ export class ContainerRuntime
|
|
|
4840
4910
|
snapshotTree = snapshot.snapshotTree;
|
|
4841
4911
|
} else {
|
|
4842
4912
|
const versions = await this.storage.getVersions(
|
|
4913
|
+
// eslint-disable-next-line unicorn/no-null
|
|
4843
4914
|
null,
|
|
4844
4915
|
1,
|
|
4845
4916
|
scenarioName,
|
|
@@ -4855,9 +4926,8 @@ export class ContainerRuntime
|
|
|
4855
4926
|
}
|
|
4856
4927
|
|
|
4857
4928
|
props.getSnapshotDuration = trace.trace().duration;
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
const snapshotRefSeq = await seqFromTree(snapshotTree, readAndParseBlob);
|
|
4929
|
+
|
|
4930
|
+
const snapshotRefSeq = await seqFromTree(snapshotTree, this.readAndParseBlob);
|
|
4861
4931
|
props.snapshotRefSeq = snapshotRefSeq;
|
|
4862
4932
|
props.newerSnapshotPresent = snapshotRefSeq >= targetRefSeq;
|
|
4863
4933
|
|
|
@@ -4937,28 +5007,28 @@ export class ContainerRuntime
|
|
|
4937
5007
|
}
|
|
4938
5008
|
|
|
4939
5009
|
public summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults {
|
|
4940
|
-
if (this.
|
|
4941
|
-
return this.
|
|
4942
|
-
} else if (this.summaryManager
|
|
4943
|
-
return this.summaryManager.summarizeOnDemand(options);
|
|
4944
|
-
} else {
|
|
5010
|
+
if (this._summarizer !== undefined) {
|
|
5011
|
+
return this._summarizer.summarizeOnDemand(options);
|
|
5012
|
+
} else if (this.summaryManager === undefined) {
|
|
4945
5013
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
4946
5014
|
// disableSummaries is turned on. We are throwing instead of returning a failure here,
|
|
4947
5015
|
// because it is a misuse of the API rather than an expected failure.
|
|
4948
5016
|
throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
5017
|
+
} else {
|
|
5018
|
+
return this.summaryManager.summarizeOnDemand(options);
|
|
4949
5019
|
}
|
|
4950
5020
|
}
|
|
4951
5021
|
|
|
4952
5022
|
public enqueueSummarize(options: IEnqueueSummarizeOptions): EnqueueSummarizeResult {
|
|
4953
|
-
if (this.
|
|
4954
|
-
return this.
|
|
4955
|
-
} else if (this.summaryManager
|
|
4956
|
-
return this.summaryManager.enqueueSummarize(options);
|
|
4957
|
-
} else {
|
|
5023
|
+
if (this._summarizer !== undefined) {
|
|
5024
|
+
return this._summarizer.enqueueSummarize(options);
|
|
5025
|
+
} else if (this.summaryManager === undefined) {
|
|
4958
5026
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
4959
5027
|
// generateSummaries is turned off. We are throwing instead of returning a failure here,
|
|
4960
5028
|
// because it is a misuse of the API rather than an expected failure.
|
|
4961
5029
|
throw new UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
5030
|
+
} else {
|
|
5031
|
+
return this.summaryManager.enqueueSummarize(options);
|
|
4962
5032
|
}
|
|
4963
5033
|
}
|
|
4964
5034
|
|