@fluidframework/container-loader 2.0.0-rc.2.0.2 → 2.0.0-rc.3.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 +33 -0
- package/api-report/container-loader.api.md +13 -13
- package/dist/attachment.d.ts +6 -9
- package/dist/attachment.d.ts.map +1 -1
- package/dist/attachment.js +5 -5
- package/dist/attachment.js.map +1 -1
- package/dist/audience.d.ts +1 -1
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +4 -4
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.d.ts +1 -1
- package/dist/catchUpMonitor.d.ts.map +1 -1
- package/dist/catchUpMonitor.js +2 -2
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts +4 -4
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +48 -43
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +3 -3
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +27 -27
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +9 -46
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +105 -116
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +19 -7
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +7 -2
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +3 -3
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +6 -6
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +4 -3
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +2 -2
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.d.ts +2 -1
- package/dist/debugLogger.d.ts.map +1 -1
- package/dist/debugLogger.js +4 -4
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts +11 -7
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +53 -50
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.d.ts +1 -1
- package/dist/deltaQueue.d.ts.map +1 -1
- package/dist/deltaQueue.js +5 -5
- package/dist/deltaQueue.js.map +1 -1
- package/dist/error.d.ts +3 -2
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +5 -5
- package/dist/error.js.map +1 -1
- package/dist/legacy.d.ts +29 -0
- package/dist/loader.d.ts +4 -4
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +23 -23
- package/dist/loader.js.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts +2 -2
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js +2 -2
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
- package/dist/noopHeuristic.d.ts +1 -1
- package/dist/noopHeuristic.d.ts.map +1 -1
- package/dist/noopHeuristic.js +6 -6
- package/dist/noopHeuristic.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/protocol.d.ts +1 -1
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +2 -2
- package/dist/protocol.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts +4 -4
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/public.d.ts +14 -0
- package/dist/quorum.d.ts +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 +2 -2
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +7 -7
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/serializedStateManager.d.ts +86 -16
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +182 -82
- package/dist/serializedStateManager.js.map +1 -1
- package/dist/utils.d.ts +24 -9
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +82 -25
- package/dist/utils.js.map +1 -1
- package/internal.d.ts +11 -0
- package/legacy.d.ts +11 -0
- package/lib/attachment.d.ts +6 -9
- package/lib/attachment.d.ts.map +1 -1
- package/lib/attachment.js +1 -1
- package/lib/attachment.js.map +1 -1
- package/lib/audience.d.ts +1 -1
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js +1 -1
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.d.ts +1 -1
- package/lib/catchUpMonitor.d.ts.map +1 -1
- package/lib/catchUpMonitor.js +1 -1
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts +4 -4
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +11 -6
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +3 -3
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +2 -2
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +9 -46
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +37 -48
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +19 -7
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +7 -2
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +3 -3
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +2 -2
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +4 -3
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.d.ts +2 -1
- package/lib/debugLogger.d.ts.map +1 -1
- package/lib/debugLogger.js +1 -1
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts +11 -7
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +13 -10
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.d.ts +1 -1
- package/lib/deltaQueue.d.ts.map +1 -1
- package/lib/deltaQueue.js +2 -2
- package/lib/deltaQueue.js.map +1 -1
- package/lib/error.d.ts +3 -2
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js +2 -2
- package/lib/error.js.map +1 -1
- package/lib/legacy.d.ts +29 -0
- package/lib/loader.d.ts +4 -4
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +4 -4
- package/lib/loader.js.map +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts +2 -2
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js +2 -2
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
- package/lib/noopHeuristic.d.ts +1 -1
- package/lib/noopHeuristic.d.ts.map +1 -1
- package/lib/noopHeuristic.js +2 -2
- package/lib/noopHeuristic.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/protocol.d.ts +1 -1
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +1 -1
- package/lib/protocol.js.map +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts +4 -4
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/public.d.ts +14 -0
- package/lib/quorum.d.ts +1 -1
- package/lib/quorum.d.ts.map +1 -1
- package/lib/quorum.js +4 -0
- package/lib/quorum.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts +2 -2
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +3 -3
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/serializedStateManager.d.ts +86 -16
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +174 -77
- package/lib/serializedStateManager.js.map +1 -1
- package/lib/utils.d.ts +24 -9
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +69 -15
- package/lib/utils.js.map +1 -1
- package/package.json +37 -58
- package/src/attachment.ts +10 -8
- package/src/audience.ts +3 -2
- package/src/catchUpMonitor.ts +2 -2
- package/src/connectionManager.ts +27 -20
- package/src/connectionStateHandler.ts +7 -7
- package/src/container.ts +90 -143
- package/src/containerContext.ts +22 -12
- package/src/containerStorageAdapter.ts +7 -6
- package/src/contracts.ts +4 -5
- package/src/debugLogger.ts +3 -4
- package/src/deltaManager.ts +40 -30
- package/src/deltaQueue.ts +2 -2
- package/src/error.ts +5 -4
- package/src/loader.ts +25 -23
- package/src/location-redirection-utilities/resolveWithLocationRedirection.ts +4 -4
- package/src/noopHeuristic.ts +3 -3
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +2 -2
- package/src/protocolTreeDocumentStorageService.ts +4 -1
- package/src/quorum.ts +2 -1
- package/src/retriableDocumentStorageService.ts +6 -5
- package/src/serializedStateManager.ts +299 -111
- package/src/utils.ts +103 -24
- package/api-extractor-cjs.json +0 -8
- package/dist/container-loader-alpha.d.ts +0 -275
- package/dist/container-loader-beta.d.ts +0 -101
- package/dist/container-loader-public.d.ts +0 -101
- package/dist/container-loader-untrimmed.d.ts +0 -331
- package/lib/container-loader-alpha.d.ts +0 -275
- package/lib/container-loader-beta.d.ts +0 -101
- package/lib/container-loader-public.d.ts +0 -101
- package/lib/container-loader-untrimmed.d.ts +0 -331
- package/lib/test/attachment.spec.js +0 -380
- package/lib/test/attachment.spec.js.map +0 -1
- package/lib/test/catchUpMonitor.spec.js +0 -88
- package/lib/test/catchUpMonitor.spec.js.map +0 -1
- package/lib/test/connectionManager.spec.js +0 -201
- package/lib/test/connectionManager.spec.js.map +0 -1
- package/lib/test/connectionStateHandler.spec.js +0 -555
- package/lib/test/connectionStateHandler.spec.js.map +0 -1
- package/lib/test/container.spec.js +0 -64
- package/lib/test/container.spec.js.map +0 -1
- package/lib/test/deltaManager.spec.js +0 -405
- package/lib/test/deltaManager.spec.js.map +0 -1
- package/lib/test/loader.spec.js +0 -212
- package/lib/test/loader.spec.js.map +0 -1
- package/lib/test/locationRedirectionTests.spec.js +0 -44
- package/lib/test/locationRedirectionTests.spec.js.map +0 -1
- package/lib/test/serializedStateManager.spec.js +0 -148
- package/lib/test/serializedStateManager.spec.js.map +0 -1
- package/lib/test/snapshotConversionTest.spec.js +0 -79
- package/lib/test/snapshotConversionTest.spec.js.map +0 -1
- package/lib/test/types/validateContainerLoaderPrevious.generated.js +0 -38
- package/lib/test/types/validateContainerLoaderPrevious.generated.js.map +0 -1
- package/lib/test/utils.spec.js +0 -31
- package/lib/test/utils.spec.js.map +0 -1
- /package/{dist → lib}/tsdoc-metadata.json +0 -0
package/dist/container.js
CHANGED
|
@@ -8,31 +8,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
8
8
|
};
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.Container = exports.ReportIfTooLong = exports.waitContainerToCatchUp = void 0;
|
|
11
|
-
const uuid_1 = require("uuid");
|
|
12
|
-
const core_utils_1 = require("@fluidframework/core-utils");
|
|
13
11
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
14
|
-
const core_interfaces_1 = require("@fluidframework/core-interfaces");
|
|
15
12
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
16
|
-
const
|
|
13
|
+
const internal_1 = require("@fluidframework/container-definitions/internal");
|
|
14
|
+
const core_interfaces_1 = require("@fluidframework/core-interfaces");
|
|
15
|
+
const internal_2 = require("@fluidframework/core-utils/internal");
|
|
16
|
+
const internal_3 = require("@fluidframework/driver-utils/internal");
|
|
17
17
|
const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
18
|
-
const
|
|
18
|
+
const internal_4 = require("@fluidframework/telemetry-utils/internal");
|
|
19
19
|
const structured_clone_1 = __importDefault(require("@ungap/structured-clone"));
|
|
20
|
+
const uuid_1 = require("uuid");
|
|
21
|
+
const attachment_js_1 = require("./attachment.js");
|
|
20
22
|
const audience_js_1 = require("./audience.js");
|
|
23
|
+
const connectionManager_js_1 = require("./connectionManager.js");
|
|
24
|
+
const connectionState_js_1 = require("./connectionState.js");
|
|
25
|
+
const connectionStateHandler_js_1 = require("./connectionStateHandler.js");
|
|
21
26
|
const containerContext_js_1 = require("./containerContext.js");
|
|
27
|
+
const containerStorageAdapter_js_1 = require("./containerStorageAdapter.js");
|
|
22
28
|
const contracts_js_1 = require("./contracts.js");
|
|
23
29
|
const deltaManager_js_1 = require("./deltaManager.js");
|
|
24
30
|
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
31
|
const noopHeuristic_js_1 = require("./noopHeuristic.js");
|
|
31
|
-
const
|
|
32
|
-
const connectionState_js_1 = require("./connectionState.js");
|
|
32
|
+
const packageVersion_js_1 = require("./packageVersion.js");
|
|
33
33
|
const protocol_js_1 = require("./protocol.js");
|
|
34
|
-
const
|
|
34
|
+
const quorum_js_1 = require("./quorum.js");
|
|
35
35
|
const serializedStateManager_js_1 = require("./serializedStateManager.js");
|
|
36
|
+
const utils_js_1 = require("./utils.js");
|
|
36
37
|
const detachedContainerRefSeqNumber = 0;
|
|
37
38
|
const dirtyContainerEvent = "dirty";
|
|
38
39
|
const savedContainerEvent = "saved";
|
|
@@ -57,7 +58,7 @@ const packageNotFactoryError = "Code package does not implement IRuntimeFactory"
|
|
|
57
58
|
async function waitContainerToCatchUp(container) {
|
|
58
59
|
// Make sure we stop waiting if container is closed.
|
|
59
60
|
if (container.closed) {
|
|
60
|
-
throw new
|
|
61
|
+
throw new internal_4.UsageError("waitContainerToCatchUp: Container closed");
|
|
61
62
|
}
|
|
62
63
|
return new Promise((resolve, reject) => {
|
|
63
64
|
const deltaManager = container.deltaManager;
|
|
@@ -65,8 +66,8 @@ async function waitContainerToCatchUp(container) {
|
|
|
65
66
|
container.off("closed", closedCallback);
|
|
66
67
|
const baseMessage = "Container closed while waiting to catch up";
|
|
67
68
|
reject(err !== undefined
|
|
68
|
-
? (0,
|
|
69
|
-
: new
|
|
69
|
+
? (0, internal_4.wrapError)(err, (innerMessage) => new internal_4.GenericError(`${baseMessage}: ${innerMessage}`))
|
|
70
|
+
: new internal_4.GenericError(baseMessage));
|
|
70
71
|
};
|
|
71
72
|
container.on("closed", closedCallback);
|
|
72
73
|
// Depending on config, transition to "connected" state may include the guarantee
|
|
@@ -74,11 +75,11 @@ async function waitContainerToCatchUp(container) {
|
|
|
74
75
|
// Waiting for "connected" state in either case gets us at least to our own Join op
|
|
75
76
|
// which is a reasonable approximation of "caught up"
|
|
76
77
|
const waitForOps = () => {
|
|
77
|
-
(0,
|
|
78
|
+
(0, internal_2.assert)(container.connectionState === connectionState_js_1.ConnectionState.CatchingUp ||
|
|
78
79
|
container.connectionState === connectionState_js_1.ConnectionState.Connected, 0x0cd /* "Container disconnected while waiting for ops!" */);
|
|
79
80
|
const hasCheckpointSequenceNumber = deltaManager.hasCheckpointSequenceNumber;
|
|
80
81
|
const connectionOpSeqNumber = deltaManager.lastKnownSeqNumber;
|
|
81
|
-
(0,
|
|
82
|
+
(0, internal_2.assert)(deltaManager.lastSequenceNumber <= connectionOpSeqNumber, 0x266 /* "lastKnownSeqNumber should never be below last processed sequence number" */);
|
|
82
83
|
if (deltaManager.lastSequenceNumber === connectionOpSeqNumber) {
|
|
83
84
|
container.off("closed", closedCallback);
|
|
84
85
|
resolve(hasCheckpointSequenceNumber);
|
|
@@ -102,10 +103,10 @@ async function waitContainerToCatchUp(container) {
|
|
|
102
103
|
return;
|
|
103
104
|
}
|
|
104
105
|
const callback = () => {
|
|
105
|
-
container.off(
|
|
106
|
+
container.off(internal_4.connectedEventName, callback);
|
|
106
107
|
waitForOps();
|
|
107
108
|
};
|
|
108
|
-
container.on(
|
|
109
|
+
container.on(internal_4.connectedEventName, callback);
|
|
109
110
|
if (container.connectionState === connectionState_js_1.ConnectionState.Disconnected) {
|
|
110
111
|
container.connect();
|
|
111
112
|
}
|
|
@@ -120,7 +121,7 @@ const getCodeProposal = (quorum) => quorum.get("code") ?? quorum.get("code2");
|
|
|
120
121
|
* @param action - functor to call and measure
|
|
121
122
|
*/
|
|
122
123
|
async function ReportIfTooLong(logger, eventName, action) {
|
|
123
|
-
const event =
|
|
124
|
+
const event = internal_4.PerformanceEvent.start(logger, { eventName });
|
|
124
125
|
const props = await action();
|
|
125
126
|
if (event.duration > 200) {
|
|
126
127
|
event.end(props);
|
|
@@ -128,7 +129,7 @@ async function ReportIfTooLong(logger, eventName, action) {
|
|
|
128
129
|
}
|
|
129
130
|
exports.ReportIfTooLong = ReportIfTooLong;
|
|
130
131
|
const summarizerClientType = "summarizer";
|
|
131
|
-
class Container extends
|
|
132
|
+
class Container extends internal_4.EventEmitterWithErrorHandling {
|
|
132
133
|
/**
|
|
133
134
|
* Load an existing container.
|
|
134
135
|
*/
|
|
@@ -136,7 +137,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
136
137
|
const { version, pendingLocalState, loadMode, resolvedUrl, loadToSequenceNumber } = loadProps;
|
|
137
138
|
const container = new Container(createProps, loadProps);
|
|
138
139
|
const disableRecordHeapSize = container.mc.config.getBoolean("Fluid.Loader.DisableRecordHeapSize");
|
|
139
|
-
return
|
|
140
|
+
return internal_4.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "Load" }, async (event) => new Promise((resolve, reject) => {
|
|
140
141
|
const defaultMode = { opsBeforeReturn: "cached" };
|
|
141
142
|
// if we have pendingLocalState, anything we cached is not useful and we shouldn't wait for connection
|
|
142
143
|
// to return container, so ignore this value and use undefined for opsBeforeReturn
|
|
@@ -145,7 +146,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
145
146
|
: loadMode ?? defaultMode;
|
|
146
147
|
const onClosed = (err) => {
|
|
147
148
|
// pre-0.58 error message: containerClosedWithoutErrorDuringLoad
|
|
148
|
-
reject(err ?? new
|
|
149
|
+
reject(err ?? new internal_4.GenericError("Container closed without error during load"));
|
|
149
150
|
};
|
|
150
151
|
container.on("closed", onClosed);
|
|
151
152
|
container
|
|
@@ -157,7 +158,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
157
158
|
event.end({ ...props, ...loadMode });
|
|
158
159
|
resolve(container);
|
|
159
160
|
}, (error) => {
|
|
160
|
-
const err = (0,
|
|
161
|
+
const err = (0, internal_4.normalizeError)(error);
|
|
161
162
|
// Depending where error happens, we can be attempting to connect to web socket
|
|
162
163
|
// and continuously retrying (consider offline mode)
|
|
163
164
|
// Host has no container to close, so it's prudent to do it here
|
|
@@ -175,7 +176,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
175
176
|
*/
|
|
176
177
|
static async createDetached(createProps, codeDetails) {
|
|
177
178
|
const container = new Container(createProps);
|
|
178
|
-
return
|
|
179
|
+
return internal_4.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "CreateDetached" }, async (_event) => {
|
|
179
180
|
await container.createDetached(codeDetails);
|
|
180
181
|
return container;
|
|
181
182
|
}, { start: true, end: true, cancel: "generic" });
|
|
@@ -186,7 +187,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
186
187
|
*/
|
|
187
188
|
static async rehydrateDetachedFromSnapshot(createProps, snapshot) {
|
|
188
189
|
const container = new Container(createProps);
|
|
189
|
-
return
|
|
190
|
+
return internal_4.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "RehydrateDetachedFromSnapshot" }, async (_event) => {
|
|
190
191
|
const detachedContainerState = (0, utils_js_1.getDetachedContainerStateFromSerializedContainer)(snapshot);
|
|
191
192
|
await container.rehydrateDetachedFromSnapshot(detachedContainerState);
|
|
192
193
|
return container;
|
|
@@ -315,14 +316,14 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
315
316
|
*/
|
|
316
317
|
async getEntryPoint() {
|
|
317
318
|
if (this._disposed) {
|
|
318
|
-
throw new
|
|
319
|
+
throw new internal_4.UsageError("The context is already disposed");
|
|
319
320
|
}
|
|
320
321
|
if (this._runtime !== undefined) {
|
|
321
322
|
return this._runtime.getEntryPoint?.();
|
|
322
323
|
}
|
|
323
324
|
return new Promise((resolve, reject) => {
|
|
324
325
|
const runtimeInstantiatedHandler = () => {
|
|
325
|
-
(0,
|
|
326
|
+
(0, internal_2.assert)(this._runtime !== undefined, 0x5a3 /* runtimeInstantiated fired but runtime is still undefined */);
|
|
326
327
|
resolve(this._runtime.getEntryPoint?.());
|
|
327
328
|
this._lifecycleEvents.off("disposed", disposedHandler);
|
|
328
329
|
};
|
|
@@ -369,14 +370,14 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
369
370
|
this._lifecycleEvents = new client_utils_1.TypedEventEmitter();
|
|
370
371
|
this._disposed = false;
|
|
371
372
|
this.attach = (0, utils_js_1.runSingle)(async (request, attachProps) => {
|
|
372
|
-
await
|
|
373
|
+
await internal_4.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
|
|
373
374
|
if (this._lifecycleState !== "loaded" ||
|
|
374
375
|
this.attachmentData.state === container_definitions_1.AttachState.Attached) {
|
|
375
376
|
// pre-0.58 error message: containerNotValidForAttach
|
|
376
|
-
throw new
|
|
377
|
+
throw new internal_4.UsageError(`The Container is not in a valid state for attach [${this._lifecycleState}] and [${this.attachState}]`);
|
|
377
378
|
}
|
|
378
379
|
const normalizeErrorAndClose = (error) => {
|
|
379
|
-
const newError = (0,
|
|
380
|
+
const newError = (0, internal_4.normalizeError)(error);
|
|
380
381
|
this.close(newError);
|
|
381
382
|
// add resolved URL on error object so that host has the ability to find this document and delete it
|
|
382
383
|
newError.addTelemetryProperties({
|
|
@@ -400,7 +401,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
400
401
|
};
|
|
401
402
|
const createAttachmentSummary = (redirectTable) => {
|
|
402
403
|
try {
|
|
403
|
-
(0,
|
|
404
|
+
(0, internal_2.assert)(this.deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
|
|
404
405
|
return (0, utils_js_1.combineAppAndProtocolSummary)(this.runtime.createSummary(redirectTable), this.captureProtocolSummary());
|
|
405
406
|
}
|
|
406
407
|
catch (error) {
|
|
@@ -411,9 +412,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
411
412
|
// Actually go and create the resolved document
|
|
412
413
|
if (this.service === undefined) {
|
|
413
414
|
const createNewResolvedUrl = await this.urlResolver.resolve(request);
|
|
414
|
-
(0,
|
|
415
|
+
(0, internal_2.assert)(this.client.details.type !== summarizerClientType &&
|
|
415
416
|
createNewResolvedUrl !== undefined, 0x2c4 /* "client should not be summarizer before container is created" */);
|
|
416
|
-
this.service = await (0,
|
|
417
|
+
this.service = await (0, internal_3.runWithRetry)(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger, false), "containerAttach", this.mc.logger, {
|
|
417
418
|
cancel: this._deltaManager.closeAbortController.signal,
|
|
418
419
|
});
|
|
419
420
|
}
|
|
@@ -434,7 +435,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
434
435
|
throw normalizeErrorAndClose(error);
|
|
435
436
|
});
|
|
436
437
|
}
|
|
437
|
-
|
|
438
|
+
const snapshotWithBlobs = await attachP;
|
|
439
|
+
this.serializedStateManager.setInitialSnapshot(snapshotWithBlobs);
|
|
438
440
|
if (!this.closed) {
|
|
439
441
|
this.handleDeltaConnectionArg({
|
|
440
442
|
fetchOpsFromStorage: false,
|
|
@@ -493,7 +495,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
493
495
|
const clientType = `${interactive ? "interactive" : "noninteractive"}${type !== undefined && type !== "" ? `/${type}` : ""}`;
|
|
494
496
|
// Need to use the property getter for docId because for detached flow we don't have the docId initially.
|
|
495
497
|
// We assign the id later so property getter is used.
|
|
496
|
-
this.subLogger = (0,
|
|
498
|
+
this.subLogger = (0, internal_4.createChildLogger)({
|
|
497
499
|
logger: subLogger,
|
|
498
500
|
properties: {
|
|
499
501
|
all: {
|
|
@@ -528,7 +530,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
528
530
|
},
|
|
529
531
|
});
|
|
530
532
|
// Prefix all events in this file with container-loader
|
|
531
|
-
this.mc = (0,
|
|
533
|
+
this.mc = (0, internal_4.createChildMonitoringContext)({ logger: this.subLogger, namespace: "Container" });
|
|
532
534
|
this._deltaManager = this.createDeltaManager();
|
|
533
535
|
this.connectionStateHandler = (0, connectionStateHandler_js_1.createConnectionStateHandler)({
|
|
534
536
|
logger: this.mc.logger,
|
|
@@ -584,7 +586,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
584
586
|
// We expose our storage publicly, so it's possible others may call uploadSummaryWithContext() with a
|
|
585
587
|
// non-combined summary tree (in particular, ContainerRuntime.submitSummary). We'll intercept those calls
|
|
586
588
|
// using this callback and fix them up.
|
|
587
|
-
const addProtocolSummaryIfMissing = (summaryTree) => (0,
|
|
589
|
+
const addProtocolSummaryIfMissing = (summaryTree) => (0, internal_3.isCombinedAppAndProtocolSummary)(summaryTree) === true
|
|
588
590
|
? summaryTree
|
|
589
591
|
: (0, utils_js_1.combineAppAndProtocolSummary)(summaryTree, this.captureProtocolSummary());
|
|
590
592
|
// Whether the combined summary tree has been forced on by either the loader option or the monitoring context.
|
|
@@ -636,11 +638,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
636
638
|
this.verifyClosed();
|
|
637
639
|
}
|
|
638
640
|
verifyClosed() {
|
|
639
|
-
(0,
|
|
640
|
-
(0,
|
|
641
|
+
(0, internal_2.assert)(this.connectionState === connectionState_js_1.ConnectionState.Disconnected, 0x0cf /* "disconnect event was not raised!" */);
|
|
642
|
+
(0, internal_2.assert)(this._lifecycleState === "closed" || this._lifecycleState === "disposed", 0x314 /* Container properly closed */);
|
|
641
643
|
}
|
|
642
644
|
closeCore(error) {
|
|
643
|
-
(0,
|
|
645
|
+
(0, internal_2.assert)(!this.closed, 0x315 /* re-entrancy */);
|
|
644
646
|
try {
|
|
645
647
|
// Ensure that we raise all key events even if one of these throws
|
|
646
648
|
try {
|
|
@@ -679,7 +681,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
679
681
|
}
|
|
680
682
|
}
|
|
681
683
|
disposeCore(error) {
|
|
682
|
-
(0,
|
|
684
|
+
(0, internal_2.assert)(!this._disposed, 0x54c /* Container already disposed */);
|
|
683
685
|
this._disposed = true;
|
|
684
686
|
try {
|
|
685
687
|
// Ensure that we raise all key events even if one of these throws
|
|
@@ -735,10 +737,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
735
737
|
}
|
|
736
738
|
async getPendingLocalStateCore(props) {
|
|
737
739
|
if (this.closed || this._disposed) {
|
|
738
|
-
throw new
|
|
740
|
+
throw new internal_4.UsageError("Pending state cannot be retried if the container is closed or disposed");
|
|
739
741
|
}
|
|
740
|
-
(0,
|
|
741
|
-
(0,
|
|
742
|
+
(0, internal_2.assert)(this.attachmentData.state === container_definitions_1.AttachState.Attached, 0x0d1 /* "Container should be attached before close" */);
|
|
743
|
+
(0, internal_2.assert)(this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid", 0x0d2 /* "resolved url should be valid Fluid url" */);
|
|
742
744
|
const pendingState = await this.serializedStateManager.getPendingLocalStateCore(props, this.clientId, this.runtime, this.resolvedUrl);
|
|
743
745
|
return pendingState;
|
|
744
746
|
}
|
|
@@ -747,18 +749,18 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
747
749
|
}
|
|
748
750
|
serialize() {
|
|
749
751
|
if (this.attachmentData.state === container_definitions_1.AttachState.Attached || this.closed) {
|
|
750
|
-
throw new
|
|
752
|
+
throw new internal_4.UsageError("Container must not be attached or closed.");
|
|
751
753
|
}
|
|
752
754
|
const attachingData = this.attachmentData.state === container_definitions_1.AttachState.Attaching ? this.attachmentData : undefined;
|
|
753
755
|
const combinedSummary = attachingData?.summary ??
|
|
754
756
|
(0, utils_js_1.combineAppAndProtocolSummary)(this.runtime.createSummary(), this.captureProtocolSummary());
|
|
755
|
-
const {
|
|
757
|
+
const { baseSnapshot, snapshotBlobs } = (0, utils_js_1.getSnapshotTreeAndBlobsFromSerializedContainer)(combinedSummary);
|
|
756
758
|
const pendingRuntimeState = attachingData !== undefined ? this.runtime.getPendingLocalState() : undefined;
|
|
757
|
-
(0,
|
|
759
|
+
(0, internal_2.assert)(!(0, internal_2.isPromiseLike)(pendingRuntimeState), 0x8e3 /* should not be a promise */);
|
|
758
760
|
const detachedContainerState = {
|
|
759
761
|
attached: false,
|
|
760
|
-
baseSnapshot
|
|
761
|
-
snapshotBlobs
|
|
762
|
+
baseSnapshot,
|
|
763
|
+
snapshotBlobs,
|
|
762
764
|
pendingRuntimeState,
|
|
763
765
|
hasAttachmentBlobs: !!this.detachedBlobStorage && this.detachedBlobStorage.size > 0,
|
|
764
766
|
};
|
|
@@ -782,10 +784,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
782
784
|
}
|
|
783
785
|
connect() {
|
|
784
786
|
if (this.closed) {
|
|
785
|
-
throw new
|
|
787
|
+
throw new internal_4.UsageError(`The Container is closed and cannot be connected`);
|
|
786
788
|
}
|
|
787
789
|
else if (this.attachState !== container_definitions_1.AttachState.Attached) {
|
|
788
|
-
throw new
|
|
790
|
+
throw new internal_4.UsageError(`The Container is not attached and cannot be connected`);
|
|
789
791
|
}
|
|
790
792
|
else if (!this.connected) {
|
|
791
793
|
// Note: no need to fetch ops as we do it preemptively as part of DeltaManager.attachOpHandler().
|
|
@@ -798,8 +800,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
798
800
|
}
|
|
799
801
|
}
|
|
800
802
|
connectInternal(args) {
|
|
801
|
-
(0,
|
|
802
|
-
(0,
|
|
803
|
+
(0, internal_2.assert)(!this.closed, 0x2c5 /* "Attempting to connect() a closed Container" */);
|
|
804
|
+
(0, internal_2.assert)(this.attachState === container_definitions_1.AttachState.Attached, 0x2c6 /* "Attempting to connect() a container that is not attached" */);
|
|
803
805
|
// Resume processing ops and connect to delta stream
|
|
804
806
|
this.resumeInternal(args);
|
|
805
807
|
// Set Auto Reconnect Mode
|
|
@@ -808,20 +810,20 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
808
810
|
}
|
|
809
811
|
disconnect() {
|
|
810
812
|
if (this.closed) {
|
|
811
|
-
throw new
|
|
813
|
+
throw new internal_4.UsageError(`The Container is closed and cannot be disconnected`);
|
|
812
814
|
}
|
|
813
815
|
else {
|
|
814
816
|
this.disconnectInternal({ text: "DocumentDisconnect" });
|
|
815
817
|
}
|
|
816
818
|
}
|
|
817
819
|
disconnectInternal(reason) {
|
|
818
|
-
(0,
|
|
820
|
+
(0, internal_2.assert)(!this.closed, 0x2c7 /* "Attempting to disconnect() a closed Container" */);
|
|
819
821
|
// Set Auto Reconnect Mode
|
|
820
822
|
const mode = contracts_js_1.ReconnectMode.Disabled;
|
|
821
823
|
this.setAutoReconnectInternal(mode, reason);
|
|
822
824
|
}
|
|
823
825
|
resumeInternal(args) {
|
|
824
|
-
(0,
|
|
826
|
+
(0, internal_2.assert)(!this.closed, 0x0d9 /* "Attempting to connect() a closed DeltaManager" */);
|
|
825
827
|
// Resume processing ops
|
|
826
828
|
if (this.inboundQueuePausedFromInit) {
|
|
827
829
|
this.inboundQueuePausedFromInit = false;
|
|
@@ -832,7 +834,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
832
834
|
this.connectToDeltaStream(args);
|
|
833
835
|
}
|
|
834
836
|
async proposeCodeDetails(codeDetails) {
|
|
835
|
-
if (!(0,
|
|
837
|
+
if (!(0, internal_1.isFluidCodeDetails)(codeDetails)) {
|
|
836
838
|
throw new Error("Provided codeDetails are not IFluidCodeDetails");
|
|
837
839
|
}
|
|
838
840
|
if (this.codeLoader.IFluidCodeDetailsComparer) {
|
|
@@ -858,7 +860,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
858
860
|
return;
|
|
859
861
|
}
|
|
860
862
|
// pre-0.58 error message: existingContextDoesNotSatisfyIncomingProposal
|
|
861
|
-
const error = new
|
|
863
|
+
const error = new internal_4.GenericError("Existing context does not satisfy incoming proposal");
|
|
862
864
|
this.close(error);
|
|
863
865
|
}
|
|
864
866
|
/**
|
|
@@ -935,22 +937,24 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
935
937
|
state: container_definitions_1.AttachState.Attached,
|
|
936
938
|
};
|
|
937
939
|
timings.phase2 = client_utils_1.performance.now();
|
|
940
|
+
const supportGetSnapshotApi = this.mc.config.getBoolean("Fluid.Container.UseLoadingGroupIdForSnapshotFetch") ===
|
|
941
|
+
true && this.service?.policies?.supportGetSnapshotApi === true;
|
|
938
942
|
// Fetch specified snapshot.
|
|
939
|
-
const {
|
|
943
|
+
const { baseSnapshot, version } = await this.serializedStateManager.fetchSnapshot(specifiedVersion, supportGetSnapshotApi);
|
|
940
944
|
this._loadedFromVersion = version;
|
|
941
|
-
const attributes = await
|
|
945
|
+
const attributes = await (0, utils_js_1.getDocumentAttributes)(this.storageAdapter, baseSnapshot);
|
|
942
946
|
// If we saved ops, we will replay them and don't need DeltaManager to fetch them
|
|
943
|
-
const
|
|
944
|
-
|
|
947
|
+
const lastProcessedSequenceNumber = pendingLocalState?.savedOps[pendingLocalState.savedOps.length - 1]?.sequenceNumber ??
|
|
948
|
+
attributes.sequenceNumber;
|
|
945
949
|
let opsBeforeReturnP;
|
|
946
950
|
if (loadMode.pauseAfterLoad === true) {
|
|
947
951
|
// If we are trying to pause at a specific sequence number, ensure the latest snapshot is not newer than the desired sequence number.
|
|
948
952
|
if (loadMode.opsBeforeReturn === "sequenceNumber") {
|
|
949
|
-
(0,
|
|
953
|
+
(0, internal_2.assert)(loadToSequenceNumber !== undefined, 0x727 /* sequenceNumber should be defined */);
|
|
950
954
|
// Note: It is possible that we think the latest snapshot is newer than the specified sequence number
|
|
951
955
|
// due to saved ops that may be replayed after the snapshot.
|
|
952
956
|
// https://dev.azure.com/fluidframework/internal/_workitems/edit/5055
|
|
953
|
-
if (
|
|
957
|
+
if (lastProcessedSequenceNumber > loadToSequenceNumber) {
|
|
954
958
|
throw new Error("Cannot satisfy request to pause the container at the specified sequence number. Most recent snapshot is newer than the specified sequence number.");
|
|
955
959
|
}
|
|
956
960
|
}
|
|
@@ -991,24 +995,24 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
991
995
|
case undefined:
|
|
992
996
|
// Start prefetch, but not set opsBeforeReturnP - boot is not blocked by it!
|
|
993
997
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
994
|
-
this.attachDeltaManagerOpHandler(
|
|
998
|
+
this.attachDeltaManagerOpHandler(attributes, loadMode.deltaConnection !== "none" ? "all" : "none", lastProcessedSequenceNumber);
|
|
995
999
|
break;
|
|
996
1000
|
case "sequenceNumber":
|
|
997
1001
|
case "cached":
|
|
998
1002
|
case "all":
|
|
999
|
-
opsBeforeReturnP = this.attachDeltaManagerOpHandler(
|
|
1003
|
+
opsBeforeReturnP = this.attachDeltaManagerOpHandler(attributes, loadMode.opsBeforeReturn, lastProcessedSequenceNumber);
|
|
1000
1004
|
break;
|
|
1001
1005
|
default:
|
|
1002
|
-
(0,
|
|
1006
|
+
(0, internal_2.unreachableCase)(loadMode.opsBeforeReturn);
|
|
1003
1007
|
}
|
|
1004
1008
|
// ...load in the existing quorum
|
|
1005
1009
|
// Initialize the protocol handler
|
|
1006
|
-
await this.initializeProtocolStateFromSnapshot(attributes, this.storageAdapter,
|
|
1010
|
+
await this.initializeProtocolStateFromSnapshot(attributes, this.storageAdapter, baseSnapshot);
|
|
1007
1011
|
timings.phase3 = client_utils_1.performance.now();
|
|
1008
1012
|
const codeDetails = this.getCodeDetailsFromQuorum();
|
|
1009
|
-
await this.instantiateRuntime(codeDetails,
|
|
1013
|
+
await this.instantiateRuntime(codeDetails, baseSnapshot,
|
|
1010
1014
|
// give runtime a dummy value so it knows we're loading from a stash blob
|
|
1011
|
-
pendingLocalState ? pendingLocalState?.pendingRuntimeState ?? {} : undefined, (0,
|
|
1015
|
+
pendingLocalState ? pendingLocalState?.pendingRuntimeState ?? {} : undefined, (0, internal_3.isInstanceOfISnapshot)(baseSnapshot) ? baseSnapshot : undefined);
|
|
1012
1016
|
// replay saved ops
|
|
1013
1017
|
if (pendingLocalState) {
|
|
1014
1018
|
for (const message of pendingLocalState.savedOps) {
|
|
@@ -1026,8 +1030,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1026
1030
|
if (!this.closed) {
|
|
1027
1031
|
if (opsBeforeReturnP !== undefined) {
|
|
1028
1032
|
this._deltaManager.inbound.resume();
|
|
1029
|
-
await
|
|
1030
|
-
await
|
|
1033
|
+
await internal_4.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "WaitOps" }, async () => opsBeforeReturnP);
|
|
1034
|
+
await internal_4.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "WaitOpProcessing" }, async () => this._deltaManager.inbound.waitTillProcessingDone());
|
|
1031
1035
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1032
1036
|
this._deltaManager.inbound.pause();
|
|
1033
1037
|
}
|
|
@@ -1086,15 +1090,15 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1086
1090
|
}
|
|
1087
1091
|
async rehydrateDetachedFromSnapshot({ baseSnapshot, snapshotBlobs, hasAttachmentBlobs, pendingRuntimeState, }) {
|
|
1088
1092
|
if (hasAttachmentBlobs) {
|
|
1089
|
-
(0,
|
|
1093
|
+
(0, internal_2.assert)(!!this.detachedBlobStorage && this.detachedBlobStorage.size > 0, 0x250 /* "serialized container with attachment blobs must be rehydrated with detached blob storage" */);
|
|
1090
1094
|
}
|
|
1091
1095
|
const snapshotTreeWithBlobContents = (0, utils_js_1.combineSnapshotTreeAndSnapshotBlobs)(baseSnapshot, snapshotBlobs);
|
|
1092
1096
|
this.storageAdapter.loadSnapshotFromSnapshotBlobs(snapshotBlobs);
|
|
1093
|
-
const attributes = await
|
|
1097
|
+
const attributes = await (0, utils_js_1.getDocumentAttributes)(this.storageAdapter, snapshotTreeWithBlobContents);
|
|
1094
1098
|
await this.attachDeltaManagerOpHandler(attributes);
|
|
1095
1099
|
// Initialize the protocol handler
|
|
1096
1100
|
const baseTree = (0, utils_js_1.getProtocolSnapshotTree)(snapshotTreeWithBlobContents);
|
|
1097
|
-
const qValues = await (0,
|
|
1101
|
+
const qValues = await (0, internal_3.readAndParse)(this.storageAdapter, baseTree.blobs.quorumValues);
|
|
1098
1102
|
this.initializeProtocolState(attributes, {
|
|
1099
1103
|
members: [],
|
|
1100
1104
|
proposals: [],
|
|
@@ -1104,20 +1108,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1104
1108
|
await this.instantiateRuntime(codeDetails, snapshotTreeWithBlobContents, pendingRuntimeState);
|
|
1105
1109
|
this.setLoaded();
|
|
1106
1110
|
}
|
|
1107
|
-
async getDocumentAttributes(storage, tree) {
|
|
1108
|
-
if (tree === undefined) {
|
|
1109
|
-
return {
|
|
1110
|
-
minimumSequenceNumber: 0,
|
|
1111
|
-
sequenceNumber: 0,
|
|
1112
|
-
};
|
|
1113
|
-
}
|
|
1114
|
-
// Backward compatibility: old docs would have ".attributes" instead of "attributes"
|
|
1115
|
-
const attributesHash = ".protocol" in tree.trees
|
|
1116
|
-
? tree.trees[".protocol"].blobs.attributes
|
|
1117
|
-
: tree.blobs[".attributes"];
|
|
1118
|
-
const attributes = await (0, driver_utils_1.readAndParse)(storage, attributesHash);
|
|
1119
|
-
return attributes;
|
|
1120
|
-
}
|
|
1121
1111
|
async initializeProtocolStateFromSnapshot(attributes, storage, snapshot) {
|
|
1122
1112
|
const quorumSnapshot = {
|
|
1123
1113
|
members: [],
|
|
@@ -1128,16 +1118,16 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1128
1118
|
const baseTree = (0, utils_js_1.getProtocolSnapshotTree)(snapshot);
|
|
1129
1119
|
[quorumSnapshot.members, quorumSnapshot.proposals, quorumSnapshot.values] =
|
|
1130
1120
|
await Promise.all([
|
|
1131
|
-
(0,
|
|
1132
|
-
(0,
|
|
1133
|
-
(0,
|
|
1121
|
+
(0, internal_3.readAndParse)(storage, baseTree.blobs.quorumMembers),
|
|
1122
|
+
(0, internal_3.readAndParse)(storage, baseTree.blobs.quorumProposals),
|
|
1123
|
+
(0, internal_3.readAndParse)(storage, baseTree.blobs.quorumValues),
|
|
1134
1124
|
]);
|
|
1135
1125
|
}
|
|
1136
1126
|
this.initializeProtocolState(attributes, quorumSnapshot);
|
|
1137
1127
|
}
|
|
1138
1128
|
initializeProtocolState(attributes, quorumSnapshot) {
|
|
1139
1129
|
const protocol = this.protocolHandlerBuilder(attributes, quorumSnapshot, (key, value) => this.submitMessage(protocol_definitions_1.MessageType.Propose, JSON.stringify({ key, value })));
|
|
1140
|
-
const protocolLogger = (0,
|
|
1130
|
+
const protocolLogger = (0, internal_4.createChildLogger)({
|
|
1141
1131
|
logger: this.subLogger,
|
|
1142
1132
|
namespace: "ProtocolHandler",
|
|
1143
1133
|
});
|
|
@@ -1153,13 +1143,13 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1153
1143
|
});
|
|
1154
1144
|
protocol.quorum.on("approveProposal", (sequenceNumber, key, value) => {
|
|
1155
1145
|
if (key === "code" || key === "code2") {
|
|
1156
|
-
if (!(0,
|
|
1146
|
+
if (!(0, internal_1.isFluidCodeDetails)(value)) {
|
|
1157
1147
|
this.mc.logger.sendErrorEvent({
|
|
1158
1148
|
eventName: "CodeProposalNotIFluidCodeDetails",
|
|
1159
1149
|
});
|
|
1160
1150
|
}
|
|
1161
1151
|
this.processCodeProposal().catch((error) => {
|
|
1162
|
-
const normalizedError = (0,
|
|
1152
|
+
const normalizedError = (0, internal_4.normalizeError)(error);
|
|
1163
1153
|
this.close(normalizedError);
|
|
1164
1154
|
throw error;
|
|
1165
1155
|
});
|
|
@@ -1241,14 +1231,14 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1241
1231
|
}
|
|
1242
1232
|
createDeltaManager() {
|
|
1243
1233
|
const serviceProvider = () => this.service;
|
|
1244
|
-
const deltaManager = new deltaManager_js_1.DeltaManager(serviceProvider, (0,
|
|
1234
|
+
const deltaManager = new deltaManager_js_1.DeltaManager(serviceProvider, (0, internal_4.createChildLogger)({ logger: this.subLogger, namespace: "DeltaManager" }), () => this.activeConnection(), (props) => new connectionManager_js_1.ConnectionManager(serviceProvider, () => this.isDirty, this.client, this._canReconnect, (0, internal_4.createChildLogger)({ logger: this.subLogger, namespace: "ConnectionManager" }), props));
|
|
1245
1235
|
// Disable inbound queues as Container is not ready to accept any ops until we are fully loaded!
|
|
1246
1236
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1247
1237
|
deltaManager.inbound.pause();
|
|
1248
1238
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1249
1239
|
deltaManager.inboundSignal.pause();
|
|
1250
1240
|
deltaManager.on("connect", (details, _opsBehind) => {
|
|
1251
|
-
(0,
|
|
1241
|
+
(0, internal_2.assert)(this.connectionMode === details.mode, 0x4b7 /* mismatch */);
|
|
1252
1242
|
this.connectionStateHandler.receivedConnectEvent(details);
|
|
1253
1243
|
});
|
|
1254
1244
|
deltaManager.on("establishingConnection", (reason) => {
|
|
@@ -1284,13 +1274,13 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1284
1274
|
});
|
|
1285
1275
|
return deltaManager;
|
|
1286
1276
|
}
|
|
1287
|
-
async attachDeltaManagerOpHandler(attributes, prefetchType) {
|
|
1277
|
+
async attachDeltaManagerOpHandler(attributes, prefetchType, lastProcessedSequenceNumber) {
|
|
1288
1278
|
return this._deltaManager.attachOpHandler(attributes.minimumSequenceNumber, attributes.sequenceNumber, {
|
|
1289
1279
|
process: (message) => this.processRemoteMessage(message),
|
|
1290
1280
|
processSignal: (message) => {
|
|
1291
1281
|
this.processSignal(message);
|
|
1292
1282
|
},
|
|
1293
|
-
}, prefetchType);
|
|
1283
|
+
}, prefetchType, lastProcessedSequenceNumber);
|
|
1294
1284
|
}
|
|
1295
1285
|
logConnectionStateChangeTelemetry(value, oldState, reason) {
|
|
1296
1286
|
// Log actual event
|
|
@@ -1309,7 +1299,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1309
1299
|
if (value === connectionState_js_1.ConnectionState.Connected) {
|
|
1310
1300
|
durationFromDisconnected =
|
|
1311
1301
|
time - this.connectionTransitionTimes[connectionState_js_1.ConnectionState.Disconnected];
|
|
1312
|
-
durationFromDisconnected = (0,
|
|
1302
|
+
durationFromDisconnected = (0, internal_4.formatTick)(durationFromDisconnected);
|
|
1313
1303
|
}
|
|
1314
1304
|
else if (value === connectionState_js_1.ConnectionState.CatchingUp) {
|
|
1315
1305
|
// This info is of most interesting while Catching Up.
|
|
@@ -1333,7 +1323,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1333
1323
|
clientId: this.clientId,
|
|
1334
1324
|
autoReconnect,
|
|
1335
1325
|
opsBehind,
|
|
1336
|
-
online:
|
|
1326
|
+
online: internal_3.OnlineStatus[(0, internal_3.isOnline)()],
|
|
1337
1327
|
lastVisible: this.lastVisible !== undefined
|
|
1338
1328
|
? client_utils_1.performance.now() - this.lastVisible
|
|
1339
1329
|
: undefined,
|
|
@@ -1359,7 +1349,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1359
1349
|
// Both protocol and context should not be undefined if we got so far.
|
|
1360
1350
|
this.setContextConnectedState(state, this.readOnlyInfo.readonly ?? false);
|
|
1361
1351
|
this.protocolHandler.setConnectionState(state, this.clientId);
|
|
1362
|
-
(0,
|
|
1352
|
+
(0, internal_4.raiseConnectedEvent)(this.mc.logger, this, state, this.clientId, disconnectedReason?.text);
|
|
1363
1353
|
}
|
|
1364
1354
|
// back-compat: ADO #1385: Remove in the future, summary op should come through submitSummaryMessage()
|
|
1365
1355
|
submitContainerMessage(type, contents, batch, metadata) {
|
|
@@ -1369,7 +1359,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1369
1359
|
case protocol_definitions_1.MessageType.Summarize:
|
|
1370
1360
|
return this.submitSummaryMessage(contents);
|
|
1371
1361
|
default: {
|
|
1372
|
-
const newError = new
|
|
1362
|
+
const newError = new internal_4.GenericError("invalidContainerSubmitOpType", undefined /* error */, { messageType: type });
|
|
1373
1363
|
this.close(newError);
|
|
1374
1364
|
return -1;
|
|
1375
1365
|
}
|
|
@@ -1419,13 +1409,13 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1419
1409
|
// That means that if relay service changes settings, such changes will impact only newly booted
|
|
1420
1410
|
// clients.
|
|
1421
1411
|
// All existing will continue to use settings they got earlier.
|
|
1422
|
-
(0,
|
|
1412
|
+
(0, internal_2.assert)(serviceConfiguration !== undefined, 0x2e4 /* "there should be service config for active connection" */);
|
|
1423
1413
|
this.noopHeuristic = new noopHeuristic_js_1.NoopHeuristic(serviceConfiguration.noopTimeFrequency, serviceConfiguration.noopCountFrequency);
|
|
1424
1414
|
this.noopHeuristic.on("wantsNoop", () => {
|
|
1425
1415
|
// On disconnect we notify the heuristic which should prevent it from wanting a noop.
|
|
1426
1416
|
// Hitting this assert would imply we lost activeConnection between notifying the heuristic of a processed message and
|
|
1427
1417
|
// running the microtask that the heuristic queued in response.
|
|
1428
|
-
(0,
|
|
1418
|
+
(0, internal_2.assert)(this.activeConnection(), 0x241 /* "Trying to send noop without active connection" */);
|
|
1429
1419
|
this.submitMessage(protocol_definitions_1.MessageType.NoOp);
|
|
1430
1420
|
});
|
|
1431
1421
|
}
|
|
@@ -1433,11 +1423,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1433
1423
|
// The contract with the protocolHandler is that returning "immediateNoOp" is equivalent to "please immediately accept the proposal I just processed".
|
|
1434
1424
|
if (result.immediateNoOp === true) {
|
|
1435
1425
|
// ADO:1385: Remove cast and use MessageType once definition changes propagate
|
|
1436
|
-
this.submitMessage(
|
|
1426
|
+
this.submitMessage(internal_3.MessageType2.Accept);
|
|
1437
1427
|
}
|
|
1438
1428
|
}
|
|
1439
1429
|
this.emit("op", message);
|
|
1440
1430
|
}
|
|
1431
|
+
// unknown should be removed once `@alpha` tag is removed from IContainerContext
|
|
1441
1432
|
submitSignal(content, targetClientId) {
|
|
1442
1433
|
this._deltaManager.submitSignal(JSON.stringify(content), targetClientId);
|
|
1443
1434
|
}
|
|
@@ -1452,12 +1443,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1452
1443
|
}
|
|
1453
1444
|
}
|
|
1454
1445
|
async instantiateRuntime(codeDetails, snapshotTree, pendingLocalState, snapshot) {
|
|
1455
|
-
(0,
|
|
1446
|
+
(0, internal_2.assert)(this._runtime?.disposed !== false, 0x0dd /* "Existing runtime not disposed" */);
|
|
1456
1447
|
// The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
|
|
1457
1448
|
// are set. Global requests will still go directly to the loader
|
|
1458
1449
|
const maybeLoader = this.scope;
|
|
1459
1450
|
const loader = new loader_js_1.RelativeLoader(this, maybeLoader.ILoader);
|
|
1460
|
-
const loadCodeResult = await
|
|
1451
|
+
const loadCodeResult = await internal_4.PerformanceEvent.timedExecAsync(this.subLogger, { eventName: "CodeLoad" }, async () => this.codeLoader.load(codeDetails));
|
|
1461
1452
|
this._loadedModule = {
|
|
1462
1453
|
module: loadCodeResult.module,
|
|
1463
1454
|
// An older interface ICodeLoader could return an IFluidModule which didn't have details.
|
|
@@ -1470,11 +1461,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1470
1461
|
if (runtimeFactory === undefined) {
|
|
1471
1462
|
throw new Error(packageNotFactoryError);
|
|
1472
1463
|
}
|
|
1473
|
-
const getSpecifiedCodeDetails = () => (this.protocolHandler.quorum.get("code") ??
|
|
1474
|
-
this.protocolHandler.quorum.get("code2"));
|
|
1475
1464
|
const existing = snapshotTree !== undefined;
|
|
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,
|
|
1477
|
-
this._runtime = await
|
|
1465
|
+
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, this._deltaManager.clientDetails, existing, this.subLogger, pendingLocalState, snapshot);
|
|
1466
|
+
this._runtime = await internal_4.PerformanceEvent.timedExecAsync(this.subLogger, { eventName: "InstantiateRuntime" }, async () => runtimeFactory.instantiateRuntime(context, existing));
|
|
1478
1467
|
this._lifecycleEvents.emit("runtimeInstantiated");
|
|
1479
1468
|
this._loadedCodeDetails = codeDetails;
|
|
1480
1469
|
}
|
|
@@ -1504,7 +1493,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1504
1493
|
}
|
|
1505
1494
|
// intentional fallthrough
|
|
1506
1495
|
case "delayed":
|
|
1507
|
-
(0,
|
|
1496
|
+
(0, internal_2.assert)(this.inboundQueuePausedFromInit, 0x346 /* inboundQueuePausedFromInit should be true */);
|
|
1508
1497
|
this.inboundQueuePausedFromInit = false;
|
|
1509
1498
|
this._deltaManager.inbound.resume();
|
|
1510
1499
|
this._deltaManager.inboundSignal.resume();
|
|
@@ -1512,7 +1501,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1512
1501
|
case "none":
|
|
1513
1502
|
break;
|
|
1514
1503
|
default:
|
|
1515
|
-
(0,
|
|
1504
|
+
(0, internal_2.unreachableCase)(deltaConnectionArg);
|
|
1516
1505
|
}
|
|
1517
1506
|
}
|
|
1518
1507
|
}
|