@fluidframework/container-loader 2.0.0-dev.1.4.6.106135 → 2.0.0-dev.2.2.0.111723

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 (84) hide show
  1. package/.eslintrc.js +21 -8
  2. package/README.md +21 -11
  3. package/dist/audience.d.ts +0 -4
  4. package/dist/audience.d.ts.map +1 -1
  5. package/dist/audience.js +6 -11
  6. package/dist/audience.js.map +1 -1
  7. package/dist/connectionManager.d.ts.map +1 -1
  8. package/dist/connectionManager.js +46 -7
  9. package/dist/connectionManager.js.map +1 -1
  10. package/dist/connectionStateHandler.d.ts +20 -11
  11. package/dist/connectionStateHandler.d.ts.map +1 -1
  12. package/dist/connectionStateHandler.js +65 -36
  13. package/dist/connectionStateHandler.js.map +1 -1
  14. package/dist/container.d.ts +0 -2
  15. package/dist/container.d.ts.map +1 -1
  16. package/dist/container.js +29 -34
  17. package/dist/container.js.map +1 -1
  18. package/dist/containerContext.d.ts +1 -1
  19. package/dist/containerContext.d.ts.map +1 -1
  20. package/dist/containerContext.js +2 -2
  21. package/dist/containerContext.js.map +1 -1
  22. package/dist/containerStorageAdapter.js +1 -1
  23. package/dist/containerStorageAdapter.js.map +1 -1
  24. package/dist/deltaManager.d.ts +1 -3
  25. package/dist/deltaManager.d.ts.map +1 -1
  26. package/dist/deltaManager.js +38 -14
  27. package/dist/deltaManager.js.map +1 -1
  28. package/dist/packageVersion.d.ts +1 -1
  29. package/dist/packageVersion.js +1 -1
  30. package/dist/packageVersion.js.map +1 -1
  31. package/dist/protocol.d.ts +8 -3
  32. package/dist/protocol.d.ts.map +1 -1
  33. package/dist/protocol.js +34 -8
  34. package/dist/protocol.js.map +1 -1
  35. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  36. package/dist/retriableDocumentStorageService.js +7 -3
  37. package/dist/retriableDocumentStorageService.js.map +1 -1
  38. package/lib/audience.d.ts +0 -4
  39. package/lib/audience.d.ts.map +1 -1
  40. package/lib/audience.js +6 -11
  41. package/lib/audience.js.map +1 -1
  42. package/lib/connectionManager.d.ts.map +1 -1
  43. package/lib/connectionManager.js +46 -7
  44. package/lib/connectionManager.js.map +1 -1
  45. package/lib/connectionStateHandler.d.ts +20 -11
  46. package/lib/connectionStateHandler.d.ts.map +1 -1
  47. package/lib/connectionStateHandler.js +65 -36
  48. package/lib/connectionStateHandler.js.map +1 -1
  49. package/lib/container.d.ts +0 -2
  50. package/lib/container.d.ts.map +1 -1
  51. package/lib/container.js +29 -34
  52. package/lib/container.js.map +1 -1
  53. package/lib/containerContext.d.ts +1 -1
  54. package/lib/containerContext.d.ts.map +1 -1
  55. package/lib/containerContext.js +2 -2
  56. package/lib/containerContext.js.map +1 -1
  57. package/lib/containerStorageAdapter.js +1 -1
  58. package/lib/containerStorageAdapter.js.map +1 -1
  59. package/lib/deltaManager.d.ts +1 -3
  60. package/lib/deltaManager.d.ts.map +1 -1
  61. package/lib/deltaManager.js +41 -17
  62. package/lib/deltaManager.js.map +1 -1
  63. package/lib/packageVersion.d.ts +1 -1
  64. package/lib/packageVersion.js +1 -1
  65. package/lib/packageVersion.js.map +1 -1
  66. package/lib/protocol.d.ts +8 -3
  67. package/lib/protocol.d.ts.map +1 -1
  68. package/lib/protocol.js +33 -7
  69. package/lib/protocol.js.map +1 -1
  70. package/lib/retriableDocumentStorageService.d.ts.map +1 -1
  71. package/lib/retriableDocumentStorageService.js +7 -3
  72. package/lib/retriableDocumentStorageService.js.map +1 -1
  73. package/package.json +27 -29
  74. package/prettier.config.cjs +8 -0
  75. package/src/audience.ts +6 -12
  76. package/src/connectionManager.ts +52 -10
  77. package/src/connectionStateHandler.ts +87 -39
  78. package/src/container.ts +34 -36
  79. package/src/containerContext.ts +2 -2
  80. package/src/containerStorageAdapter.ts +1 -1
  81. package/src/deltaManager.ts +59 -37
  82. package/src/packageVersion.ts +1 -1
  83. package/src/protocol.ts +31 -8
  84. package/src/retriableDocumentStorageService.ts +7 -3
package/dist/container.js CHANGED
@@ -191,7 +191,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
191
191
  });
192
192
  // Prefix all events in this file with container-loader
193
193
  this.mc = (0, telemetry_utils_1.loggerToMonitoringContext)(telemetry_utils_1.ChildLogger.create(this.subLogger, "Container"));
194
- const summarizeProtocolTree = (_a = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree")) !== null && _a !== void 0 ? _a : this.loader.services.options.summarizeProtocolTree;
194
+ const summarizeProtocolTree = (_a = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree2")) !== null && _a !== void 0 ? _a : this.loader.services.options.summarizeProtocolTree;
195
195
  this.options = Object.assign(Object.assign({}, this.loader.services.options), { summarizeProtocolTree });
196
196
  this._deltaManager = this.createDeltaManager();
197
197
  this._clientId = (_b = config.serializedContainerState) === null || _b === void 0 ? void 0 : _b.clientId;
@@ -203,15 +203,29 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
203
203
  }
204
204
  this.logConnectionStateChangeTelemetry(value, oldState, reason);
205
205
  if (this._lifecycleState === "loaded") {
206
- this.propagateConnectionState(false /* initial transition */);
206
+ this.propagateConnectionState(false /* initial transition */, value === connectionState_1.ConnectionState.Disconnected ? reason : undefined /* disconnectedReason */);
207
207
  }
208
208
  },
209
209
  shouldClientJoinWrite: () => this._deltaManager.connectionManager.shouldJoinWrite(),
210
210
  maxClientLeaveWaitTime: this.loader.services.options.maxClientLeaveWaitTime,
211
211
  logConnectionIssue: (eventName, details) => {
212
+ const mode = this.connectionMode;
212
213
  // We get here when socket does not receive any ops on "write" connection, including
213
214
  // its own join op. Attempt recovery option.
214
- this._deltaManager.logConnectionIssue(Object.assign({ eventName, duration: common_utils_1.performance.now() - this.connectionTransitionTimes[connectionState_1.ConnectionState.CatchingUp] }, (details === undefined ? {} : { details: JSON.stringify(details) })));
215
+ this._deltaManager.logConnectionIssue(Object.assign({ eventName,
216
+ mode, duration: common_utils_1.performance.now() - this.connectionTransitionTimes[connectionState_1.ConnectionState.CatchingUp] }, (details === undefined ? {} : { details: JSON.stringify(details) })));
217
+ // If this is "write" connection, it took too long to receive join op. But in most cases that's due
218
+ // to very slow op fetches and we will eventually get there.
219
+ // For "read" connections, we get here due to self join signal not arriving on time. We will need to
220
+ // better understand when and why it may happen.
221
+ // For now, attempt to recover by reconnecting. In future, maybe we can query relay service for
222
+ // current state of audience.
223
+ // Other possible recovery path - move to connected state (i.e. ConnectionStateHandler.joinOpTimer
224
+ // to call this.applyForConnectedState("addMemberEvent") for "read" connections)
225
+ if (mode === "read") {
226
+ this.disconnect();
227
+ this.connect();
228
+ }
215
229
  },
216
230
  }, this.deltaManager, this._clientId);
217
231
  this.on(savedContainerEvent, () => {
@@ -931,10 +945,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
931
945
  this.initializeProtocolState(attributes, quorumSnapshot);
932
946
  }
933
947
  initializeProtocolState(attributes, quorumSnapshot) {
934
- var _a, _b;
948
+ var _a;
935
949
  const protocolHandlerBuilder = (_a = this.protocolHandlerBuilder) !== null && _a !== void 0 ? _a : ((...args) => new protocol_1.ProtocolHandler(...args, new audience_1.Audience()));
936
- const protocol = protocolHandlerBuilder(attributes, quorumSnapshot, (key, value) => this.submitMessage(protocol_definitions_1.MessageType.Propose, JSON.stringify({ key, value })), (_b = this._initialClients) !== null && _b !== void 0 ? _b : []);
937
- this._initialClients = undefined;
950
+ const protocol = protocolHandlerBuilder(attributes, quorumSnapshot, (key, value) => this.submitMessage(protocol_definitions_1.MessageType.Propose, JSON.stringify({ key, value })));
938
951
  const protocolLogger = telemetry_utils_1.ChildLogger.create(this.subLogger, "ProtocolHandler");
939
952
  protocol.quorum.on("error", (error) => {
940
953
  protocolLogger.sendErrorEvent(error);
@@ -1033,21 +1046,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1033
1046
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
1034
1047
  deltaManager.inboundSignal.pause();
1035
1048
  deltaManager.on("connect", (details, _opsBehind) => {
1036
- var _a;
1037
- if (this._protocolHandler === undefined) {
1038
- // Store the initial clients so that they can be submitted to the
1039
- // protocol handler when it is created.
1040
- this._initialClients = details.initialClients;
1041
- }
1042
- else {
1043
- // When reconnecting, the protocol handler is already created,
1044
- // so we can update the audience right now.
1045
- this._protocolHandler.audience.clear();
1046
- for (const priorClient of (_a = details.initialClients) !== null && _a !== void 0 ? _a : []) {
1047
- this._protocolHandler.audience.addMember(priorClient.clientId, priorClient.client);
1048
- }
1049
- }
1050
- this.connectionStateHandler.receivedConnectEvent(this.connectionMode, details);
1049
+ (0, common_utils_1.assert)(this.connectionMode === details.mode, "mismatch");
1050
+ this.connectionStateHandler.receivedConnectEvent(details);
1051
1051
  });
1052
1052
  deltaManager.on("disconnect", (reason) => {
1053
1053
  var _a;
@@ -1059,7 +1059,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1059
1059
  // Some "warning" events come from outside the container and are logged
1060
1060
  // elsewhere (e.g. summarizing container). We shouldn't log these here.
1061
1061
  if (warn.logged !== true) {
1062
- this.logContainerError(warn);
1062
+ this.mc.logger.sendTelemetryEvent({ eventName: "ContainerWarning" }, warn);
1063
1063
  }
1064
1064
  this.emit("warning", warn);
1065
1065
  });
@@ -1118,7 +1118,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1118
1118
  this.firstConnection = false;
1119
1119
  }
1120
1120
  }
1121
- propagateConnectionState(initialTransition) {
1121
+ propagateConnectionState(initialTransition, disconnectedReason) {
1122
1122
  var _a;
1123
1123
  // When container loaded, we want to propagate initial connection state.
1124
1124
  // After that, we communicate only transitions to Connected & Disconnected states, skipping all other states.
@@ -1138,7 +1138,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1138
1138
  // Both protocol and context should not be undefined if we got so far.
1139
1139
  this.setContextConnectedState(state, (_a = this._deltaManager.connectionManager.readOnlyInfo.readonly) !== null && _a !== void 0 ? _a : false);
1140
1140
  this.protocolHandler.setConnectionState(state, this.clientId);
1141
- (0, telemetry_utils_1.raiseConnectedEvent)(this.mc.logger, this, state, this.clientId);
1141
+ (0, telemetry_utils_1.raiseConnectedEvent)(this.mc.logger, this, state, this.clientId, disconnectedReason);
1142
1142
  if (logOpsOnReconnect) {
1143
1143
  this.mc.logger.sendTelemetryEvent({ eventName: "OpsSentOnReconnect", count: this.messageCountAfterDisconnection });
1144
1144
  }
@@ -1160,7 +1160,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1160
1160
  let clientSequenceNumber = -1;
1161
1161
  for (const message of batch) {
1162
1162
  clientSequenceNumber = this.submitMessage(protocol_definitions_1.MessageType.Operation, message.contents, true, // batch
1163
- message.metadata);
1163
+ message.metadata, message.compression);
1164
1164
  }
1165
1165
  this._deltaManager.flush();
1166
1166
  return clientSequenceNumber;
@@ -1177,7 +1177,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1177
1177
  this.options.summarizeProtocolTree === true;
1178
1178
  return this.submitMessage(protocol_definitions_1.MessageType.Summarize, JSON.stringify(summary), false /* batch */);
1179
1179
  }
1180
- submitMessage(type, contents, batch, metadata) {
1180
+ submitMessage(type, contents, batch, metadata, compression) {
1181
1181
  var _a;
1182
1182
  if (this.connectionState !== connectionState_1.ConnectionState.Connected) {
1183
1183
  this.mc.logger.sendErrorEvent({ eventName: "SubmitMessageWithNoConnection", type });
@@ -1185,14 +1185,14 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1185
1185
  }
1186
1186
  this.messageCountAfterDisconnection += 1;
1187
1187
  (_a = this.collabWindowTracker) === null || _a === void 0 ? void 0 : _a.stopSequenceNumberUpdate();
1188
- return this._deltaManager.submit(type, contents, batch, metadata);
1188
+ return this._deltaManager.submit(type, contents, batch, metadata, compression);
1189
1189
  }
1190
1190
  processRemoteMessage(message) {
1191
1191
  const local = this.clientId === message.clientId;
1192
1192
  // Allow the protocol handler to process the message
1193
1193
  const result = this.protocolHandler.processMessage(message, local);
1194
1194
  // Forward messages to the loaded runtime for processing
1195
- this.context.process(message, local, undefined);
1195
+ this.context.process(message, local);
1196
1196
  // Inactive (not in quorum or not writers) clients don't take part in the minimum sequence number calculation.
1197
1197
  if (this.activeConnection()) {
1198
1198
  if (this.collabWindowTracker === undefined) {
@@ -1203,9 +1203,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1203
1203
  (0, common_utils_1.assert)(this.serviceConfiguration !== undefined, 0x2e4 /* "there should be service config for active connection" */);
1204
1204
  this.collabWindowTracker = new collabWindowTracker_1.CollabWindowTracker((type) => {
1205
1205
  (0, common_utils_1.assert)(this.activeConnection(), 0x241 /* "disconnect should result in stopSequenceNumberUpdate() call" */);
1206
- // back-compat: There is a bug in 1.2 runtime where clients cannot handle
1207
- // ops whose contents are undefined
1208
- this.submitMessage(type, null);
1206
+ this.submitMessage(type);
1209
1207
  }, this.serviceConfiguration.noopTimeFrequency, this.serviceConfiguration.noopCountFrequency);
1210
1208
  }
1211
1209
  this.collabWindowTracker.scheduleSequenceNumberUpdate(message, result.immediateNoOp === true);
@@ -1267,9 +1265,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1267
1265
  this._dirtyContainer = dirty;
1268
1266
  this.emit(dirty ? dirtyContainerEvent : savedContainerEvent);
1269
1267
  }
1270
- logContainerError(warning) {
1271
- this.mc.logger.sendErrorEvent({ eventName: "ContainerWarning" }, warning);
1272
- }
1273
1268
  /**
1274
1269
  * Set the connected state of the ContainerContext
1275
1270
  * This controls the "connected" state of the ContainerRuntime as well