@fluidframework/container-loader 0.51.3 → 0.53.0-46105

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.
Files changed (66) hide show
  1. package/dist/connectionStateHandler.d.ts +1 -0
  2. package/dist/connectionStateHandler.d.ts.map +1 -1
  3. package/dist/connectionStateHandler.js +11 -3
  4. package/dist/connectionStateHandler.js.map +1 -1
  5. package/dist/container.d.ts +15 -23
  6. package/dist/container.d.ts.map +1 -1
  7. package/dist/container.js +125 -140
  8. package/dist/container.js.map +1 -1
  9. package/dist/containerContext.d.ts +5 -4
  10. package/dist/containerContext.d.ts.map +1 -1
  11. package/dist/containerContext.js +4 -0
  12. package/dist/containerContext.js.map +1 -1
  13. package/dist/deltaManager.d.ts +0 -7
  14. package/dist/deltaManager.d.ts.map +1 -1
  15. package/dist/deltaManager.js +38 -50
  16. package/dist/deltaManager.js.map +1 -1
  17. package/dist/deltaQueue.d.ts +5 -1
  18. package/dist/deltaQueue.d.ts.map +1 -1
  19. package/dist/deltaQueue.js.map +1 -1
  20. package/dist/loader.d.ts +8 -3
  21. package/dist/loader.d.ts.map +1 -1
  22. package/dist/loader.js +6 -1
  23. package/dist/loader.js.map +1 -1
  24. package/dist/packageVersion.d.ts +1 -1
  25. package/dist/packageVersion.d.ts.map +1 -1
  26. package/dist/packageVersion.js +1 -1
  27. package/dist/packageVersion.js.map +1 -1
  28. package/dist/utils.js +6 -5
  29. package/dist/utils.js.map +1 -1
  30. package/lib/connectionStateHandler.d.ts +1 -0
  31. package/lib/connectionStateHandler.d.ts.map +1 -1
  32. package/lib/connectionStateHandler.js +11 -3
  33. package/lib/connectionStateHandler.js.map +1 -1
  34. package/lib/container.d.ts +15 -23
  35. package/lib/container.d.ts.map +1 -1
  36. package/lib/container.js +127 -142
  37. package/lib/container.js.map +1 -1
  38. package/lib/containerContext.d.ts +5 -4
  39. package/lib/containerContext.d.ts.map +1 -1
  40. package/lib/containerContext.js +4 -0
  41. package/lib/containerContext.js.map +1 -1
  42. package/lib/deltaManager.d.ts +0 -7
  43. package/lib/deltaManager.d.ts.map +1 -1
  44. package/lib/deltaManager.js +38 -50
  45. package/lib/deltaManager.js.map +1 -1
  46. package/lib/deltaQueue.d.ts +5 -1
  47. package/lib/deltaQueue.d.ts.map +1 -1
  48. package/lib/deltaQueue.js.map +1 -1
  49. package/lib/loader.d.ts +8 -3
  50. package/lib/loader.d.ts.map +1 -1
  51. package/lib/loader.js +6 -1
  52. package/lib/loader.js.map +1 -1
  53. package/lib/packageVersion.d.ts +1 -1
  54. package/lib/packageVersion.d.ts.map +1 -1
  55. package/lib/packageVersion.js +1 -1
  56. package/lib/packageVersion.js.map +1 -1
  57. package/lib/utils.js +6 -5
  58. package/lib/utils.js.map +1 -1
  59. package/package.json +11 -11
  60. package/src/connectionStateHandler.ts +14 -4
  61. package/src/container.ts +150 -160
  62. package/src/containerContext.ts +8 -3
  63. package/src/deltaManager.ts +50 -56
  64. package/src/deltaQueue.ts +10 -1
  65. package/src/loader.ts +33 -24
  66. package/src/packageVersion.ts +1 -1
package/dist/container.js CHANGED
@@ -65,7 +65,7 @@ async function waitContainerToCatchUp(container) {
65
65
  if (container.closed) {
66
66
  throw new Error("Container is closed");
67
67
  }
68
- return new Promise((accept, reject) => {
68
+ return new Promise((resolve, reject) => {
69
69
  const deltaManager = container.deltaManager;
70
70
  container.on("closed", reject);
71
71
  const waitForOps = () => {
@@ -74,12 +74,12 @@ async function waitContainerToCatchUp(container) {
74
74
  const connectionOpSeqNumber = deltaManager.lastKnownSeqNumber;
75
75
  common_utils_1.assert(deltaManager.lastSequenceNumber <= connectionOpSeqNumber, 0x266 /* "lastKnownSeqNumber should never be below last processed sequence number" */);
76
76
  if (deltaManager.lastSequenceNumber === connectionOpSeqNumber) {
77
- accept(hasCheckpointSequenceNumber);
77
+ resolve(hasCheckpointSequenceNumber);
78
78
  return;
79
79
  }
80
80
  const callbackOps = (message) => {
81
81
  if (connectionOpSeqNumber <= message.sequenceNumber) {
82
- accept(hasCheckpointSequenceNumber);
82
+ resolve(hasCheckpointSequenceNumber);
83
83
  deltaManager.off("op", callbackOps);
84
84
  }
85
85
  };
@@ -144,7 +144,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
144
144
  this.subLogger = telemetry_utils_1.ChildLogger.create(loader.services.subLogger, undefined, {
145
145
  all: {
146
146
  clientType,
147
- loaderVersion: packageVersion_1.pkgVersion,
148
147
  containerId: uuid_1.v4(),
149
148
  docId: () => this.id,
150
149
  containerAttachState: () => this._attachState,
@@ -229,22 +228,22 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
229
228
  switch (event) {
230
229
  case dirtyContainerEvent:
231
230
  if (this._dirtyContainer) {
232
- listener(this._dirtyContainer);
231
+ listener();
233
232
  }
234
233
  break;
235
234
  case savedContainerEvent:
236
235
  if (!this._dirtyContainer) {
237
- listener(this._dirtyContainer);
236
+ listener();
238
237
  }
239
238
  break;
240
239
  case telemetry_utils_1.connectedEventName:
241
240
  if (this.connected) {
242
- listener(event, this.clientId);
241
+ listener(this.clientId);
243
242
  }
244
243
  break;
245
244
  case telemetry_utils_1.disconnectedEventName:
246
245
  if (!this.connected) {
247
- listener(event);
246
+ listener();
248
247
  }
249
248
  break;
250
249
  default:
@@ -291,16 +290,18 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
291
290
  container.close(err);
292
291
  onClosed(err);
293
292
  });
294
- }), { start: true, end: true, cancel: "error" });
293
+ }), { start: true, end: true, cancel: "generic" });
295
294
  }
296
295
  /**
297
296
  * Create a new container in a detached state.
298
297
  */
299
298
  static async createDetached(loader, codeDetails) {
300
299
  const container = new Container(loader, {});
301
- container._lifecycleState = "loading";
302
- await container.createDetached(codeDetails);
303
- return container;
300
+ return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.logger, { eventName: "CreateDetached" }, async (_event) => {
301
+ container._lifecycleState = "loading";
302
+ await container.createDetached(codeDetails);
303
+ return container;
304
+ }, { start: true, end: true, cancel: "generic" });
304
305
  }
305
306
  /**
306
307
  * Create a new container in a detached state that is initialized with a
@@ -308,10 +309,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
308
309
  */
309
310
  static async rehydrateDetachedFromSnapshot(loader, snapshot) {
310
311
  const container = new Container(loader, {});
311
- const deserializedSummary = JSON.parse(snapshot);
312
- container._lifecycleState = "loading";
313
- await container.rehydrateDetachedFromSnapshot(deserializedSummary);
314
- return container;
312
+ return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.logger, { eventName: "RehydrateDetachedFromSnapshot" }, async (_event) => {
313
+ const deserializedSummary = JSON.parse(snapshot);
314
+ container._lifecycleState = "loading";
315
+ await container.rehydrateDetachedFromSnapshot(deserializedSummary);
316
+ return container;
317
+ }, { start: true, end: true, cancel: "generic" });
315
318
  }
316
319
  get loaded() {
317
320
  return (this._lifecycleState !== "created" && this._lifecycleState !== "loading");
@@ -356,31 +359,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
356
359
  get loadedFromVersion() {
357
360
  return this._loadedFromVersion;
358
361
  }
359
- /**
360
- * Tells if container is in read-only mode.
361
- * Data stores should listen for "readonly" notifications and disallow user making changes to data stores.
362
- * Readonly state can be because of no storage write permission,
363
- * or due to host forcing readonly mode for container.
364
- *
365
- * We do not differentiate here between no write access to storage vs. host disallowing changes to container -
366
- * in all cases container runtime and data stores should respect readonly state and not allow local changes.
367
- *
368
- * It is undefined if we have not yet established websocket connection
369
- * and do not know if user has write access to a file.
370
- * @deprecated - use readOnlyInfo
371
- */
372
- get readonly() {
373
- return this._deltaManager.readonly;
374
- }
375
- /**
376
- * Tells if user has no write permissions for file in storage
377
- * It is undefined if we have not yet established websocket connection
378
- * and do not know if user has write access to a file.
379
- * @deprecated - use readOnlyInfo
380
- */
381
- get readonlyPermissions() {
382
- return this._deltaManager.readonlyPermissions;
383
- }
384
362
  get readOnlyInfo() {
385
363
  return this._deltaManager.readOnlyInfo;
386
364
  }
@@ -428,15 +406,31 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
428
406
  return this._deltaManager.clientDetails;
429
407
  }
430
408
  /**
431
- * @deprecated use codeDetails
409
+ * The current code details for the container's runtime
410
+ * @deprecated use getSpecifiedCodeDetails for the code details currently specified for this container, or
411
+ * getLoadedCodeDetails for the code details that the container's context was loaded with.
412
+ * To be removed after getSpecifiedCodeDetails and getLoadedCodeDetails become ubiquitous.
432
413
  */
433
- get chaincodePackage() {
434
- return this.codeDetails;
435
- }
436
414
  get codeDetails() {
437
415
  var _a, _b;
438
416
  return (_b = (_a = this._context) === null || _a === void 0 ? void 0 : _a.codeDetails) !== null && _b !== void 0 ? _b : this.getCodeDetailsFromQuorum();
439
417
  }
418
+ /**
419
+ * Get the code details that are currently specified for the container.
420
+ * @returns The current code details if any are specified, undefined if none are specified.
421
+ */
422
+ getSpecifiedCodeDetails() {
423
+ return this.getCodeDetailsFromQuorum();
424
+ }
425
+ /**
426
+ * Get the code details that were used to load the container.
427
+ * @returns The code details that were used to load the container if it is loaded, undefined if it is not yet
428
+ * loaded.
429
+ */
430
+ getLoadedCodeDetails() {
431
+ var _a;
432
+ return (_a = this._context) === null || _a === void 0 ? void 0 : _a.codeDetails;
433
+ }
440
434
  /**
441
435
  * Retrieves the audience associated with the document
442
436
  */
@@ -473,6 +467,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
473
467
  try {
474
468
  this._deltaManager.close(error);
475
469
  (_a = this._protocolHandler) === null || _a === void 0 ? void 0 : _a.close();
470
+ this.connectionStateHandler.dispose();
476
471
  (_b = this._context) === null || _b === void 0 ? void 0 : _b.dispose(error !== undefined ? new Error(error.message) : undefined);
477
472
  common_utils_1.assert(this.connectionState === ConnectionState.Disconnected, 0x0cf /* "disconnect event was not raised!" */);
478
473
  (_c = this._storageService) === null || _c === void 0 ? void 0 : _c.dispose();
@@ -517,95 +512,93 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
517
512
  const protocolSummary = this.captureProtocolSummary();
518
513
  const combinedSummary = driver_utils_1.combineAppAndProtocolSummary(appSummary, protocolSummary);
519
514
  if (this.loader.services.detachedBlobStorage && this.loader.services.detachedBlobStorage.size > 0) {
520
- combinedSummary.tree[".hasAttachmentBlobs"] = { type: 2 /* Blob */, content: "true" };
515
+ combinedSummary.tree[".hasAttachmentBlobs"] = { type: protocol_definitions_1.SummaryType.Blob, content: "true" };
521
516
  }
522
517
  return JSON.stringify(combinedSummary);
523
518
  }
524
519
  async attach(request) {
525
- if (this._lifecycleState !== "loaded") {
526
- throw new container_utils_1.UsageError(`containerNotValidForAttach [${this._lifecycleState}]`);
527
- }
528
- // If container is already attached or attach is in progress, throw an error.
529
- common_utils_1.assert(this._attachState === container_definitions_1.AttachState.Detached && !this.attachStarted, 0x205 /* "attach() called more than once" */);
530
- this.attachStarted = true;
531
- // If attachment blobs were uploaded in detached state we will go through a different attach flow
532
- const hasAttachmentBlobs = this.loader.services.detachedBlobStorage !== undefined
533
- && this.loader.services.detachedBlobStorage.size > 0;
534
- try {
535
- common_utils_1.assert(this.deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
536
- let summary;
537
- if (!hasAttachmentBlobs) {
538
- // Get the document state post attach - possibly can just call attach but we need to change the
539
- // semantics around what the attach means as far as async code goes.
540
- const appSummary = this.context.createSummary();
541
- const protocolSummary = this.captureProtocolSummary();
542
- summary = driver_utils_1.combineAppAndProtocolSummary(appSummary, protocolSummary);
543
- // Set the state as attaching as we are starting the process of attaching container.
544
- // This should be fired after taking the summary because it is the place where we are
545
- // starting to attach the container to storage.
546
- // Also, this should only be fired in detached container.
547
- this._attachState = container_definitions_1.AttachState.Attaching;
548
- this.context.notifyAttaching();
549
- }
550
- // Actually go and create the resolved document
551
- const createNewResolvedUrl = await this.urlResolver.resolve(request);
552
- driver_utils_1.ensureFluidResolvedUrl(createNewResolvedUrl);
553
- if (this.service === undefined) {
554
- this.service = await driver_utils_1.runWithRetry(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger), "containerAttach", this.logger, {});
520
+ await telemetry_utils_1.PerformanceEvent.timedExecAsync(this.logger, { eventName: "Attach" }, async () => {
521
+ if (this._lifecycleState !== "loaded") {
522
+ throw new container_utils_1.UsageError(`containerNotValidForAttach [${this._lifecycleState}]`);
555
523
  }
556
- const resolvedUrl = this.service.resolvedUrl;
557
- driver_utils_1.ensureFluidResolvedUrl(resolvedUrl);
558
- this._resolvedUrl = resolvedUrl;
559
- await this.connectStorageService();
560
- if (hasAttachmentBlobs) {
561
- // upload blobs to storage
562
- common_utils_1.assert(!!this.loader.services.detachedBlobStorage, 0x24e /* "assertion for type narrowing" */);
563
- // build a table mapping IDs assigned locally to IDs assigned by storage and pass it to runtime to
564
- // support blob handles that only know about the local IDs
565
- const redirectTable = new Map();
566
- // if new blobs are added while uploading, upload them too
567
- while (redirectTable.size < this.loader.services.detachedBlobStorage.size) {
568
- const newIds = this.loader.services.detachedBlobStorage.getBlobIds().filter((id) => !redirectTable.has(id));
569
- for (const id of newIds) {
570
- const blob = await this.loader.services.detachedBlobStorage.readBlob(id);
571
- const response = await this.storageService.createBlob(blob);
572
- redirectTable.set(id, response.id);
524
+ // If container is already attached or attach is in progress, throw an error.
525
+ common_utils_1.assert(this._attachState === container_definitions_1.AttachState.Detached && !this.attachStarted, 0x205 /* "attach() called more than once" */);
526
+ this.attachStarted = true;
527
+ // If attachment blobs were uploaded in detached state we will go through a different attach flow
528
+ const hasAttachmentBlobs = this.loader.services.detachedBlobStorage !== undefined
529
+ && this.loader.services.detachedBlobStorage.size > 0;
530
+ try {
531
+ common_utils_1.assert(this.deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
532
+ let summary;
533
+ if (!hasAttachmentBlobs) {
534
+ // Get the document state post attach - possibly can just call attach but we need to change the
535
+ // semantics around what the attach means as far as async code goes.
536
+ const appSummary = this.context.createSummary();
537
+ const protocolSummary = this.captureProtocolSummary();
538
+ summary = driver_utils_1.combineAppAndProtocolSummary(appSummary, protocolSummary);
539
+ // Set the state as attaching as we are starting the process of attaching container.
540
+ // This should be fired after taking the summary because it is the place where we are
541
+ // starting to attach the container to storage.
542
+ // Also, this should only be fired in detached container.
543
+ this._attachState = container_definitions_1.AttachState.Attaching;
544
+ this.context.notifyAttaching();
545
+ }
546
+ // Actually go and create the resolved document
547
+ const createNewResolvedUrl = await this.urlResolver.resolve(request);
548
+ driver_utils_1.ensureFluidResolvedUrl(createNewResolvedUrl);
549
+ if (this.service === undefined) {
550
+ this.service = await driver_utils_1.runWithRetry(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger), "containerAttach", this.logger, {});
551
+ }
552
+ const resolvedUrl = this.service.resolvedUrl;
553
+ driver_utils_1.ensureFluidResolvedUrl(resolvedUrl);
554
+ this._resolvedUrl = resolvedUrl;
555
+ await this.connectStorageService();
556
+ if (hasAttachmentBlobs) {
557
+ // upload blobs to storage
558
+ common_utils_1.assert(!!this.loader.services.detachedBlobStorage, 0x24e /* "assertion for type narrowing" */);
559
+ // build a table mapping IDs assigned locally to IDs assigned by storage and pass it to runtime to
560
+ // support blob handles that only know about the local IDs
561
+ const redirectTable = new Map();
562
+ // if new blobs are added while uploading, upload them too
563
+ while (redirectTable.size < this.loader.services.detachedBlobStorage.size) {
564
+ const newIds = this.loader.services.detachedBlobStorage.getBlobIds().filter((id) => !redirectTable.has(id));
565
+ for (const id of newIds) {
566
+ const blob = await this.loader.services.detachedBlobStorage.readBlob(id);
567
+ const response = await this.storageService.createBlob(blob);
568
+ redirectTable.set(id, response.id);
569
+ }
573
570
  }
571
+ // take summary and upload
572
+ const appSummary = this.context.createSummary(redirectTable);
573
+ const protocolSummary = this.captureProtocolSummary();
574
+ summary = driver_utils_1.combineAppAndProtocolSummary(appSummary, protocolSummary);
575
+ this._attachState = container_definitions_1.AttachState.Attaching;
576
+ this.context.notifyAttaching();
577
+ await this.storageService.uploadSummaryWithContext(summary, {
578
+ referenceSequenceNumber: 0,
579
+ ackHandle: undefined,
580
+ proposalHandle: undefined,
581
+ });
582
+ }
583
+ this._attachState = container_definitions_1.AttachState.Attached;
584
+ this.emit("attached");
585
+ // Propagate current connection state through the system.
586
+ this.propagateConnectionState();
587
+ if (!this.closed) {
588
+ this.resumeInternal({ fetchOpsFromStorage: false, reason: "createDetached" });
574
589
  }
575
- // take summary and upload
576
- const appSummary = this.context.createSummary(redirectTable);
577
- const protocolSummary = this.captureProtocolSummary();
578
- summary = driver_utils_1.combineAppAndProtocolSummary(appSummary, protocolSummary);
579
- this._attachState = container_definitions_1.AttachState.Attaching;
580
- this.context.notifyAttaching();
581
- await this.storageService.uploadSummaryWithContext(summary, {
582
- referenceSequenceNumber: 0,
583
- ackHandle: undefined,
584
- proposalHandle: undefined,
585
- });
586
- }
587
- this._attachState = container_definitions_1.AttachState.Attached;
588
- this.emit("attached");
589
- // Propagate current connection state through the system.
590
- this.propagateConnectionState();
591
- if (!this.closed) {
592
- this.resumeInternal({ fetchOpsFromStorage: false, reason: "createDetached" });
593
590
  }
594
- }
595
- catch (error) {
596
- // we should retry upon any retriable errors, so we shouldn't see them here
597
- common_utils_1.assert(!driver_utils_1.canRetryOnError(error), 0x24f /* "retriable error thrown from attach()" */);
598
- // add resolved URL on error object so that host has the ability to find this document and delete it
599
- const newError = telemetry_utils_1.normalizeError(error);
600
- const resolvedUrl = this.resolvedUrl;
601
- if (resolvedUrl) {
602
- driver_utils_1.ensureFluidResolvedUrl(resolvedUrl);
603
- newError.addTelemetryProperties({ resolvedUrl: resolvedUrl.url });
591
+ catch (error) {
592
+ // add resolved URL on error object so that host has the ability to find this document and delete it
593
+ const newError = telemetry_utils_1.normalizeError(error);
594
+ const resolvedUrl = this.resolvedUrl;
595
+ if (driver_utils_1.isFluidResolvedUrl(resolvedUrl)) {
596
+ newError.addTelemetryProperties({ resolvedUrl: resolvedUrl.url });
597
+ }
598
+ this.close(newError);
599
+ throw newError;
604
600
  }
605
- this.close(newError);
606
- // eslint-disable-next-line @typescript-eslint/no-throw-literal
607
- throw newError;
608
- }
601
+ }, { start: true, end: true, cancel: "generic" });
609
602
  }
610
603
  async request(path) {
611
604
  return telemetry_utils_1.PerformanceEvent.timedExecAsync(this.logger, { eventName: "Request" }, async () => this.context.request(path), { end: true, cancel: "error" });
@@ -922,7 +915,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
922
915
  }
923
916
  async createDetached(source) {
924
917
  const attributes = {
925
- branch: "",
926
918
  sequenceNumber: detachedContainerRefSeqNumber,
927
919
  term: 1,
928
920
  minimumSequenceNumber: 0,
@@ -984,7 +976,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
984
976
  async getDocumentAttributes(storage, tree) {
985
977
  if (tree === undefined) {
986
978
  return {
987
- branch: this.id,
988
979
  minimumSequenceNumber: 0,
989
980
  sequenceNumber: 0,
990
981
  term: 1,
@@ -1053,7 +1044,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1053
1044
  const quorumSnapshot = this.protocolHandler.quorum.snapshot();
1054
1045
  // Save attributes for the document
1055
1046
  const documentAttributes = {
1056
- branch: this.id,
1057
1047
  minimumSequenceNumber: this.protocolHandler.minimumSequenceNumber,
1058
1048
  sequenceNumber: this.protocolHandler.sequenceNumber,
1059
1049
  term: this.protocolHandler.term,
@@ -1062,22 +1052,22 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1062
1052
  tree: {
1063
1053
  attributes: {
1064
1054
  content: JSON.stringify(documentAttributes),
1065
- type: 2 /* Blob */,
1055
+ type: protocol_definitions_1.SummaryType.Blob,
1066
1056
  },
1067
1057
  quorumMembers: {
1068
1058
  content: JSON.stringify(quorumSnapshot.members),
1069
- type: 2 /* Blob */,
1059
+ type: protocol_definitions_1.SummaryType.Blob,
1070
1060
  },
1071
1061
  quorumProposals: {
1072
1062
  content: JSON.stringify(quorumSnapshot.proposals),
1073
- type: 2 /* Blob */,
1063
+ type: protocol_definitions_1.SummaryType.Blob,
1074
1064
  },
1075
1065
  quorumValues: {
1076
1066
  content: JSON.stringify(quorumSnapshot.values),
1077
- type: 2 /* Blob */,
1067
+ type: protocol_definitions_1.SummaryType.Blob,
1078
1068
  },
1079
1069
  },
1080
- type: 1 /* Tree */,
1070
+ type: protocol_definitions_1.SummaryType.Tree,
1081
1071
  };
1082
1072
  return summary;
1083
1073
  }
@@ -1102,6 +1092,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1102
1092
  if (this.clientDetailsOverride !== undefined) {
1103
1093
  merge_1.default(client.details, this.clientDetailsOverride);
1104
1094
  }
1095
+ client.details.environment = [client.details.environment, ` loaderVersion:${packageVersion_1.pkgVersion}`].join(";");
1105
1096
  return client;
1106
1097
  }
1107
1098
  /**
@@ -1111,14 +1102,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1111
1102
  * If it's not true, runtime is not in position to send ops.
1112
1103
  */
1113
1104
  activeConnection() {
1114
- const active = this.connectionState === ConnectionState.Connected &&
1105
+ return this.connectionState === ConnectionState.Connected &&
1115
1106
  this._deltaManager.connectionMode === "write";
1116
- // Check for presence of current client in quorum for "write" connections - inactive clients
1117
- // would get leave op after some long timeout (5 min) and that should automatically transition
1118
- // state to "read" mode.
1119
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1120
- common_utils_1.assert(!active || this.getQuorum().getMember(this.clientId) !== undefined, 0x276 /* "active connection not present in quorum" */);
1121
- return active;
1122
1107
  }
1123
1108
  createDeltaManager() {
1124
1109
  const deltaManager = new deltaManager_1.DeltaManager(() => this.service, this.client, telemetry_utils_1.ChildLogger.create(this.subLogger, "DeltaManager"), this._canReconnect, () => this.activeConnection());