@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/dist/container.js
CHANGED
|
@@ -10,6 +10,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.Container = exports.ReportIfTooLong = exports.waitContainerToCatchUp = void 0;
|
|
11
11
|
// eslint-disable-next-line import/no-internal-modules
|
|
12
12
|
const merge_1 = __importDefault(require("lodash/merge"));
|
|
13
|
+
// eslint-disable-next-line import/no-internal-modules
|
|
14
|
+
const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
|
13
15
|
const uuid_1 = require("uuid");
|
|
14
16
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
15
17
|
const container_definitions_1 = require("@fluidframework/container-definitions");
|
|
@@ -127,9 +129,15 @@ async function ReportIfTooLong(logger, eventName, action) {
|
|
|
127
129
|
}
|
|
128
130
|
exports.ReportIfTooLong = ReportIfTooLong;
|
|
129
131
|
const summarizerClientType = "summarizer";
|
|
132
|
+
/**
|
|
133
|
+
* @deprecated - In the next release Container will no longer be exported, IContainer should be used in its place.
|
|
134
|
+
*/
|
|
130
135
|
class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
136
|
+
/**
|
|
137
|
+
* @internal
|
|
138
|
+
*/
|
|
131
139
|
constructor(loader, config, protocolHandlerBuilder) {
|
|
132
|
-
var _a, _b;
|
|
140
|
+
var _a, _b, _c;
|
|
133
141
|
super((name, error) => {
|
|
134
142
|
this.mc.logger.sendErrorEvent({
|
|
135
143
|
eventName: "ContainerEventHandlerException",
|
|
@@ -165,6 +173,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
165
173
|
this.messageCountAfterDisconnection = 0;
|
|
166
174
|
this.attachStarted = false;
|
|
167
175
|
this._dirtyContainer = false;
|
|
176
|
+
this.savedOps = [];
|
|
168
177
|
this.setAutoReconnectTime = common_utils_1.performance.now();
|
|
169
178
|
this._disposed = false;
|
|
170
179
|
this.clientDetailsOverride = config.clientDetailsOverride;
|
|
@@ -203,15 +212,14 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
203
212
|
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; },
|
|
204
213
|
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; },
|
|
205
214
|
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; },
|
|
215
|
+
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; },
|
|
206
216
|
connectionStateDuration: () => common_utils_1.performance.now() - this.connectionTransitionTimes[this.connectionState],
|
|
207
217
|
},
|
|
208
218
|
});
|
|
209
219
|
// Prefix all events in this file with container-loader
|
|
210
220
|
this.mc = (0, telemetry_utils_1.loggerToMonitoringContext)(telemetry_utils_1.ChildLogger.create(this.subLogger, "Container"));
|
|
211
|
-
|
|
212
|
-
this.options = Object.assign(Object.assign({}, this.loader.services.options), { summarizeProtocolTree });
|
|
221
|
+
this.options = (0, cloneDeep_1.default)(this.loader.services.options);
|
|
213
222
|
this._deltaManager = this.createDeltaManager();
|
|
214
|
-
this._clientId = (_b = config.serializedContainerState) === null || _b === void 0 ? void 0 : _b.clientId;
|
|
215
223
|
this.connectionStateHandler = (0, connectionStateHandler_1.createConnectionStateHandler)({
|
|
216
224
|
logger: this.mc.logger,
|
|
217
225
|
connectionStateChanged: (value, oldState, reason) => {
|
|
@@ -250,13 +258,20 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
250
258
|
this.connect();
|
|
251
259
|
}
|
|
252
260
|
},
|
|
253
|
-
}, this.deltaManager,
|
|
261
|
+
}, this.deltaManager, (_a = config.serializedContainerState) === null || _a === void 0 ? void 0 : _a.clientId);
|
|
254
262
|
this.on(savedContainerEvent, () => {
|
|
255
263
|
this.connectionStateHandler.containerSaved();
|
|
256
264
|
});
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
265
|
+
// We expose our storage publicly, so it's possible others may call uploadSummaryWithContext() with a
|
|
266
|
+
// non-combined summary tree (in particular, ContainerRuntime.submitSummary). We'll intercept those calls
|
|
267
|
+
// using this callback and fix them up.
|
|
268
|
+
const addProtocolSummaryIfMissing = (summaryTree) => (0, driver_utils_1.isCombinedAppAndProtocolSummary)(summaryTree) === true
|
|
269
|
+
? summaryTree
|
|
270
|
+
: (0, driver_utils_1.combineAppAndProtocolSummary)(summaryTree, this.captureProtocolSummary());
|
|
271
|
+
// Whether the combined summary tree has been forced on by either the loader option or the monitoring context.
|
|
272
|
+
// Even if not forced on via this flag, combined summaries may still be enabled by service policy.
|
|
273
|
+
const forceEnableSummarizeProtocolTree = (_b = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree2")) !== null && _b !== void 0 ? _b : this.loader.services.options.summarizeProtocolTree;
|
|
274
|
+
this.storageAdapter = new containerStorageAdapter_1.ContainerStorageAdapter(this.loader.services.detachedBlobStorage, this.mc.logger, (_c = config.serializedContainerState) === null || _c === void 0 ? void 0 : _c.snapshotBlobs, addProtocolSummaryIfMissing, forceEnableSummarizeProtocolTree);
|
|
260
275
|
const isDomAvailable = typeof document === "object" &&
|
|
261
276
|
document !== null &&
|
|
262
277
|
typeof document.addEventListener === "function" &&
|
|
@@ -277,45 +292,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
277
292
|
};
|
|
278
293
|
document.addEventListener("visibilitychange", this.visibilityEventHandler);
|
|
279
294
|
}
|
|
280
|
-
// We observed that most users of platform do not check Container.connected event on load, causing bugs.
|
|
281
|
-
// As such, we are raising events when new listener pops up.
|
|
282
|
-
// Note that we can raise both "disconnected" & "connect" events at the same time,
|
|
283
|
-
// if we are in connecting stage.
|
|
284
|
-
this.on("newListener", (event, listener) => {
|
|
285
|
-
// Fire events on the end of JS turn, giving a chance for caller to be in consistent state.
|
|
286
|
-
Promise.resolve()
|
|
287
|
-
.then(() => {
|
|
288
|
-
switch (event) {
|
|
289
|
-
case dirtyContainerEvent:
|
|
290
|
-
if (this._dirtyContainer) {
|
|
291
|
-
listener();
|
|
292
|
-
}
|
|
293
|
-
break;
|
|
294
|
-
case savedContainerEvent:
|
|
295
|
-
if (!this._dirtyContainer) {
|
|
296
|
-
listener();
|
|
297
|
-
}
|
|
298
|
-
break;
|
|
299
|
-
case telemetry_utils_1.connectedEventName:
|
|
300
|
-
if (this.connected) {
|
|
301
|
-
listener(this.clientId);
|
|
302
|
-
}
|
|
303
|
-
break;
|
|
304
|
-
case telemetry_utils_1.disconnectedEventName:
|
|
305
|
-
if (!this.connected) {
|
|
306
|
-
listener();
|
|
307
|
-
}
|
|
308
|
-
break;
|
|
309
|
-
default:
|
|
310
|
-
}
|
|
311
|
-
})
|
|
312
|
-
.catch((error) => {
|
|
313
|
-
this.mc.logger.sendErrorEvent({ eventName: "RaiseConnectedEventError" }, error);
|
|
314
|
-
});
|
|
315
|
-
});
|
|
316
295
|
}
|
|
317
296
|
/**
|
|
318
297
|
* Load an existing container.
|
|
298
|
+
* @internal
|
|
319
299
|
*/
|
|
320
300
|
static async load(loader, loadOptions, pendingLocalState, protocolHandlerBuilder) {
|
|
321
301
|
const container = new Container(loader, {
|
|
@@ -393,7 +373,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
393
373
|
this._lifecycleState === "disposed");
|
|
394
374
|
}
|
|
395
375
|
get storage() {
|
|
396
|
-
return this.
|
|
376
|
+
return this.storageAdapter;
|
|
397
377
|
}
|
|
398
378
|
get context() {
|
|
399
379
|
if (this._context === undefined) {
|
|
@@ -464,6 +444,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
464
444
|
get clientDetails() {
|
|
465
445
|
return this._deltaManager.clientDetails;
|
|
466
446
|
}
|
|
447
|
+
get offlineLoadEnabled() {
|
|
448
|
+
var _a;
|
|
449
|
+
// summarizer will not have any pending state we want to save
|
|
450
|
+
return (((_a = this.mc.config.getBoolean("Fluid.Container.enableOfflineLoad")) !== null && _a !== void 0 ? _a : false) &&
|
|
451
|
+
this.clientDetails.capabilities.interactive);
|
|
452
|
+
}
|
|
467
453
|
/**
|
|
468
454
|
* Get the code details that are currently specified for the container.
|
|
469
455
|
* @returns The current code details if any are specified, undefined if none are specified.
|
|
@@ -506,6 +492,38 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
506
492
|
get codeLoader() {
|
|
507
493
|
return this.loader.services.codeLoader;
|
|
508
494
|
}
|
|
495
|
+
/**
|
|
496
|
+
* {@inheritDoc @fluidframework/container-definitions#IContainer.entryPoint}
|
|
497
|
+
*/
|
|
498
|
+
async getEntryPoint() {
|
|
499
|
+
var _a, _b;
|
|
500
|
+
// Only the disposing/disposed lifecycle states should prevent access to the entryPoint; closing/closed should still
|
|
501
|
+
// allow it since they mean a kind of read-only state for the Container.
|
|
502
|
+
// Note that all 4 are lifecycle states but only 'closed' and 'disposed' are emitted as events.
|
|
503
|
+
if (this._lifecycleState === "disposing" || this._lifecycleState === "disposed") {
|
|
504
|
+
throw new container_utils_1.UsageError("The container is disposing or disposed");
|
|
505
|
+
}
|
|
506
|
+
while (this._context === undefined) {
|
|
507
|
+
await new Promise((resolve, reject) => {
|
|
508
|
+
const contextChangedHandler = () => {
|
|
509
|
+
resolve();
|
|
510
|
+
this.off("disposed", disposedHandler);
|
|
511
|
+
};
|
|
512
|
+
const disposedHandler = (error) => {
|
|
513
|
+
reject(error !== null && error !== void 0 ? error : "The Container is disposed");
|
|
514
|
+
this.off("contextChanged", contextChangedHandler);
|
|
515
|
+
};
|
|
516
|
+
this.once("contextChanged", contextChangedHandler);
|
|
517
|
+
this.once("disposed", disposedHandler);
|
|
518
|
+
});
|
|
519
|
+
// The Promise above should only resolve (vs reject) if the 'contextChanged' event was emitted and that
|
|
520
|
+
// should have set this._context; making sure.
|
|
521
|
+
(0, common_utils_1.assert)(this._context !== undefined, 0x5a2 /* Context still not defined after contextChanged event */);
|
|
522
|
+
}
|
|
523
|
+
// Disable lint rule for the sake of more complete stack traces
|
|
524
|
+
// eslint-disable-next-line no-return-await
|
|
525
|
+
return await ((_b = (_a = this._context).getEntryPoint) === null || _b === void 0 ? void 0 : _b.call(_a));
|
|
526
|
+
}
|
|
509
527
|
/**
|
|
510
528
|
* Retrieves the quorum associated with the document
|
|
511
529
|
*/
|
|
@@ -536,15 +554,19 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
536
554
|
try {
|
|
537
555
|
// Raise event first, to ensure we capture _lifecycleState before transition.
|
|
538
556
|
// This gives us a chance to know what errors happened on open vs. on fully loaded container.
|
|
557
|
+
// Log generic events instead of error events if container is in loading state, as most errors are not really FF errors
|
|
558
|
+
// which can pollute telemetry for real bugs
|
|
539
559
|
this.mc.logger.sendTelemetryEvent({
|
|
540
560
|
eventName: "ContainerClose",
|
|
541
|
-
category:
|
|
561
|
+
category: this._lifecycleState !== "loading" && error !== undefined
|
|
562
|
+
? "error"
|
|
563
|
+
: "generic",
|
|
542
564
|
}, error);
|
|
543
565
|
this._lifecycleState = "closing";
|
|
544
566
|
(_a = this._protocolHandler) === null || _a === void 0 ? void 0 : _a.close();
|
|
545
567
|
this.connectionStateHandler.dispose();
|
|
546
568
|
(_b = this._context) === null || _b === void 0 ? void 0 : _b.dispose(error !== undefined ? new Error(error.message) : undefined);
|
|
547
|
-
this.
|
|
569
|
+
this.storageAdapter.dispose();
|
|
548
570
|
// Notify storage about critical errors. They may be due to disconnect between client & server knowledge
|
|
549
571
|
// about file, like file being overwritten in storage, but client having stale local cache.
|
|
550
572
|
// Driver need to ensure all caches are cleared on critical errors
|
|
@@ -573,7 +595,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
573
595
|
// This gives us a chance to know what errors happened on open vs. on fully loaded container.
|
|
574
596
|
this.mc.logger.sendTelemetryEvent({
|
|
575
597
|
eventName: "ContainerDispose",
|
|
576
|
-
category:
|
|
598
|
+
category: "generic",
|
|
577
599
|
}, error);
|
|
578
600
|
// ! Progressing from "closed" to "disposing" is not allowed
|
|
579
601
|
if (this._lifecycleState !== "closed") {
|
|
@@ -582,7 +604,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
582
604
|
(_a = this._protocolHandler) === null || _a === void 0 ? void 0 : _a.close();
|
|
583
605
|
this.connectionStateHandler.dispose();
|
|
584
606
|
(_b = this._context) === null || _b === void 0 ? void 0 : _b.dispose(error !== undefined ? new Error(error.message) : undefined);
|
|
585
|
-
this.
|
|
607
|
+
this.storageAdapter.dispose();
|
|
586
608
|
// Notify storage about critical errors. They may be due to disconnect between client & server knowledge
|
|
587
609
|
// about file, like file being overwritten in storage, but client having stale local cache.
|
|
588
610
|
// Driver need to ensure all caches are cleared on critical errors
|
|
@@ -605,15 +627,21 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
605
627
|
// runtime matches pending ops to successful ones by clientId and client seq num, so we need to close the
|
|
606
628
|
// container at the same time we get pending state, otherwise this container could reconnect and resubmit with
|
|
607
629
|
// a new clientId and a future container using stale pending state without the new clientId would resubmit them
|
|
630
|
+
if (!this.offlineLoadEnabled) {
|
|
631
|
+
throw new container_utils_1.UsageError("Can't get pending local state unless offline load is enabled");
|
|
632
|
+
}
|
|
608
633
|
(0, common_utils_1.assert)(this.attachState === container_definitions_1.AttachState.Attached, 0x0d1 /* "Container should be attached before close" */);
|
|
609
634
|
(0, common_utils_1.assert)(this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid", 0x0d2 /* "resolved url should be valid Fluid url" */);
|
|
610
635
|
(0, common_utils_1.assert)(!!this._protocolHandler, 0x2e3 /* "Must have a valid protocol handler instance" */);
|
|
611
|
-
(0, common_utils_1.assert)(this.
|
|
636
|
+
(0, common_utils_1.assert)(!!this.baseSnapshot, 0x5d4 /* no base snapshot */);
|
|
637
|
+
(0, common_utils_1.assert)(!!this.baseSnapshotBlobs, 0x5d5 /* no snapshot blobs */);
|
|
612
638
|
const pendingState = {
|
|
613
639
|
pendingRuntimeState: this.context.getPendingLocalState(),
|
|
640
|
+
baseSnapshot: this.baseSnapshot,
|
|
641
|
+
snapshotBlobs: this.baseSnapshotBlobs,
|
|
642
|
+
savedOps: this.savedOps,
|
|
614
643
|
url: this.resolvedUrl.url,
|
|
615
|
-
|
|
616
|
-
term: this._protocolHandler.attributes.term,
|
|
644
|
+
term: protocol_1.OnlyValidTermValue,
|
|
617
645
|
clientId: this.clientId,
|
|
618
646
|
};
|
|
619
647
|
this.mc.logger.sendTelemetryEvent({ eventName: "CloseAndGetPendingLocalState" });
|
|
@@ -665,7 +693,13 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
665
693
|
// starting to attach the container to storage.
|
|
666
694
|
// Also, this should only be fired in detached container.
|
|
667
695
|
this._attachState = container_definitions_1.AttachState.Attaching;
|
|
668
|
-
this.
|
|
696
|
+
this.emit("attaching");
|
|
697
|
+
if (this.offlineLoadEnabled) {
|
|
698
|
+
const snapshot = (0, utils_1.getSnapshotTreeFromSerializedContainer)(summary);
|
|
699
|
+
this.baseSnapshot = snapshot;
|
|
700
|
+
this.baseSnapshotBlobs =
|
|
701
|
+
(0, containerStorageAdapter_1.getBlobContentsFromTreeWithBlobContents)(snapshot);
|
|
702
|
+
}
|
|
669
703
|
}
|
|
670
704
|
// Actually go and create the resolved document
|
|
671
705
|
const createNewResolvedUrl = await this.urlResolver.resolve(request);
|
|
@@ -679,7 +713,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
679
713
|
const resolvedUrl = this.service.resolvedUrl;
|
|
680
714
|
(0, driver_utils_1.ensureFluidResolvedUrl)(resolvedUrl);
|
|
681
715
|
this._resolvedUrl = resolvedUrl;
|
|
682
|
-
await this.
|
|
716
|
+
await this.storageAdapter.connectToService(this.service);
|
|
683
717
|
if (hasAttachmentBlobs) {
|
|
684
718
|
// upload blobs to storage
|
|
685
719
|
(0, common_utils_1.assert)(!!this.loader.services.detachedBlobStorage, 0x24e /* "assertion for type narrowing" */);
|
|
@@ -693,7 +727,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
693
727
|
.filter((id) => !redirectTable.has(id));
|
|
694
728
|
for (const id of newIds) {
|
|
695
729
|
const blob = await this.loader.services.detachedBlobStorage.readBlob(id);
|
|
696
|
-
const response = await this.
|
|
730
|
+
const response = await this.storageAdapter.createBlob(blob);
|
|
697
731
|
redirectTable.set(id, response.id);
|
|
698
732
|
}
|
|
699
733
|
}
|
|
@@ -702,8 +736,14 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
702
736
|
const protocolSummary = this.captureProtocolSummary();
|
|
703
737
|
summary = (0, driver_utils_1.combineAppAndProtocolSummary)(appSummary, protocolSummary);
|
|
704
738
|
this._attachState = container_definitions_1.AttachState.Attaching;
|
|
705
|
-
this.
|
|
706
|
-
|
|
739
|
+
this.emit("attaching");
|
|
740
|
+
if (this.offlineLoadEnabled) {
|
|
741
|
+
const snapshot = (0, utils_1.getSnapshotTreeFromSerializedContainer)(summary);
|
|
742
|
+
this.baseSnapshot = snapshot;
|
|
743
|
+
this.baseSnapshotBlobs =
|
|
744
|
+
(0, containerStorageAdapter_1.getBlobContentsFromTreeWithBlobContents)(snapshot);
|
|
745
|
+
}
|
|
746
|
+
await this.storageAdapter.uploadSummaryWithContext(summary, {
|
|
707
747
|
referenceSequenceNumber: 0,
|
|
708
748
|
ackHandle: undefined,
|
|
709
749
|
proposalHandle: undefined,
|
|
@@ -838,7 +878,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
838
878
|
(_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
|
839
879
|
}
|
|
840
880
|
async getVersion(version) {
|
|
841
|
-
const versions = await this.
|
|
881
|
+
const versions = await this.storageAdapter.getVersions(version, 1);
|
|
842
882
|
return versions[0];
|
|
843
883
|
}
|
|
844
884
|
recordConnectStartTime() {
|
|
@@ -860,6 +900,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
860
900
|
* @param specifiedVersion - Version SHA to load snapshot. If not specified, will fetch the latest snapshot.
|
|
861
901
|
*/
|
|
862
902
|
async load(specifiedVersion, loadMode, pendingLocalState) {
|
|
903
|
+
var _a;
|
|
863
904
|
if (this._resolvedUrl === undefined) {
|
|
864
905
|
throw new Error("Attempting to load without a resolved url");
|
|
865
906
|
}
|
|
@@ -880,15 +921,15 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
880
921
|
};
|
|
881
922
|
// Start websocket connection as soon as possible. Note that there is no op handler attached yet, but the
|
|
882
923
|
// DeltaManager is resilient to this and will wait to start processing ops until after it is attached.
|
|
883
|
-
if (loadMode.deltaConnection === undefined) {
|
|
924
|
+
if (loadMode.deltaConnection === undefined && !pendingLocalState) {
|
|
884
925
|
this.connectToDeltaStream(connectionArgs);
|
|
885
926
|
}
|
|
886
927
|
if (!pendingLocalState) {
|
|
887
|
-
await this.
|
|
928
|
+
await this.storageAdapter.connectToService(this.service);
|
|
888
929
|
}
|
|
889
930
|
else {
|
|
890
931
|
// if we have pendingLocalState we can load without storage; don't wait for connection
|
|
891
|
-
this.
|
|
932
|
+
this.storageAdapter.connectToService(this.service).catch((error) => {
|
|
892
933
|
var _a;
|
|
893
934
|
this.close(error);
|
|
894
935
|
(_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
|
@@ -898,15 +939,23 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
898
939
|
// Fetch specified snapshot.
|
|
899
940
|
const { snapshot, versionId } = pendingLocalState === undefined
|
|
900
941
|
? await this.fetchSnapshotTree(specifiedVersion)
|
|
901
|
-
: { snapshot:
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
942
|
+
: { snapshot: pendingLocalState.baseSnapshot, versionId: undefined };
|
|
943
|
+
if (pendingLocalState) {
|
|
944
|
+
this.baseSnapshot = pendingLocalState.baseSnapshot;
|
|
945
|
+
this.baseSnapshotBlobs = pendingLocalState.snapshotBlobs;
|
|
946
|
+
}
|
|
947
|
+
else {
|
|
948
|
+
(0, common_utils_1.assert)(snapshot !== undefined, 0x237 /* "Snapshot should exist" */);
|
|
949
|
+
if (this.offlineLoadEnabled) {
|
|
950
|
+
this.baseSnapshot = snapshot;
|
|
951
|
+
// Save contents of snapshot now, otherwise closeAndGetPendingLocalState() must be async
|
|
952
|
+
this.baseSnapshotBlobs = await (0, containerStorageAdapter_1.getBlobContentsFromTree)(snapshot, this.storage);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
const attributes = await this.getDocumentAttributes(this.storageAdapter, snapshot);
|
|
956
|
+
// If we saved ops, we will replay them and don't need DeltaManager to fetch them
|
|
957
|
+
const sequenceNumber = (_a = pendingLocalState === null || pendingLocalState === void 0 ? void 0 : pendingLocalState.savedOps[pendingLocalState.savedOps.length - 1]) === null || _a === void 0 ? void 0 : _a.sequenceNumber;
|
|
958
|
+
const dmAttributes = sequenceNumber !== undefined ? Object.assign(Object.assign({}, attributes), { sequenceNumber }) : attributes;
|
|
910
959
|
let opsBeforeReturnP;
|
|
911
960
|
// Attach op handlers to finish initialization and be able to start processing ops
|
|
912
961
|
// Kick off any ops fetching if required.
|
|
@@ -914,32 +963,35 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
914
963
|
case undefined:
|
|
915
964
|
// Start prefetch, but not set opsBeforeReturnP - boot is not blocked by it!
|
|
916
965
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
917
|
-
this.attachDeltaManagerOpHandler(
|
|
966
|
+
this.attachDeltaManagerOpHandler(dmAttributes, loadMode.deltaConnection !== "none" ? "all" : "none");
|
|
918
967
|
break;
|
|
919
968
|
case "cached":
|
|
920
|
-
opsBeforeReturnP = this.attachDeltaManagerOpHandler(
|
|
969
|
+
opsBeforeReturnP = this.attachDeltaManagerOpHandler(dmAttributes, "cached");
|
|
921
970
|
break;
|
|
922
971
|
case "all":
|
|
923
|
-
opsBeforeReturnP = this.attachDeltaManagerOpHandler(
|
|
972
|
+
opsBeforeReturnP = this.attachDeltaManagerOpHandler(dmAttributes, "all");
|
|
924
973
|
break;
|
|
925
974
|
default:
|
|
926
975
|
(0, common_utils_1.unreachableCase)(loadMode.opsBeforeReturn);
|
|
927
976
|
}
|
|
928
977
|
// ...load in the existing quorum
|
|
929
978
|
// Initialize the protocol handler
|
|
930
|
-
|
|
931
|
-
await this.initializeProtocolStateFromSnapshot(attributes, this.storageService, snapshot);
|
|
932
|
-
}
|
|
933
|
-
else {
|
|
934
|
-
this.initializeProtocolState(attributes, {
|
|
935
|
-
members: pendingLocalState.protocol.members,
|
|
936
|
-
proposals: pendingLocalState.protocol.proposals,
|
|
937
|
-
values: pendingLocalState.protocol.values,
|
|
938
|
-
});
|
|
939
|
-
}
|
|
979
|
+
await this.initializeProtocolStateFromSnapshot(attributes, this.storageAdapter, snapshot);
|
|
940
980
|
const codeDetails = this.getCodeDetailsFromQuorum();
|
|
941
981
|
await this.instantiateContext(true, // existing
|
|
942
982
|
codeDetails, snapshot, pendingLocalState === null || pendingLocalState === void 0 ? void 0 : pendingLocalState.pendingRuntimeState);
|
|
983
|
+
// replay saved ops
|
|
984
|
+
if (pendingLocalState) {
|
|
985
|
+
for (const message of pendingLocalState.savedOps) {
|
|
986
|
+
this.processRemoteMessage(message);
|
|
987
|
+
// allow runtime to apply stashed ops at this op's sequence number
|
|
988
|
+
await this.context.notifyOpReplay(message);
|
|
989
|
+
}
|
|
990
|
+
pendingLocalState.savedOps = [];
|
|
991
|
+
// now set clientId to stashed clientId so live ops are correctly processed as local
|
|
992
|
+
(0, common_utils_1.assert)(this.clientId === undefined, 0x5d6 /* Unexpected clientId when setting stashed clientId */);
|
|
993
|
+
this._clientId = pendingLocalState === null || pendingLocalState === void 0 ? void 0 : pendingLocalState.clientId;
|
|
994
|
+
}
|
|
943
995
|
// We might have hit some failure that did not manifest itself in exception in this flow,
|
|
944
996
|
// do not start op processing in such case - static version of Container.load() will handle it correctly.
|
|
945
997
|
if (!this.closed) {
|
|
@@ -952,6 +1004,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
952
1004
|
}
|
|
953
1005
|
switch (loadMode.deltaConnection) {
|
|
954
1006
|
case undefined:
|
|
1007
|
+
if (pendingLocalState) {
|
|
1008
|
+
// connect to delta stream now since we did not before
|
|
1009
|
+
this.connectToDeltaStream(connectionArgs);
|
|
1010
|
+
}
|
|
1011
|
+
// intentional fallthrough
|
|
955
1012
|
case "delayed":
|
|
956
1013
|
(0, common_utils_1.assert)(this.inboundQueuePausedFromInit, 0x346 /* inboundQueuePausedFromInit should be true */);
|
|
957
1014
|
this.inboundQueuePausedFromInit = false;
|
|
@@ -984,7 +1041,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
984
1041
|
async createDetached(source) {
|
|
985
1042
|
const attributes = {
|
|
986
1043
|
sequenceNumber: detachedContainerRefSeqNumber,
|
|
987
|
-
term:
|
|
1044
|
+
term: protocol_1.OnlyValidTermValue,
|
|
988
1045
|
minimumSequenceNumber: 0,
|
|
989
1046
|
};
|
|
990
1047
|
await this.attachDeltaManagerOpHandler(attributes);
|
|
@@ -1006,12 +1063,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1006
1063
|
delete detachedContainerSnapshot.tree[".hasAttachmentBlobs"];
|
|
1007
1064
|
}
|
|
1008
1065
|
const snapshotTree = (0, utils_1.getSnapshotTreeFromSerializedContainer)(detachedContainerSnapshot);
|
|
1009
|
-
this.
|
|
1010
|
-
const attributes = await this.getDocumentAttributes(this.
|
|
1066
|
+
this.storageAdapter.loadSnapshotForRehydratingContainer(snapshotTree);
|
|
1067
|
+
const attributes = await this.getDocumentAttributes(this.storageAdapter, snapshotTree);
|
|
1011
1068
|
await this.attachDeltaManagerOpHandler(attributes);
|
|
1012
1069
|
// Initialize the protocol handler
|
|
1013
1070
|
const baseTree = (0, utils_1.getProtocolSnapshotTree)(snapshotTree);
|
|
1014
|
-
const qValues = await (0, driver_utils_1.readAndParse)(this.
|
|
1071
|
+
const qValues = await (0, driver_utils_1.readAndParse)(this.storageAdapter, baseTree.blobs.quorumValues);
|
|
1015
1072
|
const codeDetails = (0, quorum_1.getCodeDetailsFromQuorumValues)(qValues);
|
|
1016
1073
|
this.initializeProtocolState(attributes, {
|
|
1017
1074
|
members: [],
|
|
@@ -1027,7 +1084,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1027
1084
|
return {
|
|
1028
1085
|
minimumSequenceNumber: 0,
|
|
1029
1086
|
sequenceNumber: 0,
|
|
1030
|
-
term:
|
|
1087
|
+
term: protocol_1.OnlyValidTermValue,
|
|
1031
1088
|
};
|
|
1032
1089
|
}
|
|
1033
1090
|
// Backward compatibility: old docs would have ".attributes" instead of "attributes"
|
|
@@ -1035,10 +1092,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1035
1092
|
? tree.trees[".protocol"].blobs.attributes
|
|
1036
1093
|
: tree.blobs[".attributes"];
|
|
1037
1094
|
const attributes = await (0, driver_utils_1.readAndParse)(storage, attributesHash);
|
|
1038
|
-
// Backward compatibility for older summaries with no term
|
|
1039
|
-
if (attributes.term === undefined) {
|
|
1040
|
-
attributes.term = 1;
|
|
1041
|
-
}
|
|
1042
1095
|
return attributes;
|
|
1043
1096
|
}
|
|
1044
1097
|
async initializeProtocolStateFromSnapshot(attributes, storage, snapshot) {
|
|
@@ -1158,7 +1211,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1158
1211
|
}
|
|
1159
1212
|
createDeltaManager() {
|
|
1160
1213
|
const serviceProvider = () => this.service;
|
|
1161
|
-
const deltaManager = new deltaManager_1.DeltaManager(serviceProvider, telemetry_utils_1.ChildLogger.create(this.subLogger, "DeltaManager"), () => this.activeConnection(), (props) => new connectionManager_1.ConnectionManager(serviceProvider, this.client, this._canReconnect, telemetry_utils_1.ChildLogger.create(this.subLogger, "ConnectionManager"), props));
|
|
1214
|
+
const deltaManager = new deltaManager_1.DeltaManager(serviceProvider, telemetry_utils_1.ChildLogger.create(this.subLogger, "DeltaManager"), () => this.activeConnection(), (props) => new connectionManager_1.ConnectionManager(serviceProvider, () => this.isDirty, this.client, this._canReconnect, telemetry_utils_1.ChildLogger.create(this.subLogger, "ConnectionManager"), props));
|
|
1162
1215
|
// Disable inbound queues as Container is not ready to accept any ops until we are fully loaded!
|
|
1163
1216
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1164
1217
|
deltaManager.inbound.pause();
|
|
@@ -1197,8 +1250,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1197
1250
|
return deltaManager;
|
|
1198
1251
|
}
|
|
1199
1252
|
async attachDeltaManagerOpHandler(attributes, prefetchType) {
|
|
1200
|
-
|
|
1201
|
-
return this._deltaManager.attachOpHandler(attributes.minimumSequenceNumber, attributes.sequenceNumber, (_a = attributes.term) !== null && _a !== void 0 ? _a : 1, {
|
|
1253
|
+
return this._deltaManager.attachOpHandler(attributes.minimumSequenceNumber, attributes.sequenceNumber, {
|
|
1202
1254
|
process: (message) => this.processRemoteMessage(message),
|
|
1203
1255
|
processSignal: (message) => {
|
|
1204
1256
|
this.processSignal(message);
|
|
@@ -1261,7 +1313,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1261
1313
|
this.messageCountAfterDisconnection = 0;
|
|
1262
1314
|
}
|
|
1263
1315
|
// Both protocol and context should not be undefined if we got so far.
|
|
1264
|
-
this.setContextConnectedState(state, (_a = this.
|
|
1316
|
+
this.setContextConnectedState(state, (_a = this.readOnlyInfo.readonly) !== null && _a !== void 0 ? _a : false);
|
|
1265
1317
|
this.protocolHandler.setConnectionState(state, this.clientId);
|
|
1266
1318
|
(0, telemetry_utils_1.raiseConnectedEvent)(this.mc.logger, this, state, this.clientId, disconnectedReason);
|
|
1267
1319
|
if (logOpsOnReconnect) {
|
|
@@ -1288,16 +1340,16 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1288
1340
|
}
|
|
1289
1341
|
}
|
|
1290
1342
|
/** @returns clientSequenceNumber of last message in a batch */
|
|
1291
|
-
submitBatch(batch) {
|
|
1343
|
+
submitBatch(batch, referenceSequenceNumber) {
|
|
1292
1344
|
let clientSequenceNumber = -1;
|
|
1293
1345
|
for (const message of batch) {
|
|
1294
1346
|
clientSequenceNumber = this.submitMessage(protocol_definitions_1.MessageType.Operation, message.contents, true, // batch
|
|
1295
|
-
message.metadata, message.compression);
|
|
1347
|
+
message.metadata, message.compression, referenceSequenceNumber);
|
|
1296
1348
|
}
|
|
1297
1349
|
this._deltaManager.flush();
|
|
1298
1350
|
return clientSequenceNumber;
|
|
1299
1351
|
}
|
|
1300
|
-
submitSummaryMessage(summary) {
|
|
1352
|
+
submitSummaryMessage(summary, referenceSequenceNumber) {
|
|
1301
1353
|
// github #6451: this is only needed for staging so the server
|
|
1302
1354
|
// know when the protocol tree is included
|
|
1303
1355
|
// this can be removed once all clients send
|
|
@@ -1305,10 +1357,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1305
1357
|
if (summary.details === undefined) {
|
|
1306
1358
|
summary.details = {};
|
|
1307
1359
|
}
|
|
1308
|
-
summary.details.includesProtocolTree = this.
|
|
1309
|
-
return this.submitMessage(protocol_definitions_1.MessageType.Summarize, JSON.stringify(summary), false /* batch
|
|
1360
|
+
summary.details.includesProtocolTree = this.storageAdapter.summarizeProtocolTree;
|
|
1361
|
+
return this.submitMessage(protocol_definitions_1.MessageType.Summarize, JSON.stringify(summary), false /* batch */, undefined /* metadata */, undefined /* compression */, referenceSequenceNumber);
|
|
1310
1362
|
}
|
|
1311
|
-
submitMessage(type, contents, batch, metadata, compression) {
|
|
1363
|
+
submitMessage(type, contents, batch, metadata, compression, referenceSequenceNumber) {
|
|
1312
1364
|
var _a;
|
|
1313
1365
|
if (this.connectionState !== connectionState_1.ConnectionState.Connected) {
|
|
1314
1366
|
this.mc.logger.sendErrorEvent({ eventName: "SubmitMessageWithNoConnection", type });
|
|
@@ -1316,9 +1368,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1316
1368
|
}
|
|
1317
1369
|
this.messageCountAfterDisconnection += 1;
|
|
1318
1370
|
(_a = this.collabWindowTracker) === null || _a === void 0 ? void 0 : _a.stopSequenceNumberUpdate();
|
|
1319
|
-
return this._deltaManager.submit(type, contents, batch, metadata, compression);
|
|
1371
|
+
return this._deltaManager.submit(type, contents, batch, metadata, compression, referenceSequenceNumber);
|
|
1320
1372
|
}
|
|
1321
1373
|
processRemoteMessage(message) {
|
|
1374
|
+
if (this.offlineLoadEnabled) {
|
|
1375
|
+
this.savedOps.push(message);
|
|
1376
|
+
}
|
|
1322
1377
|
const local = this.clientId === message.clientId;
|
|
1323
1378
|
// Allow the protocol handler to process the message
|
|
1324
1379
|
const result = this.protocolHandler.processMessage(message, local);
|
|
@@ -1370,7 +1425,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1370
1425
|
});
|
|
1371
1426
|
}
|
|
1372
1427
|
this._loadedFromVersion = version;
|
|
1373
|
-
const snapshot = (_a = (await this.
|
|
1428
|
+
const snapshot = (_a = (await this.storageAdapter.getSnapshotTree(version))) !== null && _a !== void 0 ? _a : undefined;
|
|
1374
1429
|
if (snapshot === undefined && version !== undefined) {
|
|
1375
1430
|
this.mc.logger.sendErrorEvent({ eventName: "getSnapshotTreeFailed", id: version.id });
|
|
1376
1431
|
}
|
|
@@ -1389,7 +1444,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
|
|
|
1389
1444
|
// The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
|
|
1390
1445
|
// are set. Global requests will still go directly to the loader
|
|
1391
1446
|
const loader = new loader_1.RelativeLoader(this, this.loader);
|
|
1392
|
-
this._context = await containerContext_1.ContainerContext.createOrLoad(this, this.scope, this.codeLoader, codeDetails, snapshot, new deltaManagerProxy_1.DeltaManagerProxy(this._deltaManager), new quorum_1.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);
|
|
1447
|
+
this._context = await containerContext_1.ContainerContext.createOrLoad(this, this.scope, this.codeLoader, codeDetails, snapshot, new deltaManagerProxy_1.DeltaManagerProxy(this._deltaManager), new quorum_1.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);
|
|
1393
1448
|
this.emit("contextChanged", codeDetails);
|
|
1394
1449
|
}
|
|
1395
1450
|
updateDirtyContainerState(dirty) {
|