@fluidframework/container-loader 0.58.2001 → 0.59.1000-61898

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 (74) 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.d.ts.map +1 -1
  26. package/dist/packageVersion.js +1 -1
  27. package/dist/packageVersion.js.map +1 -1
  28. package/dist/retriableDocumentStorageService.js +1 -1
  29. package/dist/retriableDocumentStorageService.js.map +1 -1
  30. package/dist/utils.d.ts.map +1 -1
  31. package/dist/utils.js +0 -1
  32. package/dist/utils.js.map +1 -1
  33. package/lib/connectionManager.d.ts +0 -2
  34. package/lib/connectionManager.d.ts.map +1 -1
  35. package/lib/connectionManager.js +14 -11
  36. package/lib/connectionManager.js.map +1 -1
  37. package/lib/container.d.ts +22 -10
  38. package/lib/container.d.ts.map +1 -1
  39. package/lib/container.js +81 -39
  40. package/lib/container.js.map +1 -1
  41. package/lib/containerContext.d.ts +5 -7
  42. package/lib/containerContext.d.ts.map +1 -1
  43. package/lib/containerContext.js +6 -4
  44. package/lib/containerContext.js.map +1 -1
  45. package/lib/contracts.d.ts +8 -1
  46. package/lib/contracts.d.ts.map +1 -1
  47. package/lib/contracts.js +19 -0
  48. package/lib/contracts.js.map +1 -1
  49. package/lib/deltaManager.d.ts +2 -1
  50. package/lib/deltaManager.d.ts.map +1 -1
  51. package/lib/deltaManager.js +1 -1
  52. package/lib/deltaManager.js.map +1 -1
  53. package/lib/loader.d.ts +4 -4
  54. package/lib/loader.d.ts.map +1 -1
  55. package/lib/loader.js.map +1 -1
  56. package/lib/packageVersion.d.ts +1 -1
  57. package/lib/packageVersion.d.ts.map +1 -1
  58. package/lib/packageVersion.js +1 -1
  59. package/lib/packageVersion.js.map +1 -1
  60. package/lib/retriableDocumentStorageService.js +1 -1
  61. package/lib/retriableDocumentStorageService.js.map +1 -1
  62. package/lib/utils.d.ts.map +1 -1
  63. package/lib/utils.js +0 -1
  64. package/lib/utils.js.map +1 -1
  65. package/package.json +25 -13
  66. package/src/connectionManager.ts +16 -12
  67. package/src/container.ts +98 -39
  68. package/src/containerContext.ts +11 -13
  69. package/src/contracts.ts +20 -0
  70. package/src/deltaManager.ts +3 -2
  71. package/src/loader.ts +5 -6
  72. package/src/packageVersion.ts +1 -1
  73. package/src/retriableDocumentStorageService.ts +1 -1
  74. package/src/utils.ts +0 -1
package/lib/container.js CHANGED
@@ -6,8 +6,7 @@
6
6
  import merge from "lodash/merge";
7
7
  import { v4 as uuid } from "uuid";
8
8
  import { assert, performance, unreachableCase } from "@fluidframework/common-utils";
9
- import { isFluidCodeDetails, } from "@fluidframework/core-interfaces";
10
- import { AttachState, } from "@fluidframework/container-definitions";
9
+ import { AttachState, isFluidCodeDetails, } from "@fluidframework/container-definitions";
11
10
  import { DataCorruptionError, extractSafePropertiesFromMessage, GenericError, UsageError, } from "@fluidframework/container-utils";
12
11
  import { readAndParse, OnlineStatus, isOnline, ensureFluidResolvedUrl, combineAppAndProtocolSummary, runWithRetry, isFluidResolvedUrl, } from "@fluidframework/driver-utils";
13
12
  import { isSystemMessage, ProtocolOpHandler, } from "@fluidframework/protocol-base";
@@ -15,7 +14,7 @@ import { MessageType, SummaryType, } from "@fluidframework/protocol-definitions"
15
14
  import { ChildLogger, EventEmitterWithErrorHandling, PerformanceEvent, raiseConnectedEvent, TelemetryLogger, connectedEventName, disconnectedEventName, normalizeError, loggerToMonitoringContext, } from "@fluidframework/telemetry-utils";
16
15
  import { Audience } from "./audience";
17
16
  import { ContainerContext } from "./containerContext";
18
- import { ReconnectMode } from "./contracts";
17
+ import { ReconnectMode, getPackageName } from "./contracts";
19
18
  import { DeltaManager } from "./deltaManager";
20
19
  import { DeltaManagerProxy } from "./deltaManagerProxy";
21
20
  import { RelativeLoader } from "./loader";
@@ -102,6 +101,7 @@ export async function waitContainerToCatchUp(container) {
102
101
  const getCodeProposal =
103
102
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
104
103
  (quorum) => { var _a; return (_a = quorum.get("code")) !== null && _a !== void 0 ? _a : quorum.get("code2"); };
104
+ const summarizerClientType = "summarizer";
105
105
  export class Container extends EventEmitterWithErrorHandling {
106
106
  constructor(loader, config) {
107
107
  var _a, _b, _c;
@@ -119,7 +119,6 @@ export class Container extends EventEmitterWithErrorHandling {
119
119
  this._attachState = AttachState.Detached;
120
120
  this.resumedOpProcessingAfterLoad = false;
121
121
  this.firstConnection = true;
122
- this.manualReconnectInProgress = false;
123
122
  this.connectionTransitionTimes = [];
124
123
  this.messageCountAfterDisconnection = 0;
125
124
  this.attachStarted = false;
@@ -346,7 +345,7 @@ export class Container extends EventEmitterWithErrorHandling {
346
345
  }
347
346
  get context() {
348
347
  if (this._context === undefined) {
349
- throw new Error("Attempted to access context before it was defined");
348
+ throw new GenericError("Attempted to access context before it was defined");
350
349
  }
351
350
  return this._context;
352
351
  }
@@ -367,6 +366,9 @@ export class Container extends EventEmitterWithErrorHandling {
367
366
  get readOnlyInfo() {
368
367
  return this._deltaManager.readOnlyInfo;
369
368
  }
369
+ get closeSignal() {
370
+ return this._deltaManager.closeAbortController.signal;
371
+ }
370
372
  /**
371
373
  * Tracks host requiring read-only mode.
372
374
  */
@@ -541,7 +543,10 @@ export class Container extends EventEmitterWithErrorHandling {
541
543
  const createNewResolvedUrl = await this.urlResolver.resolve(request);
542
544
  ensureFluidResolvedUrl(createNewResolvedUrl);
543
545
  if (this.service === undefined) {
544
- this.service = await runWithRetry(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger), "containerAttach", this.mc.logger, {});
546
+ assert(this.client.details.type !== summarizerClientType, 0x2c4 /* "client should not be summarizer before container is created" */);
547
+ this.service = await runWithRetry(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger, false), "containerAttach", this.mc.logger, {
548
+ cancel: this.closeSignal,
549
+ });
545
550
  }
546
551
  const resolvedUrl = this.service.resolvedUrl;
547
552
  ensureFluidResolvedUrl(resolvedUrl);
@@ -597,11 +602,28 @@ export class Container extends EventEmitterWithErrorHandling {
597
602
  async request(path) {
598
603
  return PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Request" }, async () => this.context.request(path), { end: true, cancel: "error" });
599
604
  }
605
+ /**
606
+ * Dictates whether or not the current container will automatically attempt to reconnect to the delta stream
607
+ * after receiving a disconnect event
608
+ * @param reconnect - Boolean indicating if reconnect should automatically occur
609
+ * @deprecated - 0.58, This API will be removed in 1.0
610
+ * Use `connect()` and `disconnect()` instead of `setAutoReconnect(true)` and `setAutoReconnect(false)` respectively
611
+ * See https://github.com/microsoft/FluidFramework/issues/9167 for context
612
+ */
600
613
  setAutoReconnect(reconnect) {
601
614
  if (this.closed) {
602
615
  throw new Error("Attempting to setAutoReconnect() a closed Container");
603
616
  }
604
617
  const mode = reconnect ? ReconnectMode.Enabled : ReconnectMode.Disabled;
618
+ this.setAutoReconnectInternal(mode);
619
+ // If container state is not attached and resumed, then don't connect to delta stream. Also don't set the
620
+ // manual reconnection flag to true as we haven't made the initial connection yet.
621
+ if (reconnect && this._attachState === AttachState.Attached && this.resumedOpProcessingAfterLoad) {
622
+ // Ensure connection to web socket
623
+ this.connectToDeltaStream({ reason: "autoReconnect" });
624
+ }
625
+ }
626
+ setAutoReconnectInternal(mode) {
605
627
  const currentMode = this._deltaManager.connectionManager.reconnectMode;
606
628
  if (currentMode === mode) {
607
629
  return;
@@ -610,23 +632,56 @@ export class Container extends EventEmitterWithErrorHandling {
610
632
  const duration = now - this.setAutoReconnectTime;
611
633
  this.setAutoReconnectTime = now;
612
634
  this.mc.logger.sendTelemetryEvent({
613
- eventName: reconnect ? "AutoReconnectEnabled" : "AutoReconnectDisabled",
635
+ eventName: mode === ReconnectMode.Enabled ? "AutoReconnectEnabled" : "AutoReconnectDisabled",
614
636
  connectionMode: this.connectionMode,
615
637
  connectionState: ConnectionState[this.connectionState],
616
638
  duration,
617
639
  });
618
640
  this._deltaManager.connectionManager.setAutoReconnect(mode);
619
- // If container state is not attached and resumed, then don't connect to delta stream. Also don't set the
620
- // manual reconnection flag to true as we haven't made the initial connection yet.
621
- if (reconnect && this._attachState === AttachState.Attached && this.resumedOpProcessingAfterLoad) {
622
- if (this.connectionState === ConnectionState.Disconnected) {
623
- // Only track this as a manual reconnection if we are truly the ones kicking it off.
624
- this.manualReconnectInProgress = true;
625
- }
626
- // Ensure connection to web socket
627
- this.connectToDeltaStream({ reason: "autoReconnect" });
641
+ }
642
+ connect() {
643
+ if (this.closed) {
644
+ throw new UsageError(`The Container is closed and cannot be connected`);
645
+ }
646
+ else if (this._attachState !== AttachState.Attached) {
647
+ throw new UsageError(`The Container is not attached and cannot be connected`);
648
+ }
649
+ else if (!this.connected) {
650
+ // Note: no need to fetch ops as we do it preemptively as part of DeltaManager.attachOpHandler().
651
+ // If there is gap, we will learn about it once connected, but the gap should be small (if any),
652
+ // assuming that connect() is called quickly after initial container boot.
653
+ this.connectInternal({ reason: "DocumentConnect", fetchOpsFromStorage: false });
654
+ }
655
+ }
656
+ connectInternal(args) {
657
+ assert(!this.closed, 0x2c5 /* "Attempting to connect() a closed Container" */);
658
+ assert(this._attachState === AttachState.Attached, 0x2c6 /* "Attempting to connect() a container that is not attached" */);
659
+ // Resume processing ops and connect to delta stream
660
+ this.resumeInternal(args);
661
+ // Set Auto Reconnect Mode
662
+ const mode = ReconnectMode.Enabled;
663
+ this.setAutoReconnectInternal(mode);
664
+ }
665
+ disconnect() {
666
+ if (this.closed) {
667
+ throw new UsageError(`The Container is closed and cannot be disconnected`);
668
+ }
669
+ else {
670
+ this.disconnectInternal();
628
671
  }
629
672
  }
673
+ disconnectInternal() {
674
+ assert(!this.closed, 0x2c7 /* "Attempting to disconnect() a closed Container" */);
675
+ // Set Auto Reconnect Mode
676
+ const mode = ReconnectMode.Disabled;
677
+ this.setAutoReconnectInternal(mode);
678
+ }
679
+ /**
680
+ * Have the container attempt to resume processing ops
681
+ * @deprecated - 0.58, This API will be removed in 1.0
682
+ * Use `connect()` instead
683
+ * See https://github.com/microsoft/FluidFramework/issues/9167 for context
684
+ */
630
685
  resume() {
631
686
  if (!this.closed) {
632
687
  // Note: no need to fetch ops as we do it preemptively as part of DeltaManager.attachOpHandler().
@@ -646,26 +701,12 @@ export class Container extends EventEmitterWithErrorHandling {
646
701
  // Ensure connection to web socket
647
702
  this.connectToDeltaStream(args);
648
703
  }
649
- /**
650
- * @deprecated 0.56, will be removed in next release from IContainerContext
651
- * Raise non-critical error to host. Calling this API will not close container.
652
- * For critical errors, please call Container.close(error).
653
- * @param error - an error to raise
654
- */
655
- raiseContainerWarning(warning) {
656
- // Some "warning" events come from outside the container and are logged
657
- // elsewhere (e.g. summarizing container). We shouldn't log these here.
658
- if (warning.logged !== true) {
659
- this.logContainerError(warning);
660
- }
661
- this.emit("warning", warning);
662
- }
663
704
  async getAbsoluteUrl(relativeUrl) {
664
705
  var _a;
665
706
  if (this.resolvedUrl === undefined) {
666
707
  return undefined;
667
708
  }
668
- return this.urlResolver.getAbsoluteUrl(this.resolvedUrl, relativeUrl, (_a = this._context) === null || _a === void 0 ? void 0 : _a.codeDetails);
709
+ return this.urlResolver.getAbsoluteUrl(this.resolvedUrl, relativeUrl, getPackageName((_a = this._context) === null || _a === void 0 ? void 0 : _a.codeDetails));
669
710
  }
670
711
  async proposeCodeDetails(codeDetails) {
671
712
  if (!isFluidCodeDetails(codeDetails)) {
@@ -723,7 +764,7 @@ export class Container extends EventEmitterWithErrorHandling {
723
764
  if (this._resolvedUrl === undefined) {
724
765
  throw new Error("Attempting to load without a resolved url");
725
766
  }
726
- this.service = await this.serviceFactory.createDocumentService(this._resolvedUrl, this.subLogger);
767
+ this.service = await this.serviceFactory.createDocumentService(this._resolvedUrl, this.subLogger, this.client.details.type === summarizerClientType);
727
768
  // Ideally we always connect as "read" by default.
728
769
  // Currently that works with SPO & r11s, because we get "write" connection when connecting to non-existing file.
729
770
  // We should not rely on it by (one of them will address the issue, but we need to address both)
@@ -1023,12 +1064,17 @@ export class Container extends EventEmitterWithErrorHandling {
1023
1064
  this.connectionStateHandler.receivedConnectEvent(this.connectionMode, details);
1024
1065
  });
1025
1066
  deltaManager.on("disconnect", (reason) => {
1026
- this.manualReconnectInProgress = false;
1027
1067
  this.collabWindowTracker.stopSequenceNumberUpdate();
1028
1068
  this.connectionStateHandler.receivedDisconnectEvent(reason);
1029
1069
  });
1030
1070
  deltaManager.on("throttled", (warning) => {
1031
- this.raiseContainerWarning(warning);
1071
+ const warn = warning;
1072
+ // Some "warning" events come from outside the container and are logged
1073
+ // elsewhere (e.g. summarizing container). We shouldn't log these here.
1074
+ if (warn.logged !== true) {
1075
+ this.logContainerError(warn);
1076
+ }
1077
+ this.emit("warning", warn);
1032
1078
  });
1033
1079
  deltaManager.on("readonly", (readonly) => {
1034
1080
  this.emit("readonly", readonly);
@@ -1075,9 +1121,6 @@ export class Container extends EventEmitterWithErrorHandling {
1075
1121
  if (this.firstConnection) {
1076
1122
  connectionInitiationReason = "InitialConnect";
1077
1123
  }
1078
- else if (this.manualReconnectInProgress) {
1079
- connectionInitiationReason = "ManualReconnect";
1080
- }
1081
1124
  else {
1082
1125
  connectionInitiationReason = "AutoReconnect";
1083
1126
  }
@@ -1089,7 +1132,6 @@ export class Container extends EventEmitterWithErrorHandling {
1089
1132
  opsBehind, online: OnlineStatus[isOnline()], lastVisible: this.lastVisible !== undefined ? performance.now() - this.lastVisible : undefined, checkpointSequenceNumber }, this._deltaManager.connectionProps));
1090
1133
  if (value === ConnectionState.Connected) {
1091
1134
  this.firstConnection = false;
1092
- this.manualReconnectInProgress = false;
1093
1135
  }
1094
1136
  }
1095
1137
  propagateConnectionState() {
@@ -1227,7 +1269,7 @@ export class Container extends EventEmitterWithErrorHandling {
1227
1269
  // The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
1228
1270
  // are set. Global requests will still go directly to the loader
1229
1271
  const loader = new RelativeLoader(this, this.loader);
1230
- this._context = await ContainerContext.createOrLoad(this, this.scope, this.codeLoader, codeDetails, snapshot, new DeltaManagerProxy(this._deltaManager), new 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);
1272
+ 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), (message) => this.submitSignal(message), (error) => this.close(error), Container.version, (dirty) => this.updateDirtyContainerState(dirty), existing, pendingLocalState);
1231
1273
  this.emit("contextChanged", codeDetails);
1232
1274
  }
1233
1275
  updateDirtyContainerState(dirty) {