@fluidframework/container-loader 0.58.2002 → 0.59.1000

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 (72) hide show
  1. package/dist/connectionManager.d.ts +0 -2
  2. package/dist/connectionManager.d.ts.map +1 -1
  3. package/dist/connectionManager.js +14 -11
  4. package/dist/connectionManager.js.map +1 -1
  5. package/dist/container.d.ts +22 -10
  6. package/dist/container.d.ts.map +1 -1
  7. package/dist/container.js +81 -39
  8. package/dist/container.js.map +1 -1
  9. package/dist/containerContext.d.ts +5 -7
  10. package/dist/containerContext.d.ts.map +1 -1
  11. package/dist/containerContext.js +6 -4
  12. package/dist/containerContext.js.map +1 -1
  13. package/dist/contracts.d.ts +8 -1
  14. package/dist/contracts.d.ts.map +1 -1
  15. package/dist/contracts.js +21 -1
  16. package/dist/contracts.js.map +1 -1
  17. package/dist/deltaManager.d.ts +2 -1
  18. package/dist/deltaManager.d.ts.map +1 -1
  19. package/dist/deltaManager.js +1 -1
  20. package/dist/deltaManager.js.map +1 -1
  21. package/dist/loader.d.ts +4 -4
  22. package/dist/loader.d.ts.map +1 -1
  23. package/dist/loader.js.map +1 -1
  24. package/dist/packageVersion.d.ts +1 -1
  25. package/dist/packageVersion.js +1 -1
  26. package/dist/packageVersion.js.map +1 -1
  27. package/dist/retriableDocumentStorageService.js +1 -1
  28. package/dist/retriableDocumentStorageService.js.map +1 -1
  29. package/dist/utils.d.ts.map +1 -1
  30. package/dist/utils.js +0 -1
  31. package/dist/utils.js.map +1 -1
  32. package/lib/connectionManager.d.ts +0 -2
  33. package/lib/connectionManager.d.ts.map +1 -1
  34. package/lib/connectionManager.js +14 -11
  35. package/lib/connectionManager.js.map +1 -1
  36. package/lib/container.d.ts +22 -10
  37. package/lib/container.d.ts.map +1 -1
  38. package/lib/container.js +81 -39
  39. package/lib/container.js.map +1 -1
  40. package/lib/containerContext.d.ts +5 -7
  41. package/lib/containerContext.d.ts.map +1 -1
  42. package/lib/containerContext.js +6 -4
  43. package/lib/containerContext.js.map +1 -1
  44. package/lib/contracts.d.ts +8 -1
  45. package/lib/contracts.d.ts.map +1 -1
  46. package/lib/contracts.js +19 -0
  47. package/lib/contracts.js.map +1 -1
  48. package/lib/deltaManager.d.ts +2 -1
  49. package/lib/deltaManager.d.ts.map +1 -1
  50. package/lib/deltaManager.js +1 -1
  51. package/lib/deltaManager.js.map +1 -1
  52. package/lib/loader.d.ts +4 -4
  53. package/lib/loader.d.ts.map +1 -1
  54. package/lib/loader.js.map +1 -1
  55. package/lib/packageVersion.d.ts +1 -1
  56. package/lib/packageVersion.js +1 -1
  57. package/lib/packageVersion.js.map +1 -1
  58. package/lib/retriableDocumentStorageService.js +1 -1
  59. package/lib/retriableDocumentStorageService.js.map +1 -1
  60. package/lib/utils.d.ts.map +1 -1
  61. package/lib/utils.js +0 -1
  62. package/lib/utils.js.map +1 -1
  63. package/package.json +25 -13
  64. package/src/connectionManager.ts +16 -12
  65. package/src/container.ts +98 -39
  66. package/src/containerContext.ts +11 -13
  67. package/src/contracts.ts +20 -0
  68. package/src/deltaManager.ts +3 -2
  69. package/src/loader.ts +5 -6
  70. package/src/packageVersion.ts +1 -1
  71. package/src/retriableDocumentStorageService.ts +1 -1
  72. package/src/utils.ts +0 -1
package/dist/container.js CHANGED
@@ -12,7 +12,6 @@ exports.Container = exports.waitContainerToCatchUp = exports.ConnectionState = v
12
12
  const merge_1 = __importDefault(require("lodash/merge"));
13
13
  const uuid_1 = require("uuid");
14
14
  const common_utils_1 = require("@fluidframework/common-utils");
15
- const core_interfaces_1 = require("@fluidframework/core-interfaces");
16
15
  const container_definitions_1 = require("@fluidframework/container-definitions");
17
16
  const container_utils_1 = require("@fluidframework/container-utils");
18
17
  const driver_utils_1 = require("@fluidframework/driver-utils");
@@ -109,6 +108,7 @@ exports.waitContainerToCatchUp = waitContainerToCatchUp;
109
108
  const getCodeProposal =
110
109
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
111
110
  (quorum) => { var _a; return (_a = quorum.get("code")) !== null && _a !== void 0 ? _a : quorum.get("code2"); };
111
+ const summarizerClientType = "summarizer";
112
112
  class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
113
113
  constructor(loader, config) {
114
114
  var _a, _b, _c;
@@ -126,7 +126,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
126
126
  this._attachState = container_definitions_1.AttachState.Detached;
127
127
  this.resumedOpProcessingAfterLoad = false;
128
128
  this.firstConnection = true;
129
- this.manualReconnectInProgress = false;
130
129
  this.connectionTransitionTimes = [];
131
130
  this.messageCountAfterDisconnection = 0;
132
131
  this.attachStarted = false;
@@ -353,7 +352,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
353
352
  }
354
353
  get context() {
355
354
  if (this._context === undefined) {
356
- throw new Error("Attempted to access context before it was defined");
355
+ throw new container_utils_1.GenericError("Attempted to access context before it was defined");
357
356
  }
358
357
  return this._context;
359
358
  }
@@ -374,6 +373,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
374
373
  get readOnlyInfo() {
375
374
  return this._deltaManager.readOnlyInfo;
376
375
  }
376
+ get closeSignal() {
377
+ return this._deltaManager.closeAbortController.signal;
378
+ }
377
379
  /**
378
380
  * Tracks host requiring read-only mode.
379
381
  */
@@ -548,7 +550,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
548
550
  const createNewResolvedUrl = await this.urlResolver.resolve(request);
549
551
  driver_utils_1.ensureFluidResolvedUrl(createNewResolvedUrl);
550
552
  if (this.service === undefined) {
551
- this.service = await driver_utils_1.runWithRetry(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger), "containerAttach", this.mc.logger, {});
553
+ common_utils_1.assert(this.client.details.type !== summarizerClientType, 0x2c4 /* "client should not be summarizer before container is created" */);
554
+ this.service = await driver_utils_1.runWithRetry(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger, false), "containerAttach", this.mc.logger, {
555
+ cancel: this.closeSignal,
556
+ });
552
557
  }
553
558
  const resolvedUrl = this.service.resolvedUrl;
554
559
  driver_utils_1.ensureFluidResolvedUrl(resolvedUrl);
@@ -604,11 +609,28 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
604
609
  async request(path) {
605
610
  return telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Request" }, async () => this.context.request(path), { end: true, cancel: "error" });
606
611
  }
612
+ /**
613
+ * Dictates whether or not the current container will automatically attempt to reconnect to the delta stream
614
+ * after receiving a disconnect event
615
+ * @param reconnect - Boolean indicating if reconnect should automatically occur
616
+ * @deprecated - 0.58, This API will be removed in 1.0
617
+ * Use `connect()` and `disconnect()` instead of `setAutoReconnect(true)` and `setAutoReconnect(false)` respectively
618
+ * See https://github.com/microsoft/FluidFramework/issues/9167 for context
619
+ */
607
620
  setAutoReconnect(reconnect) {
608
621
  if (this.closed) {
609
622
  throw new Error("Attempting to setAutoReconnect() a closed Container");
610
623
  }
611
624
  const mode = reconnect ? contracts_1.ReconnectMode.Enabled : contracts_1.ReconnectMode.Disabled;
625
+ this.setAutoReconnectInternal(mode);
626
+ // If container state is not attached and resumed, then don't connect to delta stream. Also don't set the
627
+ // manual reconnection flag to true as we haven't made the initial connection yet.
628
+ if (reconnect && this._attachState === container_definitions_1.AttachState.Attached && this.resumedOpProcessingAfterLoad) {
629
+ // Ensure connection to web socket
630
+ this.connectToDeltaStream({ reason: "autoReconnect" });
631
+ }
632
+ }
633
+ setAutoReconnectInternal(mode) {
612
634
  const currentMode = this._deltaManager.connectionManager.reconnectMode;
613
635
  if (currentMode === mode) {
614
636
  return;
@@ -617,23 +639,56 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
617
639
  const duration = now - this.setAutoReconnectTime;
618
640
  this.setAutoReconnectTime = now;
619
641
  this.mc.logger.sendTelemetryEvent({
620
- eventName: reconnect ? "AutoReconnectEnabled" : "AutoReconnectDisabled",
642
+ eventName: mode === contracts_1.ReconnectMode.Enabled ? "AutoReconnectEnabled" : "AutoReconnectDisabled",
621
643
  connectionMode: this.connectionMode,
622
644
  connectionState: ConnectionState[this.connectionState],
623
645
  duration,
624
646
  });
625
647
  this._deltaManager.connectionManager.setAutoReconnect(mode);
626
- // If container state is not attached and resumed, then don't connect to delta stream. Also don't set the
627
- // manual reconnection flag to true as we haven't made the initial connection yet.
628
- if (reconnect && this._attachState === container_definitions_1.AttachState.Attached && this.resumedOpProcessingAfterLoad) {
629
- if (this.connectionState === ConnectionState.Disconnected) {
630
- // Only track this as a manual reconnection if we are truly the ones kicking it off.
631
- this.manualReconnectInProgress = true;
632
- }
633
- // Ensure connection to web socket
634
- this.connectToDeltaStream({ reason: "autoReconnect" });
648
+ }
649
+ connect() {
650
+ if (this.closed) {
651
+ throw new container_utils_1.UsageError(`The Container is closed and cannot be connected`);
652
+ }
653
+ else if (this._attachState !== container_definitions_1.AttachState.Attached) {
654
+ throw new container_utils_1.UsageError(`The Container is not attached and cannot be connected`);
655
+ }
656
+ else if (!this.connected) {
657
+ // Note: no need to fetch ops as we do it preemptively as part of DeltaManager.attachOpHandler().
658
+ // If there is gap, we will learn about it once connected, but the gap should be small (if any),
659
+ // assuming that connect() is called quickly after initial container boot.
660
+ this.connectInternal({ reason: "DocumentConnect", fetchOpsFromStorage: false });
661
+ }
662
+ }
663
+ connectInternal(args) {
664
+ common_utils_1.assert(!this.closed, 0x2c5 /* "Attempting to connect() a closed Container" */);
665
+ common_utils_1.assert(this._attachState === container_definitions_1.AttachState.Attached, 0x2c6 /* "Attempting to connect() a container that is not attached" */);
666
+ // Resume processing ops and connect to delta stream
667
+ this.resumeInternal(args);
668
+ // Set Auto Reconnect Mode
669
+ const mode = contracts_1.ReconnectMode.Enabled;
670
+ this.setAutoReconnectInternal(mode);
671
+ }
672
+ disconnect() {
673
+ if (this.closed) {
674
+ throw new container_utils_1.UsageError(`The Container is closed and cannot be disconnected`);
675
+ }
676
+ else {
677
+ this.disconnectInternal();
635
678
  }
636
679
  }
680
+ disconnectInternal() {
681
+ common_utils_1.assert(!this.closed, 0x2c7 /* "Attempting to disconnect() a closed Container" */);
682
+ // Set Auto Reconnect Mode
683
+ const mode = contracts_1.ReconnectMode.Disabled;
684
+ this.setAutoReconnectInternal(mode);
685
+ }
686
+ /**
687
+ * Have the container attempt to resume processing ops
688
+ * @deprecated - 0.58, This API will be removed in 1.0
689
+ * Use `connect()` instead
690
+ * See https://github.com/microsoft/FluidFramework/issues/9167 for context
691
+ */
637
692
  resume() {
638
693
  if (!this.closed) {
639
694
  // Note: no need to fetch ops as we do it preemptively as part of DeltaManager.attachOpHandler().
@@ -653,29 +708,15 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
653
708
  // Ensure connection to web socket
654
709
  this.connectToDeltaStream(args);
655
710
  }
656
- /**
657
- * @deprecated 0.56, will be removed in next release from IContainerContext
658
- * Raise non-critical error to host. Calling this API will not close container.
659
- * For critical errors, please call Container.close(error).
660
- * @param error - an error to raise
661
- */
662
- raiseContainerWarning(warning) {
663
- // Some "warning" events come from outside the container and are logged
664
- // elsewhere (e.g. summarizing container). We shouldn't log these here.
665
- if (warning.logged !== true) {
666
- this.logContainerError(warning);
667
- }
668
- this.emit("warning", warning);
669
- }
670
711
  async getAbsoluteUrl(relativeUrl) {
671
712
  var _a;
672
713
  if (this.resolvedUrl === undefined) {
673
714
  return undefined;
674
715
  }
675
- return this.urlResolver.getAbsoluteUrl(this.resolvedUrl, relativeUrl, (_a = this._context) === null || _a === void 0 ? void 0 : _a.codeDetails);
716
+ return this.urlResolver.getAbsoluteUrl(this.resolvedUrl, relativeUrl, contracts_1.getPackageName((_a = this._context) === null || _a === void 0 ? void 0 : _a.codeDetails));
676
717
  }
677
718
  async proposeCodeDetails(codeDetails) {
678
- if (!core_interfaces_1.isFluidCodeDetails(codeDetails)) {
719
+ if (!container_definitions_1.isFluidCodeDetails(codeDetails)) {
679
720
  throw new Error("Provided codeDetails are not IFluidCodeDetails");
680
721
  }
681
722
  if (this.codeLoader.IFluidCodeDetailsComparer) {
@@ -730,7 +771,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
730
771
  if (this._resolvedUrl === undefined) {
731
772
  throw new Error("Attempting to load without a resolved url");
732
773
  }
733
- this.service = await this.serviceFactory.createDocumentService(this._resolvedUrl, this.subLogger);
774
+ this.service = await this.serviceFactory.createDocumentService(this._resolvedUrl, this.subLogger, this.client.details.type === summarizerClientType);
734
775
  // Ideally we always connect as "read" by default.
735
776
  // Currently that works with SPO & r11s, because we get "write" connection when connecting to non-existing file.
736
777
  // We should not rely on it by (one of them will address the issue, but we need to address both)
@@ -934,7 +975,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
934
975
  });
935
976
  protocol.quorum.on("approveProposal", (sequenceNumber, key, value) => {
936
977
  if (key === "code" || key === "code2") {
937
- if (!core_interfaces_1.isFluidCodeDetails(value)) {
978
+ if (!container_definitions_1.isFluidCodeDetails(value)) {
938
979
  this.mc.logger.sendErrorEvent({
939
980
  eventName: "CodeProposalNotIFluidCodeDetails",
940
981
  });
@@ -1030,12 +1071,17 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1030
1071
  this.connectionStateHandler.receivedConnectEvent(this.connectionMode, details);
1031
1072
  });
1032
1073
  deltaManager.on("disconnect", (reason) => {
1033
- this.manualReconnectInProgress = false;
1034
1074
  this.collabWindowTracker.stopSequenceNumberUpdate();
1035
1075
  this.connectionStateHandler.receivedDisconnectEvent(reason);
1036
1076
  });
1037
1077
  deltaManager.on("throttled", (warning) => {
1038
- this.raiseContainerWarning(warning);
1078
+ const warn = warning;
1079
+ // Some "warning" events come from outside the container and are logged
1080
+ // elsewhere (e.g. summarizing container). We shouldn't log these here.
1081
+ if (warn.logged !== true) {
1082
+ this.logContainerError(warn);
1083
+ }
1084
+ this.emit("warning", warn);
1039
1085
  });
1040
1086
  deltaManager.on("readonly", (readonly) => {
1041
1087
  this.emit("readonly", readonly);
@@ -1082,9 +1128,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1082
1128
  if (this.firstConnection) {
1083
1129
  connectionInitiationReason = "InitialConnect";
1084
1130
  }
1085
- else if (this.manualReconnectInProgress) {
1086
- connectionInitiationReason = "ManualReconnect";
1087
- }
1088
1131
  else {
1089
1132
  connectionInitiationReason = "AutoReconnect";
1090
1133
  }
@@ -1096,7 +1139,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1096
1139
  opsBehind, online: driver_utils_1.OnlineStatus[driver_utils_1.isOnline()], lastVisible: this.lastVisible !== undefined ? common_utils_1.performance.now() - this.lastVisible : undefined, checkpointSequenceNumber }, this._deltaManager.connectionProps));
1097
1140
  if (value === ConnectionState.Connected) {
1098
1141
  this.firstConnection = false;
1099
- this.manualReconnectInProgress = false;
1100
1142
  }
1101
1143
  }
1102
1144
  propagateConnectionState() {
@@ -1234,7 +1276,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1234
1276
  // The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
1235
1277
  // are set. Global requests will still go directly to the loader
1236
1278
  const loader = new loader_1.RelativeLoader(this, this.loader);
1237
- 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, (warning) => this.raiseContainerWarning(warning), (type, contents, batch, metadata) => this.submitContainerMessage(type, contents, batch, metadata), (message) => this.submitSignal(message), (error) => this.close(error), Container.version, (dirty) => this.updateDirtyContainerState(dirty), existing, pendingLocalState);
1279
+ 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), (message) => this.submitSignal(message), (error) => this.close(error), Container.version, (dirty) => this.updateDirtyContainerState(dirty), existing, pendingLocalState);
1238
1280
  this.emit("contextChanged", codeDetails);
1239
1281
  }
1240
1282
  updateDirtyContainerState(dirty) {