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