@fluidframework/container-loader 2.0.0-internal.4.3.0 → 2.0.0-internal.5.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 +28 -0
- package/README.md +6 -3
- package/dist/connectionManager.d.ts +5 -3
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +19 -15
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +11 -9
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +11 -11
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +62 -36
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +71 -89
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +2 -2
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +3 -7
- 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.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/deltaManager.d.ts +3 -2
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +4 -5
- package/dist/deltaManager.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +9 -5
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +28 -34
- package/dist/loader.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/retriableDocumentStorageService.d.ts +3 -2
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/lib/connectionManager.d.ts +5 -3
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +20 -16
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +11 -9
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +12 -12
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +62 -36
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +72 -90
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +2 -2
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +3 -7
- 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.map +1 -1
- package/lib/contracts.d.ts +3 -3
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/deltaManager.d.ts +3 -2
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +5 -6
- package/lib/deltaManager.js.map +1 -1
- package/lib/index.d.ts +1 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/loader.d.ts +9 -5
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +28 -34
- package/lib/loader.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/retriableDocumentStorageService.d.ts +3 -2
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/package.json +27 -10
- package/src/connectionManager.ts +29 -20
- package/src/connectionStateHandler.ts +26 -17
- package/src/container.ts +169 -147
- package/src/containerContext.ts +3 -9
- package/src/containerStorageAdapter.ts +4 -4
- package/src/contracts.ts +3 -3
- package/src/deltaManager.ts +13 -8
- package/src/index.ts +1 -8
- package/src/loader.ts +56 -47
- package/src/packageVersion.ts +1 -1
- package/src/retriableDocumentStorageService.ts +3 -2
package/dist/container.js
CHANGED
|
@@ -127,14 +127,11 @@ async function ReportIfTooLong(logger, eventName, action) {
|
|
|
127
127
|
}
|
|
128
128
|
exports.ReportIfTooLong = ReportIfTooLong;
|
|
129
129
|
const summarizerClientType = "summarizer";
|
|
130
|
-
/**
|
|
131
|
-
* @deprecated - In the next release Container will no longer be exported, IContainer should be used in its place.
|
|
132
|
-
*/
|
|
133
130
|
class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
134
131
|
/**
|
|
135
132
|
* @internal
|
|
136
133
|
*/
|
|
137
|
-
constructor(
|
|
134
|
+
constructor(createProps, loadProps) {
|
|
138
135
|
var _a, _b, _c;
|
|
139
136
|
super((name, error) => {
|
|
140
137
|
this.mc.logger.sendErrorEvent({
|
|
@@ -142,8 +139,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
142
139
|
name: typeof name === "string" ? name : undefined,
|
|
143
140
|
}, error);
|
|
144
141
|
});
|
|
145
|
-
this.
|
|
146
|
-
this.protocolHandlerBuilder = protocolHandlerBuilder;
|
|
142
|
+
this.createProps = createProps;
|
|
147
143
|
// Tells if container can reconnect on losing fist connection
|
|
148
144
|
// If false, container gets closed on loss of connection.
|
|
149
145
|
this._canReconnect = true;
|
|
@@ -174,10 +170,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
174
170
|
this.savedOps = [];
|
|
175
171
|
this.setAutoReconnectTime = common_utils_1.performance.now();
|
|
176
172
|
this._disposed = false;
|
|
177
|
-
this.clientDetailsOverride =
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
this._canReconnect = config.canReconnect;
|
|
173
|
+
this.clientDetailsOverride = createProps.clientDetailsOverride;
|
|
174
|
+
if (createProps.canReconnect !== undefined) {
|
|
175
|
+
this._canReconnect = createProps.canReconnect;
|
|
181
176
|
}
|
|
182
177
|
// Create logger for data stores to use
|
|
183
178
|
const type = this.client.details.type;
|
|
@@ -185,15 +180,15 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
185
180
|
const clientType = `${interactive ? "interactive" : "noninteractive"}${type !== undefined && type !== "" ? `/${type}` : ""}`;
|
|
186
181
|
// Need to use the property getter for docId because for detached flow we don't have the docId initially.
|
|
187
182
|
// We assign the id later so property getter is used.
|
|
188
|
-
this.subLogger = telemetry_utils_1.ChildLogger.create(
|
|
183
|
+
this.subLogger = telemetry_utils_1.ChildLogger.create(createProps.subLogger, undefined, {
|
|
189
184
|
all: {
|
|
190
185
|
clientType,
|
|
191
186
|
containerId: (0, uuid_1.v4)(),
|
|
192
|
-
docId: () => { var _a
|
|
187
|
+
docId: () => { var _a; return (_a = this.resolvedUrl) === null || _a === void 0 ? void 0 : _a.id; },
|
|
193
188
|
containerAttachState: () => this._attachState,
|
|
194
189
|
containerLifecycleState: () => this._lifecycleState,
|
|
195
190
|
containerConnectionState: () => connectionState_1.ConnectionState[this.connectionState],
|
|
196
|
-
serializedContainer:
|
|
191
|
+
serializedContainer: (loadProps === null || loadProps === void 0 ? void 0 : loadProps.pendingLocalState) !== undefined,
|
|
197
192
|
},
|
|
198
193
|
// we need to be judicious with our logging here to avoid generating too much data
|
|
199
194
|
// all data logged here should be broadly applicable, and not specific to a
|
|
@@ -219,15 +214,15 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
219
214
|
// Warning: this is only a shallow clone. Mutation of any individual loader option will mutate it for
|
|
220
215
|
// all clients that were loaded from the same loader (including summarizer clients).
|
|
221
216
|
// Tracking alternative ways to handle this in AB#4129.
|
|
222
|
-
this.options = Object.assign({}, this.
|
|
217
|
+
this.options = Object.assign({}, this.createProps.options);
|
|
223
218
|
this._deltaManager = this.createDeltaManager();
|
|
224
219
|
this.connectionStateHandler = (0, connectionStateHandler_1.createConnectionStateHandler)({
|
|
225
220
|
logger: this.mc.logger,
|
|
226
|
-
connectionStateChanged: (value, oldState, reason) => {
|
|
221
|
+
connectionStateChanged: (value, oldState, reason, error) => {
|
|
227
222
|
if (value === connectionState_1.ConnectionState.Connected) {
|
|
228
223
|
this._clientId = this.connectionStateHandler.pendingClientId;
|
|
229
224
|
}
|
|
230
|
-
this.logConnectionStateChangeTelemetry(value, oldState, reason);
|
|
225
|
+
this.logConnectionStateChangeTelemetry(value, oldState, reason, error);
|
|
231
226
|
if (this._lifecycleState === "loaded") {
|
|
232
227
|
this.propagateConnectionState(false /* initial transition */, value === connectionState_1.ConnectionState.Disconnected
|
|
233
228
|
? reason
|
|
@@ -235,7 +230,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
235
230
|
}
|
|
236
231
|
},
|
|
237
232
|
shouldClientJoinWrite: () => this._deltaManager.connectionManager.shouldJoinWrite(),
|
|
238
|
-
maxClientLeaveWaitTime: this.
|
|
233
|
+
maxClientLeaveWaitTime: this.createProps.options.maxClientLeaveWaitTime,
|
|
239
234
|
logConnectionIssue: (eventName, category, details) => {
|
|
240
235
|
const mode = this.connectionMode;
|
|
241
236
|
// We get here when socket does not receive any ops on "write" connection, including
|
|
@@ -259,7 +254,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
259
254
|
this.connect();
|
|
260
255
|
}
|
|
261
256
|
},
|
|
262
|
-
}, this.deltaManager, (_a =
|
|
257
|
+
}, this.deltaManager, (_a = loadProps === null || loadProps === void 0 ? void 0 : loadProps.pendingLocalState) === null || _a === void 0 ? void 0 : _a.clientId);
|
|
263
258
|
this.on(savedContainerEvent, () => {
|
|
264
259
|
this.connectionStateHandler.containerSaved();
|
|
265
260
|
});
|
|
@@ -271,8 +266,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
271
266
|
: (0, driver_utils_1.combineAppAndProtocolSummary)(summaryTree, this.captureProtocolSummary());
|
|
272
267
|
// Whether the combined summary tree has been forced on by either the loader option or the monitoring context.
|
|
273
268
|
// Even if not forced on via this flag, combined summaries may still be enabled by service policy.
|
|
274
|
-
const forceEnableSummarizeProtocolTree = (_b = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree2")) !== null && _b !== void 0 ? _b : this.
|
|
275
|
-
this.storageAdapter = new containerStorageAdapter_1.ContainerStorageAdapter(this.
|
|
269
|
+
const forceEnableSummarizeProtocolTree = (_b = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree2")) !== null && _b !== void 0 ? _b : this.createProps.options.summarizeProtocolTree;
|
|
270
|
+
this.storageAdapter = new containerStorageAdapter_1.ContainerStorageAdapter(this.createProps.detachedBlobStorage, this.mc.logger, (_c = loadProps === null || loadProps === void 0 ? void 0 : loadProps.pendingLocalState) === null || _c === void 0 ? void 0 : _c.snapshotBlobs, addProtocolSummaryIfMissing, forceEnableSummarizeProtocolTree);
|
|
276
271
|
const isDomAvailable = typeof document === "object" &&
|
|
277
272
|
document !== null &&
|
|
278
273
|
typeof document.addEventListener === "function" &&
|
|
@@ -294,37 +289,34 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
294
289
|
document.addEventListener("visibilitychange", this.visibilityEventHandler);
|
|
295
290
|
}
|
|
296
291
|
}
|
|
292
|
+
static async clone(container, loadProps, createParamOverrides) {
|
|
293
|
+
return this.load(loadProps, Object.assign(Object.assign({}, container.createProps), createParamOverrides));
|
|
294
|
+
}
|
|
297
295
|
/**
|
|
298
296
|
* Load an existing container.
|
|
299
297
|
* @internal
|
|
300
298
|
*/
|
|
301
|
-
static async load(
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
resolvedUrl: loadOptions.resolvedUrl,
|
|
305
|
-
canReconnect: loadOptions.canReconnect,
|
|
306
|
-
serializedContainerState: pendingLocalState,
|
|
307
|
-
}, protocolHandlerBuilder);
|
|
299
|
+
static async load(loadProps, createProps) {
|
|
300
|
+
const { version, pendingLocalState, loadMode, resolvedUrl } = loadProps;
|
|
301
|
+
const container = new Container(createProps, loadProps);
|
|
308
302
|
return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "Load" }, async (event) => new Promise((resolve, reject) => {
|
|
309
|
-
var _a, _b;
|
|
310
|
-
const version = loadOptions.version;
|
|
311
303
|
const defaultMode = { opsBeforeReturn: "cached" };
|
|
312
304
|
// if we have pendingLocalState, anything we cached is not useful and we shouldn't wait for connection
|
|
313
305
|
// to return container, so ignore this value and use undefined for opsBeforeReturn
|
|
314
306
|
const mode = pendingLocalState
|
|
315
|
-
? Object.assign(Object.assign({}, (
|
|
307
|
+
? Object.assign(Object.assign({}, (loadMode !== null && loadMode !== void 0 ? loadMode : defaultMode)), { opsBeforeReturn: undefined }) : loadMode !== null && loadMode !== void 0 ? loadMode : defaultMode;
|
|
316
308
|
const onClosed = (err) => {
|
|
317
309
|
// pre-0.58 error message: containerClosedWithoutErrorDuringLoad
|
|
318
310
|
reject(err !== null && err !== void 0 ? err : new container_utils_1.GenericError("Container closed without error during load"));
|
|
319
311
|
};
|
|
320
312
|
container.on("closed", onClosed);
|
|
321
313
|
container
|
|
322
|
-
.load(version, mode, pendingLocalState)
|
|
314
|
+
.load(version, mode, resolvedUrl, pendingLocalState)
|
|
323
315
|
.finally(() => {
|
|
324
316
|
container.removeListener("closed", onClosed);
|
|
325
317
|
})
|
|
326
318
|
.then((props) => {
|
|
327
|
-
event.end(Object.assign(Object.assign({}, props),
|
|
319
|
+
event.end(Object.assign(Object.assign({}, props), loadMode));
|
|
328
320
|
resolve(container);
|
|
329
321
|
}, (error) => {
|
|
330
322
|
const err = (0, telemetry_utils_1.normalizeError)(error);
|
|
@@ -339,8 +331,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
339
331
|
/**
|
|
340
332
|
* Create a new container in a detached state.
|
|
341
333
|
*/
|
|
342
|
-
static async createDetached(
|
|
343
|
-
const container = new Container(
|
|
334
|
+
static async createDetached(createProps, codeDetails) {
|
|
335
|
+
const container = new Container(createProps);
|
|
344
336
|
return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "CreateDetached" }, async (_event) => {
|
|
345
337
|
await container.createDetached(codeDetails);
|
|
346
338
|
return container;
|
|
@@ -350,8 +342,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
350
342
|
* Create a new container in a detached state that is initialized with a
|
|
351
343
|
* snapshot from a previous detached container.
|
|
352
344
|
*/
|
|
353
|
-
static async rehydrateDetachedFromSnapshot(
|
|
354
|
-
const container = new Container(
|
|
345
|
+
static async rehydrateDetachedFromSnapshot(createProps, snapshot) {
|
|
346
|
+
const container = new Container(createProps);
|
|
355
347
|
return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "RehydrateDetachedFromSnapshot" }, async (_event) => {
|
|
356
348
|
const deserializedSummary = JSON.parse(snapshot);
|
|
357
349
|
await container.rehydrateDetachedFromSnapshot(deserializedSummary);
|
|
@@ -395,7 +387,19 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
395
387
|
return this;
|
|
396
388
|
}
|
|
397
389
|
get resolvedUrl() {
|
|
398
|
-
|
|
390
|
+
var _a;
|
|
391
|
+
/**
|
|
392
|
+
* All attached containers will have a document service,
|
|
393
|
+
* this is required, as attached containers are attached to
|
|
394
|
+
* a service. Detached containers will neither have a document
|
|
395
|
+
* service or a resolved url as they only exist locally.
|
|
396
|
+
* in order to create a document service a resolved url must
|
|
397
|
+
* first be obtained, this is how the container is identified.
|
|
398
|
+
* Because of this, the document service's resolved url
|
|
399
|
+
* is always the same as the containers, as we had to
|
|
400
|
+
* obtain the resolved url, and then create the service from it.
|
|
401
|
+
*/
|
|
402
|
+
return (_a = this.service) === null || _a === void 0 ? void 0 : _a.resolvedUrl;
|
|
399
403
|
}
|
|
400
404
|
get loadedFromVersion() {
|
|
401
405
|
return this._loadedFromVersion;
|
|
@@ -482,16 +486,16 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
482
486
|
return this._dirtyContainer;
|
|
483
487
|
}
|
|
484
488
|
get serviceFactory() {
|
|
485
|
-
return this.
|
|
489
|
+
return this.createProps.documentServiceFactory;
|
|
486
490
|
}
|
|
487
491
|
get urlResolver() {
|
|
488
|
-
return this.
|
|
492
|
+
return this.createProps.urlResolver;
|
|
489
493
|
}
|
|
490
494
|
get scope() {
|
|
491
|
-
return this.
|
|
495
|
+
return this.createProps.scope;
|
|
492
496
|
}
|
|
493
497
|
get codeLoader() {
|
|
494
|
-
return this.
|
|
498
|
+
return this.createProps.codeLoader;
|
|
495
499
|
}
|
|
496
500
|
/**
|
|
497
501
|
* {@inheritDoc @fluidframework/container-definitions#IContainer.entryPoint}
|
|
@@ -548,7 +552,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
548
552
|
(0, common_utils_1.assert)(this._lifecycleState === "closed" || this._lifecycleState === "disposed", 0x314 /* Container properly closed */);
|
|
549
553
|
}
|
|
550
554
|
closeCore(error) {
|
|
551
|
-
var _a
|
|
555
|
+
var _a;
|
|
552
556
|
(0, common_utils_1.assert)(!this.closed, 0x315 /* re-entrancy */);
|
|
553
557
|
try {
|
|
554
558
|
// Ensure that we raise all key events even if one of these throws
|
|
@@ -566,12 +570,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
566
570
|
this._lifecycleState = "closing";
|
|
567
571
|
(_a = this._protocolHandler) === null || _a === void 0 ? void 0 : _a.close();
|
|
568
572
|
this.connectionStateHandler.dispose();
|
|
569
|
-
(_b = this._context) === null || _b === void 0 ? void 0 : _b.dispose(error !== undefined ? new Error(error.message) : undefined);
|
|
570
|
-
this.storageAdapter.dispose();
|
|
571
|
-
// Notify storage about critical errors. They may be due to disconnect between client & server knowledge
|
|
572
|
-
// about file, like file being overwritten in storage, but client having stale local cache.
|
|
573
|
-
// Driver need to ensure all caches are cleared on critical errors
|
|
574
|
-
(_c = this.service) === null || _c === void 0 ? void 0 : _c.dispose(error);
|
|
575
573
|
}
|
|
576
574
|
catch (exception) {
|
|
577
575
|
this.mc.logger.sendErrorEvent({ eventName: "ContainerCloseException" }, exception);
|
|
@@ -660,8 +658,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
660
658
|
const appSummary = this.context.createSummary();
|
|
661
659
|
const protocolSummary = this.captureProtocolSummary();
|
|
662
660
|
const combinedSummary = (0, driver_utils_1.combineAppAndProtocolSummary)(appSummary, protocolSummary);
|
|
663
|
-
if (this.
|
|
664
|
-
this.loader.services.detachedBlobStorage.size > 0) {
|
|
661
|
+
if (this.createProps.detachedBlobStorage && this.createProps.detachedBlobStorage.size > 0) {
|
|
665
662
|
combinedSummary.tree[".hasAttachmentBlobs"] = {
|
|
666
663
|
type: protocol_definitions_1.SummaryType.Blob,
|
|
667
664
|
content: "true",
|
|
@@ -680,8 +677,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
680
677
|
(0, common_utils_1.assert)(this._attachState === container_definitions_1.AttachState.Detached && !this.attachStarted, 0x205 /* "attach() called more than once" */);
|
|
681
678
|
this.attachStarted = true;
|
|
682
679
|
// If attachment blobs were uploaded in detached state we will go through a different attach flow
|
|
683
|
-
const hasAttachmentBlobs = this.
|
|
684
|
-
this.
|
|
680
|
+
const hasAttachmentBlobs = this.createProps.detachedBlobStorage !== undefined &&
|
|
681
|
+
this.createProps.detachedBlobStorage.size > 0;
|
|
685
682
|
try {
|
|
686
683
|
(0, common_utils_1.assert)(this.deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
|
|
687
684
|
let summary;
|
|
@@ -705,31 +702,28 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
705
702
|
}
|
|
706
703
|
}
|
|
707
704
|
// Actually go and create the resolved document
|
|
708
|
-
const createNewResolvedUrl = await this.urlResolver.resolve(request);
|
|
709
|
-
(0, driver_utils_1.ensureFluidResolvedUrl)(createNewResolvedUrl);
|
|
710
705
|
if (this.service === undefined) {
|
|
711
|
-
|
|
706
|
+
const createNewResolvedUrl = await this.urlResolver.resolve(request);
|
|
707
|
+
(0, common_utils_1.assert)(this.client.details.type !== summarizerClientType &&
|
|
708
|
+
createNewResolvedUrl !== undefined, 0x2c4 /* "client should not be summarizer before container is created" */);
|
|
712
709
|
this.service = await (0, driver_utils_1.runWithRetry)(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger, false), "containerAttach", this.mc.logger, {
|
|
713
710
|
cancel: this.closeSignal,
|
|
714
711
|
});
|
|
715
712
|
}
|
|
716
|
-
const resolvedUrl = this.service.resolvedUrl;
|
|
717
|
-
(0, driver_utils_1.ensureFluidResolvedUrl)(resolvedUrl);
|
|
718
|
-
this._resolvedUrl = resolvedUrl;
|
|
719
713
|
await this.storageAdapter.connectToService(this.service);
|
|
720
714
|
if (hasAttachmentBlobs) {
|
|
721
715
|
// upload blobs to storage
|
|
722
|
-
(0, common_utils_1.assert)(!!this.
|
|
716
|
+
(0, common_utils_1.assert)(!!this.createProps.detachedBlobStorage, 0x24e /* "assertion for type narrowing" */);
|
|
723
717
|
// build a table mapping IDs assigned locally to IDs assigned by storage and pass it to runtime to
|
|
724
718
|
// support blob handles that only know about the local IDs
|
|
725
719
|
const redirectTable = new Map();
|
|
726
720
|
// if new blobs are added while uploading, upload them too
|
|
727
|
-
while (redirectTable.size < this.
|
|
728
|
-
const newIds = this.
|
|
721
|
+
while (redirectTable.size < this.createProps.detachedBlobStorage.size) {
|
|
722
|
+
const newIds = this.createProps.detachedBlobStorage
|
|
729
723
|
.getBlobIds()
|
|
730
724
|
.filter((id) => !redirectTable.has(id));
|
|
731
725
|
for (const id of newIds) {
|
|
732
|
-
const blob = await this.
|
|
726
|
+
const blob = await this.createProps.detachedBlobStorage.readBlob(id);
|
|
733
727
|
const response = await this.storageAdapter.createBlob(blob);
|
|
734
728
|
redirectTable.set(id, response.id);
|
|
735
729
|
}
|
|
@@ -764,12 +758,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
764
758
|
catch (error) {
|
|
765
759
|
// add resolved URL on error object so that host has the ability to find this document and delete it
|
|
766
760
|
const newError = (0, telemetry_utils_1.normalizeError)(error);
|
|
767
|
-
|
|
768
|
-
if ((0, driver_utils_1.isFluidResolvedUrl)(resolvedUrl)) {
|
|
769
|
-
newError.addTelemetryProperties({ resolvedUrl: resolvedUrl.url });
|
|
770
|
-
}
|
|
761
|
+
newError.addTelemetryProperties({ resolvedUrl: (_a = this.resolvedUrl) === null || _a === void 0 ? void 0 : _a.url });
|
|
771
762
|
this.close(newError);
|
|
772
|
-
(_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, newError);
|
|
773
763
|
throw newError;
|
|
774
764
|
}
|
|
775
765
|
}, { start: true, end: true, cancel: "generic" });
|
|
@@ -864,7 +854,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
864
854
|
.catch(() => false);
|
|
865
855
|
}
|
|
866
856
|
async processCodeProposal() {
|
|
867
|
-
var _a;
|
|
868
857
|
const codeDetails = this.getCodeDetailsFromQuorum();
|
|
869
858
|
await Promise.all([
|
|
870
859
|
this.deltaManager.inbound.pause(),
|
|
@@ -878,7 +867,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
878
867
|
// pre-0.58 error message: existingContextDoesNotSatisfyIncomingProposal
|
|
879
868
|
const error = new container_utils_1.GenericError("Existing context does not satisfy incoming proposal");
|
|
880
869
|
this.close(error);
|
|
881
|
-
(_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
|
882
870
|
}
|
|
883
871
|
async getVersion(version) {
|
|
884
872
|
const versions = await this.storageAdapter.getVersions(version, 1);
|
|
@@ -902,12 +890,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
902
890
|
*
|
|
903
891
|
* @param specifiedVersion - Version SHA to load snapshot. If not specified, will fetch the latest snapshot.
|
|
904
892
|
*/
|
|
905
|
-
async load(specifiedVersion, loadMode, pendingLocalState) {
|
|
893
|
+
async load(specifiedVersion, loadMode, resolvedUrl, pendingLocalState) {
|
|
906
894
|
var _a;
|
|
907
|
-
|
|
908
|
-
throw new Error("Attempting to load without a resolved url");
|
|
909
|
-
}
|
|
910
|
-
this.service = await this.serviceFactory.createDocumentService(this._resolvedUrl, this.subLogger, this.client.details.type === summarizerClientType);
|
|
895
|
+
this.service = await this.serviceFactory.createDocumentService(resolvedUrl, this.subLogger, this.client.details.type === summarizerClientType);
|
|
911
896
|
// Ideally we always connect as "read" by default.
|
|
912
897
|
// Currently that works with SPO & r11s, because we get "write" connection when connecting to non-existing file.
|
|
913
898
|
// We should not rely on it by (one of them will address the issue, but we need to address both)
|
|
@@ -933,9 +918,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
933
918
|
else {
|
|
934
919
|
// if we have pendingLocalState we can load without storage; don't wait for connection
|
|
935
920
|
this.storageAdapter.connectToService(this.service).catch((error) => {
|
|
936
|
-
var _a;
|
|
937
921
|
this.close(error);
|
|
938
|
-
(_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
|
939
922
|
});
|
|
940
923
|
}
|
|
941
924
|
this._attachState = container_definitions_1.AttachState.Attached;
|
|
@@ -1061,8 +1044,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1061
1044
|
}
|
|
1062
1045
|
async rehydrateDetachedFromSnapshot(detachedContainerSnapshot) {
|
|
1063
1046
|
if (detachedContainerSnapshot.tree[".hasAttachmentBlobs"] !== undefined) {
|
|
1064
|
-
(0, common_utils_1.assert)(!!this.
|
|
1065
|
-
this.
|
|
1047
|
+
(0, common_utils_1.assert)(!!this.createProps.detachedBlobStorage &&
|
|
1048
|
+
this.createProps.detachedBlobStorage.size > 0, 0x250 /* "serialized container with attachment blobs must be rehydrated with detached blob storage" */);
|
|
1066
1049
|
delete detachedContainerSnapshot.tree[".hasAttachmentBlobs"];
|
|
1067
1050
|
}
|
|
1068
1051
|
const snapshotTree = (0, utils_1.getSnapshotTreeFromSerializedContainer)(detachedContainerSnapshot);
|
|
@@ -1116,7 +1099,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1116
1099
|
}
|
|
1117
1100
|
initializeProtocolState(attributes, quorumSnapshot) {
|
|
1118
1101
|
var _a;
|
|
1119
|
-
const protocolHandlerBuilder = (_a = this.protocolHandlerBuilder) !== null && _a !== void 0 ? _a : ((...args) => new protocol_1.ProtocolHandler(...args, new audience_1.Audience()));
|
|
1102
|
+
const protocolHandlerBuilder = (_a = this.createProps.protocolHandlerBuilder) !== null && _a !== void 0 ? _a : ((...args) => new protocol_1.ProtocolHandler(...args, new audience_1.Audience()));
|
|
1120
1103
|
const protocol = protocolHandlerBuilder(attributes, quorumSnapshot, (key, value) => this.submitMessage(protocol_definitions_1.MessageType.Propose, JSON.stringify({ key, value })));
|
|
1121
1104
|
const protocolLogger = telemetry_utils_1.ChildLogger.create(this.subLogger, "ProtocolHandler");
|
|
1122
1105
|
protocol.quorum.on("error", (error) => {
|
|
@@ -1137,10 +1120,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1137
1120
|
});
|
|
1138
1121
|
}
|
|
1139
1122
|
this.processCodeProposal().catch((error) => {
|
|
1140
|
-
var _a;
|
|
1141
1123
|
const normalizedError = (0, telemetry_utils_1.normalizeError)(error);
|
|
1142
1124
|
this.close(normalizedError);
|
|
1143
|
-
(_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, normalizedError);
|
|
1144
1125
|
throw error;
|
|
1145
1126
|
});
|
|
1146
1127
|
}
|
|
@@ -1224,11 +1205,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1224
1205
|
(0, common_utils_1.assert)(this.connectionMode === details.mode, 0x4b7 /* mismatch */);
|
|
1225
1206
|
this.connectionStateHandler.receivedConnectEvent(details);
|
|
1226
1207
|
});
|
|
1227
|
-
deltaManager.on("disconnect", (reason) => {
|
|
1208
|
+
deltaManager.on("disconnect", (reason, error) => {
|
|
1228
1209
|
var _a;
|
|
1229
1210
|
(_a = this.collabWindowTracker) === null || _a === void 0 ? void 0 : _a.stopSequenceNumberUpdate();
|
|
1230
1211
|
if (!this.closed) {
|
|
1231
|
-
this.connectionStateHandler.receivedDisconnectEvent(reason);
|
|
1212
|
+
this.connectionStateHandler.receivedDisconnectEvent(reason, error);
|
|
1232
1213
|
}
|
|
1233
1214
|
});
|
|
1234
1215
|
deltaManager.on("throttled", (warning) => {
|
|
@@ -1260,7 +1241,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1260
1241
|
},
|
|
1261
1242
|
}, prefetchType);
|
|
1262
1243
|
}
|
|
1263
|
-
logConnectionStateChangeTelemetry(value, oldState, reason) {
|
|
1244
|
+
logConnectionStateChangeTelemetry(value, oldState, reason, error) {
|
|
1264
1245
|
var _a;
|
|
1265
1246
|
// Log actual event
|
|
1266
1247
|
const time = common_utils_1.performance.now();
|
|
@@ -1293,7 +1274,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1293
1274
|
durationFromDisconnected,
|
|
1294
1275
|
reason,
|
|
1295
1276
|
connectionInitiationReason, pendingClientId: this.connectionStateHandler.pendingClientId, clientId: this.clientId, autoReconnect,
|
|
1296
|
-
opsBehind, online: driver_utils_1.OnlineStatus[(0, driver_utils_1.isOnline)()], lastVisible: this.lastVisible !== undefined
|
|
1277
|
+
opsBehind, online: driver_utils_1.OnlineStatus[(0, driver_utils_1.isOnline)()], lastVisible: this.lastVisible !== undefined
|
|
1278
|
+
? common_utils_1.performance.now() - this.lastVisible
|
|
1279
|
+
: undefined, checkpointSequenceNumber, quorumSize: (_a = this._protocolHandler) === null || _a === void 0 ? void 0 : _a.quorum.getMembers().size }, this._deltaManager.connectionProps), error);
|
|
1297
1280
|
if (value === connectionState_1.ConnectionState.Connected) {
|
|
1298
1281
|
this.firstConnection = false;
|
|
1299
1282
|
}
|
|
@@ -1328,7 +1311,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1328
1311
|
}
|
|
1329
1312
|
// back-compat: ADO #1385: Remove in the future, summary op should come through submitSummaryMessage()
|
|
1330
1313
|
submitContainerMessage(type, contents, batch, metadata) {
|
|
1331
|
-
var _a;
|
|
1332
1314
|
switch (type) {
|
|
1333
1315
|
case protocol_definitions_1.MessageType.Operation:
|
|
1334
1316
|
return this.submitMessage(type, JSON.stringify(contents), batch, metadata);
|
|
@@ -1337,7 +1319,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1337
1319
|
default: {
|
|
1338
1320
|
const newError = new container_utils_1.GenericError("invalidContainerSubmitOpType", undefined /* error */, { messageType: type });
|
|
1339
1321
|
this.close(newError);
|
|
1340
|
-
(_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, newError);
|
|
1341
1322
|
return -1;
|
|
1342
1323
|
}
|
|
1343
1324
|
}
|
|
@@ -1446,8 +1427,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1446
1427
|
(0, common_utils_1.assert)(((_a = this._context) === null || _a === void 0 ? void 0 : _a.disposed) !== false, 0x0dd /* "Existing context not disposed" */);
|
|
1447
1428
|
// The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
|
|
1448
1429
|
// are set. Global requests will still go directly to the loader
|
|
1449
|
-
const
|
|
1450
|
-
|
|
1430
|
+
const maybeLoader = this.scope;
|
|
1431
|
+
const loader = new loader_1.RelativeLoader(this, maybeLoader.ILoader);
|
|
1432
|
+
this._context = await containerContext_1.ContainerContext.createOrLoad(this, this.scope, this.codeLoader, codeDetails, snapshot, new deltaManagerProxy_1.DeltaManagerProxy(this._deltaManager), new quorum_1.QuorumProxy(this.protocolHandler.quorum), loader, (type, contents, batch, metadata) => this.submitContainerMessage(type, contents, batch, metadata), (summaryOp, referenceSequenceNumber) => this.submitSummaryMessage(summaryOp, referenceSequenceNumber), (batch, referenceSequenceNumber) => this.submitBatch(batch, referenceSequenceNumber), (message) => this.submitSignal(message), (error) => this.dispose(error), (error) => this.close(error), Container.version, (dirty) => this.updateDirtyContainerState(dirty), existing, pendingLocalState);
|
|
1451
1433
|
this.emit("contextChanged", codeDetails);
|
|
1452
1434
|
}
|
|
1453
1435
|
updateDirtyContainerState(dirty) {
|