@fluidframework/container-runtime 2.0.0-internal.6.3.3 → 2.0.0-internal.7.0.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/CHANGELOG.md +111 -0
- package/dist/blobManager.d.ts +4 -3
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +35 -31
- package/dist/blobManager.js.map +1 -1
- package/dist/containerHandleContext.js +3 -3
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +21 -78
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +378 -412
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +9 -9
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +1 -3
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +54 -56
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreRegistry.js +3 -3
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts +1 -1
- package/dist/dataStores.js +3 -3
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerProxyBase.js +4 -4
- package/dist/deltaManagerProxyBase.js.map +1 -1
- package/dist/deltaManagerSummarizerProxy.js +6 -6
- package/dist/deltaManagerSummarizerProxy.js.map +1 -1
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +6 -3
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +19 -16
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +17 -17
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +14 -15
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +0 -9
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +1 -13
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +1 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +1 -4
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/gcUnreferencedStateTracker.js +3 -3
- package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/dist/gc/index.d.ts +2 -2
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +3 -4
- package/dist/gc/index.js.map +1 -1
- package/dist/id-compressor/appendOnlySortedMap.js.map +1 -1
- package/dist/id-compressor/idCompressor.js.map +1 -1
- package/dist/id-compressor/identifiers.d.ts +3 -3
- package/dist/id-compressor/identifiers.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +134 -0
- package/dist/messageTypes.d.ts.map +1 -0
- package/dist/messageTypes.js +29 -0
- package/dist/messageTypes.js.map +1 -0
- package/dist/opLifecycle/batchManager.js +6 -6
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +4 -3
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +0 -4
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +4 -2
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.js +3 -3
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +17 -3
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +38 -25
- 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 +4 -20
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +33 -45
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +3 -3
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +54 -54
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js +6 -6
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +1 -1
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +41 -39
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +2 -2
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +10 -8
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerClientElection.js +6 -6
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerHeuristics.js +9 -9
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +8 -8
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeUtils.js +3 -3
- package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +2 -2
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +14 -13
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +2 -2
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +21 -21
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +8 -5
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js +3 -0
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +3 -3
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +7 -7
- package/dist/summary/summaryManager.js.map +1 -1
- package/dist/throttler.js +16 -16
- package/dist/throttler.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/blobManager.d.ts +4 -3
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +36 -32
- package/lib/blobManager.js.map +1 -1
- package/lib/containerHandleContext.js +3 -3
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +21 -78
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +339 -375
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +9 -9
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +1 -3
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +54 -56
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreRegistry.js +3 -3
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts +1 -1
- package/lib/dataStores.js +4 -4
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerProxyBase.js +4 -4
- package/lib/deltaManagerProxyBase.js.map +1 -1
- package/lib/deltaManagerSummarizerProxy.js +6 -6
- package/lib/deltaManagerSummarizerProxy.js.map +1 -1
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +6 -3
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +19 -16
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +17 -17
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js +13 -14
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +0 -9
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +0 -11
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +1 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +1 -4
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/gcUnreferencedStateTracker.js +3 -3
- package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
- package/lib/gc/index.d.ts +2 -2
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +2 -2
- package/lib/gc/index.js.map +1 -1
- package/lib/id-compressor/appendOnlySortedMap.js.map +1 -1
- package/lib/id-compressor/idCompressor.js.map +1 -1
- package/lib/id-compressor/identifiers.d.ts +3 -3
- package/lib/id-compressor/identifiers.d.ts.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/messageTypes.d.ts +134 -0
- package/lib/messageTypes.d.ts.map +1 -0
- package/lib/messageTypes.js +26 -0
- package/lib/messageTypes.js.map +1 -0
- package/lib/opLifecycle/batchManager.js +6 -6
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +4 -3
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +0 -4
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +4 -2
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.js +1 -1
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +17 -3
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +37 -24
- 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 +4 -20
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +32 -44
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +3 -3
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +54 -54
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js +6 -6
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +1 -1
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +41 -39
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +2 -2
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +10 -8
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerClientElection.js +6 -6
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerHeuristics.js +9 -9
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +8 -8
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeUtils.js +3 -3
- package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +2 -2
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +14 -13
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +2 -2
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +21 -21
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +8 -5
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js +3 -0
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +3 -3
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +6 -6
- package/lib/summary/summaryManager.js.map +1 -1
- package/lib/throttler.js +16 -16
- package/lib/throttler.js.map +1 -1
- package/package.json +57 -22
- package/src/blobManager.ts +38 -28
- package/src/containerRuntime.ts +210 -278
- package/src/dataStore.ts +1 -1
- package/src/dataStoreContext.ts +4 -7
- package/src/dataStores.ts +4 -4
- package/src/gc/garbageCollection.md +53 -5
- package/src/gc/garbageCollection.ts +6 -3
- package/src/gc/gcDefinitions.ts +14 -27
- package/src/gc/gcEarlyAdoption.md +145 -0
- package/src/gc/gcHelpers.ts +0 -12
- package/src/gc/gcTelemetry.ts +1 -4
- package/src/gc/index.ts +2 -3
- package/src/index.ts +7 -4
- package/src/messageTypes.ts +225 -0
- package/src/opLifecycle/README.md +40 -40
- package/src/opLifecycle/definitions.ts +2 -1
- package/src/opLifecycle/opDecompressor.ts +0 -8
- package/src/opLifecycle/opGroupingManager.ts +7 -6
- package/src/opLifecycle/opSplitter.ts +2 -2
- package/src/opLifecycle/remoteMessageProcessor.ts +54 -33
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +30 -52
- package/src/summary/runningSummarizer.ts +4 -2
- package/src/summary/summarizer.ts +5 -3
- package/src/summary/summarizerNode/summarizerNode.ts +1 -1
- package/src/summary/summarizerTypes.ts +2 -1
- package/src/summary/summaryFormat.ts +3 -0
package/dist/containerRuntime.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -19,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
19
23
|
return result;
|
|
20
24
|
};
|
|
21
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
-
exports.ContainerRuntime = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.RuntimeMessage = exports.defaultPendingOpsRetryDelayMs = exports.defaultPendingOpsWaitTimeoutMs = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.InactiveResponseHeaderKey = exports.TombstoneResponseHeaderKey = exports.AllowInactiveRequestHeaderKey = exports.AllowTombstoneRequestHeaderKey = exports.RuntimeHeaders = exports.DefaultSummaryConfiguration =
|
|
26
|
+
exports.ContainerRuntime = exports.makeLegacySendBatchFn = exports.getDeviceSpec = exports.agentSchedulerId = exports.isRuntimeMessage = exports.RuntimeMessage = exports.defaultPendingOpsRetryDelayMs = exports.defaultPendingOpsWaitTimeoutMs = exports.CompressionAlgorithms = exports.defaultRuntimeHeaderData = exports.InactiveResponseHeaderKey = exports.TombstoneResponseHeaderKey = exports.AllowInactiveRequestHeaderKey = exports.AllowTombstoneRequestHeaderKey = exports.RuntimeHeaders = exports.DefaultSummaryConfiguration = void 0;
|
|
23
27
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
24
28
|
const core_utils_1 = require("@fluidframework/core-utils");
|
|
25
29
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
@@ -45,32 +49,12 @@ const batchTracker_1 = require("./batchTracker");
|
|
|
45
49
|
const scheduleManager_1 = require("./scheduleManager");
|
|
46
50
|
const opLifecycle_1 = require("./opLifecycle");
|
|
47
51
|
const deltaManagerSummarizerProxy_1 = require("./deltaManagerSummarizerProxy");
|
|
48
|
-
|
|
49
|
-
(function (ContainerMessageType) {
|
|
50
|
-
// An op to be delivered to store
|
|
51
|
-
ContainerMessageType["FluidDataStoreOp"] = "component";
|
|
52
|
-
// Creates a new store
|
|
53
|
-
ContainerMessageType["Attach"] = "attach";
|
|
54
|
-
// Chunked operation.
|
|
55
|
-
ContainerMessageType["ChunkedOp"] = "chunkedOp";
|
|
56
|
-
// Signifies that a blob has been attached and should not be garbage collected by storage
|
|
57
|
-
ContainerMessageType["BlobAttach"] = "blobAttach";
|
|
58
|
-
// Ties our new clientId to our old one on reconnect
|
|
59
|
-
ContainerMessageType["Rejoin"] = "rejoin";
|
|
60
|
-
// Sets the alias of a root data store
|
|
61
|
-
ContainerMessageType["Alias"] = "alias";
|
|
62
|
-
/**
|
|
63
|
-
* An op containing an IdRange of Ids allocated using the runtime's IdCompressor since
|
|
64
|
-
* the last allocation op was sent.
|
|
65
|
-
* See the [IdCompressor README](./id-compressor/README.md) for more details.
|
|
66
|
-
*/
|
|
67
|
-
ContainerMessageType["IdAllocation"] = "idAllocation";
|
|
68
|
-
})(ContainerMessageType = exports.ContainerMessageType || (exports.ContainerMessageType = {}));
|
|
52
|
+
const messageTypes_1 = require("./messageTypes");
|
|
69
53
|
/**
|
|
70
54
|
* Utility to implement compat behaviors given an unknown message type
|
|
71
55
|
* The parameters are typed to support compile-time enforcement of handling all known types/behaviors
|
|
72
56
|
*
|
|
73
|
-
* @param _unknownContainerRuntimeMessageType - Typed as
|
|
57
|
+
* @param _unknownContainerRuntimeMessageType - Typed as something unexpected, to ensure all known types have been
|
|
74
58
|
* handled before calling this function (e.g. in a switch statement).
|
|
75
59
|
* @param compatBehavior - Typed redundantly with CompatModeBehavior to ensure handling is added when updating that type
|
|
76
60
|
*/
|
|
@@ -78,6 +62,12 @@ function compatBehaviorAllowsMessageType(_unknownContainerRuntimeMessageType, co
|
|
|
78
62
|
// undefined defaults to same behavior as "FailToProcess"
|
|
79
63
|
return compatBehavior === "Ignore";
|
|
80
64
|
}
|
|
65
|
+
function prepareLocalContainerRuntimeIdAllocationMessageForTransit(message) {
|
|
66
|
+
// Remove the stashedState from the op if it's a stashed op
|
|
67
|
+
if ("stashedState" in message.contents) {
|
|
68
|
+
delete message.contents.stashedState;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
81
71
|
exports.DefaultSummaryConfiguration = {
|
|
82
72
|
state: "enabled",
|
|
83
73
|
minIdleTime: 0,
|
|
@@ -101,7 +91,7 @@ var RuntimeHeaders;
|
|
|
101
91
|
RuntimeHeaders["wait"] = "wait";
|
|
102
92
|
/** True if the request is coming from an IFluidHandle. */
|
|
103
93
|
RuntimeHeaders["viaHandle"] = "viaHandle";
|
|
104
|
-
})(RuntimeHeaders
|
|
94
|
+
})(RuntimeHeaders || (exports.RuntimeHeaders = RuntimeHeaders = {}));
|
|
105
95
|
/** True if a tombstoned object should be returned without erroring */
|
|
106
96
|
exports.AllowTombstoneRequestHeaderKey = "allowTombstone"; // Belongs in the enum above, but avoiding the breaking change
|
|
107
97
|
/** [IRRELEVANT IF throwOnInactiveLoad OPTION NOT SET] True if an inactive object should be returned without erroring */
|
|
@@ -122,7 +112,7 @@ exports.defaultRuntimeHeaderData = {
|
|
|
122
112
|
var CompressionAlgorithms;
|
|
123
113
|
(function (CompressionAlgorithms) {
|
|
124
114
|
CompressionAlgorithms["lz4"] = "lz4";
|
|
125
|
-
})(CompressionAlgorithms
|
|
115
|
+
})(CompressionAlgorithms || (exports.CompressionAlgorithms = CompressionAlgorithms = {}));
|
|
126
116
|
const maxConsecutiveReconnectsKey = "Fluid.ContainerRuntime.MaxConsecutiveReconnects";
|
|
127
117
|
const defaultFlushMode = runtime_definitions_1.FlushMode.TurnBased;
|
|
128
118
|
// The actual limit is 1Mb (socket.io and Kafka limits)
|
|
@@ -147,7 +137,7 @@ exports.defaultPendingOpsRetryDelayMs = 1000;
|
|
|
147
137
|
*/
|
|
148
138
|
const defaultCloseSummarizerDelayMs = 5000; // 5 seconds
|
|
149
139
|
/**
|
|
150
|
-
* @deprecated - use
|
|
140
|
+
* @deprecated - use ContainerRuntimeMessageType instead
|
|
151
141
|
*/
|
|
152
142
|
var RuntimeMessage;
|
|
153
143
|
(function (RuntimeMessage) {
|
|
@@ -158,7 +148,7 @@ var RuntimeMessage;
|
|
|
158
148
|
RuntimeMessage["Rejoin"] = "rejoin";
|
|
159
149
|
RuntimeMessage["Alias"] = "alias";
|
|
160
150
|
RuntimeMessage["Operation"] = "op";
|
|
161
|
-
})(RuntimeMessage
|
|
151
|
+
})(RuntimeMessage || (exports.RuntimeMessage = RuntimeMessage = {}));
|
|
162
152
|
/**
|
|
163
153
|
* @deprecated - please use version in driver-utils
|
|
164
154
|
*/
|
|
@@ -206,15 +196,227 @@ exports.makeLegacySendBatchFn = makeLegacySendBatchFn;
|
|
|
206
196
|
* It will define the store level mappings.
|
|
207
197
|
*/
|
|
208
198
|
class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
199
|
+
/**
|
|
200
|
+
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
201
|
+
*/
|
|
202
|
+
get IFluidRouter() {
|
|
203
|
+
return this;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* @deprecated - use loadRuntime instead.
|
|
207
|
+
* Load the stores from a snapshot and returns the runtime.
|
|
208
|
+
* @param context - Context of the container.
|
|
209
|
+
* @param registryEntries - Mapping to the stores.
|
|
210
|
+
* @param requestHandler - Request handlers for the container runtime
|
|
211
|
+
* @param runtimeOptions - Additional options to be passed to the runtime
|
|
212
|
+
* @param existing - (optional) When loading from an existing snapshot. Precedes context.existing if provided
|
|
213
|
+
* @param containerRuntimeCtor - (optional) Constructor to use to create the ContainerRuntime instance. This
|
|
214
|
+
* allows mixin classes to leverage this method to define their own async initializer.
|
|
215
|
+
*/
|
|
216
|
+
static async load(context, registryEntries, requestHandler, runtimeOptions = {}, containerScope = context.scope, existing, containerRuntimeCtor = ContainerRuntime) {
|
|
217
|
+
let existingFlag = true;
|
|
218
|
+
if (!existing) {
|
|
219
|
+
existingFlag = false;
|
|
220
|
+
}
|
|
221
|
+
return this.loadRuntime({
|
|
222
|
+
context,
|
|
223
|
+
registryEntries,
|
|
224
|
+
existing: existingFlag,
|
|
225
|
+
runtimeOptions,
|
|
226
|
+
containerScope,
|
|
227
|
+
containerRuntimeCtor,
|
|
228
|
+
requestHandler,
|
|
229
|
+
provideEntryPoint: () => {
|
|
230
|
+
throw new telemetry_utils_1.UsageError("ContainerRuntime.load is deprecated and should no longer be used");
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Load the stores from a snapshot and returns the runtime.
|
|
236
|
+
* @param params - An object housing the runtime properties:
|
|
237
|
+
* - context - Context of the container.
|
|
238
|
+
* - registryEntries - Mapping from data store types to their corresponding factories.
|
|
239
|
+
* - existing - Pass 'true' if loading from an existing snapshot.
|
|
240
|
+
* - requestHandler - (optional) Request handler for the request() method of the container runtime.
|
|
241
|
+
* Only relevant for back-compat while we remove the request() method and move fully to entryPoint as the main pattern.
|
|
242
|
+
* - runtimeOptions - Additional options to be passed to the runtime
|
|
243
|
+
* - containerScope - runtime services provided with context
|
|
244
|
+
* - containerRuntimeCtor - Constructor to use to create the ContainerRuntime instance.
|
|
245
|
+
* This allows mixin classes to leverage this method to define their own async initializer.
|
|
246
|
+
* - provideEntryPoint - Promise that resolves to an object which will act as entryPoint for the Container.
|
|
247
|
+
* This object should provide all the functionality that the Container is expected to provide to the loader layer.
|
|
248
|
+
*/
|
|
249
|
+
static async loadRuntime(params) {
|
|
250
|
+
const { context, registryEntries, existing, requestHandler, provideEntryPoint, runtimeOptions = {}, containerScope = {}, containerRuntimeCtor = ContainerRuntime, } = params;
|
|
251
|
+
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
252
|
+
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
253
|
+
const backCompatContext = context;
|
|
254
|
+
const passLogger = backCompatContext.taggedLogger ??
|
|
255
|
+
// eslint-disable-next-line import/no-deprecated
|
|
256
|
+
new telemetry_utils_1.TaggedLoggerAdapter(backCompatContext.logger);
|
|
257
|
+
const logger = (0, telemetry_utils_1.createChildLogger)({
|
|
258
|
+
logger: passLogger,
|
|
259
|
+
properties: {
|
|
260
|
+
all: {
|
|
261
|
+
runtimeVersion: packageVersion_1.pkgVersion,
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor = false, chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, enableGroupedBatching = false, } = runtimeOptions;
|
|
266
|
+
const registry = new dataStoreRegistry_1.FluidDataStoreRegistry(registryEntries);
|
|
267
|
+
const tryFetchBlob = async (blobName) => {
|
|
268
|
+
const blobId = context.baseSnapshot?.blobs[blobName];
|
|
269
|
+
if (context.baseSnapshot && blobId) {
|
|
270
|
+
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
271
|
+
// So once we release 0.40 container-defn package we can remove this check.
|
|
272
|
+
(0, core_utils_1.assert)(context.storage !== undefined, 0x1f5 /* "Attached state should have storage" */);
|
|
273
|
+
return (0, driver_utils_1.readAndParse)(context.storage, blobId);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const [chunks, metadata, electedSummarizerData, aliases, serializedIdCompressor] = await Promise.all([
|
|
277
|
+
tryFetchBlob(summary_1.chunksBlobName),
|
|
278
|
+
tryFetchBlob(summary_1.metadataBlobName),
|
|
279
|
+
tryFetchBlob(summary_1.electedSummarizerBlobName),
|
|
280
|
+
tryFetchBlob(summary_1.aliasBlobName),
|
|
281
|
+
tryFetchBlob(summary_1.idCompressorBlobName),
|
|
282
|
+
]);
|
|
283
|
+
// read snapshot blobs needed for BlobManager to load
|
|
284
|
+
const blobManagerSnapshot = await blobManager_1.BlobManager.load(context.baseSnapshot?.trees[summary_1.blobsTreeName], async (id) => {
|
|
285
|
+
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
286
|
+
// So once we release 0.40 container-defn package we can remove this check.
|
|
287
|
+
(0, core_utils_1.assert)(context.storage !== undefined, 0x256 /* "storage undefined in attached container" */);
|
|
288
|
+
return (0, driver_utils_1.readAndParse)(context.storage, id);
|
|
289
|
+
});
|
|
290
|
+
// Verify summary runtime sequence number matches protocol sequence number.
|
|
291
|
+
const runtimeSequenceNumber = metadata?.message?.sequenceNumber;
|
|
292
|
+
// When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
|
|
293
|
+
if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
|
|
294
|
+
const protocolSequenceNumber = context.deltaManager.initialSequenceNumber;
|
|
295
|
+
// Unless bypass is explicitly set, then take action when sequence numbers mismatch.
|
|
296
|
+
if (loadSequenceNumberVerification !== "bypass" &&
|
|
297
|
+
runtimeSequenceNumber !== protocolSequenceNumber) {
|
|
298
|
+
// "Load from summary, runtime metadata sequenceNumber !== initialSequenceNumber"
|
|
299
|
+
const error = new telemetry_utils_1.DataCorruptionError(
|
|
300
|
+
// pre-0.58 error message: SummaryMetadataMismatch
|
|
301
|
+
"Summary metadata mismatch", { runtimeVersion: packageVersion_1.pkgVersion, runtimeSequenceNumber, protocolSequenceNumber });
|
|
302
|
+
if (loadSequenceNumberVerification === "log") {
|
|
303
|
+
logger.sendErrorEvent({ eventName: "SequenceNumberMismatch" }, error);
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
context.closeFn(error);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const idCompressorEnabled = metadata?.idCompressorEnabled ?? runtimeOptions.enableRuntimeIdCompressor ?? false;
|
|
311
|
+
let idCompressor;
|
|
312
|
+
if (idCompressorEnabled) {
|
|
313
|
+
const { IdCompressor, createSessionId } = await Promise.resolve().then(() => __importStar(require("./id-compressor")));
|
|
314
|
+
idCompressor =
|
|
315
|
+
serializedIdCompressor !== undefined
|
|
316
|
+
? IdCompressor.deserialize(serializedIdCompressor, createSessionId())
|
|
317
|
+
: IdCompressor.create(logger);
|
|
318
|
+
}
|
|
319
|
+
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], {
|
|
320
|
+
summaryOptions,
|
|
321
|
+
gcOptions,
|
|
322
|
+
loadSequenceNumberVerification,
|
|
323
|
+
flushMode,
|
|
324
|
+
compressionOptions,
|
|
325
|
+
maxBatchSizeInBytes,
|
|
326
|
+
chunkSizeInBytes,
|
|
327
|
+
enableRuntimeIdCompressor,
|
|
328
|
+
enableOpReentryCheck,
|
|
329
|
+
enableGroupedBatching,
|
|
330
|
+
}, containerScope, logger, existing, blobManagerSnapshot, context.storage, idCompressor, provideEntryPoint, requestHandler, undefined);
|
|
331
|
+
// Apply stashed ops with a reference sequence number equal to the sequence number of the snapshot,
|
|
332
|
+
// or zero. This must be done before Container replays saved ops.
|
|
333
|
+
await runtime.pendingStateManager.applyStashedOpsAt(runtimeSequenceNumber ?? 0);
|
|
334
|
+
// Initialize the base state of the runtime before it's returned.
|
|
335
|
+
await runtime.initializeBaseState();
|
|
336
|
+
return runtime;
|
|
337
|
+
}
|
|
338
|
+
get clientId() {
|
|
339
|
+
return this._getClientId();
|
|
340
|
+
}
|
|
341
|
+
get storage() {
|
|
342
|
+
return this._storage;
|
|
343
|
+
}
|
|
344
|
+
get flushMode() {
|
|
345
|
+
return this._flushMode;
|
|
346
|
+
}
|
|
347
|
+
get scope() {
|
|
348
|
+
return this.containerScope;
|
|
349
|
+
}
|
|
350
|
+
get IFluidDataStoreRegistry() {
|
|
351
|
+
return this.registry;
|
|
352
|
+
}
|
|
353
|
+
get attachState() {
|
|
354
|
+
return this._getAttachState();
|
|
355
|
+
}
|
|
356
|
+
get IFluidHandleContext() {
|
|
357
|
+
return this.handleContext;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Invokes the given callback and expects that no ops are submitted
|
|
361
|
+
* until execution finishes. If an op is submitted, an error will be raised.
|
|
362
|
+
*
|
|
363
|
+
* Can be disabled by feature gate `Fluid.ContainerRuntime.DisableOpReentryCheck`
|
|
364
|
+
*
|
|
365
|
+
* @param callback - the callback to be invoked
|
|
366
|
+
*/
|
|
367
|
+
ensureNoDataModelChanges(callback) {
|
|
368
|
+
this.ensureNoDataModelChangesCalls++;
|
|
369
|
+
try {
|
|
370
|
+
return callback();
|
|
371
|
+
}
|
|
372
|
+
finally {
|
|
373
|
+
this.ensureNoDataModelChangesCalls--;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
get connected() {
|
|
377
|
+
return this._connected;
|
|
378
|
+
}
|
|
379
|
+
/** clientId of parent (non-summarizing) container that owns summarizer container */
|
|
380
|
+
get summarizerClientId() {
|
|
381
|
+
return this.summarizerClientElection?.electedClientId;
|
|
382
|
+
}
|
|
383
|
+
get disposed() {
|
|
384
|
+
return this._disposed;
|
|
385
|
+
}
|
|
386
|
+
get summarizer() {
|
|
387
|
+
(0, core_utils_1.assert)(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
|
|
388
|
+
return this._summarizer;
|
|
389
|
+
}
|
|
390
|
+
isSummariesDisabled() {
|
|
391
|
+
return this.summaryConfiguration.state === "disabled";
|
|
392
|
+
}
|
|
393
|
+
isHeuristicsDisabled() {
|
|
394
|
+
return this.summaryConfiguration.state === "disableHeuristics";
|
|
395
|
+
}
|
|
396
|
+
getMaxOpsSinceLastSummary() {
|
|
397
|
+
return this.summaryConfiguration.state !== "disabled"
|
|
398
|
+
? this.summaryConfiguration.maxOpsSinceLastSummary
|
|
399
|
+
: 0;
|
|
400
|
+
}
|
|
401
|
+
getInitialSummarizerDelayMs() {
|
|
402
|
+
// back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
|
|
403
|
+
// to ISummaryConfiguration in 0.60.
|
|
404
|
+
if (this.runtimeOptions.summaryOptions.initialSummarizerDelayMs !== undefined) {
|
|
405
|
+
return this.runtimeOptions.summaryOptions.initialSummarizerDelayMs;
|
|
406
|
+
}
|
|
407
|
+
return this.summaryConfiguration.state !== "disabled"
|
|
408
|
+
? this.summaryConfiguration.initialSummarizerDelayMs
|
|
409
|
+
: 0;
|
|
410
|
+
}
|
|
209
411
|
/**
|
|
210
412
|
* @internal
|
|
211
413
|
*/
|
|
212
|
-
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, idCompressor, requestHandler, summaryConfiguration = {
|
|
414
|
+
constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, idCompressor, provideEntryPoint, requestHandler, summaryConfiguration = {
|
|
213
415
|
// the defaults
|
|
214
416
|
...exports.DefaultSummaryConfiguration,
|
|
215
417
|
// the runtime configuration overrides
|
|
216
418
|
...runtimeOptions.summaryOptions?.summaryConfigOverrides,
|
|
217
|
-
}
|
|
419
|
+
}) {
|
|
218
420
|
super();
|
|
219
421
|
this.registry = registry;
|
|
220
422
|
this.runtimeOptions = runtimeOptions;
|
|
@@ -401,10 +603,10 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
401
603
|
if (baseSnapshot) {
|
|
402
604
|
this.summarizerNode.updateBaseSummaryState(baseSnapshot);
|
|
403
605
|
}
|
|
404
|
-
this.dataStores = new dataStores_1.DataStores((0, dataStores_1.getSummaryForDatastores)(baseSnapshot, metadata), this, (attachMsg) => this.submit({ type: ContainerMessageType.Attach, contents: attachMsg }), (id, createParam) => (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), (path) => this.garbageCollector.isNodeDeleted(path), new Map(dataStoreAliasMap));
|
|
606
|
+
this.dataStores = new dataStores_1.DataStores((0, dataStores_1.getSummaryForDatastores)(baseSnapshot, metadata), this, (attachMsg) => this.submit({ type: messageTypes_1.ContainerMessageType.Attach, contents: attachMsg }), (id, createParam) => (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), (path) => this.garbageCollector.isNodeDeleted(path), new Map(dataStoreAliasMap));
|
|
405
607
|
this.blobManager = new blobManager_1.BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (localId, blobId) => {
|
|
406
608
|
if (!this.disposed) {
|
|
407
|
-
this.submit({ type: ContainerMessageType.BlobAttach, contents: undefined }, undefined, {
|
|
609
|
+
this.submit({ type: messageTypes_1.ContainerMessageType.BlobAttach, contents: undefined }, undefined, {
|
|
408
610
|
localId,
|
|
409
611
|
blobId,
|
|
410
612
|
});
|
|
@@ -518,26 +720,6 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
518
720
|
this.summaryManager.start();
|
|
519
721
|
}
|
|
520
722
|
}
|
|
521
|
-
this.deltaManager.on("readonly", (readonly) => {
|
|
522
|
-
// we accumulate ops while being in read-only state.
|
|
523
|
-
// once user gets write permissions and we have active connection, flush all pending ops.
|
|
524
|
-
// Note that the inner (non-proxy) delta manager is needed here to get the readonly information.
|
|
525
|
-
(0, core_utils_1.assert)(readonly === this.innerDeltaManager.readOnlyInfo.readonly, 0x124 /* "inconsistent readonly property/event state" */);
|
|
526
|
-
// We need to be very careful with when we (re)send pending ops, to ensure that we only send ops
|
|
527
|
-
// when we either never send an op, or attempted to send it but we know for sure it was not
|
|
528
|
-
// sequenced by server and will never be sequenced (i.e. was lost)
|
|
529
|
-
// For loss of connection, we wait for our own "join" op and use it a a barrier to know all the
|
|
530
|
-
// ops that made it from previous connection, before switching clientId and raising "connected" event
|
|
531
|
-
// But with read-only permissions, if we transition between read-only and r/w states while on same
|
|
532
|
-
// connection, then we have no good signal to tell us when it's safe to send ops we accumulated while
|
|
533
|
-
// being in read-only state.
|
|
534
|
-
// For that reason, we support getting to read-only state only when disconnected. This ensures that we
|
|
535
|
-
// can rely on same safety mechanism and resend ops only when we establish new connection.
|
|
536
|
-
// This is applicable for read-only permissions (event is raised before connection is properly registered),
|
|
537
|
-
// but it's an extra requirement for Container.forceReadonly() API
|
|
538
|
-
(0, core_utils_1.assert)(!readonly || !this.connected, 0x125 /* "Unsafe to transition to read-only state!" */);
|
|
539
|
-
this.replayPendingStates();
|
|
540
|
-
});
|
|
541
723
|
// logging hardware telemetry
|
|
542
724
|
logger.sendTelemetryEvent({
|
|
543
725
|
eventName: "DeviceSpec",
|
|
@@ -571,233 +753,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
571
753
|
(0, core_utils_1.assert)(this._summarizer !== undefined, 0x5bf /* Summarizer object is undefined in a summarizer client */);
|
|
572
754
|
return this._summarizer;
|
|
573
755
|
}
|
|
574
|
-
return
|
|
575
|
-
});
|
|
576
|
-
}
|
|
577
|
-
/**
|
|
578
|
-
* @deprecated - Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
|
|
579
|
-
*/
|
|
580
|
-
get IFluidRouter() {
|
|
581
|
-
return this;
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* @deprecated - use loadRuntime instead.
|
|
585
|
-
* Load the stores from a snapshot and returns the runtime.
|
|
586
|
-
* @param context - Context of the container.
|
|
587
|
-
* @param registryEntries - Mapping to the stores.
|
|
588
|
-
* @param requestHandler - Request handlers for the container runtime
|
|
589
|
-
* @param runtimeOptions - Additional options to be passed to the runtime
|
|
590
|
-
* @param existing - (optional) When loading from an existing snapshot. Precedes context.existing if provided
|
|
591
|
-
* @param containerRuntimeCtor - (optional) Constructor to use to create the ContainerRuntime instance. This
|
|
592
|
-
* allows mixin classes to leverage this method to define their own async initializer.
|
|
593
|
-
*/
|
|
594
|
-
static async load(context, registryEntries, requestHandler, runtimeOptions = {}, containerScope = context.scope, existing, containerRuntimeCtor = ContainerRuntime) {
|
|
595
|
-
let existingFlag = true;
|
|
596
|
-
if (!existing) {
|
|
597
|
-
existingFlag = false;
|
|
598
|
-
}
|
|
599
|
-
return this.loadRuntime({
|
|
600
|
-
context,
|
|
601
|
-
registryEntries,
|
|
602
|
-
existing: existingFlag,
|
|
603
|
-
requestHandler,
|
|
604
|
-
runtimeOptions,
|
|
605
|
-
containerScope,
|
|
606
|
-
containerRuntimeCtor,
|
|
607
|
-
});
|
|
608
|
-
}
|
|
609
|
-
/**
|
|
610
|
-
* Load the stores from a snapshot and returns the runtime.
|
|
611
|
-
* @param params - An object housing the runtime properties:
|
|
612
|
-
* - context - Context of the container.
|
|
613
|
-
* - registryEntries - Mapping from data store types to their corresponding factories.
|
|
614
|
-
* - existing - Pass 'true' if loading from an existing snapshot.
|
|
615
|
-
* - requestHandler - (optional) Request handler for the request() method of the container runtime.
|
|
616
|
-
* Only relevant for back-compat while we remove the request() method and move fully to entryPoint as the main pattern.
|
|
617
|
-
* - runtimeOptions - Additional options to be passed to the runtime
|
|
618
|
-
* - containerScope - runtime services provided with context
|
|
619
|
-
* - containerRuntimeCtor - Constructor to use to create the ContainerRuntime instance.
|
|
620
|
-
* This allows mixin classes to leverage this method to define their own async initializer.
|
|
621
|
-
* - initializeEntryPoint - Promise that resolves to an object which will act as entryPoint for the Container.
|
|
622
|
-
* This object should provide all the functionality that the Container is expected to provide to the loader layer.
|
|
623
|
-
*/
|
|
624
|
-
static async loadRuntime(params) {
|
|
625
|
-
const { context, registryEntries, existing, requestHandler, runtimeOptions = {}, containerScope = {}, containerRuntimeCtor = ContainerRuntime, } = params;
|
|
626
|
-
const initializeEntryPoint = params.initializeEntryPoint ??
|
|
627
|
-
(async (containerRuntime) => ({
|
|
628
|
-
get IFluidRouter() {
|
|
629
|
-
return this;
|
|
630
|
-
},
|
|
631
|
-
async request(req) {
|
|
632
|
-
return containerRuntime.request(req);
|
|
633
|
-
},
|
|
634
|
-
}));
|
|
635
|
-
// If taggedLogger exists, use it. Otherwise, wrap the vanilla logger:
|
|
636
|
-
// back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
|
|
637
|
-
const backCompatContext = context;
|
|
638
|
-
const passLogger = backCompatContext.taggedLogger ??
|
|
639
|
-
// eslint-disable-next-line import/no-deprecated
|
|
640
|
-
new telemetry_utils_1.TaggedLoggerAdapter(backCompatContext.logger);
|
|
641
|
-
const logger = (0, telemetry_utils_1.createChildLogger)({
|
|
642
|
-
logger: passLogger,
|
|
643
|
-
properties: {
|
|
644
|
-
all: {
|
|
645
|
-
runtimeVersion: packageVersion_1.pkgVersion,
|
|
646
|
-
},
|
|
647
|
-
},
|
|
648
|
-
});
|
|
649
|
-
const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor = false, chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, enableGroupedBatching = false, } = runtimeOptions;
|
|
650
|
-
const registry = new dataStoreRegistry_1.FluidDataStoreRegistry(registryEntries);
|
|
651
|
-
const tryFetchBlob = async (blobName) => {
|
|
652
|
-
const blobId = context.baseSnapshot?.blobs[blobName];
|
|
653
|
-
if (context.baseSnapshot && blobId) {
|
|
654
|
-
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
655
|
-
// So once we release 0.40 container-defn package we can remove this check.
|
|
656
|
-
(0, core_utils_1.assert)(context.storage !== undefined, 0x1f5 /* "Attached state should have storage" */);
|
|
657
|
-
return (0, driver_utils_1.readAndParse)(context.storage, blobId);
|
|
658
|
-
}
|
|
659
|
-
};
|
|
660
|
-
const [chunks, metadata, electedSummarizerData, aliases, serializedIdCompressor] = await Promise.all([
|
|
661
|
-
tryFetchBlob(summary_1.chunksBlobName),
|
|
662
|
-
tryFetchBlob(summary_1.metadataBlobName),
|
|
663
|
-
tryFetchBlob(summary_1.electedSummarizerBlobName),
|
|
664
|
-
tryFetchBlob(summary_1.aliasBlobName),
|
|
665
|
-
tryFetchBlob(summary_1.idCompressorBlobName),
|
|
666
|
-
]);
|
|
667
|
-
// read snapshot blobs needed for BlobManager to load
|
|
668
|
-
const blobManagerSnapshot = await blobManager_1.BlobManager.load(context.baseSnapshot?.trees[summary_1.blobsTreeName], async (id) => {
|
|
669
|
-
// IContainerContext storage api return type still has undefined in 0.39 package version.
|
|
670
|
-
// So once we release 0.40 container-defn package we can remove this check.
|
|
671
|
-
(0, core_utils_1.assert)(context.storage !== undefined, 0x256 /* "storage undefined in attached container" */);
|
|
672
|
-
return (0, driver_utils_1.readAndParse)(context.storage, id);
|
|
756
|
+
return provideEntryPoint(this);
|
|
673
757
|
});
|
|
674
|
-
// Verify summary runtime sequence number matches protocol sequence number.
|
|
675
|
-
const runtimeSequenceNumber = metadata?.message?.sequenceNumber;
|
|
676
|
-
// When we load with pending state, we reuse an old snapshot so we don't expect these numbers to match
|
|
677
|
-
if (!context.pendingLocalState && runtimeSequenceNumber !== undefined) {
|
|
678
|
-
const protocolSequenceNumber = context.deltaManager.initialSequenceNumber;
|
|
679
|
-
// Unless bypass is explicitly set, then take action when sequence numbers mismatch.
|
|
680
|
-
if (loadSequenceNumberVerification !== "bypass" &&
|
|
681
|
-
runtimeSequenceNumber !== protocolSequenceNumber) {
|
|
682
|
-
// "Load from summary, runtime metadata sequenceNumber !== initialSequenceNumber"
|
|
683
|
-
const error = new telemetry_utils_1.DataCorruptionError(
|
|
684
|
-
// pre-0.58 error message: SummaryMetadataMismatch
|
|
685
|
-
"Summary metadata mismatch", { runtimeVersion: packageVersion_1.pkgVersion, runtimeSequenceNumber, protocolSequenceNumber });
|
|
686
|
-
if (loadSequenceNumberVerification === "log") {
|
|
687
|
-
logger.sendErrorEvent({ eventName: "SequenceNumberMismatch" }, error);
|
|
688
|
-
}
|
|
689
|
-
else {
|
|
690
|
-
context.closeFn(error);
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
const idCompressorEnabled = metadata?.idCompressorEnabled ?? runtimeOptions.enableRuntimeIdCompressor ?? false;
|
|
695
|
-
let idCompressor;
|
|
696
|
-
if (idCompressorEnabled) {
|
|
697
|
-
const { IdCompressor, createSessionId } = await Promise.resolve().then(() => __importStar(require("./id-compressor")));
|
|
698
|
-
idCompressor =
|
|
699
|
-
serializedIdCompressor !== undefined
|
|
700
|
-
? IdCompressor.deserialize(serializedIdCompressor, createSessionId())
|
|
701
|
-
: IdCompressor.create(logger);
|
|
702
|
-
}
|
|
703
|
-
const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], {
|
|
704
|
-
summaryOptions,
|
|
705
|
-
gcOptions,
|
|
706
|
-
loadSequenceNumberVerification,
|
|
707
|
-
flushMode,
|
|
708
|
-
compressionOptions,
|
|
709
|
-
maxBatchSizeInBytes,
|
|
710
|
-
chunkSizeInBytes,
|
|
711
|
-
enableRuntimeIdCompressor,
|
|
712
|
-
enableOpReentryCheck,
|
|
713
|
-
enableGroupedBatching,
|
|
714
|
-
}, containerScope, logger, existing, blobManagerSnapshot, context.storage, idCompressor, requestHandler, undefined, // summaryConfiguration
|
|
715
|
-
initializeEntryPoint);
|
|
716
|
-
await runtime.blobManager.processStashedChanges();
|
|
717
|
-
// It's possible to have ops with a reference sequence number of 0. Op sequence numbers start
|
|
718
|
-
// at 1, so we won't see a replayed saved op with a sequence number of 0.
|
|
719
|
-
await runtime.pendingStateManager.applyStashedOpsAt(0);
|
|
720
|
-
// Initialize the base state of the runtime before it's returned.
|
|
721
|
-
await runtime.initializeBaseState();
|
|
722
|
-
return runtime;
|
|
723
|
-
}
|
|
724
|
-
get clientId() {
|
|
725
|
-
return this._getClientId();
|
|
726
|
-
}
|
|
727
|
-
get storage() {
|
|
728
|
-
return this._storage;
|
|
729
|
-
}
|
|
730
|
-
/** @deprecated - The functionality is no longer exposed publicly */
|
|
731
|
-
get reSubmitFn() {
|
|
732
|
-
return (type, contents, localOpMetadata, opMetadata) => this.reSubmitCore({ type, contents }, localOpMetadata, opMetadata);
|
|
733
|
-
// Note: compatDetails is not included in this deprecated API
|
|
734
|
-
}
|
|
735
|
-
get flushMode() {
|
|
736
|
-
return this._flushMode;
|
|
737
|
-
}
|
|
738
|
-
get scope() {
|
|
739
|
-
return this.containerScope;
|
|
740
|
-
}
|
|
741
|
-
get IFluidDataStoreRegistry() {
|
|
742
|
-
return this.registry;
|
|
743
|
-
}
|
|
744
|
-
get attachState() {
|
|
745
|
-
return this._getAttachState();
|
|
746
|
-
}
|
|
747
|
-
get IFluidHandleContext() {
|
|
748
|
-
return this.handleContext;
|
|
749
|
-
}
|
|
750
|
-
/**
|
|
751
|
-
* Invokes the given callback and expects that no ops are submitted
|
|
752
|
-
* until execution finishes. If an op is submitted, an error will be raised.
|
|
753
|
-
*
|
|
754
|
-
* Can be disabled by feature gate `Fluid.ContainerRuntime.DisableOpReentryCheck`
|
|
755
|
-
*
|
|
756
|
-
* @param callback - the callback to be invoked
|
|
757
|
-
*/
|
|
758
|
-
ensureNoDataModelChanges(callback) {
|
|
759
|
-
this.ensureNoDataModelChangesCalls++;
|
|
760
|
-
try {
|
|
761
|
-
return callback();
|
|
762
|
-
}
|
|
763
|
-
finally {
|
|
764
|
-
this.ensureNoDataModelChangesCalls--;
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
get connected() {
|
|
768
|
-
return this._connected;
|
|
769
|
-
}
|
|
770
|
-
/** clientId of parent (non-summarizing) container that owns summarizer container */
|
|
771
|
-
get summarizerClientId() {
|
|
772
|
-
return this.summarizerClientElection?.electedClientId;
|
|
773
|
-
}
|
|
774
|
-
get disposed() {
|
|
775
|
-
return this._disposed;
|
|
776
|
-
}
|
|
777
|
-
get summarizer() {
|
|
778
|
-
(0, core_utils_1.assert)(this._summarizer !== undefined, 0x257 /* "This is not summarizing container" */);
|
|
779
|
-
return this._summarizer;
|
|
780
|
-
}
|
|
781
|
-
isSummariesDisabled() {
|
|
782
|
-
return this.summaryConfiguration.state === "disabled";
|
|
783
|
-
}
|
|
784
|
-
isHeuristicsDisabled() {
|
|
785
|
-
return this.summaryConfiguration.state === "disableHeuristics";
|
|
786
|
-
}
|
|
787
|
-
getMaxOpsSinceLastSummary() {
|
|
788
|
-
return this.summaryConfiguration.state !== "disabled"
|
|
789
|
-
? this.summaryConfiguration.maxOpsSinceLastSummary
|
|
790
|
-
: 0;
|
|
791
|
-
}
|
|
792
|
-
getInitialSummarizerDelayMs() {
|
|
793
|
-
// back-compat: initialSummarizerDelayMs was moved from ISummaryRuntimeOptions
|
|
794
|
-
// to ISummaryConfiguration in 0.60.
|
|
795
|
-
if (this.runtimeOptions.summaryOptions.initialSummarizerDelayMs !== undefined) {
|
|
796
|
-
return this.runtimeOptions.summaryOptions.initialSummarizerDelayMs;
|
|
797
|
-
}
|
|
798
|
-
return this.summaryConfiguration.state !== "disabled"
|
|
799
|
-
? this.summaryConfiguration.initialSummarizerDelayMs
|
|
800
|
-
: 0;
|
|
801
758
|
}
|
|
802
759
|
/**
|
|
803
760
|
* Initializes the state from the base snapshot this container runtime loaded from.
|
|
@@ -999,7 +956,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
999
956
|
// in their own batches before the originating batch is sent.
|
|
1000
957
|
// Therefore, receiving them while attempting to send the originating batch
|
|
1001
958
|
// does not mean that the container is making any progress.
|
|
1002
|
-
if (message?.type !== ContainerMessageType.ChunkedOp) {
|
|
959
|
+
if (message?.type !== messageTypes_1.ContainerMessageType.ChunkedOp) {
|
|
1003
960
|
this.consecutiveReconnects = 0;
|
|
1004
961
|
}
|
|
1005
962
|
}
|
|
@@ -1047,39 +1004,40 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1047
1004
|
* Parse an op's type and actual content from given serialized content
|
|
1048
1005
|
* ! Note: this format needs to be in-line with what is set in the "ContainerRuntime.submit(...)" method
|
|
1049
1006
|
*/
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1007
|
+
// TODO: markfields: confirm Local- versus Outbound- ContainerRuntimeMessage typing
|
|
1008
|
+
parseLocalOpContent(serializedContents) {
|
|
1009
|
+
(0, core_utils_1.assert)(serializedContents !== undefined, 0x6d5 /* content must be defined */);
|
|
1010
|
+
const message = JSON.parse(serializedContents);
|
|
1011
|
+
(0, core_utils_1.assert)(message.type !== undefined, 0x6d6 /* incorrect op content format */);
|
|
1012
|
+
return message;
|
|
1013
|
+
}
|
|
1014
|
+
async applyStashedOp(serializedOpContent) {
|
|
1057
1015
|
// Need to parse from string for back-compat
|
|
1058
|
-
const
|
|
1059
|
-
switch (type) {
|
|
1060
|
-
case ContainerMessageType.FluidDataStoreOp:
|
|
1061
|
-
return this.dataStores.applyStashedOp(contents);
|
|
1062
|
-
case ContainerMessageType.Attach:
|
|
1063
|
-
return this.dataStores.applyStashedAttachOp(contents);
|
|
1064
|
-
case ContainerMessageType.IdAllocation:
|
|
1016
|
+
const opContents = this.parseLocalOpContent(serializedOpContent);
|
|
1017
|
+
switch (opContents.type) {
|
|
1018
|
+
case messageTypes_1.ContainerMessageType.FluidDataStoreOp:
|
|
1019
|
+
return this.dataStores.applyStashedOp(opContents.contents);
|
|
1020
|
+
case messageTypes_1.ContainerMessageType.Attach:
|
|
1021
|
+
return this.dataStores.applyStashedAttachOp(opContents.contents);
|
|
1022
|
+
case messageTypes_1.ContainerMessageType.IdAllocation:
|
|
1065
1023
|
(0, core_utils_1.assert)(this.idCompressor !== undefined, 0x67b /* IdCompressor should be defined if enabled */);
|
|
1066
|
-
return this.applyStashedIdAllocationOp(contents);
|
|
1067
|
-
case ContainerMessageType.Alias:
|
|
1068
|
-
case ContainerMessageType.BlobAttach:
|
|
1024
|
+
return this.applyStashedIdAllocationOp(opContents.contents);
|
|
1025
|
+
case messageTypes_1.ContainerMessageType.Alias:
|
|
1026
|
+
case messageTypes_1.ContainerMessageType.BlobAttach:
|
|
1069
1027
|
return;
|
|
1070
|
-
case ContainerMessageType.ChunkedOp:
|
|
1028
|
+
case messageTypes_1.ContainerMessageType.ChunkedOp:
|
|
1071
1029
|
throw new Error("chunkedOp not expected here");
|
|
1072
|
-
case ContainerMessageType.Rejoin:
|
|
1030
|
+
case messageTypes_1.ContainerMessageType.Rejoin:
|
|
1073
1031
|
throw new Error("rejoin not expected here");
|
|
1074
1032
|
default: {
|
|
1075
1033
|
// This should be extremely rare for stashed ops.
|
|
1076
1034
|
// It would require a newer runtime stashing ops and then an older one applying them,
|
|
1077
1035
|
// e.g. if an app rolled back its container version
|
|
1078
|
-
const compatBehavior = compatDetails?.behavior;
|
|
1079
|
-
if (!compatBehaviorAllowsMessageType(type, compatBehavior)) {
|
|
1036
|
+
const compatBehavior = opContents.compatDetails?.behavior;
|
|
1037
|
+
if (!compatBehaviorAllowsMessageType(opContents.type, compatBehavior)) {
|
|
1080
1038
|
const error = telemetry_utils_1.DataProcessingError.create("Stashed runtime message of unknown type", "applyStashedOp", undefined /* sequencedMessage */, {
|
|
1081
1039
|
messageDetails: JSON.stringify({
|
|
1082
|
-
type,
|
|
1040
|
+
type: opContents.type,
|
|
1083
1041
|
compatBehavior,
|
|
1084
1042
|
}),
|
|
1085
1043
|
});
|
|
@@ -1098,6 +1056,23 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1098
1056
|
// Don't propagate "disconnected" event because we didn't propagate the previous "connected" event
|
|
1099
1057
|
return;
|
|
1100
1058
|
}
|
|
1059
|
+
// If there are stashed blobs in the pending state, we need to delay
|
|
1060
|
+
// propagation of the "connected" event until we have uploaded them to
|
|
1061
|
+
// ensure we don't submit ops referencing a blob that has not been uploaded
|
|
1062
|
+
const connecting = connected && !this._connected;
|
|
1063
|
+
if (connecting && this.blobManager.hasPendingStashedBlobs()) {
|
|
1064
|
+
(0, core_utils_1.assert)(!this.delayConnectClientId, 0x791 /* Connect event delay must be canceled before subsequent connect event */);
|
|
1065
|
+
(0, core_utils_1.assert)(!!clientId, 0x792 /* Must have clientId when connecting */);
|
|
1066
|
+
this.delayConnectClientId = clientId;
|
|
1067
|
+
this.blobManager.processStashedChanges().then(() => {
|
|
1068
|
+
// make sure we didn't reconnect before the promise resolved
|
|
1069
|
+
if (this.delayConnectClientId === clientId && !this.disposed) {
|
|
1070
|
+
this.delayConnectClientId = undefined;
|
|
1071
|
+
this.setConnectionStateCore(connected, clientId);
|
|
1072
|
+
}
|
|
1073
|
+
}, (error) => this.closeFn(error));
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1101
1076
|
this.setConnectionStateCore(connected, clientId);
|
|
1102
1077
|
}
|
|
1103
1078
|
setConnectionStateCore(connected, clientId) {
|
|
@@ -1150,18 +1125,33 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1150
1125
|
// or something different, like a system message.
|
|
1151
1126
|
const modernRuntimeMessage = messageArg.type === protocol_definitions_1.MessageType.Operation;
|
|
1152
1127
|
// Do shallow copy of message, as the processing flow will modify it.
|
|
1128
|
+
// There might be multiple container instances receiving the same message.
|
|
1129
|
+
// We do not need to make a deep copy. Each layer will just replace message.contents itself,
|
|
1130
|
+
// but will not modify the contents object (likely it will replace it on the message).
|
|
1153
1131
|
const messageCopy = { ...messageArg };
|
|
1154
1132
|
for (const message of this.remoteMessageProcessor.process(messageCopy)) {
|
|
1155
|
-
|
|
1133
|
+
if (modernRuntimeMessage) {
|
|
1134
|
+
this.processCore({
|
|
1135
|
+
// Cast it since we expect it to be this based on modernRuntimeMessage computation above.
|
|
1136
|
+
// There is nothing really ensuring that anytime original message.type is Operation that
|
|
1137
|
+
// the result messages will be so. In the end modern bool being true only directs to
|
|
1138
|
+
// throw error if ultimately unrecognized without compat details saying otherwise.
|
|
1139
|
+
message: message,
|
|
1140
|
+
local,
|
|
1141
|
+
modernRuntimeMessage,
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
else {
|
|
1145
|
+
// Unrecognized message will be ignored.
|
|
1146
|
+
this.processCore({ message, local, modernRuntimeMessage });
|
|
1147
|
+
}
|
|
1156
1148
|
}
|
|
1157
1149
|
}
|
|
1158
1150
|
/**
|
|
1159
1151
|
* Direct the message to the correct subsystem for processing, and implement other side effects
|
|
1160
|
-
* @param message - The unpacked message. Likely a ContainerRuntimeMessage, but could also be a system op
|
|
1161
|
-
* @param local - Did this client send the op?
|
|
1162
|
-
* @param modernRuntimeMessage - Does this appear like a current ContainerRuntimeMessage?
|
|
1163
1152
|
*/
|
|
1164
|
-
processCore(
|
|
1153
|
+
processCore(messageWithContext) {
|
|
1154
|
+
const { message, local } = messageWithContext;
|
|
1165
1155
|
// Surround the actual processing of the operation with messages to the schedule manager indicating
|
|
1166
1156
|
// the beginning and end. This allows it to emit appropriate events and/or pause the processing of new
|
|
1167
1157
|
// messages once a batch has been fully processed.
|
|
@@ -1169,16 +1159,18 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1169
1159
|
this._processedClientSequenceNumber = message.clientSequenceNumber;
|
|
1170
1160
|
try {
|
|
1171
1161
|
let localOpMetadata;
|
|
1172
|
-
if (local &&
|
|
1173
|
-
|
|
1162
|
+
if (local &&
|
|
1163
|
+
messageWithContext.modernRuntimeMessage &&
|
|
1164
|
+
message.type !== messageTypes_1.ContainerMessageType.ChunkedOp) {
|
|
1165
|
+
localOpMetadata = this.pendingStateManager.processPendingLocalMessage(messageWithContext.message);
|
|
1174
1166
|
}
|
|
1175
1167
|
// If there are no more pending messages after processing a local message,
|
|
1176
1168
|
// the document is no longer dirty.
|
|
1177
1169
|
if (!this.hasPendingMessages()) {
|
|
1178
1170
|
this.updateDocumentDirtyState(false);
|
|
1179
1171
|
}
|
|
1180
|
-
this.validateAndProcessRuntimeMessage(
|
|
1181
|
-
this.emit("op", message, modernRuntimeMessage);
|
|
1172
|
+
this.validateAndProcessRuntimeMessage(messageWithContext, localOpMetadata);
|
|
1173
|
+
this.emit("op", message, messageWithContext.modernRuntimeMessage);
|
|
1182
1174
|
this.scheduleManager.afterOpProcessing(undefined, message);
|
|
1183
1175
|
if (local) {
|
|
1184
1176
|
// If we have processed a local op, this means that the container is
|
|
@@ -1193,41 +1185,42 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1193
1185
|
}
|
|
1194
1186
|
}
|
|
1195
1187
|
/**
|
|
1196
|
-
* Assuming the given message is also a
|
|
1188
|
+
* Assuming the given message is also a TypedContainerRuntimeMessage,
|
|
1197
1189
|
* checks its type and dispatches the message to the appropriate handler in the runtime.
|
|
1198
|
-
* Throws a DataProcessingError if the message doesn't conform to
|
|
1190
|
+
* Throws a DataProcessingError if the message looks like but doesn't conform to a known TypedContainerRuntimeMessage type.
|
|
1199
1191
|
*/
|
|
1200
|
-
validateAndProcessRuntimeMessage(
|
|
1201
|
-
//
|
|
1202
|
-
const {
|
|
1203
|
-
switch (
|
|
1204
|
-
case ContainerMessageType.Attach:
|
|
1205
|
-
this.dataStores.processAttachMessage(message, local);
|
|
1192
|
+
validateAndProcessRuntimeMessage(messageWithContext, localOpMetadata) {
|
|
1193
|
+
// TODO: destructure message and modernRuntimeMessage once using typescript 5.2.2+
|
|
1194
|
+
const { local } = messageWithContext;
|
|
1195
|
+
switch (messageWithContext.message.type) {
|
|
1196
|
+
case messageTypes_1.ContainerMessageType.Attach:
|
|
1197
|
+
this.dataStores.processAttachMessage(messageWithContext.message, local);
|
|
1206
1198
|
break;
|
|
1207
|
-
case ContainerMessageType.Alias:
|
|
1208
|
-
this.dataStores.processAliasMessage(message, localOpMetadata, local);
|
|
1199
|
+
case messageTypes_1.ContainerMessageType.Alias:
|
|
1200
|
+
this.dataStores.processAliasMessage(messageWithContext.message, localOpMetadata, local);
|
|
1209
1201
|
break;
|
|
1210
|
-
case ContainerMessageType.FluidDataStoreOp:
|
|
1211
|
-
this.dataStores.processFluidDataStoreOp(message, local, localOpMetadata);
|
|
1202
|
+
case messageTypes_1.ContainerMessageType.FluidDataStoreOp:
|
|
1203
|
+
this.dataStores.processFluidDataStoreOp(messageWithContext.message, local, localOpMetadata);
|
|
1212
1204
|
break;
|
|
1213
|
-
case ContainerMessageType.BlobAttach:
|
|
1214
|
-
this.blobManager.processBlobAttachOp(message, local);
|
|
1205
|
+
case messageTypes_1.ContainerMessageType.BlobAttach:
|
|
1206
|
+
this.blobManager.processBlobAttachOp(messageWithContext.message, local);
|
|
1215
1207
|
break;
|
|
1216
|
-
case ContainerMessageType.IdAllocation:
|
|
1208
|
+
case messageTypes_1.ContainerMessageType.IdAllocation:
|
|
1217
1209
|
(0, core_utils_1.assert)(this.idCompressor !== undefined, 0x67c /* IdCompressor should be defined if enabled */);
|
|
1218
|
-
this.idCompressor.finalizeCreationRange(message.contents);
|
|
1210
|
+
this.idCompressor.finalizeCreationRange(messageWithContext.message.contents);
|
|
1219
1211
|
break;
|
|
1220
|
-
case ContainerMessageType.ChunkedOp:
|
|
1221
|
-
case ContainerMessageType.Rejoin:
|
|
1212
|
+
case messageTypes_1.ContainerMessageType.ChunkedOp:
|
|
1213
|
+
case messageTypes_1.ContainerMessageType.Rejoin:
|
|
1222
1214
|
break;
|
|
1223
1215
|
default: {
|
|
1224
1216
|
// If we didn't necessarily expect a runtime message type, then no worries - just return
|
|
1225
1217
|
// e.g. this case applies to system ops, or legacy ops that would have fallen into the above cases anyway.
|
|
1226
|
-
if (!
|
|
1218
|
+
if (!messageWithContext.modernRuntimeMessage) {
|
|
1227
1219
|
return;
|
|
1228
1220
|
}
|
|
1229
|
-
const compatBehavior = compatDetails?.behavior;
|
|
1230
|
-
if (!compatBehaviorAllowsMessageType(
|
|
1221
|
+
const compatBehavior = messageWithContext.message.compatDetails?.behavior;
|
|
1222
|
+
if (!compatBehaviorAllowsMessageType(messageWithContext.message.type, compatBehavior)) {
|
|
1223
|
+
const { message } = messageWithContext;
|
|
1231
1224
|
const error = telemetry_utils_1.DataProcessingError.create(
|
|
1232
1225
|
// Former assert 0x3ce
|
|
1233
1226
|
"Runtime message of unknown type", "OpProcessing", message, {
|
|
@@ -1305,6 +1298,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1305
1298
|
* @param wait - True if you want to wait for it.
|
|
1306
1299
|
* @deprecated - Use getAliasedDataStoreEntryPoint instead to get an aliased data store's entry point.
|
|
1307
1300
|
*/
|
|
1301
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1308
1302
|
async getRootDataStore(id, wait = true) {
|
|
1309
1303
|
return this.getRootDataStoreChannel(id, wait);
|
|
1310
1304
|
}
|
|
@@ -1369,8 +1363,8 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1369
1363
|
/**
|
|
1370
1364
|
* Returns the aliased data store's entryPoint, given the alias.
|
|
1371
1365
|
* @param alias - The alias for the data store.
|
|
1372
|
-
* @returns
|
|
1373
|
-
* data store has been assigned the given alias.
|
|
1366
|
+
* @returns The data store's entry point ({@link @fluidframework/core-interfaces#IFluidHandle}) if it exists and is aliased.
|
|
1367
|
+
* Returns undefined if no data store has been assigned the given alias.
|
|
1374
1368
|
*/
|
|
1375
1369
|
async getAliasedDataStoreEntryPoint(alias) {
|
|
1376
1370
|
await this.dataStores.waitIfPendingAlias(alias);
|
|
@@ -1437,13 +1431,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1437
1431
|
isContainerMessageDirtyable({ type, contents }) {
|
|
1438
1432
|
// For legacy purposes, exclude the old built-in AgentScheduler from dirty consideration as a special-case.
|
|
1439
1433
|
// Ultimately we should have no special-cases from the ContainerRuntime's perspective.
|
|
1440
|
-
if (type === ContainerMessageType.Attach) {
|
|
1434
|
+
if (type === messageTypes_1.ContainerMessageType.Attach) {
|
|
1441
1435
|
const attachMessage = contents;
|
|
1442
1436
|
if (attachMessage.id === exports.agentSchedulerId) {
|
|
1443
1437
|
return false;
|
|
1444
1438
|
}
|
|
1445
1439
|
}
|
|
1446
|
-
else if (type === ContainerMessageType.FluidDataStoreOp) {
|
|
1440
|
+
else if (type === messageTypes_1.ContainerMessageType.FluidDataStoreOp) {
|
|
1447
1441
|
const envelope = contents;
|
|
1448
1442
|
if (envelope.address === exports.agentSchedulerId) {
|
|
1449
1443
|
return false;
|
|
@@ -1609,7 +1603,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1609
1603
|
/**
|
|
1610
1604
|
* After GC has run and identified nodes that are sweep ready, this is called to delete the sweep ready nodes.
|
|
1611
1605
|
* @param sweepReadyRoutes - The routes of nodes that are sweep ready and should be deleted.
|
|
1612
|
-
* @returns
|
|
1606
|
+
* @returns The routes of nodes that were deleted.
|
|
1613
1607
|
*/
|
|
1614
1608
|
deleteSweepReadyNodes(sweepReadyRoutes) {
|
|
1615
1609
|
const { dataStoreRoutes, blobManagerRoutes } = this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
|
|
@@ -1671,7 +1665,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1671
1665
|
/**
|
|
1672
1666
|
* From a given list of routes, separate and return routes that belong to blob manager and data stores.
|
|
1673
1667
|
* @param routes - A list of routes that can belong to data stores or blob manager.
|
|
1674
|
-
* @returns
|
|
1668
|
+
* @returns Two route lists - One that contains routes for blob manager and another one that contains routes
|
|
1675
1669
|
* for data stores.
|
|
1676
1670
|
*/
|
|
1677
1671
|
getDataStoreAndBlobManagerRoutes(routes) {
|
|
@@ -1723,16 +1717,13 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
1723
1717
|
},
|
|
1724
1718
|
});
|
|
1725
1719
|
(0, core_utils_1.assert)(this.outbox.isEmpty, 0x3d1 /* Can't trigger summary in the middle of a batch */);
|
|
1720
|
+
// We close the summarizer and download a new snapshot and reload the container
|
|
1726
1721
|
let latestSnapshotVersionId;
|
|
1727
|
-
if (refreshLatestAck) {
|
|
1728
|
-
|
|
1722
|
+
if (refreshLatestAck === true) {
|
|
1723
|
+
return this.prefetchLatestSummaryThenClose((0, telemetry_utils_1.createChildLogger)({
|
|
1729
1724
|
logger: summaryNumberLogger,
|
|
1730
1725
|
properties: { all: { safeSummary: true } },
|
|
1731
1726
|
}));
|
|
1732
|
-
const latestSnapshotRefSeq = latestSnapshotInfo.latestSnapshotRefSeq;
|
|
1733
|
-
latestSnapshotVersionId = latestSnapshotInfo.latestSnapshotVersionId;
|
|
1734
|
-
// We might need to catch up to the latest summary's reference sequence number before pausing.
|
|
1735
|
-
await this.waitForDeltaManagerToCatchup(latestSnapshotRefSeq, summaryNumberLogger);
|
|
1736
1727
|
}
|
|
1737
1728
|
// If there are pending (unacked ops), the summary will not be eventual consistent and it may even be
|
|
1738
1729
|
// incorrect. So, wait for the container to be saved with a timeout. If the container is not saved
|
|
@@ -2052,21 +2043,21 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2052
2043
|
address: id,
|
|
2053
2044
|
contents,
|
|
2054
2045
|
};
|
|
2055
|
-
this.submit({ type: ContainerMessageType.FluidDataStoreOp, contents: envelope }, localOpMetadata);
|
|
2046
|
+
this.submit({ type: messageTypes_1.ContainerMessageType.FluidDataStoreOp, contents: envelope }, localOpMetadata);
|
|
2056
2047
|
}
|
|
2057
2048
|
submitDataStoreAliasOp(contents, localOpMetadata) {
|
|
2058
2049
|
const aliasMessage = contents;
|
|
2059
2050
|
if (!(0, dataStore_1.isDataStoreAliasMessage)(aliasMessage)) {
|
|
2060
2051
|
throw new telemetry_utils_1.UsageError("malformedDataStoreAliasMessage");
|
|
2061
2052
|
}
|
|
2062
|
-
this.submit({ type: ContainerMessageType.Alias, contents }, localOpMetadata);
|
|
2053
|
+
this.submit({ type: messageTypes_1.ContainerMessageType.Alias, contents }, localOpMetadata);
|
|
2063
2054
|
}
|
|
2064
2055
|
async uploadBlob(blob, signal) {
|
|
2065
2056
|
this.verifyNotClosed();
|
|
2066
2057
|
return this.blobManager.createBlob(blob, signal);
|
|
2067
2058
|
}
|
|
2068
2059
|
maybeSubmitIdAllocationOp(type) {
|
|
2069
|
-
if (type !== ContainerMessageType.IdAllocation) {
|
|
2060
|
+
if (type !== messageTypes_1.ContainerMessageType.IdAllocation) {
|
|
2070
2061
|
let idAllocationBatchMessage;
|
|
2071
2062
|
let idRange;
|
|
2072
2063
|
if (this.idCompressorEnabled) {
|
|
@@ -2077,7 +2068,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2077
2068
|
}
|
|
2078
2069
|
if (idRange !== undefined) {
|
|
2079
2070
|
const idAllocationMessage = {
|
|
2080
|
-
type: ContainerMessageType.IdAllocation,
|
|
2071
|
+
type: messageTypes_1.ContainerMessageType.IdAllocation,
|
|
2081
2072
|
contents: idRange,
|
|
2082
2073
|
};
|
|
2083
2074
|
idAllocationBatchMessage = {
|
|
@@ -2085,7 +2076,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2085
2076
|
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2086
2077
|
metadata: undefined,
|
|
2087
2078
|
localOpMetadata: this.idCompressor?.serialize(true),
|
|
2088
|
-
type: ContainerMessageType.IdAllocation,
|
|
2079
|
+
type: messageTypes_1.ContainerMessageType.IdAllocation,
|
|
2089
2080
|
};
|
|
2090
2081
|
}
|
|
2091
2082
|
if (idAllocationBatchMessage !== undefined) {
|
|
@@ -2142,11 +2133,11 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2142
2133
|
// Please note that this does not change file format, so it can be disabled in the future if this
|
|
2143
2134
|
// optimization no longer makes sense (for example, batch compression may make it less appealing).
|
|
2144
2135
|
if (this.currentlyBatching() &&
|
|
2145
|
-
type === ContainerMessageType.Attach &&
|
|
2136
|
+
type === messageTypes_1.ContainerMessageType.Attach &&
|
|
2146
2137
|
this.disableAttachReorder !== true) {
|
|
2147
2138
|
this.outbox.submitAttach(message);
|
|
2148
2139
|
}
|
|
2149
|
-
else if (type === ContainerMessageType.BlobAttach) {
|
|
2140
|
+
else if (type === messageTypes_1.ContainerMessageType.BlobAttach) {
|
|
2150
2141
|
// BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
|
|
2151
2142
|
this.outbox.submitBlobAttach(message);
|
|
2152
2143
|
}
|
|
@@ -2256,40 +2247,37 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2256
2247
|
}
|
|
2257
2248
|
reSubmit(message) {
|
|
2258
2249
|
// Need to parse from string for back-compat
|
|
2259
|
-
const containerRuntimeMessage = this.
|
|
2250
|
+
const containerRuntimeMessage = this.parseLocalOpContent(message.content);
|
|
2260
2251
|
this.reSubmitCore(containerRuntimeMessage, message.localOpMetadata, message.opMetadata);
|
|
2261
2252
|
}
|
|
2262
2253
|
/**
|
|
2263
2254
|
* Finds the right store and asks it to resubmit the message. This typically happens when we
|
|
2264
2255
|
* reconnect and there are pending messages.
|
|
2265
|
-
* @param message - The original
|
|
2256
|
+
* @param message - The original LocalContainerRuntimeMessage.
|
|
2266
2257
|
* @param localOpMetadata - The local metadata associated with the original message.
|
|
2267
2258
|
*/
|
|
2268
2259
|
reSubmitCore(message, localOpMetadata, opMetadata) {
|
|
2269
|
-
const contents = message.contents;
|
|
2270
2260
|
switch (message.type) {
|
|
2271
|
-
case ContainerMessageType.FluidDataStoreOp:
|
|
2261
|
+
case messageTypes_1.ContainerMessageType.FluidDataStoreOp:
|
|
2272
2262
|
// For Operations, call resubmitDataStoreOp which will find the right store
|
|
2273
2263
|
// and trigger resubmission on it.
|
|
2274
|
-
this.dataStores.resubmitDataStoreOp(contents, localOpMetadata);
|
|
2264
|
+
this.dataStores.resubmitDataStoreOp(message.contents, localOpMetadata);
|
|
2275
2265
|
break;
|
|
2276
|
-
case ContainerMessageType.Attach:
|
|
2277
|
-
case ContainerMessageType.Alias:
|
|
2266
|
+
case messageTypes_1.ContainerMessageType.Attach:
|
|
2267
|
+
case messageTypes_1.ContainerMessageType.Alias:
|
|
2278
2268
|
this.submit(message, localOpMetadata);
|
|
2279
2269
|
break;
|
|
2280
|
-
case ContainerMessageType.IdAllocation:
|
|
2281
|
-
|
|
2282
|
-
if (contents.stashedState !== undefined) {
|
|
2283
|
-
delete contents.stashedState;
|
|
2284
|
-
}
|
|
2270
|
+
case messageTypes_1.ContainerMessageType.IdAllocation: {
|
|
2271
|
+
prepareLocalContainerRuntimeIdAllocationMessageForTransit(message);
|
|
2285
2272
|
this.submit(message, localOpMetadata);
|
|
2286
2273
|
break;
|
|
2287
|
-
|
|
2274
|
+
}
|
|
2275
|
+
case messageTypes_1.ContainerMessageType.ChunkedOp:
|
|
2288
2276
|
throw new Error(`chunkedOp not expected here`);
|
|
2289
|
-
case ContainerMessageType.BlobAttach:
|
|
2277
|
+
case messageTypes_1.ContainerMessageType.BlobAttach:
|
|
2290
2278
|
this.blobManager.reSubmit(opMetadata);
|
|
2291
2279
|
break;
|
|
2292
|
-
case ContainerMessageType.Rejoin:
|
|
2280
|
+
case messageTypes_1.ContainerMessageType.Rejoin:
|
|
2293
2281
|
this.submit(message);
|
|
2294
2282
|
break;
|
|
2295
2283
|
default: {
|
|
@@ -2317,9 +2305,9 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2317
2305
|
}
|
|
2318
2306
|
rollback(content, localOpMetadata) {
|
|
2319
2307
|
// Need to parse from string for back-compat
|
|
2320
|
-
const { type, contents } = this.
|
|
2308
|
+
const { type, contents } = this.parseLocalOpContent(content);
|
|
2321
2309
|
switch (type) {
|
|
2322
|
-
case ContainerMessageType.FluidDataStoreOp:
|
|
2310
|
+
case messageTypes_1.ContainerMessageType.FluidDataStoreOp:
|
|
2323
2311
|
// For operations, call rollbackDataStoreOp which will find the right store
|
|
2324
2312
|
// and trigger rollback on it.
|
|
2325
2313
|
this.dataStores.rollbackDataStoreOp(contents, localOpMetadata);
|
|
@@ -2329,17 +2317,6 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2329
2317
|
throw new Error(`Can't rollback ${type}`);
|
|
2330
2318
|
}
|
|
2331
2319
|
}
|
|
2332
|
-
async waitForDeltaManagerToCatchup(latestSnapshotRefSeq, summaryLogger) {
|
|
2333
|
-
if (latestSnapshotRefSeq > this.deltaManager.lastSequenceNumber) {
|
|
2334
|
-
// We need to catch up to the latest summary's reference sequence number before proceeding.
|
|
2335
|
-
await telemetry_utils_1.PerformanceEvent.timedExecAsync(summaryLogger, {
|
|
2336
|
-
eventName: "WaitingForSeq",
|
|
2337
|
-
lastSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2338
|
-
targetSequenceNumber: latestSnapshotRefSeq,
|
|
2339
|
-
lastKnownSeqNumber: this.deltaManager.lastKnownSeqNumber,
|
|
2340
|
-
}, async () => waitForSeq(this.deltaManager, latestSnapshotRefSeq), { start: true, end: true, cancel: "error" });
|
|
2341
|
-
}
|
|
2342
|
-
}
|
|
2343
2320
|
/** Implementation of ISummarizerInternalsProvider.refreshLatestSummaryAck */
|
|
2344
2321
|
async refreshLatestSummaryAck(options) {
|
|
2345
2322
|
const { proposalHandle, ackHandle, summaryRefSeq, summaryLogger } = options;
|
|
@@ -2385,18 +2362,25 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2385
2362
|
await this.garbageCollector.refreshLatestSummary(result);
|
|
2386
2363
|
}
|
|
2387
2364
|
/**
|
|
2388
|
-
* Fetches the latest snapshot from storage
|
|
2389
|
-
*
|
|
2365
|
+
* Fetches the latest snapshot from storage to refresh the cache as a performance optimization and closes the
|
|
2366
|
+
* summarizer to reload from new state.
|
|
2390
2367
|
* @param summaryLogger - logger to use when fetching snapshot from storage
|
|
2391
|
-
* @returns
|
|
2368
|
+
* @returns a generic summarization error
|
|
2392
2369
|
*/
|
|
2393
|
-
async
|
|
2370
|
+
async prefetchLatestSummaryThenClose(summaryLogger) {
|
|
2394
2371
|
const readAndParseBlob = async (id) => (0, driver_utils_1.readAndParse)(this.storage, id);
|
|
2395
|
-
|
|
2372
|
+
// This is a performance optimization as the same parent is likely to be elected again, and would use its
|
|
2373
|
+
// cache to fetch the snapshot instead of the network.
|
|
2374
|
+
await this.fetchSnapshotFromStorage(summaryLogger, {
|
|
2396
2375
|
eventName: "RefreshLatestSummaryFromServerFetch",
|
|
2397
2376
|
}, readAndParseBlob, null);
|
|
2398
2377
|
await this.closeStaleSummarizer("RefreshLatestSummaryFromServerFetch");
|
|
2399
|
-
return {
|
|
2378
|
+
return {
|
|
2379
|
+
stage: "base",
|
|
2380
|
+
error: "summary state stale - Unsupported option 'refreshLatestAck'",
|
|
2381
|
+
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2382
|
+
minimumSequenceNumber: this.deltaManager.minimumSequenceNumber,
|
|
2383
|
+
};
|
|
2400
2384
|
}
|
|
2401
2385
|
async closeStaleSummarizer(codePath) {
|
|
2402
2386
|
this.mc.logger.sendTelemetryEvent({
|
|
@@ -2419,7 +2403,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2419
2403
|
return telemetry_utils_1.PerformanceEvent.timedExecAsync(logger, event, async (perfEvent) => {
|
|
2420
2404
|
const stats = {};
|
|
2421
2405
|
const trace = client_utils_1.Trace.start();
|
|
2422
|
-
const versions = await this.storage.getVersions(versionId, 1, "
|
|
2406
|
+
const versions = await this.storage.getVersions(versionId, 1, "prefetchLatestSummaryBeforeClose", versionId === null ? driver_definitions_1.FetchSource.noCache : undefined);
|
|
2423
2407
|
(0, core_utils_1.assert)(!!versions && !!versions[0], 0x137 /* "Failed to get version from storage" */);
|
|
2424
2408
|
stats.getVersionDuration = trace.trace().duration;
|
|
2425
2409
|
const maybeSnapshot = await this.storage.getSnapshotTree(versions[0]);
|
|
@@ -2447,15 +2431,17 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2447
2431
|
if (this._orderSequentiallyCalls !== 0) {
|
|
2448
2432
|
throw new telemetry_utils_1.UsageError("can't get state during orderSequentially");
|
|
2449
2433
|
}
|
|
2450
|
-
const pendingAttachmentBlobs = await this.blobManager.getPendingBlobs(waitBlobsToAttach);
|
|
2451
|
-
const pending = this.pendingStateManager.getLocalState();
|
|
2452
|
-
if (!pendingAttachmentBlobs && !this.hasPendingMessages()) {
|
|
2453
|
-
return; // no pending state to save
|
|
2454
|
-
}
|
|
2455
2434
|
// Flush pending batch.
|
|
2456
2435
|
// getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
|
|
2457
2436
|
// to close current batch.
|
|
2458
2437
|
this.flush();
|
|
2438
|
+
const pendingAttachmentBlobs = waitBlobsToAttach
|
|
2439
|
+
? await this.blobManager.attachAndGetPendingBlobs()
|
|
2440
|
+
: undefined;
|
|
2441
|
+
const pending = this.pendingStateManager.getLocalState();
|
|
2442
|
+
if (!pendingAttachmentBlobs && !this.hasPendingMessages()) {
|
|
2443
|
+
return; // no pending state to save
|
|
2444
|
+
}
|
|
2459
2445
|
const pendingState = {
|
|
2460
2446
|
pending,
|
|
2461
2447
|
pendingAttachmentBlobs,
|
|
@@ -2499,6 +2485,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2499
2485
|
* * Forms a function that will request a Summarizer.
|
|
2500
2486
|
* @param loaderRouter - the loader acting as an IFluidRouter
|
|
2501
2487
|
* */
|
|
2488
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2502
2489
|
formRequestSummarizerFn(loaderRouter) {
|
|
2503
2490
|
return async () => {
|
|
2504
2491
|
const request = {
|
|
@@ -2513,6 +2500,7 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2513
2500
|
},
|
|
2514
2501
|
url: "/_summarizer",
|
|
2515
2502
|
};
|
|
2503
|
+
// eslint-disable-next-line import/no-deprecated
|
|
2516
2504
|
const fluidObject = await (0, runtime_utils_1.requestFluidObject)(loaderRouter, request);
|
|
2517
2505
|
const summarizer = fluidObject.ISummarizer;
|
|
2518
2506
|
if (!summarizer) {
|
|
@@ -2538,26 +2526,4 @@ class ContainerRuntime extends client_utils_1.TypedEventEmitter {
|
|
|
2538
2526
|
}
|
|
2539
2527
|
}
|
|
2540
2528
|
exports.ContainerRuntime = ContainerRuntime;
|
|
2541
|
-
/**
|
|
2542
|
-
* Wait for a specific sequence number. Promise should resolve when we reach that number,
|
|
2543
|
-
* or reject if closed.
|
|
2544
|
-
*/
|
|
2545
|
-
const waitForSeq = async (deltaManager, targetSeq) => new Promise((resolve, reject) => {
|
|
2546
|
-
// TODO: remove cast to any when actual event is determined
|
|
2547
|
-
deltaManager.on("closed", reject);
|
|
2548
|
-
deltaManager.on("disposed", reject);
|
|
2549
|
-
// If we already reached target sequence number, simply resolve the promise.
|
|
2550
|
-
if (deltaManager.lastSequenceNumber >= targetSeq) {
|
|
2551
|
-
resolve();
|
|
2552
|
-
}
|
|
2553
|
-
else {
|
|
2554
|
-
const handleOp = (message) => {
|
|
2555
|
-
if (message.sequenceNumber >= targetSeq) {
|
|
2556
|
-
resolve();
|
|
2557
|
-
deltaManager.off("op", handleOp);
|
|
2558
|
-
}
|
|
2559
|
-
};
|
|
2560
|
-
deltaManager.on("op", handleOp);
|
|
2561
|
-
}
|
|
2562
|
-
});
|
|
2563
2529
|
//# sourceMappingURL=containerRuntime.js.map
|