@fluidframework/container-loader 2.0.0-dev-rc.5.0.0.268409 → 2.0.0-dev-rc.5.0.0.270987
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.alpha.api.md +59 -4
- package/api-report/container-loader.beta.api.md +7 -3
- package/api-report/container-loader.public.api.md +7 -3
- package/biome.jsonc +4 -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 +3 -2
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +162 -126
- 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 +5 -3
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +26 -5
- 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 +3 -2
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +162 -126
- 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 +5 -3
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +26 -5
- package/lib/serializedStateManager.js.map +1 -1
- package/package.json +19 -14
- package/src/catchUpMonitor.ts +1 -1
- package/src/connectionManager.ts +3 -7
- package/src/container.ts +16 -9
- 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 +25 -4
- 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
|
}
|
|
@@ -314,6 +370,11 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
314
370
|
get isInteractiveClient() {
|
|
315
371
|
return this.deltaManager.clientDetails.capabilities.interactive;
|
|
316
372
|
}
|
|
373
|
+
get supportGetSnapshotApi() {
|
|
374
|
+
const supportGetSnapshotApi = this.mc.config.getBoolean("Fluid.Container.UseLoadingGroupIdForSnapshotFetch2") ===
|
|
375
|
+
true && this.service?.policies?.supportGetSnapshotApi === true;
|
|
376
|
+
return supportGetSnapshotApi;
|
|
377
|
+
}
|
|
317
378
|
/**
|
|
318
379
|
* Get the code details that are currently specified for the container.
|
|
319
380
|
* @returns The current code details if any are specified, undefined if none are specified.
|
|
@@ -321,6 +382,7 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
321
382
|
getSpecifiedCodeDetails() {
|
|
322
383
|
return this.getCodeDetailsFromQuorum();
|
|
323
384
|
}
|
|
385
|
+
_loadedCodeDetails;
|
|
324
386
|
/**
|
|
325
387
|
* Get the code details that were used to load the container.
|
|
326
388
|
* @returns The code details that were used to load the container if it is loaded, undefined if it is not yet
|
|
@@ -329,6 +391,7 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
329
391
|
getLoadedCodeDetails() {
|
|
330
392
|
return this._loadedCodeDetails;
|
|
331
393
|
}
|
|
394
|
+
_loadedModule;
|
|
332
395
|
/**
|
|
333
396
|
* Retrieves the audience associated with the document
|
|
334
397
|
*/
|
|
@@ -367,6 +430,7 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
367
430
|
this._lifecycleEvents.once("disposed", disposedHandler);
|
|
368
431
|
});
|
|
369
432
|
}
|
|
433
|
+
_lifecycleEvents = new client_utils_1.TypedEventEmitter();
|
|
370
434
|
constructor(createProps, loadProps) {
|
|
371
435
|
super((name, error) => {
|
|
372
436
|
this.mc.logger.sendErrorEvent({
|
|
@@ -375,128 +439,6 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
375
439
|
}, error);
|
|
376
440
|
this.close((0, internal_5.normalizeError)(error));
|
|
377
441
|
});
|
|
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
442
|
const { canReconnect, clientDetailsOverride, urlResolver, documentServiceFactory, codeLoader, options, scope, subLogger, detachedBlobStorage, protocolHandlerBuilder, } = createProps;
|
|
501
443
|
this.connectionTransitionTimes[connectionState_js_1.ConnectionState.Disconnected] = client_utils_1.performance.now();
|
|
502
444
|
const pendingLocalState = loadProps?.pendingLocalState;
|
|
@@ -641,7 +583,7 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
641
583
|
const offlineLoadEnabled = (this.isInteractiveClient &&
|
|
642
584
|
this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad")) ??
|
|
643
585
|
options.enableOfflineLoad === true;
|
|
644
|
-
this.serializedStateManager = new serializedStateManager_js_1.SerializedStateManager(pendingLocalState, this.subLogger, this.storageAdapter, offlineLoadEnabled, this, () => this.
|
|
586
|
+
this.serializedStateManager = new serializedStateManager_js_1.SerializedStateManager(pendingLocalState, this.subLogger, this.storageAdapter, offlineLoadEnabled, this, () => this._deltaManager.connectionManager.shouldJoinWrite());
|
|
645
587
|
const isDomAvailable = typeof document === "object" &&
|
|
646
588
|
document !== null &&
|
|
647
589
|
typeof document.addEventListener === "function" &&
|
|
@@ -724,6 +666,7 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
724
666
|
}
|
|
725
667
|
}
|
|
726
668
|
}
|
|
669
|
+
_disposed = false;
|
|
727
670
|
disposeCore(error) {
|
|
728
671
|
(0, internal_2.assert)(!this._disposed, 0x54c /* Container already disposed */);
|
|
729
672
|
this._disposed = true;
|
|
@@ -822,6 +765,84 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
822
765
|
};
|
|
823
766
|
return JSON.stringify(detachedContainerState);
|
|
824
767
|
}
|
|
768
|
+
attach = (0, utils_js_1.runSingle)(async (request, attachProps) => {
|
|
769
|
+
await internal_5.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
|
|
770
|
+
if (this._lifecycleState !== "loaded" ||
|
|
771
|
+
this.attachmentData.state === container_definitions_1.AttachState.Attached) {
|
|
772
|
+
// pre-0.58 error message: containerNotValidForAttach
|
|
773
|
+
throw new internal_5.UsageError(`The Container is not in a valid state for attach [${this._lifecycleState}] and [${this.attachState}]`);
|
|
774
|
+
}
|
|
775
|
+
const normalizeErrorAndClose = (error) => {
|
|
776
|
+
const newError = (0, internal_5.normalizeError)(error);
|
|
777
|
+
this.close(newError);
|
|
778
|
+
// add resolved URL on error object so that host has the ability to find this document and delete it
|
|
779
|
+
newError.addTelemetryProperties({
|
|
780
|
+
resolvedUrl: this.service?.resolvedUrl?.url,
|
|
781
|
+
});
|
|
782
|
+
return newError;
|
|
783
|
+
};
|
|
784
|
+
const setAttachmentData = (attachmentData) => {
|
|
785
|
+
const previousState = this.attachmentData.state;
|
|
786
|
+
this.attachmentData = attachmentData;
|
|
787
|
+
const state = this.attachmentData.state;
|
|
788
|
+
if (state !== previousState && state !== container_definitions_1.AttachState.Detached) {
|
|
789
|
+
try {
|
|
790
|
+
this.runtime.setAttachState(state);
|
|
791
|
+
this.emit(state.toLocaleLowerCase());
|
|
792
|
+
}
|
|
793
|
+
catch (error) {
|
|
794
|
+
throw normalizeErrorAndClose(error);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
const createAttachmentSummary = (redirectTable) => {
|
|
799
|
+
try {
|
|
800
|
+
(0, internal_2.assert)(this.deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
|
|
801
|
+
return (0, utils_js_1.combineAppAndProtocolSummary)(this.runtime.createSummary(redirectTable), this.captureProtocolSummary());
|
|
802
|
+
}
|
|
803
|
+
catch (error) {
|
|
804
|
+
throw normalizeErrorAndClose(error);
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
const createOrGetStorageService = async (summary) => {
|
|
808
|
+
// Actually go and create the resolved document
|
|
809
|
+
if (this.service === undefined) {
|
|
810
|
+
const createNewResolvedUrl = await this.urlResolver.resolve(request);
|
|
811
|
+
(0, internal_2.assert)(this.client.details.type !== summarizerClientType &&
|
|
812
|
+
createNewResolvedUrl !== undefined, 0x2c4 /* "client should not be summarizer before container is created" */);
|
|
813
|
+
this.service = await (0, internal_4.runWithRetry)(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger, false), "containerAttach", this.mc.logger, {
|
|
814
|
+
cancel: this._deltaManager.closeAbortController.signal,
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
this.storageAdapter.connectToService(this.service);
|
|
818
|
+
return this.storageAdapter;
|
|
819
|
+
};
|
|
820
|
+
let attachP = (0, attachment_js_1.runRetriableAttachProcess)({
|
|
821
|
+
initialAttachmentData: this.attachmentData,
|
|
822
|
+
offlineLoadEnabled: this.serializedStateManager.offlineLoadEnabled,
|
|
823
|
+
detachedBlobStorage: this.detachedBlobStorage,
|
|
824
|
+
setAttachmentData,
|
|
825
|
+
createAttachmentSummary,
|
|
826
|
+
createOrGetStorageService,
|
|
827
|
+
});
|
|
828
|
+
// only enable the new behavior if the config is set
|
|
829
|
+
if (this.mc.config.getBoolean("Fluid.Container.RetryOnAttachFailure") !== true) {
|
|
830
|
+
attachP = attachP.catch((error) => {
|
|
831
|
+
throw normalizeErrorAndClose(error);
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
// If offline load is enabled, attachP will return the attach summary (in Snapshot format) so we can initialize SerializedStateManager
|
|
835
|
+
const snapshotWithBlobs = await attachP;
|
|
836
|
+
this.serializedStateManager.setInitialSnapshot(snapshotWithBlobs, this.supportGetSnapshotApi);
|
|
837
|
+
if (!this.closed) {
|
|
838
|
+
this.detachedBlobStorage.dispose?.();
|
|
839
|
+
this.handleDeltaConnectionArg(attachProps?.deltaConnection, {
|
|
840
|
+
fetchOpsFromStorage: false,
|
|
841
|
+
reason: { text: "createDetached" },
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
}, { start: true, end: true, cancel: "generic" });
|
|
845
|
+
});
|
|
825
846
|
setAutoReconnectInternal(mode, reason) {
|
|
826
847
|
const currentMode = this._deltaManager.connectionManager.reconnectMode;
|
|
827
848
|
if (currentMode === mode) {
|
|
@@ -894,6 +915,12 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
894
915
|
// Ensure connection to web socket
|
|
895
916
|
this.connectToDeltaStream(args);
|
|
896
917
|
}
|
|
918
|
+
getAbsoluteUrl = async (relativeUrl) => {
|
|
919
|
+
if (this.resolvedUrl === undefined) {
|
|
920
|
+
return undefined;
|
|
921
|
+
}
|
|
922
|
+
return this.urlResolver.getAbsoluteUrl(this.resolvedUrl, relativeUrl, (0, contracts_js_1.getPackageName)(this._loadedCodeDetails));
|
|
923
|
+
};
|
|
897
924
|
async proposeCodeDetails(codeDetails) {
|
|
898
925
|
if (!(0, internal_1.isFluidCodeDetails)(codeDetails)) {
|
|
899
926
|
throw new Error("Provided codeDetails are not IFluidCodeDetails");
|
|
@@ -962,6 +989,10 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
962
989
|
}
|
|
963
990
|
this._deltaManager.connect(args);
|
|
964
991
|
}
|
|
992
|
+
metadataUpdateHandler = (metadata) => {
|
|
993
|
+
this._containerMetadata = { ...this._containerMetadata, ...metadata };
|
|
994
|
+
this.emit("metadataUpdate", metadata);
|
|
995
|
+
};
|
|
965
996
|
async createDocumentService(serviceProvider) {
|
|
966
997
|
const service = await serviceProvider();
|
|
967
998
|
// Back-compat for Old driver
|
|
@@ -998,10 +1029,8 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
998
1029
|
state: container_definitions_1.AttachState.Attached,
|
|
999
1030
|
};
|
|
1000
1031
|
timings.phase2 = client_utils_1.performance.now();
|
|
1001
|
-
const supportGetSnapshotApi = this.mc.config.getBoolean("Fluid.Container.UseLoadingGroupIdForSnapshotFetch") ===
|
|
1002
|
-
true && this.service?.policies?.supportGetSnapshotApi === true;
|
|
1003
1032
|
// Fetch specified snapshot.
|
|
1004
|
-
const { baseSnapshot, version } = await this.serializedStateManager.fetchSnapshot(specifiedVersion, supportGetSnapshotApi);
|
|
1033
|
+
const { baseSnapshot, version } = await this.serializedStateManager.fetchSnapshot(specifiedVersion, this.supportGetSnapshotApi);
|
|
1005
1034
|
const baseSnapshotTree = (0, internal_4.getSnapshotTree)(baseSnapshot);
|
|
1006
1035
|
this._loadedFromVersion = version;
|
|
1007
1036
|
const attributes = await (0, utils_js_1.getDocumentAttributes)(this.storageAdapter, baseSnapshotTree);
|
|
@@ -1507,6 +1536,13 @@ class Container extends internal_5.EventEmitterWithErrorHandling {
|
|
|
1507
1536
|
this._lifecycleEvents.emit("runtimeInstantiated");
|
|
1508
1537
|
this._loadedCodeDetails = codeDetails;
|
|
1509
1538
|
}
|
|
1539
|
+
updateDirtyContainerState = (dirty) => {
|
|
1540
|
+
if (this._dirtyContainer === dirty) {
|
|
1541
|
+
return;
|
|
1542
|
+
}
|
|
1543
|
+
this._dirtyContainer = dirty;
|
|
1544
|
+
this.emit(dirty ? dirtyContainerEvent : savedContainerEvent);
|
|
1545
|
+
};
|
|
1510
1546
|
/**
|
|
1511
1547
|
* Set the connected state of the ContainerContext
|
|
1512
1548
|
* This controls the "connected" state of the ContainerRuntime as well
|