@fluidframework/container-loader 2.0.0-dev.3.1.0.125672 → 2.0.0-dev.4.2.0.153917
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 +14 -0
- package/README.md +45 -4
- package/closeAndGetPendingLocalState.md +51 -0
- package/dist/connectionManager.d.ts +2 -1
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +59 -17
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +4 -4
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +7 -0
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +44 -4
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +160 -105
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +18 -8
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +47 -4
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +41 -2
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +87 -11
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +2 -2
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/deltaManager.d.ts +4 -5
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +7 -10
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaManagerProxy.d.ts +10 -22
- package/dist/deltaManagerProxy.d.ts.map +1 -1
- package/dist/deltaManagerProxy.js +14 -50
- package/dist/deltaManagerProxy.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +10 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +25 -16
- 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 +1 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +4 -2
- package/dist/protocol.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts +6 -2
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js +7 -4
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +2 -1
- package/dist/utils.js.map +1 -1
- package/lib/connectionManager.d.ts +2 -1
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +60 -18
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +4 -4
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +7 -0
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +44 -4
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +164 -109
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +18 -8
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +48 -5
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +41 -2
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +85 -11
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +2 -2
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/deltaManager.d.ts +4 -5
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +7 -10
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaManagerProxy.d.ts +10 -22
- package/lib/deltaManagerProxy.d.ts.map +1 -1
- package/lib/deltaManagerProxy.js +14 -50
- package/lib/deltaManagerProxy.js.map +1 -1
- package/lib/index.d.ts +3 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/loader.d.ts +10 -1
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +24 -16
- 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 +1 -0
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +3 -1
- package/lib/protocol.js.map +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts +6 -2
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js +7 -4
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +2 -1
- package/lib/utils.js.map +1 -1
- package/package.json +64 -56
- package/src/connectionManager.ts +65 -24
- package/src/connectionStateHandler.ts +17 -5
- package/src/container.ts +239 -137
- package/src/containerContext.ts +74 -11
- package/src/containerStorageAdapter.ts +113 -9
- package/src/contracts.ts +2 -2
- package/src/deltaManager.ts +12 -14
- package/src/deltaManagerProxy.ts +18 -73
- package/src/index.ts +3 -3
- package/src/loader.ts +31 -26
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +4 -1
- package/src/protocolTreeDocumentStorageService.ts +6 -3
- package/src/utils.ts +7 -4
package/lib/container.js
CHANGED
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
*/
|
|
5
5
|
// eslint-disable-next-line import/no-internal-modules
|
|
6
6
|
import merge from "lodash/merge";
|
|
7
|
+
// eslint-disable-next-line import/no-internal-modules
|
|
8
|
+
import cloneDeep from "lodash/cloneDeep";
|
|
7
9
|
import { v4 as uuid } from "uuid";
|
|
8
10
|
import { assert, performance, unreachableCase } from "@fluidframework/common-utils";
|
|
9
11
|
import { AttachState, isFluidCodeDetails, } from "@fluidframework/container-definitions";
|
|
10
12
|
import { GenericError, UsageError } from "@fluidframework/container-utils";
|
|
11
|
-
import { readAndParse, OnlineStatus, isOnline, ensureFluidResolvedUrl, combineAppAndProtocolSummary, runWithRetry, isFluidResolvedUrl, } from "@fluidframework/driver-utils";
|
|
13
|
+
import { readAndParse, OnlineStatus, isOnline, ensureFluidResolvedUrl, combineAppAndProtocolSummary, runWithRetry, isFluidResolvedUrl, isCombinedAppAndProtocolSummary, } from "@fluidframework/driver-utils";
|
|
12
14
|
import { MessageType, SummaryType, } from "@fluidframework/protocol-definitions";
|
|
13
|
-
import { ChildLogger, EventEmitterWithErrorHandling, PerformanceEvent, raiseConnectedEvent, TelemetryLogger, connectedEventName,
|
|
15
|
+
import { ChildLogger, EventEmitterWithErrorHandling, PerformanceEvent, raiseConnectedEvent, TelemetryLogger, connectedEventName, normalizeError, loggerToMonitoringContext, wrapError, } from "@fluidframework/telemetry-utils";
|
|
14
16
|
import { Audience } from "./audience";
|
|
15
17
|
import { ContainerContext } from "./containerContext";
|
|
16
18
|
import { ReconnectMode, getPackageName } from "./contracts";
|
|
@@ -18,14 +20,14 @@ import { DeltaManager } from "./deltaManager";
|
|
|
18
20
|
import { DeltaManagerProxy } from "./deltaManagerProxy";
|
|
19
21
|
import { RelativeLoader } from "./loader";
|
|
20
22
|
import { pkgVersion } from "./packageVersion";
|
|
21
|
-
import { ContainerStorageAdapter } from "./containerStorageAdapter";
|
|
23
|
+
import { ContainerStorageAdapter, getBlobContentsFromTree, getBlobContentsFromTreeWithBlobContents, } from "./containerStorageAdapter";
|
|
22
24
|
import { createConnectionStateHandler } from "./connectionStateHandler";
|
|
23
25
|
import { getProtocolSnapshotTree, getSnapshotTreeFromSerializedContainer } from "./utils";
|
|
24
26
|
import { initQuorumValuesFromCodeDetails, getCodeDetailsFromQuorumValues, QuorumProxy, } from "./quorum";
|
|
25
27
|
import { CollabWindowTracker } from "./collabWindowTracker";
|
|
26
28
|
import { ConnectionManager } from "./connectionManager";
|
|
27
29
|
import { ConnectionState } from "./connectionState";
|
|
28
|
-
import { ProtocolHandler } from "./protocol";
|
|
30
|
+
import { OnlyValidTermValue, ProtocolHandler, } from "./protocol";
|
|
29
31
|
const detachedContainerRefSeqNumber = 0;
|
|
30
32
|
const dirtyContainerEvent = "dirty";
|
|
31
33
|
const savedContainerEvent = "saved";
|
|
@@ -119,9 +121,15 @@ export async function ReportIfTooLong(logger, eventName, action) {
|
|
|
119
121
|
}
|
|
120
122
|
}
|
|
121
123
|
const summarizerClientType = "summarizer";
|
|
124
|
+
/**
|
|
125
|
+
* @deprecated - In the next release Container will no longer be exported, IContainer should be used in its place.
|
|
126
|
+
*/
|
|
122
127
|
export class Container extends EventEmitterWithErrorHandling {
|
|
128
|
+
/**
|
|
129
|
+
* @internal
|
|
130
|
+
*/
|
|
123
131
|
constructor(loader, config, protocolHandlerBuilder) {
|
|
124
|
-
var _a, _b;
|
|
132
|
+
var _a, _b, _c;
|
|
125
133
|
super((name, error) => {
|
|
126
134
|
this.mc.logger.sendErrorEvent({
|
|
127
135
|
eventName: "ContainerEventHandlerException",
|
|
@@ -157,6 +165,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
157
165
|
this.messageCountAfterDisconnection = 0;
|
|
158
166
|
this.attachStarted = false;
|
|
159
167
|
this._dirtyContainer = false;
|
|
168
|
+
this.savedOps = [];
|
|
160
169
|
this.setAutoReconnectTime = performance.now();
|
|
161
170
|
this._disposed = false;
|
|
162
171
|
this.clientDetailsOverride = config.clientDetailsOverride;
|
|
@@ -195,15 +204,14 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
195
204
|
dmLastMsqSeqNumber: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.sequenceNumber; },
|
|
196
205
|
dmLastMsqSeqTimestamp: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.timestamp; },
|
|
197
206
|
dmLastMsqSeqClientId: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.clientId; },
|
|
207
|
+
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; },
|
|
198
208
|
connectionStateDuration: () => performance.now() - this.connectionTransitionTimes[this.connectionState],
|
|
199
209
|
},
|
|
200
210
|
});
|
|
201
211
|
// Prefix all events in this file with container-loader
|
|
202
212
|
this.mc = loggerToMonitoringContext(ChildLogger.create(this.subLogger, "Container"));
|
|
203
|
-
|
|
204
|
-
this.options = Object.assign(Object.assign({}, this.loader.services.options), { summarizeProtocolTree });
|
|
213
|
+
this.options = cloneDeep(this.loader.services.options);
|
|
205
214
|
this._deltaManager = this.createDeltaManager();
|
|
206
|
-
this._clientId = (_b = config.serializedContainerState) === null || _b === void 0 ? void 0 : _b.clientId;
|
|
207
215
|
this.connectionStateHandler = createConnectionStateHandler({
|
|
208
216
|
logger: this.mc.logger,
|
|
209
217
|
connectionStateChanged: (value, oldState, reason) => {
|
|
@@ -242,13 +250,20 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
242
250
|
this.connect();
|
|
243
251
|
}
|
|
244
252
|
},
|
|
245
|
-
}, this.deltaManager,
|
|
253
|
+
}, this.deltaManager, (_a = config.serializedContainerState) === null || _a === void 0 ? void 0 : _a.clientId);
|
|
246
254
|
this.on(savedContainerEvent, () => {
|
|
247
255
|
this.connectionStateHandler.containerSaved();
|
|
248
256
|
});
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
257
|
+
// We expose our storage publicly, so it's possible others may call uploadSummaryWithContext() with a
|
|
258
|
+
// non-combined summary tree (in particular, ContainerRuntime.submitSummary). We'll intercept those calls
|
|
259
|
+
// using this callback and fix them up.
|
|
260
|
+
const addProtocolSummaryIfMissing = (summaryTree) => isCombinedAppAndProtocolSummary(summaryTree) === true
|
|
261
|
+
? summaryTree
|
|
262
|
+
: combineAppAndProtocolSummary(summaryTree, this.captureProtocolSummary());
|
|
263
|
+
// Whether the combined summary tree has been forced on by either the loader option or the monitoring context.
|
|
264
|
+
// Even if not forced on via this flag, combined summaries may still be enabled by service policy.
|
|
265
|
+
const forceEnableSummarizeProtocolTree = (_b = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree2")) !== null && _b !== void 0 ? _b : this.loader.services.options.summarizeProtocolTree;
|
|
266
|
+
this.storageAdapter = new ContainerStorageAdapter(this.loader.services.detachedBlobStorage, this.mc.logger, (_c = config.serializedContainerState) === null || _c === void 0 ? void 0 : _c.snapshotBlobs, addProtocolSummaryIfMissing, forceEnableSummarizeProtocolTree);
|
|
252
267
|
const isDomAvailable = typeof document === "object" &&
|
|
253
268
|
document !== null &&
|
|
254
269
|
typeof document.addEventListener === "function" &&
|
|
@@ -269,45 +284,10 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
269
284
|
};
|
|
270
285
|
document.addEventListener("visibilitychange", this.visibilityEventHandler);
|
|
271
286
|
}
|
|
272
|
-
// We observed that most users of platform do not check Container.connected event on load, causing bugs.
|
|
273
|
-
// As such, we are raising events when new listener pops up.
|
|
274
|
-
// Note that we can raise both "disconnected" & "connect" events at the same time,
|
|
275
|
-
// if we are in connecting stage.
|
|
276
|
-
this.on("newListener", (event, listener) => {
|
|
277
|
-
// Fire events on the end of JS turn, giving a chance for caller to be in consistent state.
|
|
278
|
-
Promise.resolve()
|
|
279
|
-
.then(() => {
|
|
280
|
-
switch (event) {
|
|
281
|
-
case dirtyContainerEvent:
|
|
282
|
-
if (this._dirtyContainer) {
|
|
283
|
-
listener();
|
|
284
|
-
}
|
|
285
|
-
break;
|
|
286
|
-
case savedContainerEvent:
|
|
287
|
-
if (!this._dirtyContainer) {
|
|
288
|
-
listener();
|
|
289
|
-
}
|
|
290
|
-
break;
|
|
291
|
-
case connectedEventName:
|
|
292
|
-
if (this.connected) {
|
|
293
|
-
listener(this.clientId);
|
|
294
|
-
}
|
|
295
|
-
break;
|
|
296
|
-
case disconnectedEventName:
|
|
297
|
-
if (!this.connected) {
|
|
298
|
-
listener();
|
|
299
|
-
}
|
|
300
|
-
break;
|
|
301
|
-
default:
|
|
302
|
-
}
|
|
303
|
-
})
|
|
304
|
-
.catch((error) => {
|
|
305
|
-
this.mc.logger.sendErrorEvent({ eventName: "RaiseConnectedEventError" }, error);
|
|
306
|
-
});
|
|
307
|
-
});
|
|
308
287
|
}
|
|
309
288
|
/**
|
|
310
289
|
* Load an existing container.
|
|
290
|
+
* @internal
|
|
311
291
|
*/
|
|
312
292
|
static async load(loader, loadOptions, pendingLocalState, protocolHandlerBuilder) {
|
|
313
293
|
const container = new Container(loader, {
|
|
@@ -385,7 +365,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
385
365
|
this._lifecycleState === "disposed");
|
|
386
366
|
}
|
|
387
367
|
get storage() {
|
|
388
|
-
return this.
|
|
368
|
+
return this.storageAdapter;
|
|
389
369
|
}
|
|
390
370
|
get context() {
|
|
391
371
|
if (this._context === undefined) {
|
|
@@ -456,6 +436,12 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
456
436
|
get clientDetails() {
|
|
457
437
|
return this._deltaManager.clientDetails;
|
|
458
438
|
}
|
|
439
|
+
get offlineLoadEnabled() {
|
|
440
|
+
var _a;
|
|
441
|
+
// summarizer will not have any pending state we want to save
|
|
442
|
+
return (((_a = this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad")) !== null && _a !== void 0 ? _a : false) &&
|
|
443
|
+
this.clientDetails.capabilities.interactive);
|
|
444
|
+
}
|
|
459
445
|
/**
|
|
460
446
|
* Get the code details that are currently specified for the container.
|
|
461
447
|
* @returns The current code details if any are specified, undefined if none are specified.
|
|
@@ -498,6 +484,38 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
498
484
|
get codeLoader() {
|
|
499
485
|
return this.loader.services.codeLoader;
|
|
500
486
|
}
|
|
487
|
+
/**
|
|
488
|
+
* {@inheritDoc @fluidframework/container-definitions#IContainer.entryPoint}
|
|
489
|
+
*/
|
|
490
|
+
async getEntryPoint() {
|
|
491
|
+
var _a, _b;
|
|
492
|
+
// Only the disposing/disposed lifecycle states should prevent access to the entryPoint; closing/closed should still
|
|
493
|
+
// allow it since they mean a kind of read-only state for the Container.
|
|
494
|
+
// Note that all 4 are lifecycle states but only 'closed' and 'disposed' are emitted as events.
|
|
495
|
+
if (this._lifecycleState === "disposing" || this._lifecycleState === "disposed") {
|
|
496
|
+
throw new UsageError("The container is disposing or disposed");
|
|
497
|
+
}
|
|
498
|
+
while (this._context === undefined) {
|
|
499
|
+
await new Promise((resolve, reject) => {
|
|
500
|
+
const contextChangedHandler = () => {
|
|
501
|
+
resolve();
|
|
502
|
+
this.off("disposed", disposedHandler);
|
|
503
|
+
};
|
|
504
|
+
const disposedHandler = (error) => {
|
|
505
|
+
reject(error !== null && error !== void 0 ? error : "The Container is disposed");
|
|
506
|
+
this.off("contextChanged", contextChangedHandler);
|
|
507
|
+
};
|
|
508
|
+
this.once("contextChanged", contextChangedHandler);
|
|
509
|
+
this.once("disposed", disposedHandler);
|
|
510
|
+
});
|
|
511
|
+
// The Promise above should only resolve (vs reject) if the 'contextChanged' event was emitted and that
|
|
512
|
+
// should have set this._context; making sure.
|
|
513
|
+
assert(this._context !== undefined, 0x5a2 /* Context still not defined after contextChanged event */);
|
|
514
|
+
}
|
|
515
|
+
// Disable lint rule for the sake of more complete stack traces
|
|
516
|
+
// eslint-disable-next-line no-return-await
|
|
517
|
+
return await ((_b = (_a = this._context).getEntryPoint) === null || _b === void 0 ? void 0 : _b.call(_a));
|
|
518
|
+
}
|
|
501
519
|
/**
|
|
502
520
|
* Retrieves the quorum associated with the document
|
|
503
521
|
*/
|
|
@@ -528,15 +546,19 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
528
546
|
try {
|
|
529
547
|
// Raise event first, to ensure we capture _lifecycleState before transition.
|
|
530
548
|
// This gives us a chance to know what errors happened on open vs. on fully loaded container.
|
|
549
|
+
// Log generic events instead of error events if container is in loading state, as most errors are not really FF errors
|
|
550
|
+
// which can pollute telemetry for real bugs
|
|
531
551
|
this.mc.logger.sendTelemetryEvent({
|
|
532
552
|
eventName: "ContainerClose",
|
|
533
|
-
category:
|
|
553
|
+
category: this._lifecycleState !== "loading" && error !== undefined
|
|
554
|
+
? "error"
|
|
555
|
+
: "generic",
|
|
534
556
|
}, error);
|
|
535
557
|
this._lifecycleState = "closing";
|
|
536
558
|
(_a = this._protocolHandler) === null || _a === void 0 ? void 0 : _a.close();
|
|
537
559
|
this.connectionStateHandler.dispose();
|
|
538
560
|
(_b = this._context) === null || _b === void 0 ? void 0 : _b.dispose(error !== undefined ? new Error(error.message) : undefined);
|
|
539
|
-
this.
|
|
561
|
+
this.storageAdapter.dispose();
|
|
540
562
|
// Notify storage about critical errors. They may be due to disconnect between client & server knowledge
|
|
541
563
|
// about file, like file being overwritten in storage, but client having stale local cache.
|
|
542
564
|
// Driver need to ensure all caches are cleared on critical errors
|
|
@@ -565,7 +587,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
565
587
|
// This gives us a chance to know what errors happened on open vs. on fully loaded container.
|
|
566
588
|
this.mc.logger.sendTelemetryEvent({
|
|
567
589
|
eventName: "ContainerDispose",
|
|
568
|
-
category:
|
|
590
|
+
category: "generic",
|
|
569
591
|
}, error);
|
|
570
592
|
// ! Progressing from "closed" to "disposing" is not allowed
|
|
571
593
|
if (this._lifecycleState !== "closed") {
|
|
@@ -574,7 +596,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
574
596
|
(_a = this._protocolHandler) === null || _a === void 0 ? void 0 : _a.close();
|
|
575
597
|
this.connectionStateHandler.dispose();
|
|
576
598
|
(_b = this._context) === null || _b === void 0 ? void 0 : _b.dispose(error !== undefined ? new Error(error.message) : undefined);
|
|
577
|
-
this.
|
|
599
|
+
this.storageAdapter.dispose();
|
|
578
600
|
// Notify storage about critical errors. They may be due to disconnect between client & server knowledge
|
|
579
601
|
// about file, like file being overwritten in storage, but client having stale local cache.
|
|
580
602
|
// Driver need to ensure all caches are cleared on critical errors
|
|
@@ -597,15 +619,21 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
597
619
|
// runtime matches pending ops to successful ones by clientId and client seq num, so we need to close the
|
|
598
620
|
// container at the same time we get pending state, otherwise this container could reconnect and resubmit with
|
|
599
621
|
// a new clientId and a future container using stale pending state without the new clientId would resubmit them
|
|
622
|
+
if (!this.offlineLoadEnabled) {
|
|
623
|
+
throw new UsageError("Can't get pending local state unless offline load is enabled");
|
|
624
|
+
}
|
|
600
625
|
assert(this.attachState === AttachState.Attached, 0x0d1 /* "Container should be attached before close" */);
|
|
601
626
|
assert(this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid", 0x0d2 /* "resolved url should be valid Fluid url" */);
|
|
602
627
|
assert(!!this._protocolHandler, 0x2e3 /* "Must have a valid protocol handler instance" */);
|
|
603
|
-
assert(this.
|
|
628
|
+
assert(!!this.baseSnapshot, 0x5d4 /* no base snapshot */);
|
|
629
|
+
assert(!!this.baseSnapshotBlobs, 0x5d5 /* no snapshot blobs */);
|
|
604
630
|
const pendingState = {
|
|
605
631
|
pendingRuntimeState: this.context.getPendingLocalState(),
|
|
632
|
+
baseSnapshot: this.baseSnapshot,
|
|
633
|
+
snapshotBlobs: this.baseSnapshotBlobs,
|
|
634
|
+
savedOps: this.savedOps,
|
|
606
635
|
url: this.resolvedUrl.url,
|
|
607
|
-
|
|
608
|
-
term: this._protocolHandler.attributes.term,
|
|
636
|
+
term: OnlyValidTermValue,
|
|
609
637
|
clientId: this.clientId,
|
|
610
638
|
};
|
|
611
639
|
this.mc.logger.sendTelemetryEvent({ eventName: "CloseAndGetPendingLocalState" });
|
|
@@ -657,7 +685,13 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
657
685
|
// starting to attach the container to storage.
|
|
658
686
|
// Also, this should only be fired in detached container.
|
|
659
687
|
this._attachState = AttachState.Attaching;
|
|
660
|
-
this.
|
|
688
|
+
this.emit("attaching");
|
|
689
|
+
if (this.offlineLoadEnabled) {
|
|
690
|
+
const snapshot = getSnapshotTreeFromSerializedContainer(summary);
|
|
691
|
+
this.baseSnapshot = snapshot;
|
|
692
|
+
this.baseSnapshotBlobs =
|
|
693
|
+
getBlobContentsFromTreeWithBlobContents(snapshot);
|
|
694
|
+
}
|
|
661
695
|
}
|
|
662
696
|
// Actually go and create the resolved document
|
|
663
697
|
const createNewResolvedUrl = await this.urlResolver.resolve(request);
|
|
@@ -671,7 +705,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
671
705
|
const resolvedUrl = this.service.resolvedUrl;
|
|
672
706
|
ensureFluidResolvedUrl(resolvedUrl);
|
|
673
707
|
this._resolvedUrl = resolvedUrl;
|
|
674
|
-
await this.
|
|
708
|
+
await this.storageAdapter.connectToService(this.service);
|
|
675
709
|
if (hasAttachmentBlobs) {
|
|
676
710
|
// upload blobs to storage
|
|
677
711
|
assert(!!this.loader.services.detachedBlobStorage, 0x24e /* "assertion for type narrowing" */);
|
|
@@ -685,7 +719,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
685
719
|
.filter((id) => !redirectTable.has(id));
|
|
686
720
|
for (const id of newIds) {
|
|
687
721
|
const blob = await this.loader.services.detachedBlobStorage.readBlob(id);
|
|
688
|
-
const response = await this.
|
|
722
|
+
const response = await this.storageAdapter.createBlob(blob);
|
|
689
723
|
redirectTable.set(id, response.id);
|
|
690
724
|
}
|
|
691
725
|
}
|
|
@@ -694,8 +728,14 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
694
728
|
const protocolSummary = this.captureProtocolSummary();
|
|
695
729
|
summary = combineAppAndProtocolSummary(appSummary, protocolSummary);
|
|
696
730
|
this._attachState = AttachState.Attaching;
|
|
697
|
-
this.
|
|
698
|
-
|
|
731
|
+
this.emit("attaching");
|
|
732
|
+
if (this.offlineLoadEnabled) {
|
|
733
|
+
const snapshot = getSnapshotTreeFromSerializedContainer(summary);
|
|
734
|
+
this.baseSnapshot = snapshot;
|
|
735
|
+
this.baseSnapshotBlobs =
|
|
736
|
+
getBlobContentsFromTreeWithBlobContents(snapshot);
|
|
737
|
+
}
|
|
738
|
+
await this.storageAdapter.uploadSummaryWithContext(summary, {
|
|
699
739
|
referenceSequenceNumber: 0,
|
|
700
740
|
ackHandle: undefined,
|
|
701
741
|
proposalHandle: undefined,
|
|
@@ -830,7 +870,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
830
870
|
(_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
|
831
871
|
}
|
|
832
872
|
async getVersion(version) {
|
|
833
|
-
const versions = await this.
|
|
873
|
+
const versions = await this.storageAdapter.getVersions(version, 1);
|
|
834
874
|
return versions[0];
|
|
835
875
|
}
|
|
836
876
|
recordConnectStartTime() {
|
|
@@ -852,6 +892,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
852
892
|
* @param specifiedVersion - Version SHA to load snapshot. If not specified, will fetch the latest snapshot.
|
|
853
893
|
*/
|
|
854
894
|
async load(specifiedVersion, loadMode, pendingLocalState) {
|
|
895
|
+
var _a;
|
|
855
896
|
if (this._resolvedUrl === undefined) {
|
|
856
897
|
throw new Error("Attempting to load without a resolved url");
|
|
857
898
|
}
|
|
@@ -872,15 +913,15 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
872
913
|
};
|
|
873
914
|
// Start websocket connection as soon as possible. Note that there is no op handler attached yet, but the
|
|
874
915
|
// DeltaManager is resilient to this and will wait to start processing ops until after it is attached.
|
|
875
|
-
if (loadMode.deltaConnection === undefined) {
|
|
916
|
+
if (loadMode.deltaConnection === undefined && !pendingLocalState) {
|
|
876
917
|
this.connectToDeltaStream(connectionArgs);
|
|
877
918
|
}
|
|
878
919
|
if (!pendingLocalState) {
|
|
879
|
-
await this.
|
|
920
|
+
await this.storageAdapter.connectToService(this.service);
|
|
880
921
|
}
|
|
881
922
|
else {
|
|
882
923
|
// if we have pendingLocalState we can load without storage; don't wait for connection
|
|
883
|
-
this.
|
|
924
|
+
this.storageAdapter.connectToService(this.service).catch((error) => {
|
|
884
925
|
var _a;
|
|
885
926
|
this.close(error);
|
|
886
927
|
(_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
|
@@ -890,15 +931,23 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
890
931
|
// Fetch specified snapshot.
|
|
891
932
|
const { snapshot, versionId } = pendingLocalState === undefined
|
|
892
933
|
? await this.fetchSnapshotTree(specifiedVersion)
|
|
893
|
-
: { snapshot:
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
934
|
+
: { snapshot: pendingLocalState.baseSnapshot, versionId: undefined };
|
|
935
|
+
if (pendingLocalState) {
|
|
936
|
+
this.baseSnapshot = pendingLocalState.baseSnapshot;
|
|
937
|
+
this.baseSnapshotBlobs = pendingLocalState.snapshotBlobs;
|
|
938
|
+
}
|
|
939
|
+
else {
|
|
940
|
+
assert(snapshot !== undefined, 0x237 /* "Snapshot should exist" */);
|
|
941
|
+
if (this.offlineLoadEnabled) {
|
|
942
|
+
this.baseSnapshot = snapshot;
|
|
943
|
+
// Save contents of snapshot now, otherwise closeAndGetPendingLocalState() must be async
|
|
944
|
+
this.baseSnapshotBlobs = await getBlobContentsFromTree(snapshot, this.storage);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
const attributes = await this.getDocumentAttributes(this.storageAdapter, snapshot);
|
|
948
|
+
// If we saved ops, we will replay them and don't need DeltaManager to fetch them
|
|
949
|
+
const sequenceNumber = (_a = pendingLocalState === null || pendingLocalState === void 0 ? void 0 : pendingLocalState.savedOps[pendingLocalState.savedOps.length - 1]) === null || _a === void 0 ? void 0 : _a.sequenceNumber;
|
|
950
|
+
const dmAttributes = sequenceNumber !== undefined ? Object.assign(Object.assign({}, attributes), { sequenceNumber }) : attributes;
|
|
902
951
|
let opsBeforeReturnP;
|
|
903
952
|
// Attach op handlers to finish initialization and be able to start processing ops
|
|
904
953
|
// Kick off any ops fetching if required.
|
|
@@ -906,32 +955,35 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
906
955
|
case undefined:
|
|
907
956
|
// Start prefetch, but not set opsBeforeReturnP - boot is not blocked by it!
|
|
908
957
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
909
|
-
this.attachDeltaManagerOpHandler(
|
|
958
|
+
this.attachDeltaManagerOpHandler(dmAttributes, loadMode.deltaConnection !== "none" ? "all" : "none");
|
|
910
959
|
break;
|
|
911
960
|
case "cached":
|
|
912
|
-
opsBeforeReturnP = this.attachDeltaManagerOpHandler(
|
|
961
|
+
opsBeforeReturnP = this.attachDeltaManagerOpHandler(dmAttributes, "cached");
|
|
913
962
|
break;
|
|
914
963
|
case "all":
|
|
915
|
-
opsBeforeReturnP = this.attachDeltaManagerOpHandler(
|
|
964
|
+
opsBeforeReturnP = this.attachDeltaManagerOpHandler(dmAttributes, "all");
|
|
916
965
|
break;
|
|
917
966
|
default:
|
|
918
967
|
unreachableCase(loadMode.opsBeforeReturn);
|
|
919
968
|
}
|
|
920
969
|
// ...load in the existing quorum
|
|
921
970
|
// Initialize the protocol handler
|
|
922
|
-
|
|
923
|
-
await this.initializeProtocolStateFromSnapshot(attributes, this.storageService, snapshot);
|
|
924
|
-
}
|
|
925
|
-
else {
|
|
926
|
-
this.initializeProtocolState(attributes, {
|
|
927
|
-
members: pendingLocalState.protocol.members,
|
|
928
|
-
proposals: pendingLocalState.protocol.proposals,
|
|
929
|
-
values: pendingLocalState.protocol.values,
|
|
930
|
-
});
|
|
931
|
-
}
|
|
971
|
+
await this.initializeProtocolStateFromSnapshot(attributes, this.storageAdapter, snapshot);
|
|
932
972
|
const codeDetails = this.getCodeDetailsFromQuorum();
|
|
933
973
|
await this.instantiateContext(true, // existing
|
|
934
974
|
codeDetails, snapshot, pendingLocalState === null || pendingLocalState === void 0 ? void 0 : pendingLocalState.pendingRuntimeState);
|
|
975
|
+
// replay saved ops
|
|
976
|
+
if (pendingLocalState) {
|
|
977
|
+
for (const message of pendingLocalState.savedOps) {
|
|
978
|
+
this.processRemoteMessage(message);
|
|
979
|
+
// allow runtime to apply stashed ops at this op's sequence number
|
|
980
|
+
await this.context.notifyOpReplay(message);
|
|
981
|
+
}
|
|
982
|
+
pendingLocalState.savedOps = [];
|
|
983
|
+
// now set clientId to stashed clientId so live ops are correctly processed as local
|
|
984
|
+
assert(this.clientId === undefined, 0x5d6 /* Unexpected clientId when setting stashed clientId */);
|
|
985
|
+
this._clientId = pendingLocalState === null || pendingLocalState === void 0 ? void 0 : pendingLocalState.clientId;
|
|
986
|
+
}
|
|
935
987
|
// We might have hit some failure that did not manifest itself in exception in this flow,
|
|
936
988
|
// do not start op processing in such case - static version of Container.load() will handle it correctly.
|
|
937
989
|
if (!this.closed) {
|
|
@@ -944,6 +996,11 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
944
996
|
}
|
|
945
997
|
switch (loadMode.deltaConnection) {
|
|
946
998
|
case undefined:
|
|
999
|
+
if (pendingLocalState) {
|
|
1000
|
+
// connect to delta stream now since we did not before
|
|
1001
|
+
this.connectToDeltaStream(connectionArgs);
|
|
1002
|
+
}
|
|
1003
|
+
// intentional fallthrough
|
|
947
1004
|
case "delayed":
|
|
948
1005
|
assert(this.inboundQueuePausedFromInit, 0x346 /* inboundQueuePausedFromInit should be true */);
|
|
949
1006
|
this.inboundQueuePausedFromInit = false;
|
|
@@ -976,7 +1033,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
976
1033
|
async createDetached(source) {
|
|
977
1034
|
const attributes = {
|
|
978
1035
|
sequenceNumber: detachedContainerRefSeqNumber,
|
|
979
|
-
term:
|
|
1036
|
+
term: OnlyValidTermValue,
|
|
980
1037
|
minimumSequenceNumber: 0,
|
|
981
1038
|
};
|
|
982
1039
|
await this.attachDeltaManagerOpHandler(attributes);
|
|
@@ -998,12 +1055,12 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
998
1055
|
delete detachedContainerSnapshot.tree[".hasAttachmentBlobs"];
|
|
999
1056
|
}
|
|
1000
1057
|
const snapshotTree = getSnapshotTreeFromSerializedContainer(detachedContainerSnapshot);
|
|
1001
|
-
this.
|
|
1002
|
-
const attributes = await this.getDocumentAttributes(this.
|
|
1058
|
+
this.storageAdapter.loadSnapshotForRehydratingContainer(snapshotTree);
|
|
1059
|
+
const attributes = await this.getDocumentAttributes(this.storageAdapter, snapshotTree);
|
|
1003
1060
|
await this.attachDeltaManagerOpHandler(attributes);
|
|
1004
1061
|
// Initialize the protocol handler
|
|
1005
1062
|
const baseTree = getProtocolSnapshotTree(snapshotTree);
|
|
1006
|
-
const qValues = await readAndParse(this.
|
|
1063
|
+
const qValues = await readAndParse(this.storageAdapter, baseTree.blobs.quorumValues);
|
|
1007
1064
|
const codeDetails = getCodeDetailsFromQuorumValues(qValues);
|
|
1008
1065
|
this.initializeProtocolState(attributes, {
|
|
1009
1066
|
members: [],
|
|
@@ -1019,7 +1076,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
1019
1076
|
return {
|
|
1020
1077
|
minimumSequenceNumber: 0,
|
|
1021
1078
|
sequenceNumber: 0,
|
|
1022
|
-
term:
|
|
1079
|
+
term: OnlyValidTermValue,
|
|
1023
1080
|
};
|
|
1024
1081
|
}
|
|
1025
1082
|
// Backward compatibility: old docs would have ".attributes" instead of "attributes"
|
|
@@ -1027,10 +1084,6 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
1027
1084
|
? tree.trees[".protocol"].blobs.attributes
|
|
1028
1085
|
: tree.blobs[".attributes"];
|
|
1029
1086
|
const attributes = await readAndParse(storage, attributesHash);
|
|
1030
|
-
// Backward compatibility for older summaries with no term
|
|
1031
|
-
if (attributes.term === undefined) {
|
|
1032
|
-
attributes.term = 1;
|
|
1033
|
-
}
|
|
1034
1087
|
return attributes;
|
|
1035
1088
|
}
|
|
1036
1089
|
async initializeProtocolStateFromSnapshot(attributes, storage, snapshot) {
|
|
@@ -1150,7 +1203,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
1150
1203
|
}
|
|
1151
1204
|
createDeltaManager() {
|
|
1152
1205
|
const serviceProvider = () => this.service;
|
|
1153
|
-
const deltaManager = new DeltaManager(serviceProvider, ChildLogger.create(this.subLogger, "DeltaManager"), () => this.activeConnection(), (props) => new ConnectionManager(serviceProvider, this.client, this._canReconnect, ChildLogger.create(this.subLogger, "ConnectionManager"), props));
|
|
1206
|
+
const deltaManager = new DeltaManager(serviceProvider, ChildLogger.create(this.subLogger, "DeltaManager"), () => this.activeConnection(), (props) => new ConnectionManager(serviceProvider, () => this.isDirty, this.client, this._canReconnect, ChildLogger.create(this.subLogger, "ConnectionManager"), props));
|
|
1154
1207
|
// Disable inbound queues as Container is not ready to accept any ops until we are fully loaded!
|
|
1155
1208
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1156
1209
|
deltaManager.inbound.pause();
|
|
@@ -1189,8 +1242,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
1189
1242
|
return deltaManager;
|
|
1190
1243
|
}
|
|
1191
1244
|
async attachDeltaManagerOpHandler(attributes, prefetchType) {
|
|
1192
|
-
|
|
1193
|
-
return this._deltaManager.attachOpHandler(attributes.minimumSequenceNumber, attributes.sequenceNumber, (_a = attributes.term) !== null && _a !== void 0 ? _a : 1, {
|
|
1245
|
+
return this._deltaManager.attachOpHandler(attributes.minimumSequenceNumber, attributes.sequenceNumber, {
|
|
1194
1246
|
process: (message) => this.processRemoteMessage(message),
|
|
1195
1247
|
processSignal: (message) => {
|
|
1196
1248
|
this.processSignal(message);
|
|
@@ -1253,7 +1305,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
1253
1305
|
this.messageCountAfterDisconnection = 0;
|
|
1254
1306
|
}
|
|
1255
1307
|
// Both protocol and context should not be undefined if we got so far.
|
|
1256
|
-
this.setContextConnectedState(state, (_a = this.
|
|
1308
|
+
this.setContextConnectedState(state, (_a = this.readOnlyInfo.readonly) !== null && _a !== void 0 ? _a : false);
|
|
1257
1309
|
this.protocolHandler.setConnectionState(state, this.clientId);
|
|
1258
1310
|
raiseConnectedEvent(this.mc.logger, this, state, this.clientId, disconnectedReason);
|
|
1259
1311
|
if (logOpsOnReconnect) {
|
|
@@ -1280,16 +1332,16 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
1280
1332
|
}
|
|
1281
1333
|
}
|
|
1282
1334
|
/** @returns clientSequenceNumber of last message in a batch */
|
|
1283
|
-
submitBatch(batch) {
|
|
1335
|
+
submitBatch(batch, referenceSequenceNumber) {
|
|
1284
1336
|
let clientSequenceNumber = -1;
|
|
1285
1337
|
for (const message of batch) {
|
|
1286
1338
|
clientSequenceNumber = this.submitMessage(MessageType.Operation, message.contents, true, // batch
|
|
1287
|
-
message.metadata, message.compression);
|
|
1339
|
+
message.metadata, message.compression, referenceSequenceNumber);
|
|
1288
1340
|
}
|
|
1289
1341
|
this._deltaManager.flush();
|
|
1290
1342
|
return clientSequenceNumber;
|
|
1291
1343
|
}
|
|
1292
|
-
submitSummaryMessage(summary) {
|
|
1344
|
+
submitSummaryMessage(summary, referenceSequenceNumber) {
|
|
1293
1345
|
// github #6451: this is only needed for staging so the server
|
|
1294
1346
|
// know when the protocol tree is included
|
|
1295
1347
|
// this can be removed once all clients send
|
|
@@ -1297,10 +1349,10 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
1297
1349
|
if (summary.details === undefined) {
|
|
1298
1350
|
summary.details = {};
|
|
1299
1351
|
}
|
|
1300
|
-
summary.details.includesProtocolTree = this.
|
|
1301
|
-
return this.submitMessage(MessageType.Summarize, JSON.stringify(summary), false /* batch
|
|
1352
|
+
summary.details.includesProtocolTree = this.storageAdapter.summarizeProtocolTree;
|
|
1353
|
+
return this.submitMessage(MessageType.Summarize, JSON.stringify(summary), false /* batch */, undefined /* metadata */, undefined /* compression */, referenceSequenceNumber);
|
|
1302
1354
|
}
|
|
1303
|
-
submitMessage(type, contents, batch, metadata, compression) {
|
|
1355
|
+
submitMessage(type, contents, batch, metadata, compression, referenceSequenceNumber) {
|
|
1304
1356
|
var _a;
|
|
1305
1357
|
if (this.connectionState !== ConnectionState.Connected) {
|
|
1306
1358
|
this.mc.logger.sendErrorEvent({ eventName: "SubmitMessageWithNoConnection", type });
|
|
@@ -1308,9 +1360,12 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
1308
1360
|
}
|
|
1309
1361
|
this.messageCountAfterDisconnection += 1;
|
|
1310
1362
|
(_a = this.collabWindowTracker) === null || _a === void 0 ? void 0 : _a.stopSequenceNumberUpdate();
|
|
1311
|
-
return this._deltaManager.submit(type, contents, batch, metadata, compression);
|
|
1363
|
+
return this._deltaManager.submit(type, contents, batch, metadata, compression, referenceSequenceNumber);
|
|
1312
1364
|
}
|
|
1313
1365
|
processRemoteMessage(message) {
|
|
1366
|
+
if (this.offlineLoadEnabled) {
|
|
1367
|
+
this.savedOps.push(message);
|
|
1368
|
+
}
|
|
1314
1369
|
const local = this.clientId === message.clientId;
|
|
1315
1370
|
// Allow the protocol handler to process the message
|
|
1316
1371
|
const result = this.protocolHandler.processMessage(message, local);
|
|
@@ -1362,7 +1417,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
1362
1417
|
});
|
|
1363
1418
|
}
|
|
1364
1419
|
this._loadedFromVersion = version;
|
|
1365
|
-
const snapshot = (_a = (await this.
|
|
1420
|
+
const snapshot = (_a = (await this.storageAdapter.getSnapshotTree(version))) !== null && _a !== void 0 ? _a : undefined;
|
|
1366
1421
|
if (snapshot === undefined && version !== undefined) {
|
|
1367
1422
|
this.mc.logger.sendErrorEvent({ eventName: "getSnapshotTreeFailed", id: version.id });
|
|
1368
1423
|
}
|
|
@@ -1381,7 +1436,7 @@ export class Container extends EventEmitterWithErrorHandling {
|
|
|
1381
1436
|
// The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
|
|
1382
1437
|
// are set. Global requests will still go directly to the loader
|
|
1383
1438
|
const loader = new RelativeLoader(this, this.loader);
|
|
1384
|
-
this._context = await ContainerContext.createOrLoad(this, this.scope, this.codeLoader, codeDetails, snapshot, new DeltaManagerProxy(this._deltaManager), new QuorumProxy(this.protocolHandler.quorum), loader, (type, contents, batch, metadata) => this.submitContainerMessage(type, contents, batch, metadata), (summaryOp) => this.submitSummaryMessage(summaryOp), (batch) => this.submitBatch(batch), (message) => this.submitSignal(message), (error) => { var _a; return (_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, error); }, (error) => this.close(error), Container.version, (dirty) => this.updateDirtyContainerState(dirty), existing, pendingLocalState);
|
|
1439
|
+
this._context = await ContainerContext.createOrLoad(this, this.scope, this.codeLoader, codeDetails, snapshot, new DeltaManagerProxy(this._deltaManager), new QuorumProxy(this.protocolHandler.quorum), 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) => { var _a; return (_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, error); }, (error) => this.close(error), Container.version, (dirty) => this.updateDirtyContainerState(dirty), existing, pendingLocalState);
|
|
1385
1440
|
this.emit("contextChanged", codeDetails);
|
|
1386
1441
|
}
|
|
1387
1442
|
updateDirtyContainerState(dirty) {
|