@fluidframework/container-loader 2.0.0-dev-rc.5.0.0.267932 → 2.0.0-dev-rc.5.0.0.270401
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/api-report/{container-loader.api.md → container-loader.alpha.api.md} +58 -15
- package/api-report/container-loader.beta.api.md +44 -0
- package/api-report/container-loader.public.api.md +44 -0
- package/dist/audience.js +2 -1
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.js +11 -8
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts +2 -2
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +91 -63
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.js +35 -11
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +2 -2
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +156 -123
- 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 +34 -8
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.js +17 -9
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +2 -2
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.js +2 -0
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts +2 -2
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +48 -35
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.js +14 -7
- package/dist/deltaQueue.js.map +1 -1
- package/dist/error.js +5 -4
- package/dist/error.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +5 -0
- package/dist/loader.js +5 -1
- package/dist/loader.js.map +1 -1
- package/dist/noopHeuristic.d.ts +1 -1
- package/dist/noopHeuristic.d.ts.map +1 -1
- package/dist/noopHeuristic.js +3 -1
- 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/index.d.ts +7 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +12 -0
- package/dist/protocol/index.js.map +1 -0
- package/dist/protocol/protocol.d.ts +52 -0
- package/dist/protocol/protocol.d.ts.map +1 -0
- package/dist/protocol/protocol.js +115 -0
- package/dist/protocol/protocol.js.map +1 -0
- package/dist/protocol/quorum.d.ts +185 -0
- package/dist/protocol/quorum.d.ts.map +1 -0
- package/dist/protocol/quorum.js +440 -0
- package/dist/protocol/quorum.js.map +1 -0
- package/dist/protocol.d.ts +2 -3
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +4 -2
- package/dist/protocol.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts +7 -7
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js +16 -7
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/retriableDocumentStorageService.js +4 -1
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/serializedStateManager.d.ts +1 -2
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +10 -2
- package/dist/serializedStateManager.js.map +1 -1
- package/lib/audience.js +2 -1
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.js +11 -8
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts +2 -2
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +91 -63
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.js +35 -11
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +2 -2
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +156 -123
- 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 +34 -8
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.js +17 -9
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +2 -2
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.js +2 -0
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts +2 -2
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +48 -35
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.js +14 -7
- package/lib/deltaQueue.js.map +1 -1
- package/lib/error.js +5 -4
- package/lib/error.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +5 -0
- package/lib/loader.js +5 -1
- package/lib/loader.js.map +1 -1
- package/lib/noopHeuristic.d.ts +1 -1
- package/lib/noopHeuristic.d.ts.map +1 -1
- package/lib/noopHeuristic.js +3 -1
- 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/index.d.ts +7 -0
- package/lib/protocol/index.d.ts.map +1 -0
- package/lib/protocol/index.js +7 -0
- package/lib/protocol/index.js.map +1 -0
- package/lib/protocol/protocol.d.ts +52 -0
- package/lib/protocol/protocol.d.ts.map +1 -0
- package/lib/protocol/protocol.js +111 -0
- package/lib/protocol/protocol.js.map +1 -0
- package/lib/protocol/quorum.d.ts +185 -0
- package/lib/protocol/quorum.d.ts.map +1 -0
- package/lib/protocol/quorum.js +431 -0
- package/lib/protocol/quorum.js.map +1 -0
- package/lib/protocol.d.ts +2 -3
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +3 -1
- package/lib/protocol.js.map +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts +7 -7
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js +16 -7
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/retriableDocumentStorageService.js +4 -1
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/serializedStateManager.d.ts +1 -2
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +10 -2
- package/lib/serializedStateManager.js.map +1 -1
- package/package.json +15 -13
- package/src/catchUpMonitor.ts +1 -1
- package/src/connectionManager.ts +3 -7
- package/src/container.ts +4 -4
- package/src/containerContext.ts +2 -5
- package/src/contracts.ts +3 -6
- package/src/deltaManager.ts +3 -5
- package/src/index.ts +7 -0
- package/src/noopHeuristic.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/protocol/README.md +10 -0
- package/src/protocol/index.ts +16 -0
- package/src/protocol/protocol.ts +185 -0
- package/src/protocol/quorum.ts +584 -0
- package/src/protocol.ts +4 -6
- package/src/protocolTreeDocumentStorageService.ts +16 -8
- package/src/serializedStateManager.ts +1 -1
- package/tsconfig.json +2 -0
package/dist/container.js
CHANGED
|
@@ -197,6 +197,41 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
197
197
|
return container;
|
|
198
198
|
}, { start: true, end: true, cancel: "generic" });
|
|
199
199
|
}
|
|
200
|
+
// Tells if container can reconnect on losing fist connection
|
|
201
|
+
// If false, container gets closed on loss of connection.
|
|
202
|
+
_canReconnect;
|
|
203
|
+
clientDetailsOverride;
|
|
204
|
+
urlResolver;
|
|
205
|
+
serviceFactory;
|
|
206
|
+
codeLoader;
|
|
207
|
+
options;
|
|
208
|
+
scope;
|
|
209
|
+
subLogger;
|
|
210
|
+
// eslint-disable-next-line import/no-deprecated
|
|
211
|
+
detachedBlobStorage;
|
|
212
|
+
protocolHandlerBuilder;
|
|
213
|
+
client;
|
|
214
|
+
mc;
|
|
215
|
+
/**
|
|
216
|
+
* Used by the RelativeLoader to spawn a new Container for the same document. Used to create the summarizing client.
|
|
217
|
+
*/
|
|
218
|
+
clone;
|
|
219
|
+
/**
|
|
220
|
+
* Lifecycle state of the container, used mainly to prevent re-entrancy and telemetry
|
|
221
|
+
*
|
|
222
|
+
* States are allowed to progress to further states:
|
|
223
|
+
* "loading" - "loaded" - "closing" - "disposing" - "closed" - "disposed"
|
|
224
|
+
*
|
|
225
|
+
* For example, moving from "closed" to "disposing" is not allowed since it is an earlier state.
|
|
226
|
+
*
|
|
227
|
+
* loading: Container has been created, but is not yet in normal/loaded state
|
|
228
|
+
* loaded: Container is in normal/loaded state
|
|
229
|
+
* closing: Container has started closing process (for re-entrancy prevention)
|
|
230
|
+
* disposing: Container has started disposing process (for re-entrancy prevention)
|
|
231
|
+
* closed: Container has closed
|
|
232
|
+
* disposed: Container has been disposed
|
|
233
|
+
*/
|
|
234
|
+
_lifecycleState = "loading";
|
|
200
235
|
setLoaded() {
|
|
201
236
|
// It's conceivable the container could be closed when this is called
|
|
202
237
|
// Only transition states if currently loading
|
|
@@ -239,18 +274,39 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
239
274
|
get disposed() {
|
|
240
275
|
return this._lifecycleState === "disposing" || this._lifecycleState === "disposed";
|
|
241
276
|
}
|
|
277
|
+
storageAdapter;
|
|
278
|
+
_deltaManager;
|
|
279
|
+
service;
|
|
280
|
+
_runtime;
|
|
242
281
|
get runtime() {
|
|
243
282
|
if (this._runtime === undefined) {
|
|
244
283
|
throw new Error("Attempted to access runtime before it was defined");
|
|
245
284
|
}
|
|
246
285
|
return this._runtime;
|
|
247
286
|
}
|
|
287
|
+
_protocolHandler;
|
|
248
288
|
get protocolHandler() {
|
|
249
289
|
if (this._protocolHandler === undefined) {
|
|
250
290
|
throw new Error("Attempted to access protocolHandler before it was defined");
|
|
251
291
|
}
|
|
252
292
|
return this._protocolHandler;
|
|
253
293
|
}
|
|
294
|
+
/** During initialization we pause the inbound queues. We track this state to ensure we only call resume once */
|
|
295
|
+
inboundQueuePausedFromInit = true;
|
|
296
|
+
firstConnection = true;
|
|
297
|
+
connectionTransitionTimes = [];
|
|
298
|
+
_loadedFromVersion;
|
|
299
|
+
_dirtyContainer = false;
|
|
300
|
+
attachmentData = { state: container_definitions_1.AttachState.Detached };
|
|
301
|
+
serializedStateManager;
|
|
302
|
+
_containerId;
|
|
303
|
+
lastVisible;
|
|
304
|
+
visibilityEventHandler;
|
|
305
|
+
connectionStateHandler;
|
|
306
|
+
clientsWhoShouldHaveLeft = new Set();
|
|
307
|
+
_containerMetadata = {};
|
|
308
|
+
setAutoReconnectTime = client_utils_1.performance.now();
|
|
309
|
+
noopHeuristic;
|
|
254
310
|
get connectionMode() {
|
|
255
311
|
return this._deltaManager.connectionManager.connectionMode;
|
|
256
312
|
}
|
|
@@ -321,6 +377,7 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
321
377
|
getSpecifiedCodeDetails() {
|
|
322
378
|
return this.getCodeDetailsFromQuorum();
|
|
323
379
|
}
|
|
380
|
+
_loadedCodeDetails;
|
|
324
381
|
/**
|
|
325
382
|
* Get the code details that were used to load the container.
|
|
326
383
|
* @returns The code details that were used to load the container if it is loaded, undefined if it is not yet
|
|
@@ -329,6 +386,7 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
329
386
|
getLoadedCodeDetails() {
|
|
330
387
|
return this._loadedCodeDetails;
|
|
331
388
|
}
|
|
389
|
+
_loadedModule;
|
|
332
390
|
/**
|
|
333
391
|
* Retrieves the audience associated with the document
|
|
334
392
|
*/
|
|
@@ -367,6 +425,7 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
367
425
|
this._lifecycleEvents.once("disposed", disposedHandler);
|
|
368
426
|
});
|
|
369
427
|
}
|
|
428
|
+
_lifecycleEvents = new client_utils_1.TypedEventEmitter();
|
|
370
429
|
constructor(createProps, loadProps) {
|
|
371
430
|
super((name, error) => {
|
|
372
431
|
this.mc.logger.sendErrorEvent({
|
|
@@ -375,128 +434,6 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
375
434
|
}, error);
|
|
376
435
|
this.close((0, internal_5.normalizeError)(error));
|
|
377
436
|
});
|
|
378
|
-
/**
|
|
379
|
-
* Lifecycle state of the container, used mainly to prevent re-entrancy and telemetry
|
|
380
|
-
*
|
|
381
|
-
* States are allowed to progress to further states:
|
|
382
|
-
* "loading" - "loaded" - "closing" - "disposing" - "closed" - "disposed"
|
|
383
|
-
*
|
|
384
|
-
* For example, moving from "closed" to "disposing" is not allowed since it is an earlier state.
|
|
385
|
-
*
|
|
386
|
-
* loading: Container has been created, but is not yet in normal/loaded state
|
|
387
|
-
* loaded: Container is in normal/loaded state
|
|
388
|
-
* closing: Container has started closing process (for re-entrancy prevention)
|
|
389
|
-
* disposing: Container has started disposing process (for re-entrancy prevention)
|
|
390
|
-
* closed: Container has closed
|
|
391
|
-
* disposed: Container has been disposed
|
|
392
|
-
*/
|
|
393
|
-
this._lifecycleState = "loading";
|
|
394
|
-
/** During initialization we pause the inbound queues. We track this state to ensure we only call resume once */
|
|
395
|
-
this.inboundQueuePausedFromInit = true;
|
|
396
|
-
this.firstConnection = true;
|
|
397
|
-
this.connectionTransitionTimes = [];
|
|
398
|
-
this._dirtyContainer = false;
|
|
399
|
-
this.attachmentData = { state: container_definitions_1.AttachState.Detached };
|
|
400
|
-
this.clientsWhoShouldHaveLeft = new Set();
|
|
401
|
-
this._containerMetadata = {};
|
|
402
|
-
this.setAutoReconnectTime = client_utils_1.performance.now();
|
|
403
|
-
this._lifecycleEvents = new client_utils_1.TypedEventEmitter();
|
|
404
|
-
this._disposed = false;
|
|
405
|
-
this.attach = (0, utils_js_1.runSingle)(async (request, attachProps) => {
|
|
406
|
-
await internal_5.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
|
|
407
|
-
if (this._lifecycleState !== "loaded" ||
|
|
408
|
-
this.attachmentData.state === container_definitions_1.AttachState.Attached) {
|
|
409
|
-
// pre-0.58 error message: containerNotValidForAttach
|
|
410
|
-
throw new internal_5.UsageError(`The Container is not in a valid state for attach [${this._lifecycleState}] and [${this.attachState}]`);
|
|
411
|
-
}
|
|
412
|
-
const normalizeErrorAndClose = (error) => {
|
|
413
|
-
const newError = (0, internal_5.normalizeError)(error);
|
|
414
|
-
this.close(newError);
|
|
415
|
-
// add resolved URL on error object so that host has the ability to find this document and delete it
|
|
416
|
-
newError.addTelemetryProperties({
|
|
417
|
-
resolvedUrl: this.service?.resolvedUrl?.url,
|
|
418
|
-
});
|
|
419
|
-
return newError;
|
|
420
|
-
};
|
|
421
|
-
const setAttachmentData = (attachmentData) => {
|
|
422
|
-
const previousState = this.attachmentData.state;
|
|
423
|
-
this.attachmentData = attachmentData;
|
|
424
|
-
const state = this.attachmentData.state;
|
|
425
|
-
if (state !== previousState && state !== container_definitions_1.AttachState.Detached) {
|
|
426
|
-
try {
|
|
427
|
-
this.runtime.setAttachState(state);
|
|
428
|
-
this.emit(state.toLocaleLowerCase());
|
|
429
|
-
}
|
|
430
|
-
catch (error) {
|
|
431
|
-
throw normalizeErrorAndClose(error);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
};
|
|
435
|
-
const createAttachmentSummary = (redirectTable) => {
|
|
436
|
-
try {
|
|
437
|
-
(0, internal_2.assert)(this.deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
|
|
438
|
-
return (0, utils_js_1.combineAppAndProtocolSummary)(this.runtime.createSummary(redirectTable), this.captureProtocolSummary());
|
|
439
|
-
}
|
|
440
|
-
catch (error) {
|
|
441
|
-
throw normalizeErrorAndClose(error);
|
|
442
|
-
}
|
|
443
|
-
};
|
|
444
|
-
const createOrGetStorageService = async (summary) => {
|
|
445
|
-
// Actually go and create the resolved document
|
|
446
|
-
if (this.service === undefined) {
|
|
447
|
-
const createNewResolvedUrl = await this.urlResolver.resolve(request);
|
|
448
|
-
(0, internal_2.assert)(this.client.details.type !== summarizerClientType &&
|
|
449
|
-
createNewResolvedUrl !== undefined, 0x2c4 /* "client should not be summarizer before container is created" */);
|
|
450
|
-
this.service = await (0, internal_4.runWithRetry)(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger, false), "containerAttach", this.mc.logger, {
|
|
451
|
-
cancel: this._deltaManager.closeAbortController.signal,
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
this.storageAdapter.connectToService(this.service);
|
|
455
|
-
return this.storageAdapter;
|
|
456
|
-
};
|
|
457
|
-
let attachP = (0, attachment_js_1.runRetriableAttachProcess)({
|
|
458
|
-
initialAttachmentData: this.attachmentData,
|
|
459
|
-
offlineLoadEnabled: this.serializedStateManager.offlineLoadEnabled,
|
|
460
|
-
detachedBlobStorage: this.detachedBlobStorage,
|
|
461
|
-
setAttachmentData,
|
|
462
|
-
createAttachmentSummary,
|
|
463
|
-
createOrGetStorageService,
|
|
464
|
-
});
|
|
465
|
-
// only enable the new behavior if the config is set
|
|
466
|
-
if (this.mc.config.getBoolean("Fluid.Container.RetryOnAttachFailure") !== true) {
|
|
467
|
-
attachP = attachP.catch((error) => {
|
|
468
|
-
throw normalizeErrorAndClose(error);
|
|
469
|
-
});
|
|
470
|
-
}
|
|
471
|
-
// If offline load is enabled, attachP will return the attach summary (in Snapshot format) so we can initialize SerializedStateManager
|
|
472
|
-
const snapshotWithBlobs = await attachP;
|
|
473
|
-
this.serializedStateManager.setInitialSnapshot(snapshotWithBlobs);
|
|
474
|
-
if (!this.closed) {
|
|
475
|
-
this.detachedBlobStorage.dispose?.();
|
|
476
|
-
this.handleDeltaConnectionArg(attachProps?.deltaConnection, {
|
|
477
|
-
fetchOpsFromStorage: false,
|
|
478
|
-
reason: { text: "createDetached" },
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
}, { start: true, end: true, cancel: "generic" });
|
|
482
|
-
});
|
|
483
|
-
this.getAbsoluteUrl = async (relativeUrl) => {
|
|
484
|
-
if (this.resolvedUrl === undefined) {
|
|
485
|
-
return undefined;
|
|
486
|
-
}
|
|
487
|
-
return this.urlResolver.getAbsoluteUrl(this.resolvedUrl, relativeUrl, (0, contracts_js_1.getPackageName)(this._loadedCodeDetails));
|
|
488
|
-
};
|
|
489
|
-
this.metadataUpdateHandler = (metadata) => {
|
|
490
|
-
this._containerMetadata = { ...this._containerMetadata, ...metadata };
|
|
491
|
-
this.emit("metadataUpdate", metadata);
|
|
492
|
-
};
|
|
493
|
-
this.updateDirtyContainerState = (dirty) => {
|
|
494
|
-
if (this._dirtyContainer === dirty) {
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
this._dirtyContainer = dirty;
|
|
498
|
-
this.emit(dirty ? dirtyContainerEvent : savedContainerEvent);
|
|
499
|
-
};
|
|
500
437
|
const { canReconnect, clientDetailsOverride, urlResolver, documentServiceFactory, codeLoader, options, scope, subLogger, detachedBlobStorage, protocolHandlerBuilder, } = createProps;
|
|
501
438
|
this.connectionTransitionTimes[connectionState_js_1.ConnectionState.Disconnected] = client_utils_1.performance.now();
|
|
502
439
|
const pendingLocalState = loadProps?.pendingLocalState;
|
|
@@ -641,7 +578,7 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
641
578
|
const offlineLoadEnabled = (this.isInteractiveClient &&
|
|
642
579
|
this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad")) ??
|
|
643
580
|
options.enableOfflineLoad === true;
|
|
644
|
-
this.serializedStateManager = new serializedStateManager_js_1.SerializedStateManager(pendingLocalState, this.subLogger, this.storageAdapter, offlineLoadEnabled, this, () => this.
|
|
581
|
+
this.serializedStateManager = new serializedStateManager_js_1.SerializedStateManager(pendingLocalState, this.subLogger, this.storageAdapter, offlineLoadEnabled, this, () => this._deltaManager.connectionManager.shouldJoinWrite());
|
|
645
582
|
const isDomAvailable = typeof document === "object" &&
|
|
646
583
|
document !== null &&
|
|
647
584
|
typeof document.addEventListener === "function" &&
|
|
@@ -724,6 +661,7 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
724
661
|
}
|
|
725
662
|
}
|
|
726
663
|
}
|
|
664
|
+
_disposed = false;
|
|
727
665
|
disposeCore(error) {
|
|
728
666
|
(0, internal_2.assert)(!this._disposed, 0x54c /* Container already disposed */);
|
|
729
667
|
this._disposed = true;
|
|
@@ -822,6 +760,84 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
822
760
|
};
|
|
823
761
|
return JSON.stringify(detachedContainerState);
|
|
824
762
|
}
|
|
763
|
+
attach = (0, utils_js_1.runSingle)(async (request, attachProps) => {
|
|
764
|
+
await internal_5.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
|
|
765
|
+
if (this._lifecycleState !== "loaded" ||
|
|
766
|
+
this.attachmentData.state === container_definitions_1.AttachState.Attached) {
|
|
767
|
+
// pre-0.58 error message: containerNotValidForAttach
|
|
768
|
+
throw new internal_5.UsageError(`The Container is not in a valid state for attach [${this._lifecycleState}] and [${this.attachState}]`);
|
|
769
|
+
}
|
|
770
|
+
const normalizeErrorAndClose = (error) => {
|
|
771
|
+
const newError = (0, internal_5.normalizeError)(error);
|
|
772
|
+
this.close(newError);
|
|
773
|
+
// add resolved URL on error object so that host has the ability to find this document and delete it
|
|
774
|
+
newError.addTelemetryProperties({
|
|
775
|
+
resolvedUrl: this.service?.resolvedUrl?.url,
|
|
776
|
+
});
|
|
777
|
+
return newError;
|
|
778
|
+
};
|
|
779
|
+
const setAttachmentData = (attachmentData) => {
|
|
780
|
+
const previousState = this.attachmentData.state;
|
|
781
|
+
this.attachmentData = attachmentData;
|
|
782
|
+
const state = this.attachmentData.state;
|
|
783
|
+
if (state !== previousState && state !== container_definitions_1.AttachState.Detached) {
|
|
784
|
+
try {
|
|
785
|
+
this.runtime.setAttachState(state);
|
|
786
|
+
this.emit(state.toLocaleLowerCase());
|
|
787
|
+
}
|
|
788
|
+
catch (error) {
|
|
789
|
+
throw normalizeErrorAndClose(error);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
const createAttachmentSummary = (redirectTable) => {
|
|
794
|
+
try {
|
|
795
|
+
(0, internal_2.assert)(this.deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
|
|
796
|
+
return (0, utils_js_1.combineAppAndProtocolSummary)(this.runtime.createSummary(redirectTable), this.captureProtocolSummary());
|
|
797
|
+
}
|
|
798
|
+
catch (error) {
|
|
799
|
+
throw normalizeErrorAndClose(error);
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
const createOrGetStorageService = async (summary) => {
|
|
803
|
+
// Actually go and create the resolved document
|
|
804
|
+
if (this.service === undefined) {
|
|
805
|
+
const createNewResolvedUrl = await this.urlResolver.resolve(request);
|
|
806
|
+
(0, internal_2.assert)(this.client.details.type !== summarizerClientType &&
|
|
807
|
+
createNewResolvedUrl !== undefined, 0x2c4 /* "client should not be summarizer before container is created" */);
|
|
808
|
+
this.service = await (0, internal_4.runWithRetry)(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger, false), "containerAttach", this.mc.logger, {
|
|
809
|
+
cancel: this._deltaManager.closeAbortController.signal,
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
this.storageAdapter.connectToService(this.service);
|
|
813
|
+
return this.storageAdapter;
|
|
814
|
+
};
|
|
815
|
+
let attachP = (0, attachment_js_1.runRetriableAttachProcess)({
|
|
816
|
+
initialAttachmentData: this.attachmentData,
|
|
817
|
+
offlineLoadEnabled: this.serializedStateManager.offlineLoadEnabled,
|
|
818
|
+
detachedBlobStorage: this.detachedBlobStorage,
|
|
819
|
+
setAttachmentData,
|
|
820
|
+
createAttachmentSummary,
|
|
821
|
+
createOrGetStorageService,
|
|
822
|
+
});
|
|
823
|
+
// only enable the new behavior if the config is set
|
|
824
|
+
if (this.mc.config.getBoolean("Fluid.Container.RetryOnAttachFailure") !== true) {
|
|
825
|
+
attachP = attachP.catch((error) => {
|
|
826
|
+
throw normalizeErrorAndClose(error);
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
// If offline load is enabled, attachP will return the attach summary (in Snapshot format) so we can initialize SerializedStateManager
|
|
830
|
+
const snapshotWithBlobs = await attachP;
|
|
831
|
+
this.serializedStateManager.setInitialSnapshot(snapshotWithBlobs);
|
|
832
|
+
if (!this.closed) {
|
|
833
|
+
this.detachedBlobStorage.dispose?.();
|
|
834
|
+
this.handleDeltaConnectionArg(attachProps?.deltaConnection, {
|
|
835
|
+
fetchOpsFromStorage: false,
|
|
836
|
+
reason: { text: "createDetached" },
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
}, { start: true, end: true, cancel: "generic" });
|
|
840
|
+
});
|
|
825
841
|
setAutoReconnectInternal(mode, reason) {
|
|
826
842
|
const currentMode = this._deltaManager.connectionManager.reconnectMode;
|
|
827
843
|
if (currentMode === mode) {
|
|
@@ -894,6 +910,12 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
894
910
|
// Ensure connection to web socket
|
|
895
911
|
this.connectToDeltaStream(args);
|
|
896
912
|
}
|
|
913
|
+
getAbsoluteUrl = async (relativeUrl) => {
|
|
914
|
+
if (this.resolvedUrl === undefined) {
|
|
915
|
+
return undefined;
|
|
916
|
+
}
|
|
917
|
+
return this.urlResolver.getAbsoluteUrl(this.resolvedUrl, relativeUrl, (0, contracts_js_1.getPackageName)(this._loadedCodeDetails));
|
|
918
|
+
};
|
|
897
919
|
async proposeCodeDetails(codeDetails) {
|
|
898
920
|
if (!(0, internal_1.isFluidCodeDetails)(codeDetails)) {
|
|
899
921
|
throw new Error("Provided codeDetails are not IFluidCodeDetails");
|
|
@@ -962,6 +984,10 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
962
984
|
}
|
|
963
985
|
this._deltaManager.connect(args);
|
|
964
986
|
}
|
|
987
|
+
metadataUpdateHandler = (metadata) => {
|
|
988
|
+
this._containerMetadata = { ...this._containerMetadata, ...metadata };
|
|
989
|
+
this.emit("metadataUpdate", metadata);
|
|
990
|
+
};
|
|
965
991
|
async createDocumentService(serviceProvider) {
|
|
966
992
|
const service = await serviceProvider();
|
|
967
993
|
// Back-compat for Old driver
|
|
@@ -1507,6 +1533,13 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
1507
1533
|
this._lifecycleEvents.emit("runtimeInstantiated");
|
|
1508
1534
|
this._loadedCodeDetails = codeDetails;
|
|
1509
1535
|
}
|
|
1536
|
+
updateDirtyContainerState = (dirty) => {
|
|
1537
|
+
if (this._dirtyContainer === dirty) {
|
|
1538
|
+
return;
|
|
1539
|
+
}
|
|
1540
|
+
this._dirtyContainer = dirty;
|
|
1541
|
+
this.emit(dirty ? dirtyContainerEvent : savedContainerEvent);
|
|
1542
|
+
};
|
|
1510
1543
|
/**
|
|
1511
1544
|
* Set the connected state of the ContainerContext
|
|
1512
1545
|
* This controls the "connected" state of the ContainerRuntime as well
|