@fluidframework/container-loader 2.117.0 → 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 +76 -2
- package/README.md +53 -50
- package/{api-extractor.json → api-extractor/api-extractor-model.json} +1 -1
- package/api-report/container-loader.legacy.alpha.api.md +4 -3
- package/dist/attachment.d.ts.map +1 -1
- package/dist/audience.js +3 -2
- package/dist/audience.js.map +1 -1
- package/dist/captureReferencedContents.js +9 -9
- package/dist/captureReferencedContents.js.map +1 -1
- package/dist/catchUpMonitor.js +11 -8
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +86 -51
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.js +40 -14
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +1 -1
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +193 -143
- package/dist/container.js.map +1 -1
- package/dist/containerContext.js +48 -11
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.js +25 -17
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts.map +1 -1
- package/dist/createAndLoadContainerUtils.d.ts +34 -13
- package/dist/createAndLoadContainerUtils.d.ts.map +1 -1
- package/dist/createAndLoadContainerUtils.js +97 -37
- package/dist/createAndLoadContainerUtils.js.map +1 -1
- package/dist/debugLogger.d.ts +7 -22
- package/dist/debugLogger.d.ts.map +1 -1
- package/dist/debugLogger.js +34 -34
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts +16 -4
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +75 -49
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaManagerFactory.d.ts +23 -0
- package/dist/deltaManagerFactory.d.ts.map +1 -0
- package/dist/deltaManagerFactory.js +17 -0
- package/dist/deltaManagerFactory.js.map +1 -0
- package/dist/deltaQueue.js +14 -7
- package/dist/deltaQueue.js.map +1 -1
- package/dist/disposal.js +1 -2
- package/dist/disposal.js.map +1 -1
- package/dist/error.js +5 -4
- package/dist/error.js.map +1 -1
- package/dist/frozenServices.d.ts +2 -2
- package/dist/frozenServices.d.ts.map +1 -1
- package/dist/frozenServices.js +52 -34
- package/dist/frozenServices.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/loadContainerToSequenceNumber.d.ts +6 -5
- package/dist/loadContainerToSequenceNumber.d.ts.map +1 -1
- package/dist/loadContainerToSequenceNumber.js +5 -6
- package/dist/loadContainerToSequenceNumber.js.map +1 -1
- package/dist/loadPaused.js +1 -2
- package/dist/loadPaused.js.map +1 -1
- package/dist/loader.js +5 -1
- package/dist/loader.js.map +1 -1
- package/dist/loaderLayerCompatState.d.ts +25 -1
- package/dist/loaderLayerCompatState.d.ts.map +1 -1
- package/dist/loaderLayerCompatState.js +79 -11
- package/dist/loaderLayerCompatState.js.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js +2 -3
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
- package/dist/memoryBlobStorage.js +2 -3
- package/dist/memoryBlobStorage.js.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.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingLocalStateStore.d.ts +4 -3
- package/dist/pendingLocalStateStore.d.ts.map +1 -1
- package/dist/pendingLocalStateStore.js +26 -37
- package/dist/pendingLocalStateStore.js.map +1 -1
- package/dist/pointInTimeServices.js +4 -2
- package/dist/pointInTimeServices.js.map +1 -1
- package/dist/protocol/protocol.js +3 -0
- package/dist/protocol/protocol.js.map +1 -1
- package/dist/protocol/quorum.js +26 -5
- package/dist/protocol/quorum.js.map +1 -1
- package/dist/protocol.js +5 -3
- package/dist/protocol.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js +10 -0
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/quorum.js +1 -2
- package/dist/quorum.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +5 -1
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/serializedStateManager.d.ts +6 -0
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +19 -24
- package/dist/serializedStateManager.js.map +1 -1
- package/dist/snapshotRefresher.js +31 -36
- package/dist/snapshotRefresher.js.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +13 -13
- package/dist/utils.js.map +1 -1
- package/lib/attachment.d.ts.map +1 -1
- package/lib/audience.js +3 -2
- 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.map +1 -1
- package/lib/connectionManager.js +86 -51
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.js +37 -11
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +1 -1
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +191 -141
- package/lib/container.js.map +1 -1
- package/lib/containerContext.js +48 -11
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.js +22 -14
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts.map +1 -1
- package/lib/createAndLoadContainerUtils.d.ts +34 -13
- package/lib/createAndLoadContainerUtils.d.ts.map +1 -1
- package/lib/createAndLoadContainerUtils.js +93 -32
- package/lib/createAndLoadContainerUtils.js.map +1 -1
- package/lib/debugLogger.d.ts +7 -22
- package/lib/debugLogger.d.ts.map +1 -1
- package/lib/debugLogger.js +34 -33
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts +16 -4
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +75 -49
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaManagerFactory.d.ts +23 -0
- package/lib/deltaManagerFactory.d.ts.map +1 -0
- package/lib/deltaManagerFactory.js +14 -0
- package/lib/deltaManagerFactory.js.map +1 -0
- 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/frozenServices.d.ts +2 -2
- package/lib/frozenServices.d.ts.map +1 -1
- package/lib/frozenServices.js +48 -30
- package/lib/frozenServices.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +1 -1
- package/lib/legacyAlpha.d.ts +1 -1
- package/lib/loadContainerToSequenceNumber.d.ts +6 -5
- package/lib/loadContainerToSequenceNumber.d.ts.map +1 -1
- package/lib/loadContainerToSequenceNumber.js +4 -4
- package/lib/loadContainerToSequenceNumber.js.map +1 -1
- package/lib/loader.js +6 -2
- package/lib/loader.js.map +1 -1
- package/lib/loaderLayerCompatState.d.ts +25 -1
- package/lib/loaderLayerCompatState.d.ts.map +1 -1
- package/lib/loaderLayerCompatState.js +76 -9
- package/lib/loaderLayerCompatState.js.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.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingLocalStateStore.d.ts +4 -3
- package/lib/pendingLocalStateStore.d.ts.map +1 -1
- package/lib/pendingLocalStateStore.js +26 -37
- package/lib/pendingLocalStateStore.js.map +1 -1
- package/lib/pointInTimeServices.js +2 -0
- package/lib/pointInTimeServices.js.map +1 -1
- package/lib/protocol/protocol.js +3 -0
- package/lib/protocol/protocol.js.map +1 -1
- package/lib/protocol/quorum.js +26 -5
- package/lib/protocol/quorum.js.map +1 -1
- package/lib/protocol.js +2 -0
- package/lib/protocol.js.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js +10 -0
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/public.d.ts +1 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +5 -1
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/serializedStateManager.d.ts +6 -0
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +15 -20
- package/lib/serializedStateManager.js.map +1 -1
- package/lib/snapshotRefresher.js +31 -36
- package/lib/snapshotRefresher.js.map +1 -1
- package/lib/utils.d.ts +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +3 -3
- package/lib/utils.js.map +1 -1
- package/package.json +44 -106
- package/src/container.ts +35 -22
- package/src/createAndLoadContainerUtils.ts +131 -46
- package/src/debugLogger.ts +39 -40
- package/src/deltaManager.ts +18 -5
- package/src/deltaManagerFactory.ts +53 -0
- package/src/frozenServices.ts +6 -7
- package/src/index.ts +1 -0
- package/src/loadContainerToSequenceNumber.ts +7 -6
- package/src/loader.ts +2 -2
- package/src/loaderLayerCompatState.ts +85 -20
- package/src/packageVersion.ts +1 -1
- package/src/pendingLocalStateStore.ts +7 -3
- package/src/pointInTime/DEV.md +47 -4
- package/src/serializedStateManager.ts +6 -0
- package/src/utils.ts +3 -3
- package/tsconfig.json +1 -1
- package/internal.d.ts +0 -11
- package/legacy/alpha.d.ts +0 -11
- package/legacy.d.ts +0 -11
- /package/api-extractor/{api-extractor.current.json → api-extractor-report.current.json} +0 -0
- /package/api-extractor/{api-extractor.legacy.json → api-extractor-report.legacy.json} +0 -0
package/lib/container.js
CHANGED
|
@@ -15,15 +15,14 @@ import { EventEmitterWithErrorHandling, GenericError, PerformanceEvent, UsageErr
|
|
|
15
15
|
import { v4 as uuid } from "uuid";
|
|
16
16
|
import { runRetriableAttachProcess, } from "./attachment.js";
|
|
17
17
|
import { Audience } from "./audience.js";
|
|
18
|
-
import { ConnectionManager } from "./connectionManager.js";
|
|
19
18
|
import { ConnectionState } from "./connectionState.js";
|
|
20
19
|
import { createConnectionStateHandler, } from "./connectionStateHandler.js";
|
|
21
20
|
import { ContainerContext } from "./containerContext.js";
|
|
22
21
|
import { ContainerStorageAdapter } from "./containerStorageAdapter.js";
|
|
23
22
|
import { ReconnectMode, getPackageName, } from "./contracts.js";
|
|
24
|
-
import {
|
|
23
|
+
import { createDeltaManager } from "./deltaManagerFactory.js";
|
|
25
24
|
import { RelativeLoader } from "./loader.js";
|
|
26
|
-
import { validateDriverCompatibility, validateRuntimeCompatibility, } from "./loaderLayerCompatState.js";
|
|
25
|
+
import { validateDriverCompatibility, validateLoaderCompatibilityWithDriver, validateRuntimeCompatibility, } from "./loaderLayerCompatState.js";
|
|
27
26
|
import { createMemoryDetachedBlobStorage, tryInitializeMemoryDetachedBlobStorage, } from "./memoryBlobStorage.js";
|
|
28
27
|
import { NoopHeuristic } from "./noopHeuristic.js";
|
|
29
28
|
import { pkgVersion } from "./packageVersion.js";
|
|
@@ -177,6 +176,41 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
177
176
|
return container;
|
|
178
177
|
}, { start: true, end: true, cancel: "generic" });
|
|
179
178
|
}
|
|
179
|
+
// Tells if container can reconnect on losing fist connection
|
|
180
|
+
// If false, container gets closed on loss of connection.
|
|
181
|
+
_canReconnect;
|
|
182
|
+
clientDetailsOverride;
|
|
183
|
+
urlResolver;
|
|
184
|
+
serviceFactory;
|
|
185
|
+
codeLoader;
|
|
186
|
+
options;
|
|
187
|
+
scope;
|
|
188
|
+
subLogger;
|
|
189
|
+
detachedBlobStorage;
|
|
190
|
+
protocolHandlerBuilder;
|
|
191
|
+
signalAudience = new Audience();
|
|
192
|
+
client;
|
|
193
|
+
mc;
|
|
194
|
+
/**
|
|
195
|
+
* Used by the RelativeLoader to spawn a new Container for the same document. Used to create the summarizing client.
|
|
196
|
+
*/
|
|
197
|
+
clone;
|
|
198
|
+
/**
|
|
199
|
+
* Lifecycle state of the container, used mainly to prevent re-entrancy and telemetry
|
|
200
|
+
*
|
|
201
|
+
* States are allowed to progress to further states:
|
|
202
|
+
* "loading" - "loaded" - "closing" - "disposing" - "closed" - "disposed"
|
|
203
|
+
*
|
|
204
|
+
* For example, moving from "closed" to "disposing" is not allowed since it is an earlier state.
|
|
205
|
+
*
|
|
206
|
+
* loading: Container has been created, but is not yet in normal/loaded state
|
|
207
|
+
* loaded: Container is in normal/loaded state
|
|
208
|
+
* closing: Container has started closing process (for re-entrancy prevention)
|
|
209
|
+
* disposing: Container has started disposing process (for re-entrancy prevention)
|
|
210
|
+
* closed: Container has closed
|
|
211
|
+
* disposed: Container has been disposed
|
|
212
|
+
*/
|
|
213
|
+
_lifecycleState = "loading";
|
|
180
214
|
setLoaded() {
|
|
181
215
|
// It's conceivable the container could be closed when this is called
|
|
182
216
|
// Only transition states if currently loading
|
|
@@ -223,18 +257,48 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
223
257
|
get disposed() {
|
|
224
258
|
return this._lifecycleState === "disposing" || this._lifecycleState === "disposed";
|
|
225
259
|
}
|
|
260
|
+
storageAdapter;
|
|
261
|
+
_deltaManager;
|
|
262
|
+
service;
|
|
263
|
+
fetchOps = async (from, to, abortSignal) => {
|
|
264
|
+
const deltaStorage = await this.service?.connectToDeltaStorage();
|
|
265
|
+
if (deltaStorage === undefined) {
|
|
266
|
+
throw new Error("Cannot fetch ops: delta storage is unavailable");
|
|
267
|
+
}
|
|
268
|
+
return deltaStorage.fetchMessages(from, to, abortSignal);
|
|
269
|
+
};
|
|
270
|
+
_runtime;
|
|
226
271
|
get runtime() {
|
|
227
272
|
if (this._runtime === undefined) {
|
|
228
273
|
throw new Error("Attempted to access runtime before it was defined");
|
|
229
274
|
}
|
|
230
275
|
return this._runtime;
|
|
231
276
|
}
|
|
277
|
+
_protocolHandler;
|
|
232
278
|
get protocolHandler() {
|
|
233
279
|
if (this._protocolHandler === undefined) {
|
|
234
280
|
throw new Error("Attempted to access protocolHandler before it was defined");
|
|
235
281
|
}
|
|
236
282
|
return this._protocolHandler;
|
|
237
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* During initialization we pause the inbound queues. We track this state to ensure we only call resume once
|
|
286
|
+
*/
|
|
287
|
+
inboundQueuePausedFromInit = true;
|
|
288
|
+
connectionCount = 0;
|
|
289
|
+
connectionTransitionTimes = [];
|
|
290
|
+
_loadedFromVersion;
|
|
291
|
+
_dirtyContainer = false;
|
|
292
|
+
attachmentData = { state: AttachState.Detached };
|
|
293
|
+
serializedStateManager;
|
|
294
|
+
_containerId;
|
|
295
|
+
lastVisible;
|
|
296
|
+
visibilityEventHandler;
|
|
297
|
+
connectionStateHandler;
|
|
298
|
+
clientsWhoShouldHaveLeft = new Set();
|
|
299
|
+
_containerMetadata = {};
|
|
300
|
+
setAutoReconnectTime = performanceNow();
|
|
301
|
+
noopHeuristic;
|
|
238
302
|
get connectionMode() {
|
|
239
303
|
return this._deltaManager.connectionManager.connectionMode;
|
|
240
304
|
}
|
|
@@ -310,6 +374,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
310
374
|
getSpecifiedCodeDetails() {
|
|
311
375
|
return this.getCodeDetailsFromQuorum();
|
|
312
376
|
}
|
|
377
|
+
_loadedCodeDetails;
|
|
313
378
|
/**
|
|
314
379
|
* Get the code details that were used to load the container.
|
|
315
380
|
* @returns The code details that were used to load the container if it is loaded, undefined if it is not yet
|
|
@@ -318,6 +383,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
318
383
|
getLoadedCodeDetails() {
|
|
319
384
|
return this._loadedCodeDetails;
|
|
320
385
|
}
|
|
386
|
+
_loadedModule;
|
|
321
387
|
/**
|
|
322
388
|
* Retrieves the audience associated with the document
|
|
323
389
|
*/
|
|
@@ -356,6 +422,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
356
422
|
this._lifecycleEvents.once("disposed", disposedHandler);
|
|
357
423
|
});
|
|
358
424
|
}
|
|
425
|
+
_lifecycleEvents = new TypedEventEmitter();
|
|
359
426
|
constructor(createProps, loadProps) {
|
|
360
427
|
super((name, error) => {
|
|
361
428
|
this.mc.logger.sendErrorEvent({
|
|
@@ -364,144 +431,22 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
364
431
|
}, error);
|
|
365
432
|
this.close(normalizeError(error));
|
|
366
433
|
});
|
|
367
|
-
this.signalAudience = new Audience();
|
|
368
|
-
/**
|
|
369
|
-
* Lifecycle state of the container, used mainly to prevent re-entrancy and telemetry
|
|
370
|
-
*
|
|
371
|
-
* States are allowed to progress to further states:
|
|
372
|
-
* "loading" - "loaded" - "closing" - "disposing" - "closed" - "disposed"
|
|
373
|
-
*
|
|
374
|
-
* For example, moving from "closed" to "disposing" is not allowed since it is an earlier state.
|
|
375
|
-
*
|
|
376
|
-
* loading: Container has been created, but is not yet in normal/loaded state
|
|
377
|
-
* loaded: Container is in normal/loaded state
|
|
378
|
-
* closing: Container has started closing process (for re-entrancy prevention)
|
|
379
|
-
* disposing: Container has started disposing process (for re-entrancy prevention)
|
|
380
|
-
* closed: Container has closed
|
|
381
|
-
* disposed: Container has been disposed
|
|
382
|
-
*/
|
|
383
|
-
this._lifecycleState = "loading";
|
|
384
|
-
this.fetchOps = async (from, to, abortSignal) => {
|
|
385
|
-
const deltaStorage = await this.service?.connectToDeltaStorage();
|
|
386
|
-
if (deltaStorage === undefined) {
|
|
387
|
-
throw new Error("Cannot fetch ops: delta storage is unavailable");
|
|
388
|
-
}
|
|
389
|
-
return deltaStorage.fetchMessages(from, to, abortSignal);
|
|
390
|
-
};
|
|
391
|
-
/**
|
|
392
|
-
* During initialization we pause the inbound queues. We track this state to ensure we only call resume once
|
|
393
|
-
*/
|
|
394
|
-
this.inboundQueuePausedFromInit = true;
|
|
395
|
-
this.connectionCount = 0;
|
|
396
|
-
this.connectionTransitionTimes = [];
|
|
397
|
-
this._dirtyContainer = false;
|
|
398
|
-
this.attachmentData = { state: AttachState.Detached };
|
|
399
|
-
this.clientsWhoShouldHaveLeft = new Set();
|
|
400
|
-
this._containerMetadata = {};
|
|
401
|
-
this.setAutoReconnectTime = performanceNow();
|
|
402
|
-
this._lifecycleEvents = new TypedEventEmitter();
|
|
403
|
-
this.verifyClosedAfterCalls = 0;
|
|
404
|
-
this._disposed = false;
|
|
405
|
-
this.attach = runSingle(async (request, attachProps) => {
|
|
406
|
-
await PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
|
|
407
|
-
if (this._lifecycleState !== "loaded" ||
|
|
408
|
-
this.attachmentData.state === AttachState.Attached) {
|
|
409
|
-
// pre-0.58 error message: containerNotValidForAttach
|
|
410
|
-
throw new UsageError(`The Container is not in a valid state for attach [${this._lifecycleState}] and [${this.attachState}]`);
|
|
411
|
-
}
|
|
412
|
-
const normalizeErrorAndClose = (error) => {
|
|
413
|
-
const newError = 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 !== 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
|
-
assert(this._deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
|
|
438
|
-
return 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
|
-
assert(this.client.details.type !== summarizerClientType &&
|
|
449
|
-
createNewResolvedUrl !== undefined, 0x2c4 /* "client should not be summarizer before container is created" */);
|
|
450
|
-
this.service = await this.createDocumentService(createNewResolvedUrl, {
|
|
451
|
-
mode: "attach",
|
|
452
|
-
summary,
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
this.storageAdapter.connectToService(this.service);
|
|
456
|
-
return this.storageAdapter;
|
|
457
|
-
};
|
|
458
|
-
let attachP = runRetriableAttachProcess({
|
|
459
|
-
initialAttachmentData: this.attachmentData,
|
|
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.DisableCloseOnAttachFailure") !== 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, 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
434
|
const { canReconnect, clientDetailsOverride, urlResolver, documentServiceFactory, codeLoader, options, scope, subLogger, protocolHandlerBuilder, } = createProps;
|
|
501
|
-
|
|
502
|
-
const
|
|
503
|
-
|
|
504
|
-
|
|
435
|
+
const maybeDriverCompat = documentServiceFactory;
|
|
436
|
+
const driverCompatMonitoringContext = createChildMonitoringContext({
|
|
437
|
+
logger: subLogger,
|
|
438
|
+
namespace: "Container",
|
|
439
|
+
});
|
|
440
|
+
// Validate that the Driver is compatible with this Loader. This is the standard direction: the Loader holds
|
|
441
|
+
// a reference to the Driver and validates it.
|
|
442
|
+
validateDriverCompatibility(maybeDriverCompat.ILayerCompatDetails, (error) => { } /* disposeFn */, // There is nothing to dispose here, so just ignore the error.
|
|
443
|
+
driverCompatMonitoringContext);
|
|
444
|
+
// Validate that this Loader is compatible with the Driver. This is the reverse, non-standard direction: a
|
|
445
|
+
// layer normally validates the layer it holds a reference to, but the Driver has no reference to the Loader
|
|
446
|
+
// and so cannot validate it itself. The Driver instead publishes the requirements it has for the Loader (via
|
|
447
|
+
// ILayerCompatSupportRequirements), and the Loader validates itself against them here, on the Driver's behalf.
|
|
448
|
+
validateLoaderCompatibilityWithDriver(maybeDriverCompat.ILayerCompatDetails, maybeDriverCompat.ILayerCompatSupportRequirements, (error) => { } /* disposeFn */, // There is nothing to dispose here, so just ignore the error.
|
|
449
|
+
driverCompatMonitoringContext);
|
|
505
450
|
this.connectionTransitionTimes[ConnectionState.Disconnected] = performanceNow();
|
|
506
451
|
const pendingLocalState = loadProps?.pendingLocalState;
|
|
507
452
|
this._canReconnect = canReconnect ?? true;
|
|
@@ -682,6 +627,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
682
627
|
// "closing" will lose that info (can also solve by tracking extra state).
|
|
683
628
|
this.verifyClosedAfter(() => this._deltaManager.close(error));
|
|
684
629
|
}
|
|
630
|
+
verifyClosedAfterCalls = 0;
|
|
685
631
|
verifyClosedAfter(callback) {
|
|
686
632
|
this.verifyClosedAfterCalls++;
|
|
687
633
|
try {
|
|
@@ -736,6 +682,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
736
682
|
}
|
|
737
683
|
}
|
|
738
684
|
}
|
|
685
|
+
_disposed = false;
|
|
739
686
|
disposeCore(error) {
|
|
740
687
|
assert(!this._disposed, 0x54c /* Container already disposed */);
|
|
741
688
|
this._disposed = true;
|
|
@@ -822,6 +769,84 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
822
769
|
};
|
|
823
770
|
return JSON.stringify(detachedContainerState);
|
|
824
771
|
}
|
|
772
|
+
attach = runSingle(async (request, attachProps) => {
|
|
773
|
+
await PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
|
|
774
|
+
if (this._lifecycleState !== "loaded" ||
|
|
775
|
+
this.attachmentData.state === AttachState.Attached) {
|
|
776
|
+
// pre-0.58 error message: containerNotValidForAttach
|
|
777
|
+
throw new UsageError(`The Container is not in a valid state for attach [${this._lifecycleState}] and [${this.attachState}]`);
|
|
778
|
+
}
|
|
779
|
+
const normalizeErrorAndClose = (error) => {
|
|
780
|
+
const newError = normalizeError(error);
|
|
781
|
+
this.close(newError);
|
|
782
|
+
// add resolved URL on error object so that host has the ability to find this document and delete it
|
|
783
|
+
newError.addTelemetryProperties({
|
|
784
|
+
resolvedUrl: this.service?.resolvedUrl?.url,
|
|
785
|
+
});
|
|
786
|
+
return newError;
|
|
787
|
+
};
|
|
788
|
+
const setAttachmentData = (attachmentData) => {
|
|
789
|
+
const previousState = this.attachmentData.state;
|
|
790
|
+
this.attachmentData = attachmentData;
|
|
791
|
+
const state = this.attachmentData.state;
|
|
792
|
+
if (state !== previousState && state !== AttachState.Detached) {
|
|
793
|
+
try {
|
|
794
|
+
this.runtime.setAttachState(state);
|
|
795
|
+
this.emit(state.toLocaleLowerCase());
|
|
796
|
+
}
|
|
797
|
+
catch (error) {
|
|
798
|
+
throw normalizeErrorAndClose(error);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
const createAttachmentSummary = (redirectTable) => {
|
|
803
|
+
try {
|
|
804
|
+
assert(this._deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
|
|
805
|
+
return combineAppAndProtocolSummary(this.runtime.createSummary(redirectTable), this.captureProtocolSummary());
|
|
806
|
+
}
|
|
807
|
+
catch (error) {
|
|
808
|
+
throw normalizeErrorAndClose(error);
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
const createOrGetStorageService = async (summary) => {
|
|
812
|
+
// Actually go and create the resolved document
|
|
813
|
+
if (this.service === undefined) {
|
|
814
|
+
const createNewResolvedUrl = await this.urlResolver.resolve(request);
|
|
815
|
+
assert(this.client.details.type !== summarizerClientType &&
|
|
816
|
+
createNewResolvedUrl !== undefined, 0x2c4 /* "client should not be summarizer before container is created" */);
|
|
817
|
+
this.service = await this.createDocumentService(createNewResolvedUrl, {
|
|
818
|
+
mode: "attach",
|
|
819
|
+
summary,
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
this.storageAdapter.connectToService(this.service);
|
|
823
|
+
return this.storageAdapter;
|
|
824
|
+
};
|
|
825
|
+
let attachP = runRetriableAttachProcess({
|
|
826
|
+
initialAttachmentData: this.attachmentData,
|
|
827
|
+
detachedBlobStorage: this.detachedBlobStorage,
|
|
828
|
+
setAttachmentData,
|
|
829
|
+
createAttachmentSummary,
|
|
830
|
+
createOrGetStorageService,
|
|
831
|
+
});
|
|
832
|
+
// only enable the new behavior if the config is set
|
|
833
|
+
if (this.mc.config.getBoolean("Fluid.Container.DisableCloseOnAttachFailure") !== true) {
|
|
834
|
+
attachP = attachP.catch((error) => {
|
|
835
|
+
throw normalizeErrorAndClose(error);
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
// If offline load is enabled, attachP will return the attach summary (in Snapshot format) so we can initialize SerializedStateManager
|
|
839
|
+
const snapshotWithBlobs = await attachP;
|
|
840
|
+
this.serializedStateManager.setInitialSnapshot(snapshotWithBlobs);
|
|
841
|
+
if (!this.closed) {
|
|
842
|
+
this.detachedBlobStorage?.dispose?.();
|
|
843
|
+
this.handleDeltaConnectionArg(attachProps?.deltaConnection, {
|
|
844
|
+
fetchOpsFromStorage: false,
|
|
845
|
+
reason: { text: "createDetached" },
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
}, { start: true, end: true, cancel: "generic" });
|
|
849
|
+
});
|
|
825
850
|
setAutoReconnectInternal(mode, reason) {
|
|
826
851
|
const currentMode = this._deltaManager.connectionManager.reconnectMode;
|
|
827
852
|
if (currentMode === mode) {
|
|
@@ -894,6 +919,12 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
894
919
|
// Ensure connection to web socket
|
|
895
920
|
this.connectToDeltaStream(args);
|
|
896
921
|
}
|
|
922
|
+
getAbsoluteUrl = async (relativeUrl) => {
|
|
923
|
+
if (this.resolvedUrl === undefined) {
|
|
924
|
+
return undefined;
|
|
925
|
+
}
|
|
926
|
+
return this.urlResolver.getAbsoluteUrl(this.resolvedUrl, relativeUrl, getPackageName(this._loadedCodeDetails));
|
|
927
|
+
};
|
|
897
928
|
async proposeCodeDetails(codeDetails) {
|
|
898
929
|
if (!isFluidCodeDetails(codeDetails)) {
|
|
899
930
|
throw new Error("Provided codeDetails are not IFluidCodeDetails");
|
|
@@ -962,6 +993,10 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
962
993
|
}
|
|
963
994
|
this._deltaManager.connect(args);
|
|
964
995
|
}
|
|
996
|
+
metadataUpdateHandler = (metadata) => {
|
|
997
|
+
this._containerMetadata = { ...this._containerMetadata, ...metadata };
|
|
998
|
+
this.emit("metadataUpdate", metadata);
|
|
999
|
+
};
|
|
965
1000
|
/**
|
|
966
1001
|
* Creates a document service during container attachment or loading.
|
|
967
1002
|
* @param resolvedUrl - The resolved URL of the container.
|
|
@@ -1283,7 +1318,15 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
1283
1318
|
createDeltaManager() {
|
|
1284
1319
|
const serviceProvider = () => this.service;
|
|
1285
1320
|
const disableLoadConnectionRetries = this.mc.config.getBoolean("Fluid.Container.DisableLoadConnectionRetries") === true;
|
|
1286
|
-
const deltaManager =
|
|
1321
|
+
const deltaManager = createDeltaManager({
|
|
1322
|
+
serviceProvider,
|
|
1323
|
+
logger: this.subLogger,
|
|
1324
|
+
active: () => this.activeConnection(),
|
|
1325
|
+
containerDirty: () => this.isDirty,
|
|
1326
|
+
client: this.client,
|
|
1327
|
+
reconnectAllowed: this._canReconnect,
|
|
1328
|
+
maxInitialConnectionAttempts: disableLoadConnectionRetries ? 1 : undefined,
|
|
1329
|
+
});
|
|
1287
1330
|
// Disable inbound queues as Container is not ready to accept any ops until we are fully loaded!
|
|
1288
1331
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1289
1332
|
deltaManager.inbound.pause();
|
|
@@ -1607,6 +1650,13 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
1607
1650
|
throw error;
|
|
1608
1651
|
}
|
|
1609
1652
|
}
|
|
1653
|
+
updateDirtyContainerState = (dirty) => {
|
|
1654
|
+
if (this._dirtyContainer === dirty) {
|
|
1655
|
+
return;
|
|
1656
|
+
}
|
|
1657
|
+
this._dirtyContainer = dirty;
|
|
1658
|
+
this.emit(dirty ? dirtyContainerEvent : savedContainerEvent);
|
|
1659
|
+
};
|
|
1610
1660
|
/**
|
|
1611
1661
|
* Send the connected status to the runtime.
|
|
1612
1662
|
* @param readonly - Is the container in readonly mode?
|