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

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