@fluidframework/container-runtime 2.20.0 → 2.21.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/CHANGELOG.md +38 -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.map +1 -1
- package/dist/blobManager/blobManager.js +14 -11
- 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 +264 -194
- 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.map +1 -1
- package/lib/blobManager/blobManager.js +14 -11
- 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 +271 -196
- 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 +21 -43
- package/src/batchTracker.ts +3 -3
- package/src/blobManager/blobManager.ts +16 -14
- package/src/blobManager/blobManagerSnapSum.ts +8 -8
- package/src/channelCollection.ts +63 -44
- package/src/connectionTelemetry.ts +12 -6
- package/src/containerRuntime.ts +306 -235
- 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
|
|
@@ -897,14 +917,14 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
897
917
|
stashedBlobs: pendingRuntimeState?.pendingAttachmentBlobs,
|
|
898
918
|
closeContainer: (error) => this.closeFn(error),
|
|
899
919
|
});
|
|
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.
|
|
920
|
+
this.deltaScheduler = new deltaScheduler_js_1.DeltaScheduler(this.innerDeltaManager, this, (0, internal_7.createChildLogger)({ logger: this.baseLogger, namespace: "DeltaScheduler" }));
|
|
921
|
+
this.inboundBatchAggregator = new inboundBatchAggregator_js_1.InboundBatchAggregator(this.innerDeltaManager, () => this.clientId, (0, internal_7.createChildLogger)({ logger: this.baseLogger, namespace: "InboundBatchAggregator" }));
|
|
902
922
|
const disablePartialFlush = this.mc.config.getBoolean("Fluid.ContainerRuntime.DisablePartialFlush");
|
|
903
|
-
const legacySendBatchFn = (0, exports.makeLegacySendBatchFn)(
|
|
923
|
+
const legacySendBatchFn = (0, exports.makeLegacySendBatchFn)(submitFn, this.innerDeltaManager);
|
|
904
924
|
this.outbox = new index_js_3.Outbox({
|
|
905
925
|
shouldSend: () => this.canSendOps(),
|
|
906
926
|
pendingStateManager: this.pendingStateManager,
|
|
907
|
-
submitBatchFn
|
|
927
|
+
submitBatchFn,
|
|
908
928
|
legacySendBatchFn,
|
|
909
929
|
compressor: new index_js_3.OpCompressor(this.mc.logger),
|
|
910
930
|
splitter: opSplitter,
|
|
@@ -951,7 +971,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
951
971
|
const closeSummarizerDelayOverride = this.mc.config.getNumber("Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs");
|
|
952
972
|
this.closeSummarizerDelayMs =
|
|
953
973
|
closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
|
|
954
|
-
|
|
974
|
+
const summaryCollection = new index_js_4.SummaryCollection(this.deltaManager, this.baseLogger);
|
|
955
975
|
this.dirtyContainer =
|
|
956
976
|
this.attachState !== container_definitions_1.AttachState.Attached || this.hasPendingMessages();
|
|
957
977
|
context.updateDirtyContainerState(this.dirtyContainer);
|
|
@@ -960,14 +980,17 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
960
980
|
}
|
|
961
981
|
else {
|
|
962
982
|
const orderedClientLogger = (0, internal_7.createChildLogger)({
|
|
963
|
-
logger: this.
|
|
983
|
+
logger: this.baseLogger,
|
|
964
984
|
namespace: "OrderedClientElection",
|
|
965
985
|
});
|
|
966
986
|
const orderedClientCollection = new index_js_4.OrderedClientCollection(orderedClientLogger, this.innerDeltaManager, this._quorum);
|
|
967
987
|
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
|
-
|
|
988
|
+
this.summarizerClientElection = new index_js_4.SummarizerClientElection(orderedClientLogger, summaryCollection, orderedClientElectionForSummarizer, maxOpsSinceLastSummary);
|
|
989
|
+
if (isSummarizerClient) {
|
|
990
|
+
// eslint-disable-next-line import/no-deprecated
|
|
991
|
+
this._summarizer = new index_js_4.Summarizer(this /* ISummarizerRuntime */, () => summaryConfiguration, this /* ISummarizerInternalsProvider */, this.handleContext, summaryCollection,
|
|
992
|
+
// eslint-disable-next-line import/no-deprecated
|
|
993
|
+
async (runtime) => index_js_4.RunWhileConnectedCoordinator.create(runtime,
|
|
971
994
|
// Summarization runs in summarizer client and needs access to the real (non-proxy) active
|
|
972
995
|
// information. The proxy delta manager would always return false for summarizer client.
|
|
973
996
|
() => this.innerDeltaManager.active));
|
|
@@ -976,48 +999,49 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
976
999
|
// Only create a SummaryManager and SummarizerClientElection
|
|
977
1000
|
// if summaries are enabled and we are not the summarizer client.
|
|
978
1001
|
const defaultAction = () => {
|
|
979
|
-
if (
|
|
1002
|
+
if (summaryCollection.opsSinceLastAck > maxOpsSinceLastSummary) {
|
|
980
1003
|
this.mc.logger.sendTelemetryEvent({ eventName: "SummaryStatus:Behind" });
|
|
981
1004
|
// unregister default to no log on every op after falling behind
|
|
982
1005
|
// and register summary ack handler to re-register this handler
|
|
983
1006
|
// after successful summary
|
|
984
|
-
|
|
1007
|
+
summaryCollection.once(internal_3.MessageType.SummaryAck, () => {
|
|
985
1008
|
this.mc.logger.sendTelemetryEvent({
|
|
986
1009
|
eventName: "SummaryStatus:CaughtUp",
|
|
987
1010
|
});
|
|
988
1011
|
// we've caught up, so re-register the default action to monitor for
|
|
989
1012
|
// falling behind, and unregister ourself
|
|
990
|
-
|
|
1013
|
+
summaryCollection.on("default", defaultAction);
|
|
991
1014
|
});
|
|
992
|
-
|
|
1015
|
+
summaryCollection.off("default", defaultAction);
|
|
993
1016
|
}
|
|
994
1017
|
};
|
|
995
|
-
|
|
1018
|
+
summaryCollection.on("default", defaultAction);
|
|
996
1019
|
// Create the SummaryManager and mark the initial state
|
|
997
1020
|
this.summaryManager = new index_js_4.SummaryManager(this.summarizerClientElection, this, // IConnectedState
|
|
998
|
-
|
|
1021
|
+
summaryCollection, this.baseLogger, this.formCreateSummarizerFn(loader), new throttler_js_1.Throttler(60 * 1000, // 60 sec delay window
|
|
999
1022
|
30 * 1000, // 30 sec max delay
|
|
1000
1023
|
// throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
|
|
1001
1024
|
(0, throttler_js_1.formExponentialFn)({ coefficient: 20, initialDelay: 0 })), {
|
|
1002
|
-
initialDelayMs:
|
|
1025
|
+
initialDelayMs: initialSummarizerDelayMs,
|
|
1003
1026
|
});
|
|
1004
1027
|
// Forward events from SummaryManager
|
|
1005
|
-
[
|
|
1028
|
+
for (const eventName of [
|
|
1006
1029
|
"summarize",
|
|
1007
1030
|
"summarizeAllAttemptsFailed",
|
|
1008
1031
|
"summarizerStop",
|
|
1009
1032
|
"summarizerStart",
|
|
1010
1033
|
"summarizerStartupFailed",
|
|
1011
|
-
]
|
|
1034
|
+
]) {
|
|
1012
1035
|
this.summaryManager?.on(eventName, (...args) => {
|
|
1013
1036
|
this.emit(eventName, ...args);
|
|
1014
1037
|
});
|
|
1015
|
-
}
|
|
1038
|
+
}
|
|
1016
1039
|
this.summaryManager.start();
|
|
1017
1040
|
}
|
|
1018
1041
|
}
|
|
1019
1042
|
// logging hardware telemetry
|
|
1020
|
-
this.
|
|
1043
|
+
this.baseLogger.send({
|
|
1044
|
+
category: "generic",
|
|
1021
1045
|
eventName: "DeviceSpec",
|
|
1022
1046
|
...getDeviceSpec(),
|
|
1023
1047
|
});
|
|
@@ -1029,13 +1053,12 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1029
1053
|
summaryFormatVersion: metadata?.summaryFormatVersion,
|
|
1030
1054
|
disableIsolatedChannels: metadata?.disableIsolatedChannels,
|
|
1031
1055
|
gcVersion: metadata?.gcFeature,
|
|
1032
|
-
options: JSON.stringify(
|
|
1056
|
+
options: JSON.stringify(baseRuntimeOptions),
|
|
1033
1057
|
idCompressorModeMetadata: metadata?.documentSchema?.runtime?.idCompressorMode,
|
|
1034
|
-
idCompressorMode: this.idCompressorMode,
|
|
1058
|
+
idCompressorMode: this.sessionSchema.idCompressorMode,
|
|
1035
1059
|
sessionRuntimeSchema: JSON.stringify(this.sessionSchema),
|
|
1036
1060
|
featureGates: JSON.stringify({
|
|
1037
1061
|
...featureGatesForTelemetry,
|
|
1038
|
-
disableAttachReorder: this.disableAttachReorder,
|
|
1039
1062
|
disablePartialFlush,
|
|
1040
1063
|
closeSummarizerDelayOverride,
|
|
1041
1064
|
}),
|
|
@@ -1043,11 +1066,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1043
1066
|
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
1044
1067
|
initialSequenceNumber: this.deltaManager.initialSequenceNumber,
|
|
1045
1068
|
});
|
|
1046
|
-
(0, connectionTelemetry_js_1.ReportOpPerfTelemetry)(this.clientId, this._deltaManager, this, this.
|
|
1047
|
-
(0, batchTracker_js_1.BindBatchTracker)(this, this.
|
|
1069
|
+
(0, connectionTelemetry_js_1.ReportOpPerfTelemetry)(this.clientId, this._deltaManager, this, this.baseLogger);
|
|
1070
|
+
(0, batchTracker_js_1.BindBatchTracker)(this, this.baseLogger);
|
|
1048
1071
|
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 */);
|
|
1072
|
+
if (this._summarizer !== undefined) {
|
|
1051
1073
|
return this._summarizer;
|
|
1052
1074
|
}
|
|
1053
1075
|
return provideEntryPoint(this);
|
|
@@ -1056,8 +1078,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1056
1078
|
// saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
|
|
1057
1079
|
this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
|
|
1058
1080
|
}
|
|
1081
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1059
1082
|
onSchemaChange(schema) {
|
|
1060
|
-
this.logger.sendTelemetryEvent({
|
|
1083
|
+
this.mc.logger.sendTelemetryEvent({
|
|
1061
1084
|
eventName: "SchemaChangeAccept",
|
|
1062
1085
|
sessionRuntimeSchema: JSON.stringify(schema),
|
|
1063
1086
|
});
|
|
@@ -1092,8 +1115,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1092
1115
|
* Initializes the state from the base snapshot this container runtime loaded from.
|
|
1093
1116
|
*/
|
|
1094
1117
|
async initializeBaseState() {
|
|
1095
|
-
if (this.idCompressorMode === "on" ||
|
|
1096
|
-
(this.idCompressorMode === "delayed" && this.connected)) {
|
|
1118
|
+
if (this.sessionSchema.idCompressorMode === "on" ||
|
|
1119
|
+
(this.sessionSchema.idCompressorMode === "delayed" && this.connected)) {
|
|
1097
1120
|
this._idCompressor = await this.createIdCompressor();
|
|
1098
1121
|
// This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
|
|
1099
1122
|
(0, internal_2.assert)(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
|
|
@@ -1136,7 +1159,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1136
1159
|
// Lookup up in the cache, if not present then make the network call as multiple datastores could
|
|
1137
1160
|
// be in same loading group. So, once we have fetched the snapshot for that loading group on
|
|
1138
1161
|
// any request, then cache that as same group could be requested in future too.
|
|
1139
|
-
const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(), async () => {
|
|
1162
|
+
const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(","), async () => {
|
|
1140
1163
|
(0, internal_2.assert)(this.storage.getSnapshot !== undefined, 0x8ee /* getSnapshot api should be defined if used */);
|
|
1141
1164
|
loadedFromCache = false;
|
|
1142
1165
|
return this.storage.getSnapshot({
|
|
@@ -1145,7 +1168,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1145
1168
|
loadingGroupIds: sortedLoadingGroupIds,
|
|
1146
1169
|
});
|
|
1147
1170
|
});
|
|
1148
|
-
this.logger.sendTelemetryEvent({
|
|
1171
|
+
this.mc.logger.sendTelemetryEvent({
|
|
1149
1172
|
eventName: "GroupIdSnapshotFetched",
|
|
1150
1173
|
details: JSON.stringify({
|
|
1151
1174
|
fromCache: loadedFromCache,
|
|
@@ -1175,7 +1198,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1175
1198
|
// another snapshot from which the summarizer loaded and it is behind, then just give up as
|
|
1176
1199
|
// the summarizer state is not up to date.
|
|
1177
1200
|
// This should be a recoverable scenario and shouldn't happen as we should process the ack first.
|
|
1178
|
-
if (this.
|
|
1201
|
+
if (this._summarizer !== undefined) {
|
|
1179
1202
|
throw new Error("Summarizer client behind, loaded newer snapshot with loadingGroupId");
|
|
1180
1203
|
}
|
|
1181
1204
|
// We want to catchup from sequenceNumber to targetSequenceNumber
|
|
@@ -1237,7 +1260,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1237
1260
|
return {
|
|
1238
1261
|
status: 200,
|
|
1239
1262
|
mimeType: "fluid/object",
|
|
1240
|
-
value: this.
|
|
1263
|
+
value: this._summarizer,
|
|
1241
1264
|
};
|
|
1242
1265
|
}
|
|
1243
1266
|
return (0, internal_6.create404Response)(request);
|
|
@@ -1303,6 +1326,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1303
1326
|
const documentSchema = this.documentsSchemaController.summarizeDocumentSchema(this.deltaManager.lastSequenceNumber);
|
|
1304
1327
|
// Is document schema explicit control on?
|
|
1305
1328
|
const explicitSchemaControl = documentSchema?.runtime.explicitSchemaControl;
|
|
1329
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1306
1330
|
const metadata = {
|
|
1307
1331
|
...this.createContainerMetadata,
|
|
1308
1332
|
// Increment the summary number for the next summary that will be generated.
|
|
@@ -1316,7 +1340,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1316
1340
|
// last message's sequence number.
|
|
1317
1341
|
// See also lastMessageFromMetadata()
|
|
1318
1342
|
message: explicitSchemaControl
|
|
1319
|
-
?
|
|
1343
|
+
? // eslint-disable-next-line import/no-deprecated
|
|
1344
|
+
{ sequenceNumber: -1 }
|
|
1320
1345
|
: message,
|
|
1321
1346
|
lastMessage: explicitSchemaControl ? message : undefined,
|
|
1322
1347
|
documentSchema,
|
|
@@ -1432,9 +1457,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1432
1457
|
switch (opContents.type) {
|
|
1433
1458
|
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
1434
1459
|
case messageTypes_js_1.ContainerMessageType.Attach:
|
|
1435
|
-
case messageTypes_js_1.ContainerMessageType.Alias:
|
|
1460
|
+
case messageTypes_js_1.ContainerMessageType.Alias: {
|
|
1436
1461
|
return this.channelCollection.applyStashedOp(opContents);
|
|
1437
|
-
|
|
1462
|
+
}
|
|
1463
|
+
case messageTypes_js_1.ContainerMessageType.IdAllocation: {
|
|
1438
1464
|
// IDs allocation ops in stashed state are ignored because the tip state of the compressor
|
|
1439
1465
|
// is serialized into the pending state. This is done because generation of new IDs during
|
|
1440
1466
|
// stashed op application (or, later, resubmit) must generate new IDs and if the compressor
|
|
@@ -1444,17 +1470,22 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1444
1470
|
// and the runtime could filter out all ID allocation ops from the stashed state and apply them
|
|
1445
1471
|
// before applying the rest of the stashed ops. This would accomplish the same thing but with
|
|
1446
1472
|
// better performance in future incremental stashed state creation.
|
|
1447
|
-
(0, internal_2.assert)(this.idCompressorMode !== undefined, 0x8f1 /* ID compressor should be in use */);
|
|
1473
|
+
(0, internal_2.assert)(this.sessionSchema.idCompressorMode !== undefined, 0x8f1 /* ID compressor should be in use */);
|
|
1448
1474
|
return;
|
|
1449
|
-
|
|
1475
|
+
}
|
|
1476
|
+
case messageTypes_js_1.ContainerMessageType.DocumentSchemaChange: {
|
|
1450
1477
|
return;
|
|
1451
|
-
|
|
1478
|
+
}
|
|
1479
|
+
case messageTypes_js_1.ContainerMessageType.BlobAttach: {
|
|
1452
1480
|
return;
|
|
1453
|
-
|
|
1481
|
+
}
|
|
1482
|
+
case messageTypes_js_1.ContainerMessageType.Rejoin: {
|
|
1454
1483
|
throw new Error("rejoin not expected here");
|
|
1455
|
-
|
|
1484
|
+
}
|
|
1485
|
+
case messageTypes_js_1.ContainerMessageType.GC: {
|
|
1456
1486
|
// GC op is only sent in summarizer which should never have stashed ops.
|
|
1457
1487
|
throw new internal_7.LoggingError("GC op not expected to be stashed in summarizer");
|
|
1488
|
+
}
|
|
1458
1489
|
default: {
|
|
1459
1490
|
const error = getUnknownMessageTypeError(opContents.type, "applyStashedOp" /* codePath */);
|
|
1460
1491
|
this.closeFn(error);
|
|
@@ -1464,7 +1495,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1464
1495
|
}
|
|
1465
1496
|
async loadIdCompressor() {
|
|
1466
1497
|
if (this._idCompressor === undefined &&
|
|
1467
|
-
this.idCompressorMode !== undefined &&
|
|
1498
|
+
this.sessionSchema.idCompressorMode !== undefined &&
|
|
1468
1499
|
this._loadIdCompressor === undefined) {
|
|
1469
1500
|
this._loadIdCompressor = this.createIdCompressor()
|
|
1470
1501
|
.then((compressor) => {
|
|
@@ -1478,7 +1509,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1478
1509
|
this._idCompressor = compressor;
|
|
1479
1510
|
})
|
|
1480
1511
|
.catch((error) => {
|
|
1481
|
-
this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
1512
|
+
this.mc.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
|
|
1482
1513
|
throw error;
|
|
1483
1514
|
});
|
|
1484
1515
|
}
|
|
@@ -1489,7 +1520,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1489
1520
|
const currentClientId = this._audience.getSelf()?.clientId;
|
|
1490
1521
|
(0, internal_2.assert)(clientId === currentClientId, 0x977 /* input clientId does not match Audience */);
|
|
1491
1522
|
(0, internal_2.assert)(this.clientId === currentClientId, 0x978 /* this.clientId does not match Audience */);
|
|
1492
|
-
if (connected && this.idCompressorMode === "delayed") {
|
|
1523
|
+
if (connected && this.sessionSchema.idCompressorMode === "delayed") {
|
|
1493
1524
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1494
1525
|
this.loadIdCompressor();
|
|
1495
1526
|
}
|
|
@@ -1578,7 +1609,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1578
1609
|
// or something different, like a system message.
|
|
1579
1610
|
const hasModernRuntimeMessageEnvelope = messageCopy.type === internal_3.MessageType.Operation;
|
|
1580
1611
|
const savedOp = messageCopy.metadata?.savedOp;
|
|
1581
|
-
const logLegacyCase = (0, exports.getSingleUseLegacyLogCallback)(this.logger, messageCopy.type);
|
|
1612
|
+
const logLegacyCase = (0, exports.getSingleUseLegacyLogCallback)(this.mc.logger, messageCopy.type);
|
|
1582
1613
|
let runtimeBatch = hasModernRuntimeMessageEnvelope || isUnpackedRuntimeMessage(messageCopy);
|
|
1583
1614
|
if (runtimeBatch) {
|
|
1584
1615
|
// We expect runtime messages to have JSON contents - deserialize it in place.
|
|
@@ -1680,11 +1711,11 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1680
1711
|
let error;
|
|
1681
1712
|
try {
|
|
1682
1713
|
if (!runtimeBatch) {
|
|
1683
|
-
|
|
1714
|
+
for (const { message } of messagesWithMetadata) {
|
|
1684
1715
|
this.ensureNoDataModelChanges(() => {
|
|
1685
1716
|
this.observeNonRuntimeMessage(message);
|
|
1686
1717
|
});
|
|
1687
|
-
}
|
|
1718
|
+
}
|
|
1688
1719
|
return;
|
|
1689
1720
|
}
|
|
1690
1721
|
// Updates a message's minimum sequence number to the minimum sequence number that container
|
|
@@ -1752,8 +1783,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1752
1783
|
this.emit("op", message, true /* runtimeMessage */);
|
|
1753
1784
|
}
|
|
1754
1785
|
}
|
|
1755
|
-
catch (
|
|
1756
|
-
error =
|
|
1786
|
+
catch (error_) {
|
|
1787
|
+
error = error_;
|
|
1757
1788
|
throw error;
|
|
1758
1789
|
}
|
|
1759
1790
|
finally {
|
|
@@ -1810,30 +1841,39 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1810
1841
|
switch (message.type) {
|
|
1811
1842
|
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
1812
1843
|
case messageTypes_js_1.ContainerMessageType.Attach:
|
|
1813
|
-
case messageTypes_js_1.ContainerMessageType.Alias:
|
|
1844
|
+
case messageTypes_js_1.ContainerMessageType.Alias: {
|
|
1814
1845
|
// Remove the metadata from the message before sending it to the channel collection. The metadata
|
|
1815
1846
|
// is added by the container runtime and is not part of the message that the channel collection and
|
|
1816
1847
|
// layers below it expect.
|
|
1817
1848
|
this.channelCollection.processMessages({ envelope: message, messagesContent, local });
|
|
1818
1849
|
break;
|
|
1819
|
-
|
|
1850
|
+
}
|
|
1851
|
+
case messageTypes_js_1.ContainerMessageType.BlobAttach: {
|
|
1820
1852
|
this.blobManager.processBlobAttachMessage(message, local);
|
|
1821
1853
|
break;
|
|
1822
|
-
|
|
1854
|
+
}
|
|
1855
|
+
case messageTypes_js_1.ContainerMessageType.IdAllocation: {
|
|
1823
1856
|
this.processIdCompressorMessages(contents, savedOp);
|
|
1824
1857
|
break;
|
|
1825
|
-
|
|
1858
|
+
}
|
|
1859
|
+
case messageTypes_js_1.ContainerMessageType.GC: {
|
|
1826
1860
|
this.garbageCollector.processMessages(contents, message.timestamp, local);
|
|
1827
1861
|
break;
|
|
1828
|
-
|
|
1862
|
+
}
|
|
1863
|
+
case messageTypes_js_1.ContainerMessageType.ChunkedOp: {
|
|
1829
1864
|
// From observability POV, we should not expose the rest of the system (including "op" events on object) to these messages.
|
|
1830
1865
|
// Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
|
|
1831
1866
|
(0, internal_2.assert)(false, 0x93d /* should not even get here */);
|
|
1832
|
-
|
|
1867
|
+
}
|
|
1868
|
+
case messageTypes_js_1.ContainerMessageType.Rejoin: {
|
|
1833
1869
|
break;
|
|
1834
|
-
|
|
1835
|
-
|
|
1870
|
+
}
|
|
1871
|
+
case messageTypes_js_1.ContainerMessageType.DocumentSchemaChange: {
|
|
1872
|
+
this.documentsSchemaController.processDocumentSchemaMessages(
|
|
1873
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1874
|
+
contents, local, message.sequenceNumber);
|
|
1836
1875
|
break;
|
|
1876
|
+
}
|
|
1837
1877
|
default: {
|
|
1838
1878
|
const error = getUnknownMessageTypeError(message.type, "validateAndProcessRuntimeMessage" /* codePath */, message);
|
|
1839
1879
|
this.closeFn(error);
|
|
@@ -1851,7 +1891,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1851
1891
|
// Some other client turned on the id compressor. If we have not turned it on,
|
|
1852
1892
|
// put it in a pending queue and delay finalization.
|
|
1853
1893
|
if (this._idCompressor === undefined) {
|
|
1854
|
-
(0, internal_2.assert)(this.idCompressorMode !== undefined, 0x93c /* id compressor should be enabled */);
|
|
1894
|
+
(0, internal_2.assert)(this.sessionSchema.idCompressorMode !== undefined, 0x93c /* id compressor should be enabled */);
|
|
1855
1895
|
this.pendingIdCompressorOps.push(range);
|
|
1856
1896
|
}
|
|
1857
1897
|
else {
|
|
@@ -1885,7 +1925,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1885
1925
|
* Updates signal telemetry including emitting telemetry events.
|
|
1886
1926
|
*/
|
|
1887
1927
|
processSignalForTelemetry(envelope) {
|
|
1888
|
-
const { clientBroadcastSignalSequenceNumber } = envelope;
|
|
1928
|
+
const { clientBroadcastSignalSequenceNumber, contents: envelopeContents, address: envelopeAddress, } = envelope;
|
|
1889
1929
|
if (clientBroadcastSignalSequenceNumber === undefined) {
|
|
1890
1930
|
return;
|
|
1891
1931
|
}
|
|
@@ -1923,8 +1963,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1923
1963
|
};
|
|
1924
1964
|
// Only log `contents.type` when address is for container to avoid
|
|
1925
1965
|
// chance that contents type is customer data.
|
|
1926
|
-
if (
|
|
1927
|
-
details.contentsType =
|
|
1966
|
+
if (envelopeAddress === undefined) {
|
|
1967
|
+
details.contentsType = envelopeContents.type; // Type of signal that was received out of order.
|
|
1928
1968
|
}
|
|
1929
1969
|
this.mc.logger.sendTelemetryEvent({
|
|
1930
1970
|
eventName: "SignalOutOfOrder",
|
|
@@ -2005,8 +2045,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2005
2045
|
try {
|
|
2006
2046
|
checkpoint.rollback((message) => this.rollback(message.contents, message.localOpMetadata));
|
|
2007
2047
|
}
|
|
2008
|
-
catch (
|
|
2009
|
-
const error2 = (0, internal_7.wrapError)(
|
|
2048
|
+
catch (error_) {
|
|
2049
|
+
const error2 = (0, internal_7.wrapError)(error_, (message) => {
|
|
2010
2050
|
return internal_7.DataProcessingError.create(`RollbackError: ${message}`, "checkpointRollback", undefined);
|
|
2011
2051
|
});
|
|
2012
2052
|
this.closeFn(error2);
|
|
@@ -2117,8 +2157,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2117
2157
|
case messageTypes_js_1.ContainerMessageType.GC: {
|
|
2118
2158
|
return false;
|
|
2119
2159
|
}
|
|
2120
|
-
default:
|
|
2160
|
+
default: {
|
|
2121
2161
|
break;
|
|
2162
|
+
}
|
|
2122
2163
|
}
|
|
2123
2164
|
return true;
|
|
2124
2165
|
}
|
|
@@ -2147,7 +2188,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2147
2188
|
clientBroadcastSignalSequenceNumber;
|
|
2148
2189
|
}
|
|
2149
2190
|
// We should not track the round trip of a new signal in the case we are already tracking one.
|
|
2150
|
-
if (clientBroadcastSignalSequenceNumber %
|
|
2191
|
+
if (clientBroadcastSignalSequenceNumber % defaultTelemetrySignalSampleCount === 1 &&
|
|
2151
2192
|
this._signalTracking.roundTripSignalSequenceNumber === undefined) {
|
|
2152
2193
|
this._signalTracking.signalTimestamp = Date.now();
|
|
2153
2194
|
this._signalTracking.roundTripSignalSequenceNumber =
|
|
@@ -2213,6 +2254,12 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2213
2254
|
this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
|
|
2214
2255
|
return summarizeResult.summary;
|
|
2215
2256
|
}
|
|
2257
|
+
/**
|
|
2258
|
+
* Builds the Summary tree including all the channels and the container state.
|
|
2259
|
+
*
|
|
2260
|
+
* @remarks - Unfortunately, this function is accessed in a non-typesafe way by a legacy first-party partner,
|
|
2261
|
+
* so until we can provide a proper API for their scenario, we need to ensure this function doesn't change.
|
|
2262
|
+
*/
|
|
2216
2263
|
async summarizeInternal(fullTree, trackState, telemetryContext) {
|
|
2217
2264
|
const summarizeResult = await this.channelCollection.summarize(fullTree, trackState, telemetryContext);
|
|
2218
2265
|
// Wrap data store summaries in .channels subtree.
|
|
@@ -2293,8 +2340,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2293
2340
|
*/
|
|
2294
2341
|
deleteSweepReadyNodes(sweepReadyRoutes) {
|
|
2295
2342
|
const { dataStoreRoutes, blobManagerRoutes } = this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
|
|
2296
|
-
|
|
2297
|
-
|
|
2343
|
+
return [
|
|
2344
|
+
...this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes),
|
|
2345
|
+
...this.blobManager.deleteSweepReadyNodes(blobManagerRoutes),
|
|
2346
|
+
];
|
|
2298
2347
|
}
|
|
2299
2348
|
/**
|
|
2300
2349
|
* This is called to update objects that are tombstones.
|
|
@@ -2320,10 +2369,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2320
2369
|
* Returns the type of the GC node. Currently, there are nodes that belong to the root ("/"), data stores or
|
|
2321
2370
|
* blob manager.
|
|
2322
2371
|
*/
|
|
2372
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2323
2373
|
getNodeType(nodePath) {
|
|
2324
2374
|
if ((0, index_js_1.isBlobPath)(nodePath)) {
|
|
2375
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2325
2376
|
return index_js_2.GCNodeType.Blob;
|
|
2326
2377
|
}
|
|
2378
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2327
2379
|
return this.channelCollection.getGCNodeType(nodePath) ?? index_js_2.GCNodeType.Other;
|
|
2328
2380
|
}
|
|
2329
2381
|
/**
|
|
@@ -2337,13 +2389,19 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2337
2389
|
return ["_gcRoot"];
|
|
2338
2390
|
}
|
|
2339
2391
|
switch (this.getNodeType(nodePath)) {
|
|
2340
|
-
|
|
2392
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2393
|
+
case index_js_2.GCNodeType.Blob: {
|
|
2341
2394
|
return [index_js_1.blobManagerBasePath];
|
|
2395
|
+
}
|
|
2396
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2342
2397
|
case index_js_2.GCNodeType.DataStore:
|
|
2343
|
-
|
|
2398
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2399
|
+
case index_js_2.GCNodeType.SubDataStore: {
|
|
2344
2400
|
return this.channelCollection.getDataStorePackagePath(nodePath);
|
|
2345
|
-
|
|
2401
|
+
}
|
|
2402
|
+
default: {
|
|
2346
2403
|
(0, internal_2.assert)(false, 0x2de /* "Package path requested for unsupported node type." */);
|
|
2404
|
+
}
|
|
2347
2405
|
}
|
|
2348
2406
|
}
|
|
2349
2407
|
/**
|
|
@@ -2405,8 +2463,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2405
2463
|
* op processing, updating SummarizerNode state tracking, and garbage collection.
|
|
2406
2464
|
* @param options - options controlling how the summary is generated or submitted
|
|
2407
2465
|
*/
|
|
2466
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2408
2467
|
async submitSummary(options) {
|
|
2409
|
-
const { fullTree = false, finalAttempt = false, summaryLogger, latestSummaryRefSeqNum, } = options;
|
|
2468
|
+
const { cancellationToken, fullTree = false, finalAttempt = false, summaryLogger, latestSummaryRefSeqNum, } = options;
|
|
2410
2469
|
// The summary number for this summary. This will be updated during the summary process, so get it now and
|
|
2411
2470
|
// use it for all events logged during this summary.
|
|
2412
2471
|
const summaryNumber = this.nextSummaryNumber;
|
|
@@ -2490,7 +2549,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2490
2549
|
eventName: "LatestSummaryRefSeqNumMismatch",
|
|
2491
2550
|
details: {
|
|
2492
2551
|
...startSummaryResult,
|
|
2493
|
-
mismatchNumbers:
|
|
2552
|
+
mismatchNumbers: [...startSummaryResult.mismatchNumbers],
|
|
2494
2553
|
},
|
|
2495
2554
|
});
|
|
2496
2555
|
if (shouldValidatePreSummaryState && !finalAttempt) {
|
|
@@ -2510,7 +2569,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2510
2569
|
// summarizer to reconnect in the future.
|
|
2511
2570
|
// Also checking for cancellation is a must as summary process may be abandoned for other reasons,
|
|
2512
2571
|
// like loss of connectivity for main (interactive) client.
|
|
2513
|
-
if (
|
|
2572
|
+
if (cancellationToken.cancelled) {
|
|
2514
2573
|
return { continue: false, error: "disconnected" };
|
|
2515
2574
|
}
|
|
2516
2575
|
// That said, we rely on submitSystemMessage() that today only works in connected state.
|
|
@@ -2623,7 +2682,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2623
2682
|
};
|
|
2624
2683
|
let handle;
|
|
2625
2684
|
try {
|
|
2626
|
-
handle = await this.storage.uploadSummaryWithContext(
|
|
2685
|
+
handle = await this.storage.uploadSummaryWithContext(summaryTree, summaryContext);
|
|
2627
2686
|
}
|
|
2628
2687
|
catch (error) {
|
|
2629
2688
|
return {
|
|
@@ -2745,13 +2804,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2745
2804
|
return this.pendingMessagesCount !== 0;
|
|
2746
2805
|
}
|
|
2747
2806
|
updateDocumentDirtyState(dirty) {
|
|
2748
|
-
if (this.attachState
|
|
2749
|
-
(0, internal_2.assert)(dirty, 0x3d2 /* Non-attached container is dirty */);
|
|
2750
|
-
}
|
|
2751
|
-
else {
|
|
2807
|
+
if (this.attachState === container_definitions_1.AttachState.Attached) {
|
|
2752
2808
|
// Other way is not true = see this.isContainerMessageDirtyable()
|
|
2753
2809
|
(0, internal_2.assert)(!dirty || this.hasPendingMessages(), 0x3d3 /* if doc is dirty, there has to be pending ops */);
|
|
2754
2810
|
}
|
|
2811
|
+
else {
|
|
2812
|
+
(0, internal_2.assert)(dirty, 0x3d2 /* Non-attached container is dirty */);
|
|
2813
|
+
}
|
|
2755
2814
|
if (this.dirtyContainer === dirty) {
|
|
2756
2815
|
return;
|
|
2757
2816
|
}
|
|
@@ -2813,7 +2872,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2813
2872
|
// on this callback to do actual sending.
|
|
2814
2873
|
const schemaChangeMessage = this.documentsSchemaController.maybeSendSchemaMessage();
|
|
2815
2874
|
if (schemaChangeMessage) {
|
|
2816
|
-
this.logger.sendTelemetryEvent({
|
|
2875
|
+
this.mc.logger.sendTelemetryEvent({
|
|
2817
2876
|
eventName: "SchemaChangeProposal",
|
|
2818
2877
|
refSeq: schemaChangeMessage.refSeq,
|
|
2819
2878
|
version: schemaChangeMessage.version,
|
|
@@ -2865,6 +2924,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2865
2924
|
return;
|
|
2866
2925
|
}
|
|
2867
2926
|
this.flushTaskExists = true;
|
|
2927
|
+
// TODO: hoist this out of the function scope to save unnecessary allocations
|
|
2928
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping -- Separate `flush` method already exists in outer scope
|
|
2868
2929
|
const flush = () => {
|
|
2869
2930
|
this.flushTaskExists = false;
|
|
2870
2931
|
try {
|
|
@@ -2875,22 +2936,25 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2875
2936
|
}
|
|
2876
2937
|
};
|
|
2877
2938
|
switch (this.flushMode) {
|
|
2878
|
-
case internal_5.FlushMode.TurnBased:
|
|
2939
|
+
case internal_5.FlushMode.TurnBased: {
|
|
2879
2940
|
// When in TurnBased flush mode the runtime will buffer operations in the current turn and send them as a single
|
|
2880
2941
|
// batch at the end of the turn
|
|
2881
2942
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
2882
2943
|
Promise.resolve().then(flush);
|
|
2883
2944
|
break;
|
|
2945
|
+
}
|
|
2884
2946
|
// FlushModeExperimental is experimental and not exposed directly in the runtime APIs
|
|
2885
|
-
case internal_5.FlushModeExperimental.Async:
|
|
2947
|
+
case internal_5.FlushModeExperimental.Async: {
|
|
2886
2948
|
// When in Async flush mode, the runtime will accumulate all operations across JS turns and send them as a single
|
|
2887
2949
|
// batch when all micro-tasks are complete.
|
|
2888
2950
|
// Compared to TurnBased, this flush mode will capture more ops into the same batch.
|
|
2889
2951
|
setTimeout(flush, 0);
|
|
2890
2952
|
break;
|
|
2891
|
-
|
|
2953
|
+
}
|
|
2954
|
+
default: {
|
|
2892
2955
|
(0, internal_2.assert)(this._orderSequentiallyCalls > 0, 0x587 /* Unreachable unless running under orderSequentially */);
|
|
2893
2956
|
break;
|
|
2957
|
+
}
|
|
2894
2958
|
}
|
|
2895
2959
|
}
|
|
2896
2960
|
submitSummaryMessage(contents, referenceSequenceNumber) {
|
|
@@ -2898,10 +2962,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2898
2962
|
(0, internal_2.assert)(this.connected, 0x133 /* "Container disconnected when trying to submit system message" */);
|
|
2899
2963
|
// System message should not be sent in the middle of the batch.
|
|
2900
2964
|
(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);
|
|
2965
|
+
return this.submitSummaryFn(contents, referenceSequenceNumber);
|
|
2905
2966
|
}
|
|
2906
2967
|
/**
|
|
2907
2968
|
* Throw an error if the runtime is closed. Methods that are expected to potentially
|
|
@@ -2941,15 +3002,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2941
3002
|
* @param localOpMetadata - The local metadata associated with the original message.
|
|
2942
3003
|
*/
|
|
2943
3004
|
reSubmitCore(message, localOpMetadata, opMetadata) {
|
|
2944
|
-
(0, internal_2.assert)(
|
|
3005
|
+
(0, internal_2.assert)(this._summarizer === undefined, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
|
|
2945
3006
|
switch (message.type) {
|
|
2946
3007
|
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
2947
3008
|
case messageTypes_js_1.ContainerMessageType.Attach:
|
|
2948
|
-
case messageTypes_js_1.ContainerMessageType.Alias:
|
|
3009
|
+
case messageTypes_js_1.ContainerMessageType.Alias: {
|
|
2949
3010
|
// For Operations, call resubmitDataStoreOp which will find the right store
|
|
2950
3011
|
// and trigger resubmission on it.
|
|
2951
3012
|
this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
|
|
2952
3013
|
break;
|
|
3014
|
+
}
|
|
2953
3015
|
case messageTypes_js_1.ContainerMessageType.IdAllocation: {
|
|
2954
3016
|
// Allocation ops are never resubmitted/rebased. This is because they require special handling to
|
|
2955
3017
|
// avoid being submitted out of order. For example, if the pending state manager contained
|
|
@@ -2960,20 +3022,24 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2960
3022
|
// all pending IDs. The resubmitted allocation ops are then ignored here.
|
|
2961
3023
|
break;
|
|
2962
3024
|
}
|
|
2963
|
-
case messageTypes_js_1.ContainerMessageType.BlobAttach:
|
|
3025
|
+
case messageTypes_js_1.ContainerMessageType.BlobAttach: {
|
|
2964
3026
|
this.blobManager.reSubmit(opMetadata);
|
|
2965
3027
|
break;
|
|
2966
|
-
|
|
3028
|
+
}
|
|
3029
|
+
case messageTypes_js_1.ContainerMessageType.Rejoin: {
|
|
2967
3030
|
this.submit(message);
|
|
2968
3031
|
break;
|
|
2969
|
-
|
|
3032
|
+
}
|
|
3033
|
+
case messageTypes_js_1.ContainerMessageType.GC: {
|
|
2970
3034
|
this.submit(message);
|
|
2971
3035
|
break;
|
|
2972
|
-
|
|
3036
|
+
}
|
|
3037
|
+
case messageTypes_js_1.ContainerMessageType.DocumentSchemaChange: {
|
|
2973
3038
|
// There is no need to resend this message. Document schema controller will properly resend it again (if needed)
|
|
2974
3039
|
// on a first occasion (any ops sent after reconnect). There is a good chance, though, that it will not want to
|
|
2975
3040
|
// send any ops, as some other client already changed schema.
|
|
2976
3041
|
break;
|
|
3042
|
+
}
|
|
2977
3043
|
default: {
|
|
2978
3044
|
const error = getUnknownMessageTypeError(message.type, "reSubmitCore" /* codePath */);
|
|
2979
3045
|
this.closeFn(error);
|
|
@@ -2985,18 +3051,21 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2985
3051
|
// Need to parse from string for back-compat
|
|
2986
3052
|
const { type, contents } = this.parseLocalOpContent(content);
|
|
2987
3053
|
switch (type) {
|
|
2988
|
-
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp:
|
|
3054
|
+
case messageTypes_js_1.ContainerMessageType.FluidDataStoreOp: {
|
|
2989
3055
|
// For operations, call rollbackDataStoreOp which will find the right store
|
|
2990
3056
|
// and trigger rollback on it.
|
|
2991
3057
|
this.channelCollection.rollback(type, contents, localOpMetadata);
|
|
2992
3058
|
break;
|
|
2993
|
-
|
|
3059
|
+
}
|
|
3060
|
+
default: {
|
|
2994
3061
|
throw new Error(`Can't rollback ${type}`);
|
|
3062
|
+
}
|
|
2995
3063
|
}
|
|
2996
3064
|
}
|
|
2997
3065
|
/**
|
|
2998
3066
|
* Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck
|
|
2999
3067
|
*/
|
|
3068
|
+
// eslint-disable-next-line import/no-deprecated
|
|
3000
3069
|
async refreshLatestSummaryAck(options) {
|
|
3001
3070
|
const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
|
|
3002
3071
|
// proposalHandle is always passed from RunningSummarizer.
|
|
@@ -3066,15 +3135,16 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3066
3135
|
snapshotTree = snapshot.snapshotTree;
|
|
3067
3136
|
}
|
|
3068
3137
|
else {
|
|
3069
|
-
const versions = await this.storage.getVersions(
|
|
3138
|
+
const versions = await this.storage.getVersions(
|
|
3139
|
+
// eslint-disable-next-line unicorn/no-null
|
|
3140
|
+
null, 1, scenarioName, internal_3.FetchSource.noCache);
|
|
3070
3141
|
(0, internal_2.assert)(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
|
|
3071
3142
|
snapshotTree = await this.storage.getSnapshotTree(versions[0]);
|
|
3072
3143
|
(0, internal_2.assert)(!!snapshotTree, 0x138 /* "Failed to get snapshot from storage" */);
|
|
3073
3144
|
props.snapshotVersion = versions[0].id;
|
|
3074
3145
|
}
|
|
3075
3146
|
props.getSnapshotDuration = trace.trace().duration;
|
|
3076
|
-
const
|
|
3077
|
-
const snapshotRefSeq = await (0, internal_6.seqFromTree)(snapshotTree, readAndParseBlob);
|
|
3147
|
+
const snapshotRefSeq = await (0, internal_6.seqFromTree)(snapshotTree, this.readAndParseBlob);
|
|
3078
3148
|
props.snapshotRefSeq = snapshotRefSeq;
|
|
3079
3149
|
props.newerSnapshotPresent = snapshotRefSeq >= targetRefSeq;
|
|
3080
3150
|
perfEvent.end({ details: props });
|
|
@@ -3127,32 +3197,32 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
3127
3197
|
: internal_7.PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) => logAndReturnPendingState(event, getSyncState()));
|
|
3128
3198
|
}
|
|
3129
3199
|
summarizeOnDemand(options) {
|
|
3130
|
-
if (this.
|
|
3131
|
-
return this.
|
|
3132
|
-
}
|
|
3133
|
-
else if (this.summaryManager !== undefined) {
|
|
3134
|
-
return this.summaryManager.summarizeOnDemand(options);
|
|
3200
|
+
if (this._summarizer !== undefined) {
|
|
3201
|
+
return this._summarizer.summarizeOnDemand(options);
|
|
3135
3202
|
}
|
|
3136
|
-
else {
|
|
3203
|
+
else if (this.summaryManager === undefined) {
|
|
3137
3204
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
3138
3205
|
// disableSummaries is turned on. We are throwing instead of returning a failure here,
|
|
3139
3206
|
// because it is a misuse of the API rather than an expected failure.
|
|
3140
3207
|
throw new internal_7.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
3141
3208
|
}
|
|
3209
|
+
else {
|
|
3210
|
+
return this.summaryManager.summarizeOnDemand(options);
|
|
3211
|
+
}
|
|
3142
3212
|
}
|
|
3143
3213
|
enqueueSummarize(options) {
|
|
3144
|
-
if (this.
|
|
3145
|
-
return this.
|
|
3214
|
+
if (this._summarizer !== undefined) {
|
|
3215
|
+
return this._summarizer.enqueueSummarize(options);
|
|
3146
3216
|
}
|
|
3147
|
-
else if (this.summaryManager
|
|
3148
|
-
return this.summaryManager.enqueueSummarize(options);
|
|
3149
|
-
}
|
|
3150
|
-
else {
|
|
3217
|
+
else if (this.summaryManager === undefined) {
|
|
3151
3218
|
// If we're not the summarizer, and we don't have a summaryManager, we expect that
|
|
3152
3219
|
// generateSummaries is turned off. We are throwing instead of returning a failure here,
|
|
3153
3220
|
// because it is a misuse of the API rather than an expected failure.
|
|
3154
3221
|
throw new internal_7.UsageError(`Can't summarize, disableSummaries: ${this.summariesDisabled}`);
|
|
3155
3222
|
}
|
|
3223
|
+
else {
|
|
3224
|
+
return this.summaryManager.enqueueSummarize(options);
|
|
3225
|
+
}
|
|
3156
3226
|
}
|
|
3157
3227
|
/**
|
|
3158
3228
|
* Forms a function that will create and retrieve a Summarizer.
|