@fluidframework/container-loader 2.0.0-internal.5.4.0 → 2.0.0-internal.6.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 +81 -0
- package/dist/connectionManager.d.ts +1 -1
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +24 -25
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +2 -1
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +9 -16
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +10 -5
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +160 -99
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +2 -12
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +1 -20
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.js +3 -5
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +11 -2
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +3 -3
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.js +2 -3
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts +16 -3
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +62 -24
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.js +1 -2
- package/dist/deltaQueue.js.map +1 -1
- package/dist/loader.d.ts +12 -0
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +57 -42
- 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/protocol.d.ts.map +1 -1
- package/dist/protocol.js +2 -3
- package/dist/protocol.js.map +1 -1
- package/dist/utils.d.ts +8 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +24 -6
- package/dist/utils.js.map +1 -1
- package/lib/connectionManager.d.ts +1 -1
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +25 -26
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +2 -1
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +9 -16
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +10 -5
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +159 -98
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +2 -12
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +1 -20
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.js +3 -5
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +11 -2
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js +3 -3
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.js +2 -3
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts +16 -3
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +62 -24
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.js +1 -2
- package/lib/deltaQueue.js.map +1 -1
- package/lib/loader.d.ts +12 -0
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +57 -42
- 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/protocol.d.ts.map +1 -1
- package/lib/protocol.js +2 -3
- package/lib/protocol.js.map +1 -1
- package/lib/utils.d.ts +8 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +22 -5
- package/lib/utils.js.map +1 -1
- package/package.json +11 -11
- package/src/connectionManager.ts +7 -3
- package/src/connectionStateHandler.ts +3 -2
- package/src/container.ts +113 -28
- package/src/containerContext.ts +0 -24
- package/src/contracts.ts +16 -5
- package/src/deltaManager.ts +22 -5
- package/src/loader.ts +37 -23
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +0 -1
- package/src/utils.ts +29 -0
package/dist/container.js
CHANGED
|
@@ -111,7 +111,7 @@ async function waitContainerToCatchUp(container) {
|
|
|
111
111
|
exports.waitContainerToCatchUp = waitContainerToCatchUp;
|
|
112
112
|
const getCodeProposal =
|
|
113
113
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
114
|
-
(quorum) =>
|
|
114
|
+
(quorum) => quorum.get("code") ?? quorum.get("code2");
|
|
115
115
|
/**
|
|
116
116
|
* Helper function to report to telemetry cases where operation takes longer than expected (200ms)
|
|
117
117
|
* @param logger - logger to use
|
|
@@ -132,7 +132,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
132
132
|
* @internal
|
|
133
133
|
*/
|
|
134
134
|
constructor(createProps, loadProps) {
|
|
135
|
-
var _a;
|
|
136
135
|
super((name, error) => {
|
|
137
136
|
this.mc.logger.sendErrorEvent({
|
|
138
137
|
eventName: "ContainerEventHandlerException",
|
|
@@ -182,8 +181,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
182
181
|
};
|
|
183
182
|
const { canReconnect, clientDetailsOverride, urlResolver, documentServiceFactory, codeLoader, options, scope, subLogger, detachedBlobStorage, protocolHandlerBuilder, } = createProps;
|
|
184
183
|
this.connectionTransitionTimes[connectionState_1.ConnectionState.Disconnected] = common_utils_1.performance.now();
|
|
185
|
-
const pendingLocalState = loadProps
|
|
186
|
-
this._canReconnect = canReconnect
|
|
184
|
+
const pendingLocalState = loadProps?.pendingLocalState;
|
|
185
|
+
this._canReconnect = canReconnect ?? true;
|
|
187
186
|
this.clientDetailsOverride = clientDetailsOverride;
|
|
188
187
|
this.urlResolver = urlResolver;
|
|
189
188
|
this.serviceFactory = documentServiceFactory;
|
|
@@ -191,14 +190,17 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
191
190
|
// Warning: this is only a shallow clone. Mutation of any individual loader option will mutate it for
|
|
192
191
|
// all clients that were loaded from the same loader (including summarizer clients).
|
|
193
192
|
// Tracking alternative ways to handle this in AB#4129.
|
|
194
|
-
this.options =
|
|
193
|
+
this.options = { ...options };
|
|
195
194
|
this.scope = scope;
|
|
196
195
|
this.detachedBlobStorage = detachedBlobStorage;
|
|
197
196
|
this.protocolHandlerBuilder =
|
|
198
|
-
protocolHandlerBuilder
|
|
197
|
+
protocolHandlerBuilder ?? ((...args) => new protocol_1.ProtocolHandler(...args, new audience_1.Audience()));
|
|
199
198
|
// Note that we capture the createProps here so we can replicate the creation call when we want to clone.
|
|
200
199
|
this.clone = async (_loadProps, createParamOverrides) => {
|
|
201
|
-
return Container.load(_loadProps,
|
|
200
|
+
return Container.load(_loadProps, {
|
|
201
|
+
...createProps,
|
|
202
|
+
...createParamOverrides,
|
|
203
|
+
});
|
|
202
204
|
};
|
|
203
205
|
// Create logger for data stores to use
|
|
204
206
|
const type = this.client.details.type;
|
|
@@ -212,7 +214,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
212
214
|
all: {
|
|
213
215
|
clientType,
|
|
214
216
|
containerId: (0, uuid_1.v4)(),
|
|
215
|
-
docId: () =>
|
|
217
|
+
docId: () => this.resolvedUrl?.id,
|
|
216
218
|
containerAttachState: () => this._attachState,
|
|
217
219
|
containerLifecycleState: () => this._lifecycleState,
|
|
218
220
|
containerConnectionState: () => connectionState_1.ConnectionState[this.connectionState],
|
|
@@ -223,22 +225,19 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
223
225
|
// specific error or class of errors
|
|
224
226
|
error: {
|
|
225
227
|
// load information to associate errors with the specific load point
|
|
226
|
-
dmInitialSeqNumber: () =>
|
|
227
|
-
dmLastProcessedSeqNumber: () =>
|
|
228
|
-
dmLastKnownSeqNumber: () =>
|
|
229
|
-
containerLoadedFromVersionId: () =>
|
|
230
|
-
containerLoadedFromVersionDate: () =>
|
|
228
|
+
dmInitialSeqNumber: () => this._deltaManager?.initialSequenceNumber,
|
|
229
|
+
dmLastProcessedSeqNumber: () => this._deltaManager?.lastSequenceNumber,
|
|
230
|
+
dmLastKnownSeqNumber: () => this._deltaManager?.lastKnownSeqNumber,
|
|
231
|
+
containerLoadedFromVersionId: () => this._loadedFromVersion?.id,
|
|
232
|
+
containerLoadedFromVersionDate: () => this._loadedFromVersion?.date,
|
|
231
233
|
// message information to associate errors with the specific execution state
|
|
232
234
|
// dmLastMsqSeqNumber: if present, same as dmLastProcessedSeqNumber
|
|
233
|
-
dmLastMsqSeqNumber: () =>
|
|
234
|
-
dmLastMsqSeqTimestamp: () =>
|
|
235
|
-
dmLastMsqSeqClientId: () =>
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
: (_d = (_c = this.deltaManager) === null || _c === void 0 ? void 0 : _c.lastMessage) === null || _d === void 0 ? void 0 : _d.clientId;
|
|
240
|
-
},
|
|
241
|
-
dmLastMsgClientSeq: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.clientSequenceNumber; },
|
|
235
|
+
dmLastMsqSeqNumber: () => this.deltaManager?.lastMessage?.sequenceNumber,
|
|
236
|
+
dmLastMsqSeqTimestamp: () => this.deltaManager?.lastMessage?.timestamp,
|
|
237
|
+
dmLastMsqSeqClientId: () => this.deltaManager?.lastMessage?.clientId === null
|
|
238
|
+
? "null"
|
|
239
|
+
: this.deltaManager?.lastMessage?.clientId,
|
|
240
|
+
dmLastMsgClientSeq: () => this.deltaManager?.lastMessage?.clientSequenceNumber,
|
|
242
241
|
connectionStateDuration: () => common_utils_1.performance.now() - this.connectionTransitionTimes[this.connectionState],
|
|
243
242
|
},
|
|
244
243
|
},
|
|
@@ -268,9 +267,14 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
268
267
|
// Report issues only if we already loaded container - op processing is paused while container is loading,
|
|
269
268
|
// so we always time-out processing of join op in cases where fetching snapshot takes a minute.
|
|
270
269
|
// It's not a problem with op processing itself - such issues should be tracked as part of boot perf monitoring instead.
|
|
271
|
-
this._deltaManager.logConnectionIssue(
|
|
272
|
-
|
|
273
|
-
|
|
270
|
+
this._deltaManager.logConnectionIssue({
|
|
271
|
+
eventName,
|
|
272
|
+
mode,
|
|
273
|
+
category: this._lifecycleState === "loading" ? "generic" : category,
|
|
274
|
+
duration: common_utils_1.performance.now() -
|
|
275
|
+
this.connectionTransitionTimes[connectionState_1.ConnectionState.CatchingUp],
|
|
276
|
+
...(details === undefined ? {} : { details: JSON.stringify(details) }),
|
|
277
|
+
});
|
|
274
278
|
// If this is "write" connection, it took too long to receive join op. But in most cases that's due
|
|
275
279
|
// to very slow op fetches and we will eventually get there.
|
|
276
280
|
// For "read" connections, we get here due to self join signal not arriving on time. We will need to
|
|
@@ -287,7 +291,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
287
291
|
clientShouldHaveLeft: (clientId) => {
|
|
288
292
|
this.clientsWhoShouldHaveLeft.add(clientId);
|
|
289
293
|
},
|
|
290
|
-
}, this.deltaManager, pendingLocalState
|
|
294
|
+
}, this.deltaManager, pendingLocalState?.clientId);
|
|
291
295
|
this.on(savedContainerEvent, () => {
|
|
292
296
|
this.connectionStateHandler.containerSaved();
|
|
293
297
|
});
|
|
@@ -296,11 +300,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
296
300
|
// using this callback and fix them up.
|
|
297
301
|
const addProtocolSummaryIfMissing = (summaryTree) => (0, driver_utils_1.isCombinedAppAndProtocolSummary)(summaryTree) === true
|
|
298
302
|
? summaryTree
|
|
299
|
-
: (0,
|
|
303
|
+
: (0, utils_1.combineAppAndProtocolSummary)(summaryTree, this.captureProtocolSummary());
|
|
300
304
|
// Whether the combined summary tree has been forced on by either the loader option or the monitoring context.
|
|
301
305
|
// Even if not forced on via this flag, combined summaries may still be enabled by service policy.
|
|
302
|
-
const forceEnableSummarizeProtocolTree =
|
|
303
|
-
|
|
306
|
+
const forceEnableSummarizeProtocolTree = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree2") ??
|
|
307
|
+
options.summarizeProtocolTree;
|
|
308
|
+
this.storageAdapter = new containerStorageAdapter_1.ContainerStorageAdapter(detachedBlobStorage, this.mc.logger, pendingLocalState?.snapshotBlobs, addProtocolSummaryIfMissing, forceEnableSummarizeProtocolTree);
|
|
304
309
|
const isDomAvailable = typeof document === "object" &&
|
|
305
310
|
document !== null &&
|
|
306
311
|
typeof document.addEventListener === "function" &&
|
|
@@ -327,7 +332,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
327
332
|
* @internal
|
|
328
333
|
*/
|
|
329
334
|
static async load(loadProps, createProps) {
|
|
330
|
-
const { version, pendingLocalState, loadMode, resolvedUrl } = loadProps;
|
|
335
|
+
const { version, pendingLocalState, loadMode, resolvedUrl, loadToSequenceNumber } = loadProps;
|
|
331
336
|
const container = new Container(createProps, loadProps);
|
|
332
337
|
const disableRecordHeapSize = container.mc.config.getBoolean("Fluid.Loader.DisableRecordHeapSize");
|
|
333
338
|
return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "Load" }, async (event) => new Promise((resolve, reject) => {
|
|
@@ -335,19 +340,20 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
335
340
|
// if we have pendingLocalState, anything we cached is not useful and we shouldn't wait for connection
|
|
336
341
|
// to return container, so ignore this value and use undefined for opsBeforeReturn
|
|
337
342
|
const mode = pendingLocalState
|
|
338
|
-
?
|
|
343
|
+
? { ...(loadMode ?? defaultMode), opsBeforeReturn: undefined }
|
|
344
|
+
: loadMode ?? defaultMode;
|
|
339
345
|
const onClosed = (err) => {
|
|
340
346
|
// pre-0.58 error message: containerClosedWithoutErrorDuringLoad
|
|
341
|
-
reject(err
|
|
347
|
+
reject(err ?? new container_utils_1.GenericError("Container closed without error during load"));
|
|
342
348
|
};
|
|
343
349
|
container.on("closed", onClosed);
|
|
344
350
|
container
|
|
345
|
-
.load(version, mode, resolvedUrl, pendingLocalState)
|
|
351
|
+
.load(version, mode, resolvedUrl, pendingLocalState, loadToSequenceNumber)
|
|
346
352
|
.finally(() => {
|
|
347
353
|
container.removeListener("closed", onClosed);
|
|
348
354
|
})
|
|
349
355
|
.then((props) => {
|
|
350
|
-
event.end(
|
|
356
|
+
event.end({ ...props, ...loadMode });
|
|
351
357
|
resolve(container);
|
|
352
358
|
}, (error) => {
|
|
353
359
|
const err = (0, telemetry_utils_1.normalizeError)(error);
|
|
@@ -415,7 +421,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
415
421
|
return this;
|
|
416
422
|
}
|
|
417
423
|
get resolvedUrl() {
|
|
418
|
-
var _a;
|
|
419
424
|
/**
|
|
420
425
|
* All attached containers will have a document service,
|
|
421
426
|
* this is required, as attached containers are attached to
|
|
@@ -427,7 +432,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
427
432
|
* is always the same as the containers, as we had to
|
|
428
433
|
* obtain the resolved url, and then create the service from it.
|
|
429
434
|
*/
|
|
430
|
-
return
|
|
435
|
+
return this.service?.resolvedUrl;
|
|
431
436
|
}
|
|
432
437
|
get readOnlyInfo() {
|
|
433
438
|
return this._deltaManager.readOnlyInfo;
|
|
@@ -455,8 +460,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
455
460
|
return this._clientId;
|
|
456
461
|
}
|
|
457
462
|
get offlineLoadEnabled() {
|
|
458
|
-
|
|
459
|
-
|
|
463
|
+
const enabled = this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad") ??
|
|
464
|
+
this.options?.enableOfflineLoad === true;
|
|
460
465
|
// summarizer will not have any pending state we want to save
|
|
461
466
|
return enabled && this.deltaManager.clientDetails.capabilities.interactive;
|
|
462
467
|
}
|
|
@@ -493,18 +498,16 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
493
498
|
* {@inheritDoc @fluidframework/container-definitions#IContainer.entryPoint}
|
|
494
499
|
*/
|
|
495
500
|
async getEntryPoint() {
|
|
496
|
-
var _a, _b;
|
|
497
501
|
if (this._disposed) {
|
|
498
502
|
throw new container_utils_1.UsageError("The context is already disposed");
|
|
499
503
|
}
|
|
500
504
|
if (this._runtime !== undefined) {
|
|
501
|
-
return
|
|
505
|
+
return this._runtime.getEntryPoint?.();
|
|
502
506
|
}
|
|
503
507
|
return new Promise((resolve, reject) => {
|
|
504
508
|
const runtimeInstantiatedHandler = () => {
|
|
505
|
-
var _a, _b;
|
|
506
509
|
(0, common_utils_1.assert)(this._runtime !== undefined, 0x5a3 /* runtimeInstantiated fired but runtime is still undefined */);
|
|
507
|
-
resolve(
|
|
510
|
+
resolve(this._runtime.getEntryPoint?.());
|
|
508
511
|
this._lifecycleEvents.off("disposed", disposedHandler);
|
|
509
512
|
};
|
|
510
513
|
const disposedHandler = () => {
|
|
@@ -538,7 +541,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
538
541
|
(0, common_utils_1.assert)(this._lifecycleState === "closed" || this._lifecycleState === "disposed", 0x314 /* Container properly closed */);
|
|
539
542
|
}
|
|
540
543
|
closeCore(error) {
|
|
541
|
-
var _a;
|
|
542
544
|
(0, common_utils_1.assert)(!this.closed, 0x315 /* re-entrancy */);
|
|
543
545
|
try {
|
|
544
546
|
// Ensure that we raise all key events even if one of these throws
|
|
@@ -554,7 +556,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
554
556
|
: "generic",
|
|
555
557
|
}, error);
|
|
556
558
|
this._lifecycleState = "closing";
|
|
557
|
-
|
|
559
|
+
this._protocolHandler?.close();
|
|
558
560
|
this.connectionStateHandler.dispose();
|
|
559
561
|
}
|
|
560
562
|
catch (exception) {
|
|
@@ -574,7 +576,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
574
576
|
}
|
|
575
577
|
}
|
|
576
578
|
disposeCore(error) {
|
|
577
|
-
var _a, _b, _c;
|
|
578
579
|
(0, common_utils_1.assert)(!this._disposed, 0x54c /* Container already disposed */);
|
|
579
580
|
this._disposed = true;
|
|
580
581
|
try {
|
|
@@ -591,15 +592,15 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
591
592
|
if (this._lifecycleState !== "closed") {
|
|
592
593
|
this._lifecycleState = "disposing";
|
|
593
594
|
}
|
|
594
|
-
|
|
595
|
+
this._protocolHandler?.close();
|
|
595
596
|
this.connectionStateHandler.dispose();
|
|
596
597
|
const maybeError = error !== undefined ? new Error(error.message) : undefined;
|
|
597
|
-
|
|
598
|
+
this._runtime?.dispose(maybeError);
|
|
598
599
|
this.storageAdapter.dispose();
|
|
599
600
|
// Notify storage about critical errors. They may be due to disconnect between client & server knowledge
|
|
600
601
|
// about file, like file being overwritten in storage, but client having stale local cache.
|
|
601
602
|
// Driver need to ensure all caches are cleared on critical errors
|
|
602
|
-
|
|
603
|
+
this.service?.dispose(error);
|
|
603
604
|
}
|
|
604
605
|
catch (exception) {
|
|
605
606
|
this.mc.logger.sendErrorEvent({ eventName: "ContainerDisposeException" }, exception);
|
|
@@ -615,15 +616,19 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
615
616
|
this._lifecycleEvents.emit("disposed");
|
|
616
617
|
}
|
|
617
618
|
}
|
|
618
|
-
closeAndGetPendingLocalState() {
|
|
619
|
+
async closeAndGetPendingLocalState() {
|
|
619
620
|
// runtime matches pending ops to successful ones by clientId and client seq num, so we need to close the
|
|
620
621
|
// container at the same time we get pending state, otherwise this container could reconnect and resubmit with
|
|
621
622
|
// a new clientId and a future container using stale pending state without the new clientId would resubmit them
|
|
622
|
-
|
|
623
|
+
this.disconnect(); // TODO https://dev.azure.com/fluidframework/internal/_workitems/edit/5127
|
|
624
|
+
const pendingState = await this.getPendingLocalStateCore({ notifyImminentClosure: true });
|
|
623
625
|
this.close();
|
|
624
626
|
return pendingState;
|
|
625
627
|
}
|
|
626
|
-
getPendingLocalState() {
|
|
628
|
+
async getPendingLocalState() {
|
|
629
|
+
return this.getPendingLocalStateCore({ notifyImminentClosure: false });
|
|
630
|
+
}
|
|
631
|
+
async getPendingLocalStateCore(props) {
|
|
627
632
|
if (!this.offlineLoadEnabled) {
|
|
628
633
|
throw new container_utils_1.UsageError("Can't get pending local state unless offline load is enabled");
|
|
629
634
|
}
|
|
@@ -634,8 +639,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
634
639
|
(0, common_utils_1.assert)(this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid", 0x0d2 /* "resolved url should be valid Fluid url" */);
|
|
635
640
|
(0, common_utils_1.assert)(!!this.baseSnapshot, 0x5d4 /* no base snapshot */);
|
|
636
641
|
(0, common_utils_1.assert)(!!this.baseSnapshotBlobs, 0x5d5 /* no snapshot blobs */);
|
|
642
|
+
const pendingRuntimeState = await this.runtime.getPendingLocalState(props);
|
|
637
643
|
const pendingState = {
|
|
638
|
-
pendingRuntimeState
|
|
644
|
+
pendingRuntimeState,
|
|
639
645
|
baseSnapshot: this.baseSnapshot,
|
|
640
646
|
snapshotBlobs: this.baseSnapshotBlobs,
|
|
641
647
|
savedOps: this.savedOps,
|
|
@@ -653,7 +659,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
653
659
|
(0, common_utils_1.assert)(this.attachState === container_definitions_1.AttachState.Detached, 0x0d3 /* "Should only be called in detached container" */);
|
|
654
660
|
const appSummary = this.runtime.createSummary();
|
|
655
661
|
const protocolSummary = this.captureProtocolSummary();
|
|
656
|
-
const combinedSummary = (0,
|
|
662
|
+
const combinedSummary = (0, utils_1.combineAppAndProtocolSummary)(appSummary, protocolSummary);
|
|
657
663
|
if (this.detachedBlobStorage && this.detachedBlobStorage.size > 0) {
|
|
658
664
|
combinedSummary.tree[".hasAttachmentBlobs"] = {
|
|
659
665
|
type: protocol_definitions_1.SummaryType.Blob,
|
|
@@ -664,7 +670,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
664
670
|
}
|
|
665
671
|
async attach(request) {
|
|
666
672
|
await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Attach" }, async () => {
|
|
667
|
-
var _a;
|
|
668
673
|
if (this._lifecycleState !== "loaded") {
|
|
669
674
|
// pre-0.58 error message: containerNotValidForAttach
|
|
670
675
|
throw new container_utils_1.UsageError(`The Container is not in a valid state for attach [${this._lifecycleState}]`);
|
|
@@ -682,7 +687,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
682
687
|
// semantics around what the attach means as far as async code goes.
|
|
683
688
|
const appSummary = this.runtime.createSummary();
|
|
684
689
|
const protocolSummary = this.captureProtocolSummary();
|
|
685
|
-
summary = (0,
|
|
690
|
+
summary = (0, utils_1.combineAppAndProtocolSummary)(appSummary, protocolSummary);
|
|
686
691
|
// Set the state as attaching as we are starting the process of attaching container.
|
|
687
692
|
// This should be fired after taking the summary because it is the place where we are
|
|
688
693
|
// starting to attach the container to storage.
|
|
@@ -727,7 +732,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
727
732
|
// take summary and upload
|
|
728
733
|
const appSummary = this.runtime.createSummary(redirectTable);
|
|
729
734
|
const protocolSummary = this.captureProtocolSummary();
|
|
730
|
-
summary = (0,
|
|
735
|
+
summary = (0, utils_1.combineAppAndProtocolSummary)(appSummary, protocolSummary);
|
|
731
736
|
this._attachState = container_definitions_1.AttachState.Attaching;
|
|
732
737
|
this.runtime.setAttachState(container_definitions_1.AttachState.Attaching);
|
|
733
738
|
this.emit("attaching");
|
|
@@ -756,7 +761,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
756
761
|
catch (error) {
|
|
757
762
|
// add resolved URL on error object so that host has the ability to find this document and delete it
|
|
758
763
|
const newError = (0, telemetry_utils_1.normalizeError)(error);
|
|
759
|
-
newError.addTelemetryProperties({ resolvedUrl:
|
|
764
|
+
newError.addTelemetryProperties({ resolvedUrl: this.resolvedUrl?.url });
|
|
760
765
|
this.close(newError);
|
|
761
766
|
throw newError;
|
|
762
767
|
}
|
|
@@ -863,7 +868,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
863
868
|
* Determines if the currently loaded module satisfies the incoming constraint code details
|
|
864
869
|
*/
|
|
865
870
|
async satisfies(constraintCodeDetails) {
|
|
866
|
-
var _a, _b;
|
|
867
871
|
// If we have no module, it can't satisfy anything.
|
|
868
872
|
if (this._loadedModule === undefined) {
|
|
869
873
|
return false;
|
|
@@ -873,8 +877,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
873
877
|
if (maybeCompareCodeLoader.IFluidCodeDetailsComparer !== undefined) {
|
|
874
878
|
comparers.push(maybeCompareCodeLoader.IFluidCodeDetailsComparer);
|
|
875
879
|
}
|
|
876
|
-
const maybeCompareExport =
|
|
877
|
-
if (
|
|
880
|
+
const maybeCompareExport = this._loadedModule?.module.fluidExport;
|
|
881
|
+
if (maybeCompareExport?.IFluidCodeDetailsComparer !== undefined) {
|
|
878
882
|
comparers.push(maybeCompareExport.IFluidCodeDetailsComparer);
|
|
879
883
|
}
|
|
880
884
|
// If there are no comparers, then it's impossible to know if the currently loaded package satisfies
|
|
@@ -884,7 +888,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
884
888
|
return false;
|
|
885
889
|
}
|
|
886
890
|
for (const comparer of comparers) {
|
|
887
|
-
const satisfies = await comparer.satisfies(
|
|
891
|
+
const satisfies = await comparer.satisfies(this._loadedModule?.details, constraintCodeDetails);
|
|
888
892
|
if (satisfies === false) {
|
|
889
893
|
return false;
|
|
890
894
|
}
|
|
@@ -907,8 +911,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
907
911
|
*
|
|
908
912
|
* @param specifiedVersion - Version SHA to load snapshot. If not specified, will fetch the latest snapshot.
|
|
909
913
|
*/
|
|
910
|
-
async load(specifiedVersion, loadMode, resolvedUrl, pendingLocalState) {
|
|
911
|
-
var _a, _b, _c;
|
|
914
|
+
async load(specifiedVersion, loadMode, resolvedUrl, pendingLocalState, loadToSequenceNumber) {
|
|
912
915
|
this.service = await this.serviceFactory.createDocumentService(resolvedUrl, this.subLogger, this.client.details.type === summarizerClientType);
|
|
913
916
|
// Ideally we always connect as "read" by default.
|
|
914
917
|
// Currently that works with SPO & r11s, because we get "write" connection when connecting to non-existing file.
|
|
@@ -957,9 +960,51 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
957
960
|
}
|
|
958
961
|
const attributes = await this.getDocumentAttributes(this.storageAdapter, snapshot);
|
|
959
962
|
// If we saved ops, we will replay them and don't need DeltaManager to fetch them
|
|
960
|
-
const sequenceNumber =
|
|
961
|
-
const dmAttributes = sequenceNumber !== undefined ?
|
|
963
|
+
const sequenceNumber = pendingLocalState?.savedOps[pendingLocalState.savedOps.length - 1]?.sequenceNumber;
|
|
964
|
+
const dmAttributes = sequenceNumber !== undefined ? { ...attributes, sequenceNumber } : attributes;
|
|
962
965
|
let opsBeforeReturnP;
|
|
966
|
+
if (loadMode.pauseAfterLoad === true) {
|
|
967
|
+
// If we are trying to pause at a specific sequence number, ensure the latest snapshot is not newer than the desired sequence number.
|
|
968
|
+
if (loadMode.opsBeforeReturn === "sequenceNumber") {
|
|
969
|
+
(0, common_utils_1.assert)(loadToSequenceNumber !== undefined, 0x727 /* sequenceNumber should be defined */);
|
|
970
|
+
// Note: It is possible that we think the latest snapshot is newer than the specified sequence number
|
|
971
|
+
// due to saved ops that may be replayed after the snapshot.
|
|
972
|
+
// https://dev.azure.com/fluidframework/internal/_workitems/edit/5055
|
|
973
|
+
if (dmAttributes.sequenceNumber > loadToSequenceNumber) {
|
|
974
|
+
throw new Error("Cannot satisfy request to pause the container at the specified sequence number. Most recent snapshot is newer than the specified sequence number.");
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
// Force readonly mode - this will ensure we don't receive an error for the lack of join op
|
|
978
|
+
this.forceReadonly(true);
|
|
979
|
+
// We need to setup a listener to stop op processing once we reach the desired sequence number (if specified).
|
|
980
|
+
const opHandler = () => {
|
|
981
|
+
if (loadToSequenceNumber === undefined) {
|
|
982
|
+
// If there is no specified sequence number, pause after the inbound queue is empty.
|
|
983
|
+
if (this.deltaManager.inbound.length !== 0) {
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
else {
|
|
988
|
+
// If there is a specified sequence number, keep processing until we reach it.
|
|
989
|
+
if (this.deltaManager.lastSequenceNumber < loadToSequenceNumber) {
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
// Pause op processing once we have processed the desired number of ops.
|
|
994
|
+
void this.deltaManager.inbound.pause();
|
|
995
|
+
void this.deltaManager.outbound.pause();
|
|
996
|
+
this.off("op", opHandler);
|
|
997
|
+
};
|
|
998
|
+
if ((loadToSequenceNumber === undefined && this.deltaManager.inbound.length === 0) ||
|
|
999
|
+
this.deltaManager.lastSequenceNumber === loadToSequenceNumber) {
|
|
1000
|
+
// If we have already reached the desired sequence number, call opHandler() to pause immediately.
|
|
1001
|
+
opHandler();
|
|
1002
|
+
}
|
|
1003
|
+
else {
|
|
1004
|
+
// If we have not yet reached the desired sequence number, setup a listener to pause once we reach it.
|
|
1005
|
+
this.on("op", opHandler);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
963
1008
|
// Attach op handlers to finish initialization and be able to start processing ops
|
|
964
1009
|
// Kick off any ops fetching if required.
|
|
965
1010
|
switch (loadMode.opsBeforeReturn) {
|
|
@@ -968,6 +1013,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
968
1013
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
969
1014
|
this.attachDeltaManagerOpHandler(dmAttributes, loadMode.deltaConnection !== "none" ? "all" : "none");
|
|
970
1015
|
break;
|
|
1016
|
+
case "sequenceNumber":
|
|
1017
|
+
opsBeforeReturnP = this.attachDeltaManagerOpHandler(dmAttributes, "sequenceNumber");
|
|
1018
|
+
break;
|
|
971
1019
|
case "cached":
|
|
972
1020
|
opsBeforeReturnP = this.attachDeltaManagerOpHandler(dmAttributes, "cached");
|
|
973
1021
|
break;
|
|
@@ -981,18 +1029,18 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
981
1029
|
// Initialize the protocol handler
|
|
982
1030
|
await this.initializeProtocolStateFromSnapshot(attributes, this.storageAdapter, snapshot);
|
|
983
1031
|
const codeDetails = this.getCodeDetailsFromQuorum();
|
|
984
|
-
await this.instantiateRuntime(codeDetails, snapshot, pendingLocalState
|
|
1032
|
+
await this.instantiateRuntime(codeDetails, snapshot, pendingLocalState?.pendingRuntimeState);
|
|
985
1033
|
// replay saved ops
|
|
986
1034
|
if (pendingLocalState) {
|
|
987
1035
|
for (const message of pendingLocalState.savedOps) {
|
|
988
1036
|
this.processRemoteMessage(message);
|
|
989
1037
|
// allow runtime to apply stashed ops at this op's sequence number
|
|
990
|
-
await
|
|
1038
|
+
await this.runtime.notifyOpReplay?.(message);
|
|
991
1039
|
}
|
|
992
1040
|
pendingLocalState.savedOps = [];
|
|
993
1041
|
// now set clientId to stashed clientId so live ops are correctly processed as local
|
|
994
1042
|
(0, common_utils_1.assert)(this.clientId === undefined, 0x5d6 /* Unexpected clientId when setting stashed clientId */);
|
|
995
|
-
this._clientId = pendingLocalState
|
|
1043
|
+
this._clientId = pendingLocalState?.clientId;
|
|
996
1044
|
}
|
|
997
1045
|
// We might have hit some failure that did not manifest itself in exception in this flow,
|
|
998
1046
|
// do not start op processing in such case - static version of Container.load() will handle it correctly.
|
|
@@ -1023,6 +1071,19 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1023
1071
|
(0, common_utils_1.unreachableCase)(loadMode.deltaConnection);
|
|
1024
1072
|
}
|
|
1025
1073
|
}
|
|
1074
|
+
// If we have not yet reached `loadToSequenceNumber`, we will wait for ops to arrive until we reach it
|
|
1075
|
+
if (loadToSequenceNumber !== undefined &&
|
|
1076
|
+
this.deltaManager.lastSequenceNumber < loadToSequenceNumber) {
|
|
1077
|
+
await new Promise((resolve, reject) => {
|
|
1078
|
+
const opHandler = (message) => {
|
|
1079
|
+
if (message.sequenceNumber >= loadToSequenceNumber) {
|
|
1080
|
+
resolve();
|
|
1081
|
+
this.off("op", opHandler);
|
|
1082
|
+
}
|
|
1083
|
+
};
|
|
1084
|
+
this.on("op", opHandler);
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1026
1087
|
// Safety net: static version of Container.load() should have learned about it through "closed" handler.
|
|
1027
1088
|
// But if that did not happen for some reason, fail load for sure.
|
|
1028
1089
|
// Otherwise we can get into situations where container is closed and does not try to connect to ordering
|
|
@@ -1177,8 +1238,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1177
1238
|
return pkg;
|
|
1178
1239
|
}
|
|
1179
1240
|
get client() {
|
|
1180
|
-
|
|
1181
|
-
const client = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.client) !== undefined
|
|
1241
|
+
const client = this.options?.client !== undefined
|
|
1182
1242
|
? this.options.client
|
|
1183
1243
|
: {
|
|
1184
1244
|
details: {
|
|
@@ -1226,8 +1286,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1226
1286
|
this.connectionStateHandler.cancelEstablishingConnection(reason);
|
|
1227
1287
|
});
|
|
1228
1288
|
deltaManager.on("disconnect", (reason, error) => {
|
|
1229
|
-
|
|
1230
|
-
(_a = this.noopHeuristic) === null || _a === void 0 ? void 0 : _a.notifyDisconnect();
|
|
1289
|
+
this.noopHeuristic?.notifyDisconnect();
|
|
1231
1290
|
if (!this.closed) {
|
|
1232
1291
|
this.connectionStateHandler.receivedDisconnectEvent(reason, error);
|
|
1233
1292
|
}
|
|
@@ -1262,7 +1321,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1262
1321
|
}, prefetchType);
|
|
1263
1322
|
}
|
|
1264
1323
|
logConnectionStateChangeTelemetry(value, oldState, reason, error) {
|
|
1265
|
-
var _a;
|
|
1266
1324
|
// Log actual event
|
|
1267
1325
|
const time = common_utils_1.performance.now();
|
|
1268
1326
|
this.connectionTransitionTimes[value] = time;
|
|
@@ -1292,19 +1350,31 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1292
1350
|
}
|
|
1293
1351
|
connectionInitiationReason = this.firstConnection ? "InitialConnect" : "AutoReconnect";
|
|
1294
1352
|
}
|
|
1295
|
-
this.mc.logger.sendPerformanceEvent(
|
|
1353
|
+
this.mc.logger.sendPerformanceEvent({
|
|
1354
|
+
eventName: `ConnectionStateChange_${connectionState_1.ConnectionState[value]}`,
|
|
1355
|
+
from: connectionState_1.ConnectionState[oldState],
|
|
1356
|
+
duration,
|
|
1296
1357
|
durationFromDisconnected,
|
|
1297
1358
|
reason,
|
|
1298
|
-
connectionInitiationReason,
|
|
1299
|
-
|
|
1359
|
+
connectionInitiationReason,
|
|
1360
|
+
pendingClientId: this.connectionStateHandler.pendingClientId,
|
|
1361
|
+
clientId: this.clientId,
|
|
1362
|
+
autoReconnect,
|
|
1363
|
+
opsBehind,
|
|
1364
|
+
online: driver_utils_1.OnlineStatus[(0, driver_utils_1.isOnline)()],
|
|
1365
|
+
lastVisible: this.lastVisible !== undefined
|
|
1300
1366
|
? common_utils_1.performance.now() - this.lastVisible
|
|
1301
|
-
: undefined,
|
|
1367
|
+
: undefined,
|
|
1368
|
+
checkpointSequenceNumber,
|
|
1369
|
+
quorumSize: this._protocolHandler?.quorum.getMembers().size,
|
|
1370
|
+
isDirty: this.isDirty,
|
|
1371
|
+
...this._deltaManager.connectionProps,
|
|
1372
|
+
}, error);
|
|
1302
1373
|
if (value === connectionState_1.ConnectionState.Connected) {
|
|
1303
1374
|
this.firstConnection = false;
|
|
1304
1375
|
}
|
|
1305
1376
|
}
|
|
1306
1377
|
propagateConnectionState(initialTransition, disconnectedReason) {
|
|
1307
|
-
var _a;
|
|
1308
1378
|
// When container loaded, we want to propagate initial connection state.
|
|
1309
1379
|
// After that, we communicate only transitions to Connected & Disconnected states, skipping all other states.
|
|
1310
1380
|
// This can be changed in the future, for example we likely should add "CatchingUp" event on Container.
|
|
@@ -1315,7 +1385,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1315
1385
|
}
|
|
1316
1386
|
const state = this.connectionState === connectionState_1.ConnectionState.Connected;
|
|
1317
1387
|
// Both protocol and context should not be undefined if we got so far.
|
|
1318
|
-
this.setContextConnectedState(state,
|
|
1388
|
+
this.setContextConnectedState(state, this.readOnlyInfo.readonly ?? false);
|
|
1319
1389
|
this.protocolHandler.setConnectionState(state, this.clientId);
|
|
1320
1390
|
(0, telemetry_utils_1.raiseConnectedEvent)(this.mc.logger, this, state, this.clientId, disconnectedReason);
|
|
1321
1391
|
}
|
|
@@ -1355,12 +1425,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1355
1425
|
return this.submitMessage(protocol_definitions_1.MessageType.Summarize, JSON.stringify(summary), false /* batch */, undefined /* metadata */, undefined /* compression */, referenceSequenceNumber);
|
|
1356
1426
|
}
|
|
1357
1427
|
submitMessage(type, contents, batch, metadata, compression, referenceSequenceNumber) {
|
|
1358
|
-
var _a;
|
|
1359
1428
|
if (this.connectionState !== connectionState_1.ConnectionState.Connected) {
|
|
1360
1429
|
this.mc.logger.sendErrorEvent({ eventName: "SubmitMessageWithNoConnection", type });
|
|
1361
1430
|
return -1;
|
|
1362
1431
|
}
|
|
1363
|
-
|
|
1432
|
+
this.noopHeuristic?.notifyMessageSent();
|
|
1364
1433
|
return this._deltaManager.submit(type, contents, batch, metadata, compression, referenceSequenceNumber);
|
|
1365
1434
|
}
|
|
1366
1435
|
processRemoteMessage(message) {
|
|
@@ -1435,8 +1504,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1435
1504
|
* @returns The snapshot requested, or the latest snapshot if no version was specified, plus version ID
|
|
1436
1505
|
*/
|
|
1437
1506
|
async fetchSnapshotTree(specifiedVersion) {
|
|
1438
|
-
|
|
1439
|
-
const version = await this.getVersion(specifiedVersion !== null && specifiedVersion !== void 0 ? specifiedVersion : null);
|
|
1507
|
+
const version = await this.getVersion(specifiedVersion ?? null);
|
|
1440
1508
|
if (version === undefined && specifiedVersion !== undefined) {
|
|
1441
1509
|
// We should have a defined version to load from if specified version requested
|
|
1442
1510
|
this.mc.logger.sendErrorEvent({
|
|
@@ -1445,15 +1513,14 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1445
1513
|
});
|
|
1446
1514
|
}
|
|
1447
1515
|
this._loadedFromVersion = version;
|
|
1448
|
-
const snapshot = (
|
|
1516
|
+
const snapshot = (await this.storageAdapter.getSnapshotTree(version)) ?? undefined;
|
|
1449
1517
|
if (snapshot === undefined && version !== undefined) {
|
|
1450
1518
|
this.mc.logger.sendErrorEvent({ eventName: "getSnapshotTreeFailed", id: version.id });
|
|
1451
1519
|
}
|
|
1452
|
-
return { snapshot, versionId: version
|
|
1520
|
+
return { snapshot, versionId: version?.id };
|
|
1453
1521
|
}
|
|
1454
1522
|
async instantiateRuntime(codeDetails, snapshot, pendingLocalState) {
|
|
1455
|
-
|
|
1456
|
-
(0, common_utils_1.assert)(((_a = this._runtime) === null || _a === void 0 ? void 0 : _a.disposed) !== false, 0x0dd /* "Existing runtime not disposed" */);
|
|
1523
|
+
(0, common_utils_1.assert)(this._runtime?.disposed !== false, 0x0dd /* "Existing runtime not disposed" */);
|
|
1457
1524
|
// The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
|
|
1458
1525
|
// are set. Global requests will still go directly to the loader
|
|
1459
1526
|
const maybeLoader = this.scope;
|
|
@@ -1464,22 +1531,17 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1464
1531
|
// An older interface ICodeLoader could return an IFluidModule which didn't have details.
|
|
1465
1532
|
// If we're using one of those older ICodeLoaders, then we fix up the module with the specified details here.
|
|
1466
1533
|
// TODO: Determine if this is still a realistic scenario or if this fixup could be removed.
|
|
1467
|
-
details:
|
|
1534
|
+
details: loadCodeResult.details ?? codeDetails,
|
|
1468
1535
|
};
|
|
1469
1536
|
const fluidExport = this._loadedModule.module.fluidExport;
|
|
1470
|
-
const runtimeFactory = fluidExport
|
|
1537
|
+
const runtimeFactory = fluidExport?.IRuntimeFactory;
|
|
1471
1538
|
if (runtimeFactory === undefined) {
|
|
1472
1539
|
throw new Error(packageNotFactoryError);
|
|
1473
1540
|
}
|
|
1474
|
-
const getSpecifiedCodeDetails = () =>
|
|
1475
|
-
|
|
1476
|
-
return ((_a = this.protocolHandler.quorum.get("code")) !== null && _a !== void 0 ? _a : this.protocolHandler.quorum.get("code2"));
|
|
1477
|
-
};
|
|
1541
|
+
const getSpecifiedCodeDetails = () => (this.protocolHandler.quorum.get("code") ??
|
|
1542
|
+
this.protocolHandler.quorum.get("code2"));
|
|
1478
1543
|
const existing = snapshot !== undefined;
|
|
1479
|
-
const context = new containerContext_1.ContainerContext(this.options, this.scope, snapshot, this._loadedFromVersion, this._deltaManager, this.storageAdapter, this.protocolHandler.quorum, this.protocolHandler.audience, loader, (type, contents, batch, metadata) => this.submitContainerMessage(type, contents, batch, metadata), (summaryOp, referenceSequenceNumber) => this.submitSummaryMessage(summaryOp, referenceSequenceNumber), (batch, referenceSequenceNumber) => this.submitBatch(batch, referenceSequenceNumber), (message) => this.submitSignal(message), (error) => this.dispose(error), (error) => this.close(error), this.updateDirtyContainerState, this.getAbsoluteUrl, () =>
|
|
1480
|
-
this._lifecycleEvents.once("disposed", () => {
|
|
1481
|
-
context.dispose();
|
|
1482
|
-
});
|
|
1544
|
+
const context = new containerContext_1.ContainerContext(this.options, this.scope, snapshot, this._loadedFromVersion, this._deltaManager, this.storageAdapter, this.protocolHandler.quorum, this.protocolHandler.audience, loader, (type, contents, batch, metadata) => this.submitContainerMessage(type, contents, batch, metadata), (summaryOp, referenceSequenceNumber) => this.submitSummaryMessage(summaryOp, referenceSequenceNumber), (batch, referenceSequenceNumber) => this.submitBatch(batch, referenceSequenceNumber), (message) => this.submitSignal(message), (error) => this.dispose(error), (error) => this.close(error), this.updateDirtyContainerState, this.getAbsoluteUrl, () => this.clientId, () => this.attachState, () => this.connected, getSpecifiedCodeDetails, this._deltaManager.clientDetails, existing, this.subLogger, pendingLocalState);
|
|
1483
1545
|
this._runtime = await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.subLogger, { eventName: "InstantiateRuntime" }, async () => runtimeFactory.instantiateRuntime(context, existing));
|
|
1484
1546
|
this._lifecycleEvents.emit("runtimeInstantiated");
|
|
1485
1547
|
this._loadedCodeDetails = codeDetails;
|
|
@@ -1491,8 +1553,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1491
1553
|
* @param readonly - Is the container in readonly mode?
|
|
1492
1554
|
*/
|
|
1493
1555
|
setContextConnectedState(state, readonly) {
|
|
1494
|
-
|
|
1495
|
-
if (((_a = this._runtime) === null || _a === void 0 ? void 0 : _a.disposed) === false) {
|
|
1556
|
+
if (this._runtime?.disposed === false) {
|
|
1496
1557
|
/**
|
|
1497
1558
|
* We want to lie to the ContainerRuntime when we are in readonly mode to prevent issues with pending
|
|
1498
1559
|
* ops getting through to the DeltaManager.
|