@fluidframework/container-loader 2.0.0-dev-rc.1.0.0.232845 → 2.0.0-dev-rc.2.0.0.246488
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 +5 -6
- package/{.mocharc.js → .mocharc.cjs} +1 -1
- package/CHANGELOG.md +48 -0
- package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
- package/api-extractor-lint.json +1 -1
- package/api-extractor.json +1 -1
- package/api-report/container-loader.api.md +2 -2
- package/dist/attachment.d.ts +6 -7
- package/dist/attachment.d.ts.map +1 -1
- package/dist/attachment.js +8 -7
- package/dist/attachment.js.map +1 -1
- package/dist/audience.d.ts +9 -4
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +12 -6
- package/dist/audience.js.map +1 -1
- package/dist/connectionManager.d.ts +3 -3
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +20 -18
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionState.d.ts +1 -0
- package/dist/connectionState.d.ts.map +1 -1
- package/dist/connectionState.js +1 -0
- package/dist/connectionState.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +7 -7
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +32 -32
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container-loader-alpha.d.ts +1 -0
- package/dist/container-loader-beta.d.ts +3 -0
- package/dist/container-loader-public.d.ts +3 -0
- package/dist/container-loader-untrimmed.d.ts +4 -4
- package/dist/container.d.ts +11 -22
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +101 -194
- package/dist/container.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +2 -3
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +4 -10
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +3 -3
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts +5 -5
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +6 -6
- package/dist/deltaManager.js.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -11
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +2 -2
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +13 -17
- package/dist/loader.js.map +1 -1
- package/dist/location-redirection-utilities/index.d.ts +1 -1
- package/dist/location-redirection-utilities/index.d.ts.map +1 -1
- package/dist/location-redirection-utilities/index.js +3 -3
- package/dist/location-redirection-utilities/index.js.map +1 -1
- package/dist/package.json +3 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts +0 -1
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js +0 -3
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/quorum.d.ts.map +1 -1
- package/dist/quorum.js +4 -0
- package/dist/quorum.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts +0 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +0 -6
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/serializedStateManager.d.ts +44 -0
- package/dist/serializedStateManager.d.ts.map +1 -0
- package/dist/serializedStateManager.js +149 -0
- package/dist/serializedStateManager.js.map +1 -0
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/utils.d.ts +5 -6
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +10 -4
- package/dist/utils.js.map +1 -1
- package/lib/{attachment.d.mts → attachment.d.ts} +11 -8
- package/lib/attachment.d.ts.map +1 -0
- package/lib/{attachment.mjs → attachment.js} +11 -6
- package/lib/attachment.js.map +1 -0
- package/lib/{audience.d.mts → audience.d.ts} +14 -5
- package/lib/audience.d.ts.map +1 -0
- package/lib/{audience.mjs → audience.js} +14 -4
- package/lib/audience.js.map +1 -0
- package/lib/{catchUpMonitor.d.mts → catchUpMonitor.d.ts} +1 -1
- package/lib/catchUpMonitor.d.ts.map +1 -0
- package/lib/{catchUpMonitor.mjs → catchUpMonitor.js} +1 -1
- package/lib/catchUpMonitor.js.map +1 -0
- package/lib/{connectionManager.d.mts → connectionManager.d.ts} +4 -4
- package/lib/connectionManager.d.ts.map +1 -0
- package/lib/{connectionManager.mjs → connectionManager.js} +9 -7
- package/lib/connectionManager.js.map +1 -0
- package/lib/{connectionState.d.mts → connectionState.d.ts} +2 -1
- package/lib/connectionState.d.ts.map +1 -0
- package/lib/{connectionState.mjs → connectionState.js} +2 -1
- package/lib/connectionState.js.map +1 -0
- package/lib/{connectionStateHandler.d.mts → connectionStateHandler.d.ts} +8 -8
- package/lib/connectionStateHandler.d.ts.map +1 -0
- package/lib/{connectionStateHandler.mjs → connectionStateHandler.js} +3 -3
- package/lib/connectionStateHandler.js.map +1 -0
- package/lib/{container-loader-alpha.d.mts → container-loader-alpha.d.ts} +1 -0
- package/lib/{container-loader-beta.d.mts → container-loader-beta.d.ts} +3 -0
- package/lib/{container-loader-public.d.mts → container-loader-public.d.ts} +3 -0
- package/lib/{container-loader-untrimmed.d.mts → container-loader-untrimmed.d.ts} +4 -4
- package/lib/{container.d.mts → container.d.ts} +12 -23
- package/lib/container.d.ts.map +1 -0
- package/lib/{container.mjs → container.js} +55 -148
- package/lib/container.js.map +1 -0
- package/lib/{containerContext.d.mts → containerContext.d.ts} +1 -1
- package/lib/containerContext.d.ts.map +1 -0
- package/lib/{containerContext.mjs → containerContext.js} +1 -1
- package/lib/containerContext.js.map +1 -0
- package/lib/{containerStorageAdapter.d.mts → containerStorageAdapter.d.ts} +3 -4
- package/lib/containerStorageAdapter.d.ts.map +1 -0
- package/lib/{containerStorageAdapter.mjs → containerStorageAdapter.js} +3 -9
- package/lib/containerStorageAdapter.js.map +1 -0
- package/lib/{contracts.d.mts → contracts.d.ts} +4 -4
- package/lib/contracts.d.ts.map +1 -0
- package/lib/{contracts.mjs → contracts.js} +1 -1
- package/lib/contracts.js.map +1 -0
- package/lib/{debugLogger.d.mts → debugLogger.d.ts} +1 -1
- package/lib/debugLogger.d.ts.map +1 -0
- package/lib/{debugLogger.mjs → debugLogger.js} +2 -1
- package/lib/debugLogger.js.map +1 -0
- package/lib/{deltaManager.d.mts → deltaManager.d.ts} +6 -6
- package/lib/deltaManager.d.ts.map +1 -0
- package/lib/{deltaManager.mjs → deltaManager.js} +4 -4
- package/lib/deltaManager.js.map +1 -0
- package/lib/{deltaQueue.d.mts → deltaQueue.d.ts} +1 -1
- package/lib/deltaQueue.d.ts.map +1 -0
- package/lib/{deltaQueue.mjs → deltaQueue.js} +1 -1
- package/lib/deltaQueue.js.map +1 -0
- package/lib/{disposal.d.mts → disposal.d.ts} +1 -1
- package/lib/disposal.d.ts.map +1 -0
- package/lib/{disposal.mjs → disposal.js} +1 -1
- package/lib/disposal.js.map +1 -0
- package/lib/{error.d.mts → error.d.ts} +1 -1
- package/lib/error.d.ts.map +1 -0
- package/lib/{error.mjs → error.js} +1 -1
- package/lib/error.js.map +1 -0
- package/lib/{index.d.mts → index.d.ts} +7 -7
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +10 -0
- package/lib/index.js.map +1 -0
- package/lib/{loader.d.mts → loader.d.ts} +3 -3
- package/lib/loader.d.ts.map +1 -0
- package/lib/{loader.mjs → loader.js} +7 -11
- package/lib/loader.js.map +1 -0
- package/lib/location-redirection-utilities/{index.mjs → index.d.ts} +2 -2
- package/lib/location-redirection-utilities/index.d.ts.map +1 -0
- package/lib/location-redirection-utilities/{index.d.mts → index.js} +2 -2
- package/lib/location-redirection-utilities/index.js.map +1 -0
- package/lib/location-redirection-utilities/{resolveWithLocationRedirection.d.mts → resolveWithLocationRedirection.d.ts} +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -0
- package/lib/location-redirection-utilities/{resolveWithLocationRedirection.mjs → resolveWithLocationRedirection.js} +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -0
- package/lib/{noopHeuristic.d.mts → noopHeuristic.d.ts} +1 -1
- package/lib/noopHeuristic.d.ts.map +1 -0
- package/lib/{noopHeuristic.mjs → noopHeuristic.js} +1 -1
- package/lib/noopHeuristic.js.map +1 -0
- package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
- package/lib/packageVersion.d.ts.map +1 -0
- package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
- package/lib/packageVersion.js.map +1 -0
- package/lib/{protocol.d.mts → protocol.d.ts} +1 -1
- package/lib/protocol.d.ts.map +1 -0
- package/lib/{protocol.mjs → protocol.js} +1 -1
- package/lib/protocol.js.map +1 -0
- package/lib/{protocolTreeDocumentStorageService.d.mts → protocolTreeDocumentStorageService.d.ts} +1 -2
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -0
- package/lib/{protocolTreeDocumentStorageService.mjs → protocolTreeDocumentStorageService.js} +1 -4
- package/lib/protocolTreeDocumentStorageService.js.map +1 -0
- package/lib/{quorum.d.mts → quorum.d.ts} +5 -1
- package/lib/quorum.d.ts.map +1 -0
- package/lib/{quorum.mjs → quorum.js} +5 -1
- package/lib/quorum.js.map +1 -0
- package/lib/{retriableDocumentStorageService.d.mts → retriableDocumentStorageService.d.ts} +1 -2
- package/lib/retriableDocumentStorageService.d.ts.map +1 -0
- package/lib/{retriableDocumentStorageService.mjs → retriableDocumentStorageService.js} +1 -7
- package/lib/retriableDocumentStorageService.js.map +1 -0
- package/lib/serializedStateManager.d.ts +44 -0
- package/lib/serializedStateManager.d.ts.map +1 -0
- package/lib/serializedStateManager.js +145 -0
- package/lib/serializedStateManager.js.map +1 -0
- package/lib/test/attachment.spec.js +380 -0
- package/lib/test/attachment.spec.js.map +1 -0
- package/lib/test/catchUpMonitor.spec.js +88 -0
- package/lib/test/catchUpMonitor.spec.js.map +1 -0
- package/lib/test/connectionManager.spec.js +201 -0
- package/lib/test/connectionManager.spec.js.map +1 -0
- package/lib/test/connectionStateHandler.spec.js +555 -0
- package/lib/test/connectionStateHandler.spec.js.map +1 -0
- package/lib/test/container.spec.js +64 -0
- package/lib/test/container.spec.js.map +1 -0
- package/lib/test/deltaManager.spec.js +405 -0
- package/lib/test/deltaManager.spec.js.map +1 -0
- package/lib/test/loader.spec.js +212 -0
- package/lib/test/loader.spec.js.map +1 -0
- package/lib/test/locationRedirectionTests.spec.js +44 -0
- package/lib/test/locationRedirectionTests.spec.js.map +1 -0
- package/lib/test/serializedStateManager.spec.js +148 -0
- package/lib/test/serializedStateManager.spec.js.map +1 -0
- package/lib/test/snapshotConversionTest.spec.js +79 -0
- package/lib/test/snapshotConversionTest.spec.js.map +1 -0
- package/lib/test/types/validateContainerLoaderPrevious.generated.js +38 -0
- package/lib/test/types/validateContainerLoaderPrevious.generated.js.map +1 -0
- package/lib/test/utils.spec.js +31 -0
- package/lib/test/utils.spec.js.map +1 -0
- package/lib/{utils.d.mts → utils.d.ts} +6 -7
- package/lib/utils.d.ts.map +1 -0
- package/lib/{utils.mjs → utils.js} +11 -5
- package/lib/utils.js.map +1 -0
- package/package.json +56 -62
- package/src/attachment.ts +16 -12
- package/src/audience.ts +10 -3
- package/src/connectionManager.ts +13 -9
- package/src/connectionState.ts +1 -0
- package/src/connectionStateHandler.ts +8 -7
- package/src/container.ts +96 -191
- package/src/containerStorageAdapter.ts +6 -14
- package/src/contracts.ts +3 -3
- package/src/debugLogger.ts +2 -2
- package/src/deltaManager.ts +8 -8
- package/src/error.ts +2 -2
- package/src/index.ts +6 -6
- package/src/loader.ts +8 -12
- package/src/location-redirection-utilities/index.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/protocolTreeDocumentStorageService.ts +0 -3
- package/src/quorum.ts +1 -0
- package/src/retriableDocumentStorageService.ts +0 -7
- package/src/serializedStateManager.ts +217 -0
- package/src/utils.ts +15 -10
- package/tsconfig.cjs.json +7 -0
- package/tsconfig.json +2 -5
- package/lib/attachment.d.mts.map +0 -1
- package/lib/attachment.mjs.map +0 -1
- package/lib/audience.d.mts.map +0 -1
- package/lib/audience.mjs.map +0 -1
- package/lib/catchUpMonitor.d.mts.map +0 -1
- package/lib/catchUpMonitor.mjs.map +0 -1
- package/lib/connectionManager.d.mts.map +0 -1
- package/lib/connectionManager.mjs.map +0 -1
- package/lib/connectionState.d.mts.map +0 -1
- package/lib/connectionState.mjs.map +0 -1
- package/lib/connectionStateHandler.d.mts.map +0 -1
- package/lib/connectionStateHandler.mjs.map +0 -1
- package/lib/container.d.mts.map +0 -1
- package/lib/container.mjs.map +0 -1
- package/lib/containerContext.d.mts.map +0 -1
- package/lib/containerContext.mjs.map +0 -1
- package/lib/containerStorageAdapter.d.mts.map +0 -1
- package/lib/containerStorageAdapter.mjs.map +0 -1
- package/lib/contracts.d.mts.map +0 -1
- package/lib/contracts.mjs.map +0 -1
- package/lib/debugLogger.d.mts.map +0 -1
- package/lib/debugLogger.mjs.map +0 -1
- package/lib/deltaManager.d.mts.map +0 -1
- package/lib/deltaManager.mjs.map +0 -1
- package/lib/deltaQueue.d.mts.map +0 -1
- package/lib/deltaQueue.mjs.map +0 -1
- package/lib/disposal.d.mts.map +0 -1
- package/lib/disposal.mjs.map +0 -1
- package/lib/error.d.mts.map +0 -1
- package/lib/error.mjs.map +0 -1
- package/lib/index.d.mts.map +0 -1
- package/lib/index.mjs +0 -10
- package/lib/index.mjs.map +0 -1
- package/lib/loader.d.mts.map +0 -1
- package/lib/loader.mjs.map +0 -1
- package/lib/location-redirection-utilities/index.d.mts.map +0 -1
- package/lib/location-redirection-utilities/index.mjs.map +0 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.mts.map +0 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.mjs.map +0 -1
- package/lib/noopHeuristic.d.mts.map +0 -1
- package/lib/noopHeuristic.mjs.map +0 -1
- package/lib/packageVersion.d.mts.map +0 -1
- package/lib/packageVersion.mjs.map +0 -1
- package/lib/protocol.d.mts.map +0 -1
- package/lib/protocol.mjs.map +0 -1
- package/lib/protocolTreeDocumentStorageService.d.mts.map +0 -1
- package/lib/protocolTreeDocumentStorageService.mjs.map +0 -1
- package/lib/quorum.d.mts.map +0 -1
- package/lib/quorum.mjs.map +0 -1
- package/lib/retriableDocumentStorageService.d.mts.map +0 -1
- package/lib/retriableDocumentStorageService.mjs.map +0 -1
- package/lib/utils.d.mts.map +0 -1
- package/lib/utils.mjs.map +0 -1
package/dist/container.js
CHANGED
|
@@ -17,21 +17,22 @@ const driver_utils_1 = require("@fluidframework/driver-utils");
|
|
|
17
17
|
const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
18
18
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
19
19
|
const structured_clone_1 = __importDefault(require("@ungap/structured-clone"));
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const
|
|
20
|
+
const audience_js_1 = require("./audience.js");
|
|
21
|
+
const containerContext_js_1 = require("./containerContext.js");
|
|
22
|
+
const contracts_js_1 = require("./contracts.js");
|
|
23
|
+
const deltaManager_js_1 = require("./deltaManager.js");
|
|
24
|
+
const loader_js_1 = require("./loader.js");
|
|
25
|
+
const packageVersion_js_1 = require("./packageVersion.js");
|
|
26
|
+
const containerStorageAdapter_js_1 = require("./containerStorageAdapter.js");
|
|
27
|
+
const connectionStateHandler_js_1 = require("./connectionStateHandler.js");
|
|
28
|
+
const utils_js_1 = require("./utils.js");
|
|
29
|
+
const quorum_js_1 = require("./quorum.js");
|
|
30
|
+
const noopHeuristic_js_1 = require("./noopHeuristic.js");
|
|
31
|
+
const connectionManager_js_1 = require("./connectionManager.js");
|
|
32
|
+
const connectionState_js_1 = require("./connectionState.js");
|
|
33
|
+
const protocol_js_1 = require("./protocol.js");
|
|
34
|
+
const attachment_js_1 = require("./attachment.js");
|
|
35
|
+
const serializedStateManager_js_1 = require("./serializedStateManager.js");
|
|
35
36
|
const detachedContainerRefSeqNumber = 0;
|
|
36
37
|
const dirtyContainerEvent = "dirty";
|
|
37
38
|
const savedContainerEvent = "saved";
|
|
@@ -73,8 +74,8 @@ async function waitContainerToCatchUp(container) {
|
|
|
73
74
|
// Waiting for "connected" state in either case gets us at least to our own Join op
|
|
74
75
|
// which is a reasonable approximation of "caught up"
|
|
75
76
|
const waitForOps = () => {
|
|
76
|
-
(0, core_utils_1.assert)(container.connectionState ===
|
|
77
|
-
container.connectionState ===
|
|
77
|
+
(0, core_utils_1.assert)(container.connectionState === connectionState_js_1.ConnectionState.CatchingUp ||
|
|
78
|
+
container.connectionState === connectionState_js_1.ConnectionState.Connected, 0x0cd /* "Container disconnected while waiting for ops!" */);
|
|
78
79
|
const hasCheckpointSequenceNumber = deltaManager.hasCheckpointSequenceNumber;
|
|
79
80
|
const connectionOpSeqNumber = deltaManager.lastKnownSeqNumber;
|
|
80
81
|
(0, core_utils_1.assert)(deltaManager.lastSequenceNumber <= connectionOpSeqNumber, 0x266 /* "lastKnownSeqNumber should never be below last processed sequence number" */);
|
|
@@ -96,7 +97,7 @@ async function waitContainerToCatchUp(container) {
|
|
|
96
97
|
// But that works only if service provides us checkPointSequenceNumber
|
|
97
98
|
// Our internal testing is based on R11S that does not, but almost all tests connect as "write" and
|
|
98
99
|
// use this function to catch up, so leveraging our own join op as a fence/barrier
|
|
99
|
-
if (container.connectionState ===
|
|
100
|
+
if (container.connectionState === connectionState_js_1.ConnectionState.Connected) {
|
|
100
101
|
waitForOps();
|
|
101
102
|
return;
|
|
102
103
|
}
|
|
@@ -105,15 +106,13 @@ async function waitContainerToCatchUp(container) {
|
|
|
105
106
|
waitForOps();
|
|
106
107
|
};
|
|
107
108
|
container.on(telemetry_utils_1.connectedEventName, callback);
|
|
108
|
-
if (container.connectionState ===
|
|
109
|
+
if (container.connectionState === connectionState_js_1.ConnectionState.Disconnected) {
|
|
109
110
|
container.connect();
|
|
110
111
|
}
|
|
111
112
|
});
|
|
112
113
|
}
|
|
113
114
|
exports.waitContainerToCatchUp = waitContainerToCatchUp;
|
|
114
|
-
const getCodeProposal =
|
|
115
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
116
|
-
(quorum) => quorum.get("code") ?? quorum.get("code2");
|
|
115
|
+
const getCodeProposal = (quorum) => quorum.get("code") ?? quorum.get("code2");
|
|
117
116
|
/**
|
|
118
117
|
* Helper function to report to telemetry cases where operation takes longer than expected (200ms)
|
|
119
118
|
* @param logger - logger to use
|
|
@@ -132,7 +131,6 @@ const summarizerClientType = "summarizer";
|
|
|
132
131
|
class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
133
132
|
/**
|
|
134
133
|
* Load an existing container.
|
|
135
|
-
* @internal
|
|
136
134
|
*/
|
|
137
135
|
static async load(loadProps, createProps) {
|
|
138
136
|
const { version, pendingLocalState, loadMode, resolvedUrl, loadToSequenceNumber } = loadProps;
|
|
@@ -189,7 +187,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
189
187
|
static async rehydrateDetachedFromSnapshot(createProps, snapshot) {
|
|
190
188
|
const container = new Container(createProps);
|
|
191
189
|
return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "RehydrateDetachedFromSnapshot" }, async (_event) => {
|
|
192
|
-
const detachedContainerState = (0,
|
|
190
|
+
const detachedContainerState = (0, utils_js_1.getDetachedContainerStateFromSerializedContainer)(snapshot);
|
|
193
191
|
await container.rehydrateDetachedFromSnapshot(detachedContainerState);
|
|
194
192
|
return container;
|
|
195
193
|
}, { start: true, end: true, cancel: "generic" });
|
|
@@ -271,7 +269,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
271
269
|
return this.connectionStateHandler.connectionState;
|
|
272
270
|
}
|
|
273
271
|
get connected() {
|
|
274
|
-
return this.connectionStateHandler.connectionState ===
|
|
272
|
+
return this.connectionStateHandler.connectionState === connectionState_js_1.ConnectionState.Connected;
|
|
275
273
|
}
|
|
276
274
|
/**
|
|
277
275
|
* The server provided id of the client.
|
|
@@ -280,11 +278,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
280
278
|
get clientId() {
|
|
281
279
|
return this._clientId;
|
|
282
280
|
}
|
|
283
|
-
get
|
|
284
|
-
|
|
285
|
-
this.options?.enableOfflineLoad === true;
|
|
286
|
-
// summarizer will not have any pending state we want to save
|
|
287
|
-
return enabled && this.deltaManager.clientDetails.capabilities.interactive;
|
|
281
|
+
get isInteractiveClient() {
|
|
282
|
+
return this.deltaManager.clientDetails.capabilities.interactive;
|
|
288
283
|
}
|
|
289
284
|
/**
|
|
290
285
|
* Get the code details that are currently specified for the container.
|
|
@@ -339,9 +334,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
339
334
|
this._lifecycleEvents.once("disposed", disposedHandler);
|
|
340
335
|
});
|
|
341
336
|
}
|
|
342
|
-
/**
|
|
343
|
-
* @internal
|
|
344
|
-
*/
|
|
345
337
|
constructor(createProps, loadProps) {
|
|
346
338
|
super((name, error) => {
|
|
347
339
|
this.mc.logger.sendErrorEvent({
|
|
@@ -370,14 +362,13 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
370
362
|
this.firstConnection = true;
|
|
371
363
|
this.connectionTransitionTimes = [];
|
|
372
364
|
this._dirtyContainer = false;
|
|
373
|
-
this.savedOps = [];
|
|
374
365
|
this.attachmentData = { state: container_definitions_1.AttachState.Detached };
|
|
375
366
|
this.clientsWhoShouldHaveLeft = new Set();
|
|
376
367
|
this._containerMetadata = {};
|
|
377
368
|
this.setAutoReconnectTime = client_utils_1.performance.now();
|
|
378
369
|
this._lifecycleEvents = new client_utils_1.TypedEventEmitter();
|
|
379
370
|
this._disposed = false;
|
|
380
|
-
this.attach = (0,
|
|
371
|
+
this.attach = (0, utils_js_1.runSingle)(async (request, attachProps) => {
|
|
381
372
|
await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
|
|
382
373
|
if (this._lifecycleState !== "loaded" ||
|
|
383
374
|
this.attachmentData.state === container_definitions_1.AttachState.Attached) {
|
|
@@ -410,7 +401,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
410
401
|
const createAttachmentSummary = (redirectTable) => {
|
|
411
402
|
try {
|
|
412
403
|
(0, core_utils_1.assert)(this.deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
|
|
413
|
-
return (0,
|
|
404
|
+
return (0, utils_js_1.combineAppAndProtocolSummary)(this.runtime.createSummary(redirectTable), this.captureProtocolSummary());
|
|
414
405
|
}
|
|
415
406
|
catch (error) {
|
|
416
407
|
throw normalizeErrorAndClose(error);
|
|
@@ -429,9 +420,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
429
420
|
this.storageAdapter.connectToService(this.service);
|
|
430
421
|
return this.storageAdapter;
|
|
431
422
|
};
|
|
432
|
-
let attachP = (0,
|
|
423
|
+
let attachP = (0, attachment_js_1.runRetriableAttachProcess)({
|
|
433
424
|
initialAttachmentData: this.attachmentData,
|
|
434
|
-
offlineLoadEnabled: this.offlineLoadEnabled,
|
|
425
|
+
offlineLoadEnabled: this.serializedStateManager.offlineLoadEnabled,
|
|
435
426
|
detachedBlobStorage: this.detachedBlobStorage,
|
|
436
427
|
setAttachmentData,
|
|
437
428
|
createAttachmentSummary,
|
|
@@ -443,7 +434,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
443
434
|
throw normalizeErrorAndClose(error);
|
|
444
435
|
});
|
|
445
436
|
}
|
|
446
|
-
await attachP;
|
|
437
|
+
this.serializedStateManager.setSnapshot(await attachP);
|
|
447
438
|
if (!this.closed) {
|
|
448
439
|
this.handleDeltaConnectionArg({
|
|
449
440
|
fetchOpsFromStorage: false,
|
|
@@ -456,7 +447,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
456
447
|
if (this.resolvedUrl === undefined) {
|
|
457
448
|
return undefined;
|
|
458
449
|
}
|
|
459
|
-
return this.urlResolver.getAbsoluteUrl(this.resolvedUrl, relativeUrl, (0,
|
|
450
|
+
return this.urlResolver.getAbsoluteUrl(this.resolvedUrl, relativeUrl, (0, contracts_js_1.getPackageName)(this._loadedCodeDetails));
|
|
460
451
|
};
|
|
461
452
|
this.metadataUpdateHandler = (metadata) => {
|
|
462
453
|
this._containerMetadata = { ...this._containerMetadata, ...metadata };
|
|
@@ -470,7 +461,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
470
461
|
this.emit(dirty ? dirtyContainerEvent : savedContainerEvent);
|
|
471
462
|
};
|
|
472
463
|
const { canReconnect, clientDetailsOverride, urlResolver, documentServiceFactory, codeLoader, options, scope, subLogger, detachedBlobStorage, protocolHandlerBuilder, } = createProps;
|
|
473
|
-
this.connectionTransitionTimes[
|
|
464
|
+
this.connectionTransitionTimes[connectionState_js_1.ConnectionState.Disconnected] = client_utils_1.performance.now();
|
|
474
465
|
const pendingLocalState = loadProps?.pendingLocalState;
|
|
475
466
|
this._clientId = pendingLocalState?.clientId;
|
|
476
467
|
this._canReconnect = canReconnect ?? true;
|
|
@@ -486,7 +477,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
486
477
|
this.detachedBlobStorage = detachedBlobStorage;
|
|
487
478
|
this.protocolHandlerBuilder =
|
|
488
479
|
protocolHandlerBuilder ??
|
|
489
|
-
((attributes, quorumSnapshot, sendProposal) => new
|
|
480
|
+
((attributes, quorumSnapshot, sendProposal) => new protocol_js_1.ProtocolHandler(attributes, quorumSnapshot, sendProposal, new audience_js_1.Audience(), (clientId) => this.clientsWhoShouldHaveLeft.has(clientId)));
|
|
490
481
|
// Note that we capture the createProps here so we can replicate the creation call when we want to clone.
|
|
491
482
|
this.clone = async (_loadProps, createParamOverrides) => {
|
|
492
483
|
return Container.load(_loadProps, {
|
|
@@ -495,7 +486,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
495
486
|
});
|
|
496
487
|
};
|
|
497
488
|
this._containerId = (0, uuid_1.v4)();
|
|
498
|
-
this.client = Container.setupClient(this._containerId,
|
|
489
|
+
this.client = Container.setupClient(this._containerId, options.client, this.clientDetailsOverride);
|
|
499
490
|
// Create logger for data stores to use
|
|
500
491
|
const type = this.client.details.type;
|
|
501
492
|
const interactive = this.client.details.capabilities.interactive;
|
|
@@ -511,7 +502,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
511
502
|
docId: () => this.resolvedUrl?.id,
|
|
512
503
|
containerAttachState: () => this.attachState,
|
|
513
504
|
containerLifecycleState: () => this._lifecycleState,
|
|
514
|
-
containerConnectionState: () =>
|
|
505
|
+
containerConnectionState: () => connectionState_js_1.ConnectionState[this.connectionState],
|
|
515
506
|
serializedContainer: pendingLocalState !== undefined,
|
|
516
507
|
},
|
|
517
508
|
// we need to be judicious with our logging here to avoid generating too much data
|
|
@@ -539,15 +530,15 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
539
530
|
// Prefix all events in this file with container-loader
|
|
540
531
|
this.mc = (0, telemetry_utils_1.createChildMonitoringContext)({ logger: this.subLogger, namespace: "Container" });
|
|
541
532
|
this._deltaManager = this.createDeltaManager();
|
|
542
|
-
this.connectionStateHandler = (0,
|
|
533
|
+
this.connectionStateHandler = (0, connectionStateHandler_js_1.createConnectionStateHandler)({
|
|
543
534
|
logger: this.mc.logger,
|
|
544
535
|
connectionStateChanged: (value, oldState, reason) => {
|
|
545
|
-
if (value ===
|
|
536
|
+
if (value === connectionState_js_1.ConnectionState.Connected) {
|
|
546
537
|
this._clientId = this.connectionStateHandler.pendingClientId;
|
|
547
538
|
}
|
|
548
539
|
this.logConnectionStateChangeTelemetry(value, oldState, reason);
|
|
549
540
|
if (this._lifecycleState === "loaded") {
|
|
550
|
-
this.propagateConnectionState(false /* initial transition */, value ===
|
|
541
|
+
this.propagateConnectionState(false /* initial transition */, value === connectionState_js_1.ConnectionState.Disconnected
|
|
551
542
|
? reason
|
|
552
543
|
: undefined /* disconnectedReason */);
|
|
553
544
|
}
|
|
@@ -566,7 +557,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
566
557
|
mode,
|
|
567
558
|
category: this._lifecycleState === "loading" ? "generic" : category,
|
|
568
559
|
duration: client_utils_1.performance.now() -
|
|
569
|
-
this.connectionTransitionTimes[
|
|
560
|
+
this.connectionTransitionTimes[connectionState_js_1.ConnectionState.CatchingUp],
|
|
570
561
|
...(details === undefined ? {} : { details: JSON.stringify(details) }),
|
|
571
562
|
});
|
|
572
563
|
// If this is "write" connection, it took too long to receive join op. But in most cases that's due
|
|
@@ -595,12 +586,16 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
595
586
|
// using this callback and fix them up.
|
|
596
587
|
const addProtocolSummaryIfMissing = (summaryTree) => (0, driver_utils_1.isCombinedAppAndProtocolSummary)(summaryTree) === true
|
|
597
588
|
? summaryTree
|
|
598
|
-
: (0,
|
|
589
|
+
: (0, utils_js_1.combineAppAndProtocolSummary)(summaryTree, this.captureProtocolSummary());
|
|
599
590
|
// Whether the combined summary tree has been forced on by either the loader option or the monitoring context.
|
|
600
591
|
// Even if not forced on via this flag, combined summaries may still be enabled by service policy.
|
|
601
592
|
const forceEnableSummarizeProtocolTree = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree2") ??
|
|
602
593
|
options.summarizeProtocolTree;
|
|
603
|
-
this.storageAdapter = new
|
|
594
|
+
this.storageAdapter = new containerStorageAdapter_js_1.ContainerStorageAdapter(detachedBlobStorage, this.mc.logger, pendingLocalState?.snapshotBlobs, addProtocolSummaryIfMissing, forceEnableSummarizeProtocolTree);
|
|
595
|
+
const offlineLoadEnabled = (this.isInteractiveClient &&
|
|
596
|
+
this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad")) ??
|
|
597
|
+
options.enableOfflineLoad === true;
|
|
598
|
+
this.serializedStateManager = new serializedStateManager_js_1.SerializedStateManager(pendingLocalState, this.subLogger, this.storageAdapter, offlineLoadEnabled);
|
|
604
599
|
const isDomAvailable = typeof document === "object" &&
|
|
605
600
|
document !== null &&
|
|
606
601
|
typeof document.addEventListener === "function" &&
|
|
@@ -641,7 +636,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
641
636
|
this.verifyClosed();
|
|
642
637
|
}
|
|
643
638
|
verifyClosed() {
|
|
644
|
-
(0, core_utils_1.assert)(this.connectionState ===
|
|
639
|
+
(0, core_utils_1.assert)(this.connectionState === connectionState_js_1.ConnectionState.Disconnected, 0x0cf /* "disconnect event was not raised!" */);
|
|
645
640
|
(0, core_utils_1.assert)(this._lifecycleState === "closed" || this._lifecycleState === "disposed", 0x314 /* Container properly closed */);
|
|
646
641
|
}
|
|
647
642
|
closeCore(error) {
|
|
@@ -739,47 +734,32 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
739
734
|
return this.getPendingLocalStateCore({ notifyImminentClosure: false });
|
|
740
735
|
}
|
|
741
736
|
async getPendingLocalStateCore(props) {
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
throw new telemetry_utils_1.UsageError("Can't get pending local state unless offline load is enabled");
|
|
750
|
-
}
|
|
751
|
-
if (this.closed || this._disposed) {
|
|
752
|
-
throw new telemetry_utils_1.UsageError("Pending state cannot be retried if the container is closed or disposed");
|
|
753
|
-
}
|
|
754
|
-
(0, core_utils_1.assert)(this.attachmentData.state === container_definitions_1.AttachState.Attached, 0x0d1 /* "Container should be attached before close" */);
|
|
755
|
-
(0, core_utils_1.assert)(this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid", 0x0d2 /* "resolved url should be valid Fluid url" */);
|
|
756
|
-
(0, core_utils_1.assert)(this.attachmentData.snapshot !== undefined, 0x5d5 /* no base data */);
|
|
757
|
-
const pendingRuntimeState = await this.runtime.getPendingLocalState(props);
|
|
758
|
-
const pendingState = {
|
|
759
|
-
pendingRuntimeState,
|
|
760
|
-
baseSnapshot: this.attachmentData.snapshot.tree,
|
|
761
|
-
snapshotBlobs: this.attachmentData.snapshot.blobs,
|
|
762
|
-
savedOps: this.savedOps,
|
|
763
|
-
url: this.resolvedUrl.url,
|
|
764
|
-
// no need to save this if there is no pending runtime state
|
|
765
|
-
clientId: pendingRuntimeState !== undefined ? this.clientId : undefined,
|
|
766
|
-
};
|
|
767
|
-
return JSON.stringify(pendingState);
|
|
768
|
-
});
|
|
737
|
+
if (this.closed || this._disposed) {
|
|
738
|
+
throw new telemetry_utils_1.UsageError("Pending state cannot be retried if the container is closed or disposed");
|
|
739
|
+
}
|
|
740
|
+
(0, core_utils_1.assert)(this.attachmentData.state === container_definitions_1.AttachState.Attached, 0x0d1 /* "Container should be attached before close" */);
|
|
741
|
+
(0, core_utils_1.assert)(this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid", 0x0d2 /* "resolved url should be valid Fluid url" */);
|
|
742
|
+
const pendingState = await this.serializedStateManager.getPendingLocalStateCore(props, this.clientId, this.runtime, this.resolvedUrl);
|
|
743
|
+
return pendingState;
|
|
769
744
|
}
|
|
770
745
|
get attachState() {
|
|
771
746
|
return this.attachmentData.state;
|
|
772
747
|
}
|
|
773
748
|
serialize() {
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
const
|
|
778
|
-
const
|
|
749
|
+
if (this.attachmentData.state === container_definitions_1.AttachState.Attached || this.closed) {
|
|
750
|
+
throw new telemetry_utils_1.UsageError("Container must not be attached or closed.");
|
|
751
|
+
}
|
|
752
|
+
const attachingData = this.attachmentData.state === container_definitions_1.AttachState.Attaching ? this.attachmentData : undefined;
|
|
753
|
+
const combinedSummary = attachingData?.summary ??
|
|
754
|
+
(0, utils_js_1.combineAppAndProtocolSummary)(this.runtime.createSummary(), this.captureProtocolSummary());
|
|
755
|
+
const { tree: snapshot, blobs } = (0, utils_js_1.getSnapshotTreeAndBlobsFromSerializedContainer)(combinedSummary);
|
|
756
|
+
const pendingRuntimeState = attachingData !== undefined ? this.runtime.getPendingLocalState() : undefined;
|
|
757
|
+
(0, core_utils_1.assert)(!(0, core_utils_1.isPromiseLike)(pendingRuntimeState), 0x8e3 /* should not be a promise */);
|
|
779
758
|
const detachedContainerState = {
|
|
780
759
|
attached: false,
|
|
781
760
|
baseSnapshot: snapshot,
|
|
782
761
|
snapshotBlobs: blobs,
|
|
762
|
+
pendingRuntimeState,
|
|
783
763
|
hasAttachmentBlobs: !!this.detachedBlobStorage && this.detachedBlobStorage.size > 0,
|
|
784
764
|
};
|
|
785
765
|
return JSON.stringify(detachedContainerState);
|
|
@@ -793,9 +773,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
793
773
|
const duration = now - this.setAutoReconnectTime;
|
|
794
774
|
this.setAutoReconnectTime = now;
|
|
795
775
|
this.mc.logger.sendTelemetryEvent({
|
|
796
|
-
eventName: mode ===
|
|
776
|
+
eventName: mode === contracts_js_1.ReconnectMode.Enabled ? "AutoReconnectEnabled" : "AutoReconnectDisabled",
|
|
797
777
|
connectionMode: this.connectionMode,
|
|
798
|
-
connectionState:
|
|
778
|
+
connectionState: connectionState_js_1.ConnectionState[this.connectionState],
|
|
799
779
|
duration,
|
|
800
780
|
});
|
|
801
781
|
this._deltaManager.connectionManager.setAutoReconnect(mode, reason);
|
|
@@ -823,7 +803,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
823
803
|
// Resume processing ops and connect to delta stream
|
|
824
804
|
this.resumeInternal(args);
|
|
825
805
|
// Set Auto Reconnect Mode
|
|
826
|
-
const mode =
|
|
806
|
+
const mode = contracts_js_1.ReconnectMode.Enabled;
|
|
827
807
|
this.setAutoReconnectInternal(mode, args.reason);
|
|
828
808
|
}
|
|
829
809
|
disconnect() {
|
|
@@ -837,7 +817,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
837
817
|
disconnectInternal(reason) {
|
|
838
818
|
(0, core_utils_1.assert)(!this.closed, 0x2c7 /* "Attempting to disconnect() a closed Container" */);
|
|
839
819
|
// Set Auto Reconnect Mode
|
|
840
|
-
const mode =
|
|
820
|
+
const mode = contracts_js_1.ReconnectMode.Disabled;
|
|
841
821
|
this.setAutoReconnectInternal(mode, reason);
|
|
842
822
|
}
|
|
843
823
|
resumeInternal(args) {
|
|
@@ -912,10 +892,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
912
892
|
}
|
|
913
893
|
return true;
|
|
914
894
|
}
|
|
915
|
-
async getVersion(version) {
|
|
916
|
-
const versions = await this.storageAdapter.getVersions(version, 1);
|
|
917
|
-
return versions[0];
|
|
918
|
-
}
|
|
919
895
|
connectToDeltaStream(args) {
|
|
920
896
|
// All agents need "write" access, including summarizer.
|
|
921
897
|
if (!this._canReconnect || !this.client.details.capabilities.interactive) {
|
|
@@ -960,31 +936,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
960
936
|
};
|
|
961
937
|
timings.phase2 = client_utils_1.performance.now();
|
|
962
938
|
// Fetch specified snapshot.
|
|
963
|
-
const {
|
|
964
|
-
|
|
965
|
-
: { snapshot: pendingLocalState.baseSnapshot, versionId: undefined };
|
|
966
|
-
const snapshotTree = (0, driver_utils_1.isInstanceOfISnapshot)(snapshot)
|
|
967
|
-
? snapshot.snapshotTree
|
|
968
|
-
: snapshot;
|
|
969
|
-
if (pendingLocalState) {
|
|
970
|
-
this.attachmentData = {
|
|
971
|
-
state: container_definitions_1.AttachState.Attached,
|
|
972
|
-
snapshot: {
|
|
973
|
-
tree: pendingLocalState.baseSnapshot,
|
|
974
|
-
blobs: pendingLocalState.snapshotBlobs,
|
|
975
|
-
},
|
|
976
|
-
};
|
|
977
|
-
}
|
|
978
|
-
else {
|
|
979
|
-
(0, core_utils_1.assert)(snapshotTree !== undefined, 0x237 /* "Snapshot should exist" */);
|
|
980
|
-
if (this.offlineLoadEnabled) {
|
|
981
|
-
const blobs = await (0, containerStorageAdapter_1.getBlobContentsFromTree)(snapshotTree, this.storageAdapter);
|
|
982
|
-
this.attachmentData = {
|
|
983
|
-
state: container_definitions_1.AttachState.Attached,
|
|
984
|
-
snapshot: { tree: snapshotTree, blobs },
|
|
985
|
-
};
|
|
986
|
-
}
|
|
987
|
-
}
|
|
939
|
+
const { snapshotTree, version } = await this.serializedStateManager.fetchSnapshot(specifiedVersion, this.service?.policies?.supportGetSnapshotApi);
|
|
940
|
+
this._loadedFromVersion = version;
|
|
988
941
|
const attributes = await this.getDocumentAttributes(this.storageAdapter, snapshotTree);
|
|
989
942
|
// If we saved ops, we will replay them and don't need DeltaManager to fetch them
|
|
990
943
|
const sequenceNumber = pendingLocalState?.savedOps[pendingLocalState.savedOps.length - 1]?.sequenceNumber;
|
|
@@ -1055,7 +1008,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1055
1008
|
const codeDetails = this.getCodeDetailsFromQuorum();
|
|
1056
1009
|
await this.instantiateRuntime(codeDetails, snapshotTree,
|
|
1057
1010
|
// give runtime a dummy value so it knows we're loading from a stash blob
|
|
1058
|
-
pendingLocalState ? pendingLocalState?.pendingRuntimeState ?? {} : undefined, (0, driver_utils_1.isInstanceOfISnapshot)(
|
|
1011
|
+
pendingLocalState ? pendingLocalState?.pendingRuntimeState ?? {} : undefined, (0, driver_utils_1.isInstanceOfISnapshot)(snapshotTree) ? snapshotTree : undefined);
|
|
1059
1012
|
// replay saved ops
|
|
1060
1013
|
if (pendingLocalState) {
|
|
1061
1014
|
for (const message of pendingLocalState.savedOps) {
|
|
@@ -1110,7 +1063,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1110
1063
|
}, undefined, core_interfaces_1.LogLevel.verbose);
|
|
1111
1064
|
return {
|
|
1112
1065
|
sequenceNumber: attributes.sequenceNumber,
|
|
1113
|
-
version:
|
|
1066
|
+
version: version?.id,
|
|
1114
1067
|
dmLastProcessedSeqNumber: this._deltaManager.lastSequenceNumber,
|
|
1115
1068
|
dmLastKnownSeqNumber: this._deltaManager.lastKnownSeqNumber,
|
|
1116
1069
|
};
|
|
@@ -1122,7 +1075,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1122
1075
|
};
|
|
1123
1076
|
await this.attachDeltaManagerOpHandler(attributes);
|
|
1124
1077
|
// Need to just seed the source data in the code quorum. Quorum itself is empty
|
|
1125
|
-
const qValues = (0,
|
|
1078
|
+
const qValues = (0, quorum_js_1.initQuorumValuesFromCodeDetails)(codeDetails);
|
|
1126
1079
|
this.initializeProtocolState(attributes, {
|
|
1127
1080
|
members: [],
|
|
1128
1081
|
proposals: [],
|
|
@@ -1131,16 +1084,16 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1131
1084
|
await this.instantiateRuntime(codeDetails, undefined);
|
|
1132
1085
|
this.setLoaded();
|
|
1133
1086
|
}
|
|
1134
|
-
async rehydrateDetachedFromSnapshot({
|
|
1087
|
+
async rehydrateDetachedFromSnapshot({ baseSnapshot, snapshotBlobs, hasAttachmentBlobs, pendingRuntimeState, }) {
|
|
1135
1088
|
if (hasAttachmentBlobs) {
|
|
1136
1089
|
(0, core_utils_1.assert)(!!this.detachedBlobStorage && this.detachedBlobStorage.size > 0, 0x250 /* "serialized container with attachment blobs must be rehydrated with detached blob storage" */);
|
|
1137
1090
|
}
|
|
1138
|
-
const snapshotTreeWithBlobContents = (0,
|
|
1091
|
+
const snapshotTreeWithBlobContents = (0, utils_js_1.combineSnapshotTreeAndSnapshotBlobs)(baseSnapshot, snapshotBlobs);
|
|
1139
1092
|
this.storageAdapter.loadSnapshotFromSnapshotBlobs(snapshotBlobs);
|
|
1140
1093
|
const attributes = await this.getDocumentAttributes(this.storageAdapter, snapshotTreeWithBlobContents);
|
|
1141
1094
|
await this.attachDeltaManagerOpHandler(attributes);
|
|
1142
1095
|
// Initialize the protocol handler
|
|
1143
|
-
const baseTree = (0,
|
|
1096
|
+
const baseTree = (0, utils_js_1.getProtocolSnapshotTree)(snapshotTreeWithBlobContents);
|
|
1144
1097
|
const qValues = await (0, driver_utils_1.readAndParse)(this.storageAdapter, baseTree.blobs.quorumValues);
|
|
1145
1098
|
this.initializeProtocolState(attributes, {
|
|
1146
1099
|
members: [],
|
|
@@ -1148,7 +1101,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1148
1101
|
values: qValues,
|
|
1149
1102
|
});
|
|
1150
1103
|
const codeDetails = this.getCodeDetailsFromQuorum();
|
|
1151
|
-
await this.instantiateRuntime(codeDetails, snapshotTreeWithBlobContents);
|
|
1104
|
+
await this.instantiateRuntime(codeDetails, snapshotTreeWithBlobContents, pendingRuntimeState);
|
|
1152
1105
|
this.setLoaded();
|
|
1153
1106
|
}
|
|
1154
1107
|
async getDocumentAttributes(storage, tree) {
|
|
@@ -1172,7 +1125,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1172
1125
|
values: [],
|
|
1173
1126
|
};
|
|
1174
1127
|
if (snapshot !== undefined) {
|
|
1175
|
-
const baseTree = (0,
|
|
1128
|
+
const baseTree = (0, utils_js_1.getProtocolSnapshotTree)(snapshot);
|
|
1176
1129
|
[quorumSnapshot.members, quorumSnapshot.proposals, quorumSnapshot.values] =
|
|
1177
1130
|
await Promise.all([
|
|
1178
1131
|
(0, driver_utils_1.readAndParse)(storage, baseTree.blobs.quorumMembers),
|
|
@@ -1248,10 +1201,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1248
1201
|
const pkg = getCodeProposal(quorum);
|
|
1249
1202
|
return pkg;
|
|
1250
1203
|
}
|
|
1251
|
-
static setupClient(containerId,
|
|
1252
|
-
const loaderOptionsClient = (0, structured_clone_1.default)(options?.client);
|
|
1204
|
+
static setupClient(containerId, loaderOptionsClient, clientDetailsOverride) {
|
|
1253
1205
|
const client = loaderOptionsClient !== undefined
|
|
1254
|
-
? loaderOptionsClient
|
|
1206
|
+
? (0, structured_clone_1.default)(loaderOptionsClient)
|
|
1255
1207
|
: {
|
|
1256
1208
|
details: {
|
|
1257
1209
|
capabilities: { interactive: true },
|
|
@@ -1273,7 +1225,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1273
1225
|
}
|
|
1274
1226
|
client.details.environment = [
|
|
1275
1227
|
client.details.environment,
|
|
1276
|
-
` loaderVersion:${
|
|
1228
|
+
` loaderVersion:${packageVersion_js_1.pkgVersion}`,
|
|
1277
1229
|
` containerId:${containerId}`,
|
|
1278
1230
|
].join(";");
|
|
1279
1231
|
return client;
|
|
@@ -1285,11 +1237,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1285
1237
|
* If it's not true, runtime is not in position to send ops.
|
|
1286
1238
|
*/
|
|
1287
1239
|
activeConnection() {
|
|
1288
|
-
return (this.connectionState ===
|
|
1240
|
+
return (this.connectionState === connectionState_js_1.ConnectionState.Connected && this.connectionMode === "write");
|
|
1289
1241
|
}
|
|
1290
1242
|
createDeltaManager() {
|
|
1291
1243
|
const serviceProvider = () => this.service;
|
|
1292
|
-
const deltaManager = new
|
|
1244
|
+
const deltaManager = new deltaManager_js_1.DeltaManager(serviceProvider, (0, telemetry_utils_1.createChildLogger)({ logger: this.subLogger, namespace: "DeltaManager" }), () => this.activeConnection(), (props) => new connectionManager_js_1.ConnectionManager(serviceProvider, () => this.isDirty, this.client, this._canReconnect, (0, telemetry_utils_1.createChildLogger)({ logger: this.subLogger, namespace: "ConnectionManager" }), props));
|
|
1293
1245
|
// Disable inbound queues as Container is not ready to accept any ops until we are fully loaded!
|
|
1294
1246
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1295
1247
|
deltaManager.inbound.pause();
|
|
@@ -1305,10 +1257,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1305
1257
|
deltaManager.on("cancelEstablishingConnection", (reason) => {
|
|
1306
1258
|
this.connectionStateHandler.cancelEstablishingConnection(reason);
|
|
1307
1259
|
});
|
|
1308
|
-
deltaManager.on("disconnect", (
|
|
1260
|
+
deltaManager.on("disconnect", (text, error) => {
|
|
1309
1261
|
this.noopHeuristic?.notifyDisconnect();
|
|
1310
1262
|
if (!this.closed) {
|
|
1311
|
-
this.connectionStateHandler.receivedDisconnectEvent(
|
|
1263
|
+
this.connectionStateHandler.receivedDisconnectEvent({ text, error });
|
|
1312
1264
|
}
|
|
1313
1265
|
});
|
|
1314
1266
|
deltaManager.on("throttled", (warning) => {
|
|
@@ -1321,7 +1273,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1321
1273
|
this.emit("warning", warn);
|
|
1322
1274
|
});
|
|
1323
1275
|
deltaManager.on("readonly", (readonly) => {
|
|
1324
|
-
this.setContextConnectedState(this.connectionState ===
|
|
1276
|
+
this.setContextConnectedState(this.connectionState === connectionState_js_1.ConnectionState.Connected, readonly);
|
|
1325
1277
|
this.emit("readonly", readonly);
|
|
1326
1278
|
});
|
|
1327
1279
|
deltaManager.on("closed", (error) => {
|
|
@@ -1350,16 +1302,16 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1350
1302
|
let autoReconnect;
|
|
1351
1303
|
let checkpointSequenceNumber;
|
|
1352
1304
|
let opsBehind;
|
|
1353
|
-
if (value ===
|
|
1305
|
+
if (value === connectionState_js_1.ConnectionState.Disconnected) {
|
|
1354
1306
|
autoReconnect = this._deltaManager.connectionManager.reconnectMode;
|
|
1355
1307
|
}
|
|
1356
1308
|
else {
|
|
1357
|
-
if (value ===
|
|
1309
|
+
if (value === connectionState_js_1.ConnectionState.Connected) {
|
|
1358
1310
|
durationFromDisconnected =
|
|
1359
|
-
time - this.connectionTransitionTimes[
|
|
1311
|
+
time - this.connectionTransitionTimes[connectionState_js_1.ConnectionState.Disconnected];
|
|
1360
1312
|
durationFromDisconnected = (0, telemetry_utils_1.formatTick)(durationFromDisconnected);
|
|
1361
1313
|
}
|
|
1362
|
-
else if (value ===
|
|
1314
|
+
else if (value === connectionState_js_1.ConnectionState.CatchingUp) {
|
|
1363
1315
|
// This info is of most interesting while Catching Up.
|
|
1364
1316
|
checkpointSequenceNumber = this.deltaManager.lastKnownSeqNumber;
|
|
1365
1317
|
// Need to check that we have already loaded and fetched the snapshot.
|
|
@@ -1371,8 +1323,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1371
1323
|
connectionInitiationReason = this.firstConnection ? "InitialConnect" : "AutoReconnect";
|
|
1372
1324
|
}
|
|
1373
1325
|
this.mc.logger.sendPerformanceEvent({
|
|
1374
|
-
eventName: `ConnectionStateChange_${
|
|
1375
|
-
from:
|
|
1326
|
+
eventName: `ConnectionStateChange_${connectionState_js_1.ConnectionState[value]}`,
|
|
1327
|
+
from: connectionState_js_1.ConnectionState[oldState],
|
|
1376
1328
|
duration,
|
|
1377
1329
|
durationFromDisconnected,
|
|
1378
1330
|
reason: reason?.text,
|
|
@@ -1390,7 +1342,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1390
1342
|
isDirty: this.isDirty,
|
|
1391
1343
|
...this._deltaManager.connectionProps,
|
|
1392
1344
|
}, reason?.error);
|
|
1393
|
-
if (value ===
|
|
1345
|
+
if (value === connectionState_js_1.ConnectionState.Connected) {
|
|
1394
1346
|
this.firstConnection = false;
|
|
1395
1347
|
}
|
|
1396
1348
|
}
|
|
@@ -1399,11 +1351,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1399
1351
|
// After that, we communicate only transitions to Connected & Disconnected states, skipping all other states.
|
|
1400
1352
|
// This can be changed in the future, for example we likely should add "CatchingUp" event on Container.
|
|
1401
1353
|
if (!initialTransition &&
|
|
1402
|
-
this.connectionState !==
|
|
1403
|
-
this.connectionState !==
|
|
1354
|
+
this.connectionState !== connectionState_js_1.ConnectionState.Connected &&
|
|
1355
|
+
this.connectionState !== connectionState_js_1.ConnectionState.Disconnected) {
|
|
1404
1356
|
return;
|
|
1405
1357
|
}
|
|
1406
|
-
const state = this.connectionState ===
|
|
1358
|
+
const state = this.connectionState === connectionState_js_1.ConnectionState.Connected;
|
|
1407
1359
|
// Both protocol and context should not be undefined if we got so far.
|
|
1408
1360
|
this.setContextConnectedState(state, this.readOnlyInfo.readonly ?? false);
|
|
1409
1361
|
this.protocolHandler.setConnectionState(state, this.clientId);
|
|
@@ -1445,7 +1397,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1445
1397
|
return this.submitMessage(protocol_definitions_1.MessageType.Summarize, JSON.stringify(summary), false /* batch */, undefined /* metadata */, undefined /* compression */, referenceSequenceNumber);
|
|
1446
1398
|
}
|
|
1447
1399
|
submitMessage(type, contents, batch, metadata, compression, referenceSequenceNumber) {
|
|
1448
|
-
if (this.connectionState !==
|
|
1400
|
+
if (this.connectionState !== connectionState_js_1.ConnectionState.Connected) {
|
|
1449
1401
|
this.mc.logger.sendErrorEvent({ eventName: "SubmitMessageWithNoConnection", type });
|
|
1450
1402
|
return -1;
|
|
1451
1403
|
}
|
|
@@ -1453,14 +1405,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1453
1405
|
return this._deltaManager.submit(type, contents, batch, metadata, compression, referenceSequenceNumber);
|
|
1454
1406
|
}
|
|
1455
1407
|
processRemoteMessage(message) {
|
|
1456
|
-
if (this.offlineLoadEnabled) {
|
|
1457
|
-
this.savedOps.push(message);
|
|
1458
|
-
}
|
|
1459
1408
|
const local = this.clientId === message.clientId;
|
|
1460
1409
|
// Allow the protocol handler to process the message
|
|
1461
1410
|
const result = this.protocolHandler.processMessage(message, local);
|
|
1462
1411
|
// Forward messages to the loaded runtime for processing
|
|
1463
1412
|
this.runtime.process(message, local);
|
|
1413
|
+
this.serializedStateManager.addProcessedOp(message);
|
|
1464
1414
|
// Inactive (not in quorum or not writers) clients don't take part in the minimum sequence number calculation.
|
|
1465
1415
|
if (this.activeConnection()) {
|
|
1466
1416
|
if (this.noopHeuristic === undefined) {
|
|
@@ -1470,7 +1420,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1470
1420
|
// clients.
|
|
1471
1421
|
// All existing will continue to use settings they got earlier.
|
|
1472
1422
|
(0, core_utils_1.assert)(serviceConfiguration !== undefined, 0x2e4 /* "there should be service config for active connection" */);
|
|
1473
|
-
this.noopHeuristic = new
|
|
1423
|
+
this.noopHeuristic = new noopHeuristic_js_1.NoopHeuristic(serviceConfiguration.noopTimeFrequency, serviceConfiguration.noopCountFrequency);
|
|
1474
1424
|
this.noopHeuristic.on("wantsNoop", () => {
|
|
1475
1425
|
// On disconnect we notify the heuristic which should prevent it from wanting a noop.
|
|
1476
1426
|
// Hitting this assert would imply we lost activeConnection between notifying the heuristic of a processed message and
|
|
@@ -1493,7 +1443,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1493
1443
|
}
|
|
1494
1444
|
processSignal(message) {
|
|
1495
1445
|
// No clientId indicates a system signal message.
|
|
1496
|
-
if ((0,
|
|
1446
|
+
if ((0, protocol_js_1.protocolHandlerShouldProcessSignal)(message)) {
|
|
1497
1447
|
this.protocolHandler.processSignal(message);
|
|
1498
1448
|
}
|
|
1499
1449
|
else {
|
|
@@ -1501,55 +1451,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1501
1451
|
this.runtime.processSignal(message, local);
|
|
1502
1452
|
}
|
|
1503
1453
|
}
|
|
1504
|
-
/**
|
|
1505
|
-
* Get the most recent snapshot, or a specific version.
|
|
1506
|
-
* @param specifiedVersion - The specific version of the snapshot to retrieve
|
|
1507
|
-
* @returns The snapshot requested, or the latest snapshot if no version was specified, plus version ID
|
|
1508
|
-
*/
|
|
1509
|
-
async fetchSnapshotTree(specifiedVersion) {
|
|
1510
|
-
const version = await this.getVersion(specifiedVersion ?? null);
|
|
1511
|
-
if (version === undefined && specifiedVersion !== undefined) {
|
|
1512
|
-
// We should have a defined version to load from if specified version requested
|
|
1513
|
-
this.mc.logger.sendErrorEvent({
|
|
1514
|
-
eventName: "NoVersionFoundWhenSpecified",
|
|
1515
|
-
id: specifiedVersion,
|
|
1516
|
-
});
|
|
1517
|
-
}
|
|
1518
|
-
this._loadedFromVersion = version;
|
|
1519
|
-
const snapshot = (await this.storageAdapter.getSnapshotTree(version)) ?? undefined;
|
|
1520
|
-
if (snapshot === undefined && version !== undefined) {
|
|
1521
|
-
this.mc.logger.sendErrorEvent({ eventName: "getSnapshotTreeFailed", id: version.id });
|
|
1522
|
-
}
|
|
1523
|
-
return { snapshot, versionId: version?.id };
|
|
1524
|
-
}
|
|
1525
|
-
async fetchSnapshot(specifiedVersion) {
|
|
1526
|
-
if (this.mc.config.getBoolean("Fluid.Container.FetchSnapshotUsingGetSnapshotApi") ===
|
|
1527
|
-
true &&
|
|
1528
|
-
this.service?.policies?.supportGetSnapshotApi === true) {
|
|
1529
|
-
const snapshot = await this.storageAdapter.getSnapshot({
|
|
1530
|
-
versionId: specifiedVersion,
|
|
1531
|
-
});
|
|
1532
|
-
const version = {
|
|
1533
|
-
id: snapshot.snapshotTree.id ?? "",
|
|
1534
|
-
treeId: snapshot.snapshotTree.id ?? "",
|
|
1535
|
-
};
|
|
1536
|
-
this._loadedFromVersion = version;
|
|
1537
|
-
if (snapshot === undefined && specifiedVersion !== undefined) {
|
|
1538
|
-
this.mc.logger.sendErrorEvent({
|
|
1539
|
-
eventName: "getSnapshotTreeFailed",
|
|
1540
|
-
id: version.id,
|
|
1541
|
-
});
|
|
1542
|
-
}
|
|
1543
|
-
return { snapshot, versionId: version.id };
|
|
1544
|
-
}
|
|
1545
|
-
return this.fetchSnapshotTree(specifiedVersion);
|
|
1546
|
-
}
|
|
1547
1454
|
async instantiateRuntime(codeDetails, snapshotTree, pendingLocalState, snapshot) {
|
|
1548
1455
|
(0, core_utils_1.assert)(this._runtime?.disposed !== false, 0x0dd /* "Existing runtime not disposed" */);
|
|
1549
1456
|
// The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
|
|
1550
1457
|
// are set. Global requests will still go directly to the loader
|
|
1551
1458
|
const maybeLoader = this.scope;
|
|
1552
|
-
const loader = new
|
|
1459
|
+
const loader = new loader_js_1.RelativeLoader(this, maybeLoader.ILoader);
|
|
1553
1460
|
const loadCodeResult = await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.subLogger, { eventName: "CodeLoad" }, async () => this.codeLoader.load(codeDetails));
|
|
1554
1461
|
this._loadedModule = {
|
|
1555
1462
|
module: loadCodeResult.module,
|
|
@@ -1566,7 +1473,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1566
1473
|
const getSpecifiedCodeDetails = () => (this.protocolHandler.quorum.get("code") ??
|
|
1567
1474
|
this.protocolHandler.quorum.get("code2"));
|
|
1568
1475
|
const existing = snapshotTree !== undefined;
|
|
1569
|
-
const context = new
|
|
1476
|
+
const context = new containerContext_js_1.ContainerContext(this.options, this.scope, snapshotTree, this._loadedFromVersion, this._deltaManager, this.storageAdapter, this.protocolHandler.quorum, this.protocolHandler.audience, loader, (type, contents, batch, metadata) => this.submitContainerMessage(type, contents, batch, metadata), (summaryOp, referenceSequenceNumber) => this.submitSummaryMessage(summaryOp, referenceSequenceNumber), (batch, referenceSequenceNumber) => this.submitBatch(batch, referenceSequenceNumber), (content, targetClientId) => this.submitSignal(content, targetClientId), (error) => this.dispose(error), (error) => this.close(error), this.updateDirtyContainerState, this.getAbsoluteUrl, () => this.resolvedUrl?.id, () => this.clientId, () => this.attachState, () => this.connected, getSpecifiedCodeDetails, this._deltaManager.clientDetails, existing, this.subLogger, pendingLocalState, snapshot);
|
|
1570
1477
|
this._runtime = await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.subLogger, { eventName: "InstantiateRuntime" }, async () => runtimeFactory.instantiateRuntime(context, existing));
|
|
1571
1478
|
this._lifecycleEvents.emit("runtimeInstantiated");
|
|
1572
1479
|
this._loadedCodeDetails = codeDetails;
|