@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/dist/containerRuntime.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.ContainerRuntime = exports.loadContainerRuntime = exports.getSingleUseLegacyLogCallback = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isUnpackedRuntimeMessage = exports.defaultPendingOpsRetryDelayMs = exports.defaultPendingOpsWaitTimeoutMs = exports.disabledCompressionConfig = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.InactiveResponseHeaderKey = exports.TombstoneResponseHeaderKey = exports.DeletedResponseHeaderKey = exports.DefaultSummaryConfiguration = void 0;
|
|
7
|
+
exports.ContainerRuntime = exports.loadContainerRuntime = exports.getSingleUseLegacyLogCallback = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isUnpackedRuntimeMessage = exports.defaultPendingOpsRetryDelayMs = exports.defaultPendingOpsWaitTimeoutMs = exports.disabledCompressionConfig = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.InactiveResponseHeaderKey = exports.TombstoneResponseHeaderKey = exports.DeletedResponseHeaderKey = exports.DefaultSummaryConfiguration = exports.isSummariesDisabled = void 0;
|
|
8
8
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
9
9
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
10
10
|
const internal_1 = require("@fluidframework/container-definitions/internal");
|
|
@@ -27,6 +27,7 @@ const deltaManagerProxies_js_1 = require("./deltaManagerProxies.js");
|
|
|
27
27
|
const deltaScheduler_js_1 = require("./deltaScheduler.js");
|
|
28
28
|
const index_js_2 = require("./gc/index.js");
|
|
29
29
|
const inboundBatchAggregator_js_1 = require("./inboundBatchAggregator.js");
|
|
30
|
+
const layerCompatState_js_1 = require("./layerCompatState.js");
|
|
30
31
|
const messageTypes_js_1 = require("./messageTypes.js");
|
|
31
32
|
const index_js_3 = require("./opLifecycle/index.js");
|
|
32
33
|
const packageVersion_js_1 = require("./packageVersion.js");
|
|
@@ -52,6 +53,10 @@ function getUnknownMessageTypeError(unknownContainerRuntimeMessageType, codePath
|
|
|
52
53
|
},
|
|
53
54
|
});
|
|
54
55
|
}
|
|
56
|
+
function isSummariesDisabled(config) {
|
|
57
|
+
return config.state === "disabled";
|
|
58
|
+
}
|
|
59
|
+
exports.isSummariesDisabled = isSummariesDisabled;
|
|
55
60
|
/**
|
|
56
61
|
* @legacy
|
|
57
62
|
* @alpha
|
|
@@ -67,13 +72,14 @@ exports.DefaultSummaryConfiguration = {
|
|
|
67
72
|
maxOpsSinceLastSummary: 7000,
|
|
68
73
|
initialSummarizerDelayMs: 5 * 1000, // 5 secs.
|
|
69
74
|
nonRuntimeOpWeight: 0.1,
|
|
70
|
-
runtimeOpWeight: 1
|
|
75
|
+
runtimeOpWeight: 1,
|
|
71
76
|
nonRuntimeHeuristicThreshold: 20,
|
|
72
77
|
};
|
|
73
78
|
/**
|
|
74
79
|
* Error responses when requesting a deleted object will have this header set to true
|
|
75
80
|
* @legacy
|
|
76
81
|
* @alpha
|
|
82
|
+
* @deprecated This type will be moved to internal in 2.30. External usage is not necessary or supported.
|
|
77
83
|
*/
|
|
78
84
|
exports.DeletedResponseHeaderKey = "wasDeleted";
|
|
79
85
|
/**
|
|
@@ -113,7 +119,7 @@ var CompressionAlgorithms;
|
|
|
113
119
|
* @alpha
|
|
114
120
|
*/
|
|
115
121
|
exports.disabledCompressionConfig = {
|
|
116
|
-
minimumBatchSizeInBytes:
|
|
122
|
+
minimumBatchSizeInBytes: Number.POSITIVE_INFINITY,
|
|
117
123
|
compressionAlgorithm: CompressionAlgorithms.lz4,
|
|
118
124
|
};
|
|
119
125
|
const maxConsecutiveReconnectsKey = "Fluid.ContainerRuntime.MaxConsecutiveReconnects";
|
|
@@ -168,7 +174,9 @@ function getDeviceSpec() {
|
|
|
168
174
|
};
|
|
169
175
|
}
|
|
170
176
|
}
|
|
171
|
-
catch {
|
|
177
|
+
catch {
|
|
178
|
+
// Eat the error
|
|
179
|
+
}
|
|
172
180
|
return {};
|
|
173
181
|
}
|
|
174
182
|
exports.getDeviceSpec = getDeviceSpec;
|
|
@@ -211,21 +219,20 @@ async function createSummarizer(loader, url) {
|
|
|
211
219
|
let fluidObject;
|
|
212
220
|
// Older containers may not have the "getEntryPoint" API
|
|
213
221
|
// ! This check will need to stay until LTS of loader moves past 2.0.0-internal.7.0.0
|
|
214
|
-
if (resolvedContainer.getEntryPoint
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
else {
|
|
218
|
-
// 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
|
|
219
|
-
const response = await resolvedContainer.request({
|
|
222
|
+
if (resolvedContainer.getEntryPoint === undefined) {
|
|
223
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any
|
|
224
|
+
const response = (await resolvedContainer.request({
|
|
220
225
|
url: `/${summarizerRequestUrl}`,
|
|
221
|
-
});
|
|
222
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
226
|
+
}));
|
|
223
227
|
if (response.status !== 200 || response.mimeType !== "fluid/object") {
|
|
224
228
|
throw (0, internal_6.responseToException)(response, request);
|
|
225
229
|
}
|
|
226
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-
|
|
230
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
227
231
|
fluidObject = response.value;
|
|
228
232
|
}
|
|
233
|
+
else {
|
|
234
|
+
fluidObject = await resolvedContainer.getEntryPoint();
|
|
235
|
+
}
|
|
229
236
|
if (fluidObject?.ISummarizer === undefined) {
|
|
230
237
|
throw new internal_7.UsageError("Fluid object does not implement ISummarizer");
|
|
231
238
|
}
|
|
@@ -237,7 +244,9 @@ async function createSummarizer(loader, url) {
|
|
|
237
244
|
* This allows new runtime to make documents not openable for old runtimes, one explicit document schema control is enabled.
|
|
238
245
|
* Please see addMetadataToSummary() as well
|
|
239
246
|
*/
|
|
240
|
-
function lastMessageFromMetadata(
|
|
247
|
+
function lastMessageFromMetadata(
|
|
248
|
+
// eslint-disable-next-line import/no-deprecated
|
|
249
|
+
metadata) {
|
|
241
250
|
return metadata?.documentSchema?.runtime?.explicitSchemaControl
|
|
242
251
|
? metadata?.lastMessage
|
|
243
252
|
: metadata?.message;
|
|
@@ -254,6 +263,7 @@ let getSingleUseLegacyLogCallback = (logger, type) => {
|
|
|
254
263
|
details: { codePath, type },
|
|
255
264
|
});
|
|
256
265
|
// Now that we've logged, prevent future logging (globally).
|
|
266
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
257
267
|
exports.getSingleUseLegacyLogCallback = () => () => { };
|
|
258
268
|
};
|
|
259
269
|
};
|
|
@@ -269,6 +279,8 @@ async function loadContainerRuntime(params) {
|
|
|
269
279
|
return ContainerRuntime.loadRuntime(params);
|
|
270
280
|
}
|
|
271
281
|
exports.loadContainerRuntime = loadContainerRuntime;
|
|
282
|
+
const defaultMaxConsecutiveReconnects = 7;
|
|
283
|
+
const defaultTelemetrySignalSampleCount = 100;
|
|
272
284
|
/**
|
|
273
285
|
* Represents the runtime of the container. Contains helper functions/state of the container.
|
|
274
286
|
* It will define the store level mappings.
|
|
@@ -324,7 +336,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
324
336
|
const [chunks, recentBatchInfo, metadata, electedSummarizerData, aliases, serializedIdCompressor,] = await Promise.all([
|
|
325
337
|
tryFetchBlob(index_js_4.chunksBlobName),
|
|
326
338
|
tryFetchBlob(index_js_4.recentBatchInfoBlobName),
|
|
339
|
+
// eslint-disable-next-line import/no-deprecated
|
|
327
340
|
tryFetchBlob(index_js_4.metadataBlobName),
|
|
341
|
+
// eslint-disable-next-line import/no-deprecated
|
|
328
342
|
tryFetchBlob(index_js_4.electedSummarizerBlobName),
|
|
329
343
|
tryFetchBlob(index_js_4.aliasBlobName),
|
|
330
344
|
tryFetchBlob(index_js_4.idCompressorBlobName),
|
|
@@ -338,6 +352,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
338
352
|
// When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
|
|
339
353
|
if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
|
|
340
354
|
// Unless bypass is explicitly set, then take action when sequence numbers mismatch.
|
|
355
|
+
// eslint-disable-next-line unicorn/no-lonely-if -- Separate if statements make flow easier to parse
|
|
341
356
|
if (loadSequenceNumberVerification !== "bypass" &&
|
|
342
357
|
runtimeSequenceNumber !== protocolSequenceNumber) {
|
|
343
358
|
// Message to OCEs:
|
|
@@ -360,15 +375,18 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
360
375
|
}
|
|
361
376
|
let desiredIdCompressorMode;
|
|
362
377
|
switch (mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled")) {
|
|
363
|
-
case true:
|
|
378
|
+
case true: {
|
|
364
379
|
desiredIdCompressorMode = "on";
|
|
365
380
|
break;
|
|
366
|
-
|
|
381
|
+
}
|
|
382
|
+
case false: {
|
|
367
383
|
desiredIdCompressorMode = undefined;
|
|
368
384
|
break;
|
|
369
|
-
|
|
385
|
+
}
|
|
386
|
+
default: {
|
|
370
387
|
desiredIdCompressorMode = enableRuntimeIdCompressor;
|
|
371
388
|
break;
|
|
389
|
+
}
|
|
372
390
|
}
|
|
373
391
|
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
374
392
|
// allow new containers to turn it on.
|
|
@@ -421,15 +439,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
421
439
|
if (pendingLocalState?.pendingIdCompressorState !== undefined) {
|
|
422
440
|
return deserializeIdCompressor(pendingLocalState.pendingIdCompressorState, compressorLogger);
|
|
423
441
|
}
|
|
424
|
-
else if (serializedIdCompressor
|
|
425
|
-
return
|
|
442
|
+
else if (serializedIdCompressor === undefined) {
|
|
443
|
+
return createIdCompressor(compressorLogger);
|
|
426
444
|
}
|
|
427
445
|
else {
|
|
428
|
-
return
|
|
446
|
+
return deserializeIdCompressor(serializedIdCompressor, createSessionId(), compressorLogger);
|
|
429
447
|
}
|
|
430
448
|
};
|
|
431
|
-
const compressionLz4 = compressionOptions.minimumBatchSizeInBytes !==
|
|
449
|
+
const compressionLz4 = compressionOptions.minimumBatchSizeInBytes !== Number.POSITIVE_INFINITY &&
|
|
432
450
|
compressionOptions.compressionAlgorithm === "lz4";
|
|
451
|
+
// eslint-disable-next-line import/no-deprecated
|
|
433
452
|
const documentSchemaController = new index_js_4.DocumentsSchemaController(existing, protocolSequenceNumber, metadata?.documentSchema, {
|
|
434
453
|
explicitSchemaControl,
|
|
435
454
|
compressionLz4,
|
|
@@ -507,9 +526,6 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
507
526
|
get sessionSchema() {
|
|
508
527
|
return this.documentsSchemaController.sessionSchema.runtime;
|
|
509
528
|
}
|
|
510
|
-
get idCompressorMode() {
|
|
511
|
-
return this.sessionSchema.idCompressorMode;
|
|
512
|
-
}
|
|
513
529
|
/**
|
|
514
530
|
* {@inheritDoc @fluidframework/runtime-definitions#IContainerRuntimeBase.idCompressor}
|
|
515
531
|
*/
|
|
@@ -518,7 +534,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
518
534
|
// If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
|
|
519
535
|
// That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
|
|
520
536
|
// to reason over such things as session ID space.
|
|
521
|
-
if (this.idCompressorMode === "on") {
|
|
537
|
+
if (this.sessionSchema.idCompressorMode === "on") {
|
|
522
538
|
(0, internal_2.assert)(this._idCompressor !== undefined, 0x8ea /* compressor should have been loaded */);
|
|
523
539
|
return this._idCompressor;
|
|
524
540
|
}
|
|
@@ -569,28 +585,6 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
569
585
|
get disposed() {
|
|
570
586
|
return this._disposed;
|
|
571
587
|
}
|
|
572
|
-
get summarizer() {
|
|
573
|
-
(0, internal_2.assert)(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
|
|
574
|
-
return this._summarizer;
|
|
575
|
-
}
|
|
576
|
-
isSummariesDisabled() {
|
|
577
|
-
return this.summaryConfiguration.state === "disabled";
|
|
578
|
-
}
|
|
579
|
-
getMaxOpsSinceLastSummary() {
|
|
580
|
-
return this.summaryConfiguration.state !== "disabled"
|
|
581
|
-
? this.summaryConfiguration.maxOpsSinceLastSummary
|
|
582
|
-
: 0;
|
|
583
|
-
}
|
|
584
|
-
getInitialSummarizerDelayMs() {
|
|
585
|
-
// back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
|
|
586
|
-
// to ISummaryConfiguration in 0.60.
|
|
587
|
-
if (this.runtimeOptions.summaryOptions.initialSummarizerDelayMs !== undefined) {
|
|
588
|
-
return this.runtimeOptions.summaryOptions.initialSummarizerDelayMs;
|
|
589
|
-
}
|
|
590
|
-
return this.summaryConfiguration.state !== "disabled"
|
|
591
|
-
? this.summaryConfiguration.initialSummarizerDelayMs
|
|
592
|
-
: 0;
|
|
593
|
-
}
|
|
594
588
|
/**
|
|
595
589
|
* If false, loading or using a Tombstoned object should merely log, not fail.
|
|
596
590
|
* @deprecated NOT SUPPORTED - hardcoded to return false since it's deprecated.
|
|
@@ -607,14 +601,27 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
607
601
|
get gcThrowOnTombstoneUsage() {
|
|
608
602
|
return false;
|
|
609
603
|
}
|
|
604
|
+
get ILayerCompatDetails() {
|
|
605
|
+
return layerCompatState_js_1.RuntimeCompatDetails;
|
|
606
|
+
}
|
|
610
607
|
/***/
|
|
611
|
-
constructor(context, registry,
|
|
608
|
+
constructor(context, registry,
|
|
609
|
+
// eslint-disable-next-line import/no-deprecated
|
|
610
|
+
metadata,
|
|
611
|
+
// eslint-disable-next-line import/no-deprecated
|
|
612
|
+
electedSummarizerData, chunks, dataStoreAliasMap, baseRuntimeOptions, containerScope,
|
|
612
613
|
// Create a custom ITelemetryBaseLogger to output telemetry events.
|
|
613
|
-
baseLogger, existing,
|
|
614
|
+
baseLogger, existing,
|
|
615
|
+
// eslint-disable-next-line import/no-deprecated
|
|
616
|
+
blobManagerSnapshot, _storage, createIdCompressor,
|
|
617
|
+
// eslint-disable-next-line import/no-deprecated
|
|
618
|
+
documentsSchemaController, featureGatesForTelemetry, provideEntryPoint, requestHandler,
|
|
619
|
+
// eslint-disable-next-line unicorn/no-object-as-default-parameter
|
|
620
|
+
summaryConfiguration = {
|
|
614
621
|
// the defaults
|
|
615
622
|
...exports.DefaultSummaryConfiguration,
|
|
616
623
|
// the runtime configuration overrides
|
|
617
|
-
...
|
|
624
|
+
...baseRuntimeOptions.summaryOptions?.summaryConfigOverrides,
|
|
618
625
|
}, recentBatchInfo) {
|
|
619
626
|
super();
|
|
620
627
|
this.registry = registry;
|
|
@@ -625,19 +632,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
625
632
|
this.createIdCompressor = createIdCompressor;
|
|
626
633
|
this.documentsSchemaController = documentsSchemaController;
|
|
627
634
|
this.requestHandler = requestHandler;
|
|
628
|
-
this.summaryConfiguration = summaryConfiguration;
|
|
629
635
|
this.imminentClosure = false;
|
|
630
636
|
// We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
|
|
631
637
|
// Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
|
|
632
638
|
this.pendingIdCompressorOps = [];
|
|
633
|
-
this.defaultMaxConsecutiveReconnects = 7;
|
|
634
639
|
this._orderSequentiallyCalls = 0;
|
|
635
640
|
this.flushTaskExists = false;
|
|
636
641
|
this.consecutiveReconnects = 0;
|
|
637
642
|
this.ensureNoDataModelChangesCalls = 0;
|
|
638
643
|
this._disposed = false;
|
|
639
644
|
this.emitDirtyDocumentEvent = true;
|
|
640
|
-
this.defaultTelemetrySignalSampleCount = 100;
|
|
641
645
|
this._signalTracking = {
|
|
642
646
|
totalSignalsSentInLatencyWindow: 0,
|
|
643
647
|
signalsLost: 0,
|
|
@@ -656,15 +660,19 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
656
660
|
this.snapshotCacheForLoadingGroupIds = new internal_2.PromiseCache({
|
|
657
661
|
expiry: { policy: "absolute", durationMs: 60000 },
|
|
658
662
|
});
|
|
663
|
+
this.readAndParseBlob = async (id) => (0, internal_4.readAndParse)(this.storage, id);
|
|
659
664
|
const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, loader, pendingLocalState, supportedFeatures, snapshotWithContents, } = context;
|
|
665
|
+
// In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
|
|
666
|
+
this.disposeFn = disposeFn ?? closeFn;
|
|
667
|
+
const maybeLoaderCompatDetails = context;
|
|
668
|
+
(0, layerCompatState_js_1.validateLoaderCompatibility)(maybeLoaderCompatDetails.ILayerCompatDetails, this.disposeFn);
|
|
660
669
|
// Backfill in defaults for the internal runtimeOptions, since they may not be present on the provided runtimeOptions object
|
|
661
|
-
|
|
670
|
+
const runtimeOptions = {
|
|
662
671
|
flushMode: defaultFlushMode,
|
|
663
|
-
...
|
|
672
|
+
...baseRuntimeOptions,
|
|
664
673
|
};
|
|
665
|
-
this.logger = (0, internal_7.createChildLogger)({ logger: this.baseLogger });
|
|
666
674
|
this.mc = (0, internal_7.createChildMonitoringContext)({
|
|
667
|
-
logger: this.
|
|
675
|
+
logger: this.baseLogger,
|
|
668
676
|
namespace: "ContainerRuntime",
|
|
669
677
|
});
|
|
670
678
|
// If we support multiple algorithms in the future, then we would need to manage it here carefully.
|
|
@@ -681,19 +689,23 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
681
689
|
this.innerDeltaManager = deltaManager;
|
|
682
690
|
// Here we could wrap/intercept on these functions to block/modify outgoing messages if needed.
|
|
683
691
|
// This makes ContainerRuntime the final gatekeeper for outgoing messages.
|
|
684
|
-
this
|
|
685
|
-
this.
|
|
686
|
-
|
|
692
|
+
// back-compat: ADO #1385: Make this call unconditional in the future
|
|
693
|
+
this.submitSummaryFn =
|
|
694
|
+
submitSummaryFn ??
|
|
695
|
+
((summaryOp, refseq) => submitFn(internal_3.MessageType.Summarize, summaryOp, false));
|
|
687
696
|
this.submitSignalFn = submitSignalFn;
|
|
688
697
|
// TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
|
|
689
698
|
// Values are generally expected to be set from the runtime side.
|
|
690
699
|
this.options = options ?? {};
|
|
691
700
|
this.clientDetails = clientDetails;
|
|
692
|
-
|
|
701
|
+
const isSummarizerClient = this.clientDetails.type === index_js_4.summarizerClientType;
|
|
693
702
|
this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
|
|
703
|
+
// eslint-disable-next-line unicorn/consistent-destructuring
|
|
694
704
|
this._getClientId = () => context.clientId;
|
|
705
|
+
// eslint-disable-next-line unicorn/consistent-destructuring
|
|
695
706
|
this._getAttachState = () => context.attachState;
|
|
696
707
|
this.getAbsoluteUrl = async (relativeUrl) => {
|
|
708
|
+
// eslint-disable-next-line unicorn/consistent-destructuring
|
|
697
709
|
if (context.getAbsoluteUrl === undefined) {
|
|
698
710
|
throw new Error("Driver does not implement getAbsoluteUrl");
|
|
699
711
|
}
|
|
@@ -706,10 +718,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
706
718
|
// customer should observe dirty state on the runtime (the owner of dirty state) directly, rather than on the IContainer.
|
|
707
719
|
this.on("dirty", () => context.updateDirtyContainerState(true));
|
|
708
720
|
this.on("saved", () => context.updateDirtyContainerState(false));
|
|
709
|
-
// In old loaders without dispose functionality, closeFn is equivalent but will also switch container to readonly mode
|
|
710
|
-
this.disposeFn = disposeFn ?? closeFn;
|
|
711
721
|
// In cases of summarizer, we want to dispose instead since consumer doesn't interact with this container
|
|
712
|
-
this.closeFn =
|
|
722
|
+
this.closeFn = isSummarizerClient ? this.disposeFn : closeFn;
|
|
713
723
|
let loadSummaryNumber;
|
|
714
724
|
// Get the container creation metadata. For new container, we initialize these. For existing containers,
|
|
715
725
|
// get the values from the metadata blob.
|
|
@@ -739,16 +749,14 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
739
749
|
metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
|
|
740
750
|
inputs: JSON.stringify({
|
|
741
751
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
742
|
-
gcOptions_gcGeneration:
|
|
752
|
+
gcOptions_gcGeneration: runtimeOptions.gcOptions[index_js_2.gcGenerationOptionName],
|
|
743
753
|
}),
|
|
744
754
|
});
|
|
745
755
|
this.telemetryDocumentId = metadata?.telemetryDocumentId ?? (0, uuid_1.v4)();
|
|
746
|
-
this.disableAttachReorder = this.mc.config.getBoolean("Fluid.ContainerRuntime.disableAttachOpReorder");
|
|
747
756
|
const opGroupingManager = new index_js_3.OpGroupingManager({
|
|
748
757
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
749
|
-
opCountThreshold: this.mc.config.getNumber("Fluid.ContainerRuntime.GroupedBatchingOpCount") ?? 2,
|
|
750
758
|
}, this.mc.logger);
|
|
751
|
-
const opSplitter = new index_js_3.OpSplitter(chunks,
|
|
759
|
+
const opSplitter = new index_js_3.OpSplitter(chunks, submitBatchFn, runtimeOptions.chunkSizeInBytes, runtimeOptions.maxBatchSizeInBytes, this.mc.logger);
|
|
752
760
|
this.remoteMessageProcessor = new index_js_3.RemoteMessageProcessor(opSplitter, new index_js_3.OpDecompressor(this.mc.logger), opGroupingManager);
|
|
753
761
|
const pendingRuntimeState = pendingLocalState;
|
|
754
762
|
this.pendingStateManager = new pendingStateManager_js_1.PendingStateManager({
|
|
@@ -758,7 +766,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
758
766
|
reSubmitBatch: this.reSubmitBatch.bind(this),
|
|
759
767
|
isActiveConnection: () => this.innerDeltaManager.active,
|
|
760
768
|
isAttached: () => this.attachState !== container_definitions_1.AttachState.Detached,
|
|
761
|
-
}, pendingRuntimeState?.pending, this.
|
|
769
|
+
}, pendingRuntimeState?.pending, this.baseLogger);
|
|
762
770
|
let outerDeltaManager;
|
|
763
771
|
this.useDeltaManagerOpsProxy =
|
|
764
772
|
this.mc.config.getBoolean("Fluid.ContainerRuntime.DeltaManagerOpsProxy") === true;
|
|
@@ -773,24 +781,35 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
773
781
|
}
|
|
774
782
|
this._deltaManager = outerDeltaManager;
|
|
775
783
|
this.handleContext = new containerHandleContext_js_1.ContainerFluidHandleContext("", this);
|
|
776
|
-
if (
|
|
777
|
-
this.validateSummaryHeuristicConfiguration(
|
|
778
|
-
}
|
|
779
|
-
this.summariesDisabled =
|
|
780
|
-
|
|
781
|
-
|
|
784
|
+
if (summaryConfiguration.state === "enabled") {
|
|
785
|
+
this.validateSummaryHeuristicConfiguration(summaryConfiguration);
|
|
786
|
+
}
|
|
787
|
+
this.summariesDisabled = isSummariesDisabled(summaryConfiguration);
|
|
788
|
+
const { maxOpsSinceLastSummary = 0, initialSummarizerDelayMs = 0 } = isSummariesDisabled(summaryConfiguration)
|
|
789
|
+
? {}
|
|
790
|
+
: {
|
|
791
|
+
...summaryConfiguration,
|
|
792
|
+
initialSummarizerDelayMs:
|
|
793
|
+
// back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
|
|
794
|
+
// to ISummaryConfiguration in 0.60.
|
|
795
|
+
runtimeOptions.summaryOptions.initialSummarizerDelayMs ??
|
|
796
|
+
summaryConfiguration.initialSummarizerDelayMs,
|
|
797
|
+
};
|
|
782
798
|
this.maxConsecutiveReconnects =
|
|
783
|
-
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
supportedFeatures?.get("referenceSequenceNumbers")
|
|
799
|
+
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ?? defaultMaxConsecutiveReconnects;
|
|
800
|
+
// If the context has ILayerCompatDetails, it supports referenceSequenceNumbers since that features
|
|
801
|
+
// predates ILayerCompatDetails.
|
|
802
|
+
const referenceSequenceNumbersSupported = maybeLoaderCompatDetails.ILayerCompatDetails === undefined
|
|
803
|
+
? supportedFeatures?.get("referenceSequenceNumbers") === true
|
|
804
|
+
: true;
|
|
805
|
+
if (runtimeOptions.flushMode === internal_5.FlushModeExperimental.Async &&
|
|
806
|
+
!referenceSequenceNumbersSupported) {
|
|
788
807
|
// The loader does not support reference sequence numbers, falling back on FlushMode.TurnBased
|
|
789
808
|
this.mc.logger.sendErrorEvent({ eventName: "FlushModeFallback" });
|
|
790
809
|
this._flushMode = internal_5.FlushMode.TurnBased;
|
|
791
810
|
}
|
|
792
811
|
else {
|
|
793
|
-
this._flushMode =
|
|
812
|
+
this._flushMode = runtimeOptions.flushMode;
|
|
794
813
|
}
|
|
795
814
|
this.offlineEnabled =
|
|
796
815
|
this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ?? false;
|
|
@@ -805,6 +824,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
805
824
|
if (this.offlineEnabled) {
|
|
806
825
|
this.duplicateBatchDetector = new index_js_3.DuplicateBatchDetector(recentBatchInfo);
|
|
807
826
|
}
|
|
827
|
+
// eslint-disable-next-line unicorn/consistent-destructuring
|
|
808
828
|
if (context.attachState === container_definitions_1.AttachState.Attached) {
|
|
809
829
|
const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
|
|
810
830
|
if (maxSnapshotCacheDurationMs !== undefined &&
|
|
@@ -817,13 +837,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
817
837
|
}
|
|
818
838
|
this.garbageCollector = index_js_2.GarbageCollector.create({
|
|
819
839
|
runtime: this,
|
|
820
|
-
gcOptions:
|
|
840
|
+
gcOptions: runtimeOptions.gcOptions,
|
|
821
841
|
baseSnapshot,
|
|
822
842
|
baseLogger: this.mc.logger,
|
|
823
843
|
existing,
|
|
824
844
|
metadata,
|
|
825
845
|
createContainerMetadata: this.createContainerMetadata,
|
|
826
|
-
isSummarizerClient
|
|
846
|
+
isSummarizerClient,
|
|
827
847
|
getNodePackagePath: async (nodePath) => this.getGCNodePackagePath(nodePath),
|
|
828
848
|
getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
|
|
829
849
|
readAndParseBlob: async (id) => (0, internal_4.readAndParse)(this.storage, id),
|
|
@@ -837,7 +857,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
837
857
|
const summaryReferenceSequenceNumber = baseSnapshot === undefined || metadata?.disableIsolatedChannels === true
|
|
838
858
|
? undefined
|
|
839
859
|
: loadedFromSequenceNumber;
|
|
840
|
-
this.summarizerNode = (0, index_js_4.createRootSummarizerNodeWithGC)((0, internal_7.createChildLogger)({ logger: this.
|
|
860
|
+
this.summarizerNode = (0, index_js_4.createRootSummarizerNodeWithGC)((0, internal_7.createChildLogger)({ logger: this.baseLogger, namespace: "SummarizerNode" }),
|
|
841
861
|
// Summarize function to call when summarize is called. Summarizer node always tracks summary state.
|
|
842
862
|
async (fullTree, trackState, telemetryContext) => this.summarizeInternal(fullTree, trackState, telemetryContext),
|
|
843
863
|
// Latest change sequence number, no changes since summary applied yet
|
|
@@ -895,16 +915,15 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
895
915
|
isBlobDeleted: (blobPath) => this.garbageCollector.isNodeDeleted(blobPath),
|
|
896
916
|
runtime: this,
|
|
897
917
|
stashedBlobs: pendingRuntimeState?.pendingAttachmentBlobs,
|
|
898
|
-
closeContainer: (error) => this.closeFn(error),
|
|
899
918
|
});
|
|
900
|
-
this.deltaScheduler = new deltaScheduler_js_1.DeltaScheduler(this.innerDeltaManager, this, (0, internal_7.createChildLogger)({ logger: this.
|
|
901
|
-
this.inboundBatchAggregator = new inboundBatchAggregator_js_1.InboundBatchAggregator(this.innerDeltaManager, () => this.clientId, (0, internal_7.createChildLogger)({ logger: this.
|
|
919
|
+
this.deltaScheduler = new deltaScheduler_js_1.DeltaScheduler(this.innerDeltaManager, this, (0, internal_7.createChildLogger)({ logger: this.baseLogger, namespace: "DeltaScheduler" }));
|
|
920
|
+
this.inboundBatchAggregator = new inboundBatchAggregator_js_1.InboundBatchAggregator(this.innerDeltaManager, () => this.clientId, (0, internal_7.createChildLogger)({ logger: this.baseLogger, namespace: "InboundBatchAggregator" }));
|
|
902
921
|
const disablePartialFlush = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisablePartialFlush");
|
|
903
|
-
const legacySendBatchFn = (0, exports.makeLegacySendBatchFn)(
|
|
922
|
+
const legacySendBatchFn = (0, exports.makeLegacySendBatchFn)(submitFn, this.innerDeltaManager);
|
|
904
923
|
this.outbox = new index_js_3.Outbox({
|
|
905
924
|
shouldSend: () => this.canSendOps(),
|
|
906
925
|
pendingStateManager: this.pendingStateManager,
|
|
907
|
-
submitBatchFn
|
|
926
|
+
submitBatchFn,
|
|
908
927
|
legacySendBatchFn,
|
|
909
928
|
compressor: new index_js_3.OpCompressor(this.mc.logger),
|
|
910
929
|
splitter: opSplitter,
|
|
@@ -951,7 +970,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
951
970
|
const closeSummarizerDelayOverride = this.mc.config.getNumber("Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs");
|
|
952
971
|
this.closeSummarizerDelayMs =
|
|
953
972
|
closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
|
|
954
|
-
|
|
973
|
+
const summaryCollection = new index_js_4.SummaryCollection(this.deltaManager, this.baseLogger);
|
|
955
974
|
this.dirtyContainer =
|
|
956
975
|
this.attachState !== container_definitions_1.AttachState.Attached || this.hasPendingMessages();
|
|
957
976
|
context.updateDirtyContainerState(this.dirtyContainer);
|
|
@@ -960,14 +979,17 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
960
979
|
}
|
|
961
980
|
else {
|
|
962
981
|
const orderedClientLogger = (0, internal_7.createChildLogger)({
|
|
963
|
-
logger: this.
|
|
982
|
+
logger: this.baseLogger,
|
|
964
983
|
namespace: "OrderedClientElection",
|
|
965
984
|
});
|
|
966
985
|
const orderedClientCollection = new index_js_4.OrderedClientCollection(orderedClientLogger, this.innerDeltaManager, this._quorum);
|
|
967
986
|
const orderedClientElectionForSummarizer = new index_js_4.OrderedClientElection(orderedClientLogger, orderedClientCollection, electedSummarizerData ?? this.innerDeltaManager.lastSequenceNumber, index_js_4.SummarizerClientElection.isClientEligible, this.mc.config.getBoolean("Fluid.ContainerRuntime.OrderedClientElection.EnablePerformanceEvents"));
|
|
968
|
-
this.summarizerClientElection = new index_js_4.SummarizerClientElection(orderedClientLogger,
|
|
969
|
-
if (
|
|
970
|
-
|
|
987
|
+
this.summarizerClientElection = new index_js_4.SummarizerClientElection(orderedClientLogger, summaryCollection, orderedClientElectionForSummarizer, maxOpsSinceLastSummary);
|
|
988
|
+
if (isSummarizerClient) {
|
|
989
|
+
// eslint-disable-next-line import/no-deprecated
|
|
990
|
+
this._summarizer = new index_js_4.Summarizer(this /* ISummarizerRuntime */, () => summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, summaryCollection,
|
|
991
|
+
// eslint-disable-next-line import/no-deprecated
|
|
992
|
+
async (runtime) => index_js_4.RunWhileConnectedCoordinator.create(runtime,
|
|
971
993
|
// Summarization runs in summarizer client and needs access to the real (non-proxy) active
|
|
972
994
|
// information. The proxy delta manager would always return false for summarizer client.
|
|
973
995
|
() => this.innerDeltaManager.active));
|
|
@@ -976,48 +998,49 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
976
998
|
// Only create a SummaryManager and SummarizerClientElection
|
|
977
999
|
// if summaries are enabled and we are not the summarizer client.
|
|
978
1000
|
const defaultAction = () => {
|
|
979
|
-
if (
|
|
1001
|
+
if (summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
|
|
980
1002
|
this.mc.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
|
|
981
1003
|
// unregister default to no log on every op after falling behind
|
|
982
1004
|
// and register summary ack handler to re-register this handler
|
|
983
1005
|
// after successful summary
|
|
984
|
-
|
|
1006
|
+
summaryCollection.once(internal_3.MessageType.SummaryAck, () => {
|
|
985
1007
|
this.mc.logger.sendTelemetryEvent({
|
|
986
1008
|
eventName: "SummaryStatus:CaughtUp",
|
|
987
1009
|
});
|
|
988
1010
|
// we've caught up, so re-register the default action to monitor for
|
|
989
1011
|
// falling behind, and unregister ourself
|
|
990
|
-
|
|
1012
|
+
summaryCollection.on("default", defaultAction);
|
|
991
1013
|
});
|
|
992
|
-
|
|
1014
|
+
summaryCollection.off("default", defaultAction);
|
|
993
1015
|
}
|
|
994
1016
|
};
|
|
995
|
-
|
|
1017
|
+
summaryCollection.on("default", defaultAction);
|
|
996
1018
|
// Create the SummaryManager and mark the initial state
|
|
997
1019
|
this.summaryManager = new index_js_4.SummaryManager(this.summarizerClientElection, this, // IConnectedState
|
|
998
|
-
|
|
1020
|
+
summaryCollection, this.baseLogger, this.formCreateSummarizerFn(loader), new throttler_js_1.Throttler(60 * 1000, // 60 sec delay window
|
|
999
1021
|
30 * 1000, // 30 sec max delay
|
|
1000
1022
|
// throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
|
|
1001
1023
|
(0, throttler_js_1.formExponentialFn)({ coefficient: 20, initialDelay: 0 })), {
|
|
1002
|
-
initialDelayMs:
|
|
1024
|
+
initialDelayMs: initialSummarizerDelayMs,
|
|
1003
1025
|
});
|
|
1004
1026
|
// Forward events from SummaryManager
|
|
1005
|
-
[
|
|
1027
|
+
for (const eventName of [
|
|
1006
1028
|
"summarize",
|
|
1007
1029
|
"summarizeAllAttemptsFailed",
|
|
1008
1030
|
"summarizerStop",
|
|
1009
1031
|
"summarizerStart",
|
|
1010
1032
|
"summarizerStartupFailed",
|
|
1011
|
-
]
|
|
1033
|
+
]) {
|
|
1012
1034
|
this.summaryManager?.on(eventName, (...args) => {
|
|
1013
1035
|
this.emit(eventName, ...args);
|
|
1014
1036
|
});
|
|
1015
|
-
}
|
|
1037
|
+
}
|
|
1016
1038
|
this.summaryManager.start();
|
|
1017
1039
|
}
|
|
1018
1040
|
}
|
|
1019
1041
|
// logging hardware telemetry
|
|
1020
|
-
this.
|
|
1042
|
+
this.baseLogger.send({
|
|
1043
|
+
category: "generic",
|
|
1021
1044
|
eventName: "DeviceSpec",
|
|
1022
1045
|
...getDeviceSpec(),
|
|
1023
1046
|
});
|
|
@@ -1029,13 +1052,12 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1029
1052
|
summaryFormatVersion: metadata?.summaryFormatVersion,
|
|
1030
1053
|
disableIsolatedChannels: metadata?.disableIsolatedChannels,
|
|
1031
1054
|
gcVersion: metadata?.gcFeature,
|
|
1032
|
-
options: JSON.stringify(
|
|
1055
|
+
options: JSON.stringify(baseRuntimeOptions),
|
|
1033
1056
|
idCompressorModeMetadata: metadata?.documentSchema?.runtime?.idCompressorMode,
|
|
1034
|
-
idCompressorMode: this.idCompressorMode,
|
|
1057
|
+
idCompressorMode: this.sessionSchema.idCompressorMode,
|
|
1035
1058
|
sessionRuntimeSchema: JSON.stringify(this.sessionSchema),
|
|
1036
1059
|
featureGates: JSON.stringify({
|
|
1037
1060
|
...featureGatesForTelemetry,
|
|
1038
|
-
disableAttachReorder: this.disableAttachReorder,
|
|
1039
1061
|
disablePartialFlush,
|
|
1040
1062
|
closeSummarizerDelayOverride,
|
|
1041
1063
|
}),
|
|
@@ -1043,11 +1065,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1043
1065
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
1044
1066
|
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
1045
1067
|
});
|
|
1046
|
-
(0, connectionTelemetry_js_1.ReportOpPerfTelemetry)(this.clientId, this._deltaManager, this, this.
|
|
1047
|
-
(0, batchTracker_js_1.BindBatchTracker)(this, this.
|
|
1068
|
+
(0, connectionTelemetry_js_1.ReportOpPerfTelemetry)(this.clientId, this._deltaManager, this, this.baseLogger);
|
|
1069
|
+
(0, batchTracker_js_1.BindBatchTracker)(this, this.baseLogger);
|
|
1048
1070
|
this.entryPoint = new internal_2.LazyPromise(async () => {
|
|
1049
|
-
if (this.
|
|
1050
|
-
(0, internal_2.assert)(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
|
|
1071
|
+
if (this._summarizer !== undefined) {
|
|
1051
1072
|
return this._summarizer;
|
|
1052
1073
|
}
|
|
1053
1074
|
return provideEntryPoint(this);
|
|
@@ -1056,8 +1077,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1056
1077
|
// saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
|
|
1057
1078
|
this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
|
|
1058
1079
|
}
|
|
1080
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1059
1081
|
onSchemaChange(schema) {
|
|
1060
|
-
this.logger.sendTelemetryEvent({
|
|
1082
|
+
this.mc.logger.sendTelemetryEvent({
|
|
1061
1083
|
eventName: "SchemaChangeAccept",
|
|
1062
1084
|
sessionRuntimeSchema: JSON.stringify(schema),
|
|
1063
1085
|
});
|
|
@@ -1092,8 +1114,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1092
1114
|
* Initializes the state from the base snapshot this container runtime loaded from.
|
|
1093
1115
|
*/
|
|
1094
1116
|
async initializeBaseState() {
|
|
1095
|
-
if (this.idCompressorMode === "on" ||
|
|
1096
|
-
(this.idCompressorMode === "delayed" && this.connected)) {
|
|
1117
|
+
if (this.sessionSchema.idCompressorMode === "on" ||
|
|
1118
|
+
(this.sessionSchema.idCompressorMode === "delayed" && this.connected)) {
|
|
1097
1119
|
this._idCompressor = await this.createIdCompressor();
|
|
1098
1120
|
// This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
|
|
1099
1121
|
(0, internal_2.assert)(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
|
|
@@ -1136,7 +1158,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1136
1158
|
// Lookup up in the cache, if not present then make the network call as multiple datastores could
|
|
1137
1159
|
// be in same loading group. So, once we have fetched the snapshot for that loading group on
|
|
1138
1160
|
// any request, then cache that as same group could be requested in future too.
|
|
1139
|
-
const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(), async () => {
|
|
1161
|
+
const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(","), async () => {
|
|
1140
1162
|
(0, internal_2.assert)(this.storage.getSnapshot !== undefined, 0x8ee /* getSnapshot api should be defined if used */);
|
|
1141
1163
|
loadedFromCache = false;
|
|
1142
1164
|
return this.storage.getSnapshot({
|
|
@@ -1145,7 +1167,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1145
1167
|
loadingGroupIds: sortedLoadingGroupIds,
|
|
1146
1168
|
});
|
|
1147
1169
|
});
|
|
1148
|
-
this.logger.sendTelemetryEvent({
|
|
1170
|
+
this.mc.logger.sendTelemetryEvent({
|
|
1149
1171
|
eventName: "GroupIdSnapshotFetched",
|
|
1150
1172
|
details: JSON.stringify({
|
|
1151
1173
|
fromCache: loadedFromCache,
|
|
@@ -1175,7 +1197,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1175
1197
|
// another snapshot from which the summarizer loaded and it is behind, then just give up as
|
|
1176
1198
|
// the summarizer state is not up to date.
|
|
1177
1199
|
// This should be a recoverable scenario and shouldn't happen as we should process the ack first.
|
|
1178
|
-
if (this.
|
|
1200
|
+
if (this._summarizer !== undefined) {
|
|
1179
1201
|
throw new Error("Summarizer client behind, loaded newer snapshot with loadingGroupId");
|
|
1180
1202
|
}
|
|
1181
1203
|
// We want to catchup from sequenceNumber to targetSequenceNumber
|
|
@@ -1237,7 +1259,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1237
1259
|
return {
|
|
1238
1260
|
status: 200,
|
|
1239
1261
|
mimeType: "fluid/object",
|
|
1240
|
-
value: this.
|
|
1262
|
+
value: this._summarizer,
|
|
1241
1263
|
};
|
|
1242
1264
|
}
|
|
1243
1265
|
return (0, internal_6.create404Response)(request);
|
|
@@ -1303,6 +1325,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1303
1325
|
const documentSchema = this.documentsSchemaController.summarizeDocumentSchema(this.deltaManager.lastSequenceNumber);
|
|
1304
1326
|
// Is document schema explicit control on?
|
|
1305
1327
|
const explicitSchemaControl = documentSchema?.runtime.explicitSchemaControl;
|
|
1328
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1306
1329
|
const metadata = {
|
|
1307
1330
|
...this.createContainerMetadata,
|
|
1308
1331
|
// Increment the summary number for the next summary that will be generated.
|
|
@@ -1316,7 +1339,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1316
1339
|
// last message's sequence number.
|
|
1317
1340
|
// See also lastMessageFromMetadata()
|
|
1318
1341
|
message: explicitSchemaControl
|
|
1319
|
-
?
|
|
1342
|
+
? // eslint-disable-next-line import/no-deprecated
|
|
1343
|
+
{ sequenceNumber: -1 }
|
|
1320
1344
|
: message,
|
|
1321
1345
|
lastMessage: explicitSchemaControl ? message : undefined,
|
|
1322
1346
|
documentSchema,
|
|
@@ -1432,9 +1456,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1432
1456
|
switch (opContents.type) {
|
|
1433
1457
|
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
1434
1458
|
case messageTypes_js_1.ContainerMessageType.Attach:
|
|
1435
|
-
case messageTypes_js_1.ContainerMessageType.Alias:
|
|
1459
|
+
case messageTypes_js_1.ContainerMessageType.Alias: {
|
|
1436
1460
|
return this.channelCollection.applyStashedOp(opContents);
|
|
1437
|
-
|
|
1461
|
+
}
|
|
1462
|
+
case messageTypes_js_1.ContainerMessageType.IdAllocation: {
|
|
1438
1463
|
// IDs allocation ops in stashed state are ignored because the tip state of the compressor
|
|
1439
1464
|
// is serialized into the pending state. This is done because generation of new IDs during
|
|
1440
1465
|
// stashed op application (or, later, resubmit) must generate new IDs and if the compressor
|
|
@@ -1444,17 +1469,22 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1444
1469
|
// and the runtime could filter out all ID allocation ops from the stashed state and apply them
|
|
1445
1470
|
// before applying the rest of the stashed ops. This would accomplish the same thing but with
|
|
1446
1471
|
// better performance in future incremental stashed state creation.
|
|
1447
|
-
(0, internal_2.assert)(this.idCompressorMode !== undefined, 0x8f1 /* ID compressor should be in use */);
|
|
1472
|
+
(0, internal_2.assert)(this.sessionSchema.idCompressorMode !== undefined, 0x8f1 /* ID compressor should be in use */);
|
|
1448
1473
|
return;
|
|
1449
|
-
|
|
1474
|
+
}
|
|
1475
|
+
case messageTypes_js_1.ContainerMessageType.DocumentSchemaChange: {
|
|
1450
1476
|
return;
|
|
1451
|
-
|
|
1477
|
+
}
|
|
1478
|
+
case messageTypes_js_1.ContainerMessageType.BlobAttach: {
|
|
1452
1479
|
return;
|
|
1453
|
-
|
|
1480
|
+
}
|
|
1481
|
+
case messageTypes_js_1.ContainerMessageType.Rejoin: {
|
|
1454
1482
|
throw new Error("rejoin not expected here");
|
|
1455
|
-
|
|
1483
|
+
}
|
|
1484
|
+
case messageTypes_js_1.ContainerMessageType.GC: {
|
|
1456
1485
|
// GC op is only sent in summarizer which should never have stashed ops.
|
|
1457
1486
|
throw new internal_7.LoggingError("GC op not expected to be stashed in summarizer");
|
|
1487
|
+
}
|
|
1458
1488
|
default: {
|
|
1459
1489
|
const error = getUnknownMessageTypeError(opContents.type, "applyStashedOp" /* codePath */);
|
|
1460
1490
|
this.closeFn(error);
|
|
@@ -1464,7 +1494,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1464
1494
|
}
|
|
1465
1495
|
async loadIdCompressor() {
|
|
1466
1496
|
if (this._idCompressor === undefined &&
|
|
1467
|
-
this.idCompressorMode !== undefined &&
|
|
1497
|
+
this.sessionSchema.idCompressorMode !== undefined &&
|
|
1468
1498
|
this._loadIdCompressor === undefined) {
|
|
1469
1499
|
this._loadIdCompressor = this.createIdCompressor()
|
|
1470
1500
|
.then((compressor) => {
|
|
@@ -1478,7 +1508,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1478
1508
|
this._idCompressor = compressor;
|
|
1479
1509
|
})
|
|
1480
1510
|
.catch((error) => {
|
|
1481
|
-
this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
1511
|
+
this.mc.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
1482
1512
|
throw error;
|
|
1483
1513
|
});
|
|
1484
1514
|
}
|
|
@@ -1489,7 +1519,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1489
1519
|
const currentClientId = this._audience.getSelf()?.clientId;
|
|
1490
1520
|
(0, internal_2.assert)(clientId === currentClientId, 0x977 /* input clientId does not match Audience */);
|
|
1491
1521
|
(0, internal_2.assert)(this.clientId === currentClientId, 0x978 /* this.clientId does not match Audience */);
|
|
1492
|
-
if (connected && this.idCompressorMode === "delayed") {
|
|
1522
|
+
if (connected && this.sessionSchema.idCompressorMode === "delayed") {
|
|
1493
1523
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1494
1524
|
this.loadIdCompressor();
|
|
1495
1525
|
}
|
|
@@ -1578,7 +1608,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1578
1608
|
// or something different, like a system message.
|
|
1579
1609
|
const hasModernRuntimeMessageEnvelope = messageCopy.type === internal_3.MessageType.Operation;
|
|
1580
1610
|
const savedOp = messageCopy.metadata?.savedOp;
|
|
1581
|
-
const logLegacyCase = (0, exports.getSingleUseLegacyLogCallback)(this.logger, messageCopy.type);
|
|
1611
|
+
const logLegacyCase = (0, exports.getSingleUseLegacyLogCallback)(this.mc.logger, messageCopy.type);
|
|
1582
1612
|
let runtimeBatch = hasModernRuntimeMessageEnvelope || isUnpackedRuntimeMessage(messageCopy);
|
|
1583
1613
|
if (runtimeBatch) {
|
|
1584
1614
|
// We expect runtime messages to have JSON contents - deserialize it in place.
|
|
@@ -1680,11 +1710,11 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1680
1710
|
let error;
|
|
1681
1711
|
try {
|
|
1682
1712
|
if (!runtimeBatch) {
|
|
1683
|
-
|
|
1713
|
+
for (const { message } of messagesWithMetadata) {
|
|
1684
1714
|
this.ensureNoDataModelChanges(() => {
|
|
1685
1715
|
this.observeNonRuntimeMessage(message);
|
|
1686
1716
|
});
|
|
1687
|
-
}
|
|
1717
|
+
}
|
|
1688
1718
|
return;
|
|
1689
1719
|
}
|
|
1690
1720
|
// Updates a message's minimum sequence number to the minimum sequence number that container
|
|
@@ -1752,8 +1782,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1752
1782
|
this.emit("op", message, true /* runtimeMessage */);
|
|
1753
1783
|
}
|
|
1754
1784
|
}
|
|
1755
|
-
catch (
|
|
1756
|
-
error =
|
|
1785
|
+
catch (error_) {
|
|
1786
|
+
error = error_;
|
|
1757
1787
|
throw error;
|
|
1758
1788
|
}
|
|
1759
1789
|
finally {
|
|
@@ -1810,30 +1840,39 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1810
1840
|
switch (message.type) {
|
|
1811
1841
|
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
1812
1842
|
case messageTypes_js_1.ContainerMessageType.Attach:
|
|
1813
|
-
case messageTypes_js_1.ContainerMessageType.Alias:
|
|
1843
|
+
case messageTypes_js_1.ContainerMessageType.Alias: {
|
|
1814
1844
|
// Remove the metadata from the message before sending it to the channel collection. The metadata
|
|
1815
1845
|
// is added by the container runtime and is not part of the message that the channel collection and
|
|
1816
1846
|
// layers below it expect.
|
|
1817
1847
|
this.channelCollection.processMessages({ envelope: message, messagesContent, local });
|
|
1818
1848
|
break;
|
|
1819
|
-
|
|
1849
|
+
}
|
|
1850
|
+
case messageTypes_js_1.ContainerMessageType.BlobAttach: {
|
|
1820
1851
|
this.blobManager.processBlobAttachMessage(message, local);
|
|
1821
1852
|
break;
|
|
1822
|
-
|
|
1853
|
+
}
|
|
1854
|
+
case messageTypes_js_1.ContainerMessageType.IdAllocation: {
|
|
1823
1855
|
this.processIdCompressorMessages(contents, savedOp);
|
|
1824
1856
|
break;
|
|
1825
|
-
|
|
1857
|
+
}
|
|
1858
|
+
case messageTypes_js_1.ContainerMessageType.GC: {
|
|
1826
1859
|
this.garbageCollector.processMessages(contents, message.timestamp, local);
|
|
1827
1860
|
break;
|
|
1828
|
-
|
|
1861
|
+
}
|
|
1862
|
+
case messageTypes_js_1.ContainerMessageType.ChunkedOp: {
|
|
1829
1863
|
// From observability POV, we should not expose the rest of the system (including "op" events on object) to these messages.
|
|
1830
1864
|
// Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
|
|
1831
1865
|
(0, internal_2.assert)(false, 0x93d /* should not even get here */);
|
|
1832
|
-
|
|
1866
|
+
}
|
|
1867
|
+
case messageTypes_js_1.ContainerMessageType.Rejoin: {
|
|
1833
1868
|
break;
|
|
1834
|
-
|
|
1835
|
-
|
|
1869
|
+
}
|
|
1870
|
+
case messageTypes_js_1.ContainerMessageType.DocumentSchemaChange: {
|
|
1871
|
+
this.documentsSchemaController.processDocumentSchemaMessages(
|
|
1872
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1873
|
+
contents, local, message.sequenceNumber);
|
|
1836
1874
|
break;
|
|
1875
|
+
}
|
|
1837
1876
|
default: {
|
|
1838
1877
|
const error = getUnknownMessageTypeError(message.type, "validateAndProcessRuntimeMessage" /* codePath */, message);
|
|
1839
1878
|
this.closeFn(error);
|
|
@@ -1851,7 +1890,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1851
1890
|
// Some other client turned on the id compressor. If we have not turned it on,
|
|
1852
1891
|
// put it in a pending queue and delay finalization.
|
|
1853
1892
|
if (this._idCompressor === undefined) {
|
|
1854
|
-
(0, internal_2.assert)(this.idCompressorMode !== undefined, 0x93c /* id compressor should be enabled */);
|
|
1893
|
+
(0, internal_2.assert)(this.sessionSchema.idCompressorMode !== undefined, 0x93c /* id compressor should be enabled */);
|
|
1855
1894
|
this.pendingIdCompressorOps.push(range);
|
|
1856
1895
|
}
|
|
1857
1896
|
else {
|
|
@@ -1885,7 +1924,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1885
1924
|
* Updates signal telemetry including emitting telemetry events.
|
|
1886
1925
|
*/
|
|
1887
1926
|
processSignalForTelemetry(envelope) {
|
|
1888
|
-
const { clientBroadcastSignalSequenceNumber } = envelope;
|
|
1927
|
+
const { clientBroadcastSignalSequenceNumber, contents: envelopeContents, address: envelopeAddress, } = envelope;
|
|
1889
1928
|
if (clientBroadcastSignalSequenceNumber === undefined) {
|
|
1890
1929
|
return;
|
|
1891
1930
|
}
|
|
@@ -1923,8 +1962,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1923
1962
|
};
|
|
1924
1963
|
// Only log `contents.type` when address is for container to avoid
|
|
1925
1964
|
// chance that contents type is customer data.
|
|
1926
|
-
if (
|
|
1927
|
-
details.contentsType =
|
|
1965
|
+
if (envelopeAddress === undefined) {
|
|
1966
|
+
details.contentsType = envelopeContents.type; // Type of signal that was received out of order.
|
|
1928
1967
|
}
|
|
1929
1968
|
this.mc.logger.sendTelemetryEvent({
|
|
1930
1969
|
eventName: "SignalOutOfOrder",
|
|
@@ -2005,8 +2044,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2005
2044
|
try {
|
|
2006
2045
|
checkpoint.rollback((message) => this.rollback(message.contents, message.localOpMetadata));
|
|
2007
2046
|
}
|
|
2008
|
-
catch (
|
|
2009
|
-
const error2 = (0, internal_7.wrapError)(
|
|
2047
|
+
catch (error_) {
|
|
2048
|
+
const error2 = (0, internal_7.wrapError)(error_, (message) => {
|
|
2010
2049
|
return internal_7.DataProcessingError.create(`RollbackError: ${message}`, "checkpointRollback", undefined);
|
|
2011
2050
|
});
|
|
2012
2051
|
this.closeFn(error2);
|
|
@@ -2117,8 +2156,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2117
2156
|
case messageTypes_js_1.ContainerMessageType.GC: {
|
|
2118
2157
|
return false;
|
|
2119
2158
|
}
|
|
2120
|
-
default:
|
|
2159
|
+
default: {
|
|
2121
2160
|
break;
|
|
2161
|
+
}
|
|
2122
2162
|
}
|
|
2123
2163
|
return true;
|
|
2124
2164
|
}
|
|
@@ -2147,7 +2187,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2147
2187
|
clientBroadcastSignalSequenceNumber;
|
|
2148
2188
|
}
|
|
2149
2189
|
// We should not track the round trip of a new signal in the case we are already tracking one.
|
|
2150
|
-
if (clientBroadcastSignalSequenceNumber %
|
|
2190
|
+
if (clientBroadcastSignalSequenceNumber % defaultTelemetrySignalSampleCount === 1 &&
|
|
2151
2191
|
this._signalTracking.roundTripSignalSequenceNumber === undefined) {
|
|
2152
2192
|
this._signalTracking.signalTimestamp = Date.now();
|
|
2153
2193
|
this._signalTracking.roundTripSignalSequenceNumber =
|
|
@@ -2213,6 +2253,12 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2213
2253
|
this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
|
|
2214
2254
|
return summarizeResult.summary;
|
|
2215
2255
|
}
|
|
2256
|
+
/**
|
|
2257
|
+
* Builds the Summary tree including all the channels and the container state.
|
|
2258
|
+
*
|
|
2259
|
+
* @remarks - Unfortunately, this function is accessed in a non-typesafe way by a legacy first-party partner,
|
|
2260
|
+
* so until we can provide a proper API for their scenario, we need to ensure this function doesn't change.
|
|
2261
|
+
*/
|
|
2216
2262
|
async summarizeInternal(fullTree, trackState, telemetryContext) {
|
|
2217
2263
|
const summarizeResult = await this.channelCollection.summarize(fullTree, trackState, telemetryContext);
|
|
2218
2264
|
// Wrap data store summaries in .channels subtree.
|
|
@@ -2293,8 +2339,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2293
2339
|
*/
|
|
2294
2340
|
deleteSweepReadyNodes(sweepReadyRoutes) {
|
|
2295
2341
|
const { dataStoreRoutes, blobManagerRoutes } = this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
|
|
2296
|
-
|
|
2297
|
-
|
|
2342
|
+
return [
|
|
2343
|
+
...this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes),
|
|
2344
|
+
...this.blobManager.deleteSweepReadyNodes(blobManagerRoutes),
|
|
2345
|
+
];
|
|
2298
2346
|
}
|
|
2299
2347
|
/**
|
|
2300
2348
|
* This is called to update objects that are tombstones.
|
|
@@ -2320,10 +2368,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2320
2368
|
* Returns the type of the GC node. Currently, there are nodes that belong to the root ("/"), data stores or
|
|
2321
2369
|
* blob manager.
|
|
2322
2370
|
*/
|
|
2371
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2323
2372
|
getNodeType(nodePath) {
|
|
2324
2373
|
if ((0, index_js_1.isBlobPath)(nodePath)) {
|
|
2374
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2325
2375
|
return index_js_2.GCNodeType.Blob;
|
|
2326
2376
|
}
|
|
2377
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2327
2378
|
return this.channelCollection.getGCNodeType(nodePath) ?? index_js_2.GCNodeType.Other;
|
|
2328
2379
|
}
|
|
2329
2380
|
/**
|
|
@@ -2337,13 +2388,19 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2337
2388
|
return ["_gcRoot"];
|
|
2338
2389
|
}
|
|
2339
2390
|
switch (this.getNodeType(nodePath)) {
|
|
2340
|
-
|
|
2391
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2392
|
+
case index_js_2.GCNodeType.Blob: {
|
|
2341
2393
|
return [index_js_1.blobManagerBasePath];
|
|
2394
|
+
}
|
|
2395
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2342
2396
|
case index_js_2.GCNodeType.DataStore:
|
|
2343
|
-
|
|
2397
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2398
|
+
case index_js_2.GCNodeType.SubDataStore: {
|
|
2344
2399
|
return this.channelCollection.getDataStorePackagePath(nodePath);
|
|
2345
|
-
|
|
2400
|
+
}
|
|
2401
|
+
default: {
|
|
2346
2402
|
(0, internal_2.assert)(false, 0x2de /* "Package path requested for unsupported node type." */);
|
|
2403
|
+
}
|
|
2347
2404
|
}
|
|
2348
2405
|
}
|
|
2349
2406
|
/**
|
|
@@ -2405,8 +2462,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2405
2462
|
* op processing, updating SummarizerNode state tracking, and garbage collection.
|
|
2406
2463
|
* @param options - options controlling how the summary is generated or submitted
|
|
2407
2464
|
*/
|
|
2465
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2408
2466
|
async submitSummary(options) {
|
|
2409
|
-
const { fullTree = false, finalAttempt = false, summaryLogger, latestSummaryRefSeqNum, } = options;
|
|
2467
|
+
const { cancellationToken, fullTree = false, finalAttempt = false, summaryLogger, latestSummaryRefSeqNum, } = options;
|
|
2410
2468
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
2411
2469
|
// use it for all events logged during this summary.
|
|
2412
2470
|
const summaryNumber = this.nextSummaryNumber;
|
|
@@ -2490,7 +2548,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2490
2548
|
eventName: "LatestSummaryRefSeqNumMismatch",
|
|
2491
2549
|
details: {
|
|
2492
2550
|
...startSummaryResult,
|
|
2493
|
-
mismatchNumbers:
|
|
2551
|
+
mismatchNumbers: [...startSummaryResult.mismatchNumbers],
|
|
2494
2552
|
},
|
|
2495
2553
|
});
|
|
2496
2554
|
if (shouldValidatePreSummaryState && !finalAttempt) {
|
|
@@ -2510,7 +2568,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2510
2568
|
// summarizer to reconnect in the future.
|
|
2511
2569
|
// Also checking for cancellation is a must as summary process may be abandoned for other reasons,
|
|
2512
2570
|
// like loss of connectivity for main (interactive) client.
|
|
2513
|
-
if (
|
|
2571
|
+
if (cancellationToken.cancelled) {
|
|
2514
2572
|
return { continue: false, error: "disconnected" };
|
|
2515
2573
|
}
|
|
2516
2574
|
// That said, we rely on submitSystemMessage() that today only works in connected state.
|
|
@@ -2623,7 +2681,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2623
2681
|
};
|
|
2624
2682
|
let handle;
|
|
2625
2683
|
try {
|
|
2626
|
-
handle = await this.storage.uploadSummaryWithContext(
|
|
2684
|
+
handle = await this.storage.uploadSummaryWithContext(summaryTree, summaryContext);
|
|
2627
2685
|
}
|
|
2628
2686
|
catch (error) {
|
|
2629
2687
|
return {
|
|
@@ -2745,13 +2803,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2745
2803
|
return this.pendingMessagesCount !== 0;
|
|
2746
2804
|
}
|
|
2747
2805
|
updateDocumentDirtyState(dirty) {
|
|
2748
|
-
if (this.attachState
|
|
2749
|
-
(0, internal_2.assert)(dirty, 0x3d2 /* Non-attached container is dirty */);
|
|
2750
|
-
}
|
|
2751
|
-
else {
|
|
2806
|
+
if (this.attachState === container_definitions_1.AttachState.Attached) {
|
|
2752
2807
|
// Other way is not true = see this.isContainerMessageDirtyable()
|
|
2753
2808
|
(0, internal_2.assert)(!dirty || this.hasPendingMessages(), 0x3d3 /* if doc is dirty, there has to be pending ops */);
|
|
2754
2809
|
}
|
|
2810
|
+
else {
|
|
2811
|
+
(0, internal_2.assert)(dirty, 0x3d2 /* Non-attached container is dirty */);
|
|
2812
|
+
}
|
|
2755
2813
|
if (this.dirtyContainer === dirty) {
|
|
2756
2814
|
return;
|
|
2757
2815
|
}
|
|
@@ -2813,7 +2871,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2813
2871
|
// on this callback to do actual sending.
|
|
2814
2872
|
const schemaChangeMessage = this.documentsSchemaController.maybeSendSchemaMessage();
|
|
2815
2873
|
if (schemaChangeMessage) {
|
|
2816
|
-
this.logger.sendTelemetryEvent({
|
|
2874
|
+
this.mc.logger.sendTelemetryEvent({
|
|
2817
2875
|
eventName: "SchemaChangeProposal",
|
|
2818
2876
|
refSeq: schemaChangeMessage.refSeq,
|
|
2819
2877
|
version: schemaChangeMessage.version,
|
|
@@ -2865,6 +2923,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2865
2923
|
return;
|
|
2866
2924
|
}
|
|
2867
2925
|
this.flushTaskExists = true;
|
|
2926
|
+
// TODO: hoist this out of the function scope to save unnecessary allocations
|
|
2927
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping -- Separate `flush` method already exists in outer scope
|
|
2868
2928
|
const flush = () => {
|
|
2869
2929
|
this.flushTaskExists = false;
|
|
2870
2930
|
try {
|
|
@@ -2875,22 +2935,25 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2875
2935
|
}
|
|
2876
2936
|
};
|
|
2877
2937
|
switch (this.flushMode) {
|
|
2878
|
-
case internal_5.FlushMode.TurnBased:
|
|
2938
|
+
case internal_5.FlushMode.TurnBased: {
|
|
2879
2939
|
// When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
|
|
2880
2940
|
// batch at the end of the turn
|
|
2881
2941
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
2882
2942
|
Promise.resolve().then(flush);
|
|
2883
2943
|
break;
|
|
2944
|
+
}
|
|
2884
2945
|
// FlushModeExperimental is experimental and not exposed directly in the runtime APIs
|
|
2885
|
-
case internal_5.FlushModeExperimental.Async:
|
|
2946
|
+
case internal_5.FlushModeExperimental.Async: {
|
|
2886
2947
|
// When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
|
|
2887
2948
|
// batch when all micro-tasks are complete.
|
|
2888
2949
|
// Compared to TurnBased, this flush mode will capture more ops into the same batch.
|
|
2889
2950
|
setTimeout(flush, 0);
|
|
2890
2951
|
break;
|
|
2891
|
-
|
|
2952
|
+
}
|
|
2953
|
+
default: {
|
|
2892
2954
|
(0, internal_2.assert)(this._orderSequentiallyCalls > 0, 0x587 /* Unreachable unless running under orderSequentially */);
|
|
2893
2955
|
break;
|
|
2956
|
+
}
|
|
2894
2957
|
}
|
|
2895
2958
|
}
|
|
2896
2959
|
submitSummaryMessage(contents, referenceSequenceNumber) {
|
|
@@ -2898,10 +2961,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2898
2961
|
(0, internal_2.assert)(this.connected, 0x133 /* "Container disconnected when trying to submit system message" */);
|
|
2899
2962
|
// System message should not be sent in the middle of the batch.
|
|
2900
2963
|
(0, internal_2.assert)(this.outbox.isEmpty, 0x3d4 /* System op in the middle of a batch */);
|
|
2901
|
-
|
|
2902
|
-
return this.submitSummaryFn !== undefined
|
|
2903
|
-
? this.submitSummaryFn(contents, referenceSequenceNumber)
|
|
2904
|
-
: this.submitFn(internal_3.MessageType.Summarize, contents, false);
|
|
2964
|
+
return this.submitSummaryFn(contents, referenceSequenceNumber);
|
|
2905
2965
|
}
|
|
2906
2966
|
/**
|
|
2907
2967
|
* Throw an error if the runtime is closed. Methods that are expected to potentially
|
|
@@ -2941,15 +3001,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2941
3001
|
* @param localOpMetadata - The local metadata associated with the original message.
|
|
2942
3002
|
*/
|
|
2943
3003
|
reSubmitCore(message, localOpMetadata, opMetadata) {
|
|
2944
|
-
(0, internal_2.assert)(
|
|
3004
|
+
(0, internal_2.assert)(this._summarizer === undefined, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
|
|
2945
3005
|
switch (message.type) {
|
|
2946
3006
|
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
2947
3007
|
case messageTypes_js_1.ContainerMessageType.Attach:
|
|
2948
|
-
case messageTypes_js_1.ContainerMessageType.Alias:
|
|
3008
|
+
case messageTypes_js_1.ContainerMessageType.Alias: {
|
|
2949
3009
|
// For Operations, call resubmitDataStoreOp which will find the right store
|
|
2950
3010
|
// and trigger resubmission on it.
|
|
2951
3011
|
this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
|
|
2952
3012
|
break;
|
|
3013
|
+
}
|
|
2953
3014
|
case messageTypes_js_1.ContainerMessageType.IdAllocation: {
|
|
2954
3015
|
// Allocation ops are never resubmitted/rebased. This is because they require special handling to
|
|
2955
3016
|
// avoid being submitted out of order. For example, if the pending state manager contained
|
|
@@ -2960,20 +3021,24 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2960
3021
|
// all pending IDs. The resubmitted allocation ops are then ignored here.
|
|
2961
3022
|
break;
|
|
2962
3023
|
}
|
|
2963
|
-
case messageTypes_js_1.ContainerMessageType.BlobAttach:
|
|
3024
|
+
case messageTypes_js_1.ContainerMessageType.BlobAttach: {
|
|
2964
3025
|
this.blobManager.reSubmit(opMetadata);
|
|
2965
3026
|
break;
|
|
2966
|
-
|
|
3027
|
+
}
|
|
3028
|
+
case messageTypes_js_1.ContainerMessageType.Rejoin: {
|
|
2967
3029
|
this.submit(message);
|
|
2968
3030
|
break;
|
|
2969
|
-
|
|
3031
|
+
}
|
|
3032
|
+
case messageTypes_js_1.ContainerMessageType.GC: {
|
|
2970
3033
|
this.submit(message);
|
|
2971
3034
|
break;
|
|
2972
|
-
|
|
3035
|
+
}
|
|
3036
|
+
case messageTypes_js_1.ContainerMessageType.DocumentSchemaChange: {
|
|
2973
3037
|
// There is no need to resend this message. Document schema controller will properly resend it again (if needed)
|
|
2974
3038
|
// on a first occasion (any ops sent after reconnect). There is a good chance, though, that it will not want to
|
|
2975
3039
|
// send any ops, as some other client already changed schema.
|
|
2976
3040
|
break;
|
|
3041
|
+
}
|
|
2977
3042
|
default: {
|
|
2978
3043
|
const error = getUnknownMessageTypeError(message.type, "reSubmitCore" /* codePath */);
|
|
2979
3044
|
this.closeFn(error);
|
|
@@ -2985,18 +3050,21 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2985
3050
|
// Need to parse from string for back-compat
|
|
2986
3051
|
const { type, contents } = this.parseLocalOpContent(content);
|
|
2987
3052
|
switch (type) {
|
|
2988
|
-
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
3053
|
+
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp: {
|
|
2989
3054
|
// For operations, call rollbackDataStoreOp which will find the right store
|
|
2990
3055
|
// and trigger rollback on it.
|
|
2991
3056
|
this.channelCollection.rollback(type, contents, localOpMetadata);
|
|
2992
3057
|
break;
|
|
2993
|
-
|
|
3058
|
+
}
|
|
3059
|
+
default: {
|
|
2994
3060
|
throw new Error(`Can't rollback ${type}`);
|
|
3061
|
+
}
|
|
2995
3062
|
}
|
|
2996
3063
|
}
|
|
2997
3064
|
/**
|
|
2998
3065
|
* Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck
|
|
2999
3066
|
*/
|
|
3067
|
+
// eslint-disable-next-line import/no-deprecated
|
|
3000
3068
|
async refreshLatestSummaryAck(options) {
|
|
3001
3069
|
const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
|
|
3002
3070
|
// proposalHandle is always passed from RunningSummarizer.
|
|
@@ -3066,15 +3134,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3066
3134
|
snapshotTree = snapshot.snapshotTree;
|
|
3067
3135
|
}
|
|
3068
3136
|
else {
|
|
3069
|
-
const versions = await this.storage.getVersions(
|
|
3137
|
+
const versions = await this.storage.getVersions(
|
|
3138
|
+
// eslint-disable-next-line unicorn/no-null
|
|
3139
|
+
null, 1, scenarioName, internal_3.FetchSource.noCache);
|
|
3070
3140
|
(0, internal_2.assert)(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
|
|
3071
3141
|
snapshotTree = await this.storage.getSnapshotTree(versions[0]);
|
|
3072
3142
|
(0, internal_2.assert)(!!snapshotTree, 0x138 /* "Failed to get snapshot from storage" */);
|
|
3073
3143
|
props.snapshotVersion = versions[0].id;
|
|
3074
3144
|
}
|
|
3075
3145
|
props.getSnapshotDuration = trace.trace().duration;
|
|
3076
|
-
const
|
|
3077
|
-
const snapshotRefSeq = await (0, internal_6.seqFromTree)(snapshotTree, readAndParseBlob);
|
|
3146
|
+
const snapshotRefSeq = await (0, internal_6.seqFromTree)(snapshotTree, this.readAndParseBlob);
|
|
3078
3147
|
props.snapshotRefSeq = snapshotRefSeq;
|
|
3079
3148
|
props.newerSnapshotPresent = snapshotRefSeq >= targetRefSeq;
|
|
3080
3149
|
perfEvent.end({ details: props });
|
|
@@ -3095,7 +3164,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3095
3164
|
if (this._orderSequentiallyCalls !== 0) {
|
|
3096
3165
|
throw new internal_7.UsageError("can't get state during orderSequentially");
|
|
3097
3166
|
}
|
|
3098
|
-
this.imminentClosure
|
|
3167
|
+
this.imminentClosure ||= props?.notifyImminentClosure ?? false;
|
|
3099
3168
|
const getSyncState = (pendingAttachmentBlobs) => {
|
|
3100
3169
|
const pending = this.pendingStateManager.getLocalState(props?.snapshotSequenceNumber);
|
|
3101
3170
|
const sessionExpiryTimerStarted = props?.sessionExpiryTimerStarted ?? this.garbageCollector.sessionExpiryTimerStarted;
|
|
@@ -3127,32 +3196,32 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3127
3196
|
: internal_7.PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) => logAndReturnPendingState(event, getSyncState()));
|
|
3128
3197
|
}
|
|
3129
3198
|
summarizeOnDemand(options) {
|
|
3130
|
-
if (this.
|
|
3131
|
-
return this.
|
|
3132
|
-
}
|
|
3133
|
-
else if (this.summaryManager !== undefined) {
|
|
3134
|
-
return this.summaryManager.summarizeOnDemand(options);
|
|
3199
|
+
if (this._summarizer !== undefined) {
|
|
3200
|
+
return this._summarizer.summarizeOnDemand(options);
|
|
3135
3201
|
}
|
|
3136
|
-
else {
|
|
3202
|
+
else if (this.summaryManager === undefined) {
|
|
3137
3203
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
3138
3204
|
// disableSummaries is turned on. We are throwing instead of returning a failure here,
|
|
3139
3205
|
// because it is a misuse of the API rather than an expected failure.
|
|
3140
3206
|
throw new internal_7.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
3141
3207
|
}
|
|
3208
|
+
else {
|
|
3209
|
+
return this.summaryManager.summarizeOnDemand(options);
|
|
3210
|
+
}
|
|
3142
3211
|
}
|
|
3143
3212
|
enqueueSummarize(options) {
|
|
3144
|
-
if (this.
|
|
3145
|
-
return this.
|
|
3213
|
+
if (this._summarizer !== undefined) {
|
|
3214
|
+
return this._summarizer.enqueueSummarize(options);
|
|
3146
3215
|
}
|
|
3147
|
-
else if (this.summaryManager
|
|
3148
|
-
return this.summaryManager.enqueueSummarize(options);
|
|
3149
|
-
}
|
|
3150
|
-
else {
|
|
3216
|
+
else if (this.summaryManager === undefined) {
|
|
3151
3217
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
3152
3218
|
// generateSummaries is turned off. We are throwing instead of returning a failure here,
|
|
3153
3219
|
// because it is a misuse of the API rather than an expected failure.
|
|
3154
3220
|
throw new internal_7.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
3155
3221
|
}
|
|
3222
|
+
else {
|
|
3223
|
+
return this.summaryManager.enqueueSummarize(options);
|
|
3224
|
+
}
|
|
3156
3225
|
}
|
|
3157
3226
|
/**
|
|
3158
3227
|
* Forms a function that will create and retrieve a Summarizer.
|