@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/lib/container.js CHANGED
@@ -111,10 +111,10 @@ const getCodeProposal =
111
111
  * @param eventName - event name
112
112
  * @param action - functor to call and measure
113
113
  */
114
- async function ReportIfTooLong(logger, eventName, action) {
114
+ export async function ReportIfTooLong(logger, eventName, action) {
115
115
  const event = PerformanceEvent.start(logger, { eventName });
116
116
  const props = await action();
117
- if (event.duration > 1000) {
117
+ if (event.duration > 200) {
118
118
  event.end(props);
119
119
  }
120
120
  }
@@ -184,7 +184,7 @@ export class Container extends EventEmitterWithErrorHandling {
184
184
  });
185
185
  // Prefix all events in this file with container-loader
186
186
  this.mc = loggerToMonitoringContext(ChildLogger.create(this.subLogger, "Container"));
187
- const summarizeProtocolTree = (_a = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree")) !== null && _a !== void 0 ? _a : this.loader.services.options.summarizeProtocolTree;
187
+ const summarizeProtocolTree = (_a = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree2")) !== null && _a !== void 0 ? _a : this.loader.services.options.summarizeProtocolTree;
188
188
  this.options = Object.assign(Object.assign({}, this.loader.services.options), { summarizeProtocolTree });
189
189
  this._deltaManager = this.createDeltaManager();
190
190
  this._clientId = (_b = config.serializedContainerState) === null || _b === void 0 ? void 0 : _b.clientId;
@@ -196,15 +196,29 @@ export class Container extends EventEmitterWithErrorHandling {
196
196
  }
197
197
  this.logConnectionStateChangeTelemetry(value, oldState, reason);
198
198
  if (this._lifecycleState === "loaded") {
199
- this.propagateConnectionState(false /* initial transition */);
199
+ this.propagateConnectionState(false /* initial transition */, value === ConnectionState.Disconnected ? reason : undefined /* disconnectedReason */);
200
200
  }
201
201
  },
202
202
  shouldClientJoinWrite: () => this._deltaManager.connectionManager.shouldJoinWrite(),
203
203
  maxClientLeaveWaitTime: this.loader.services.options.maxClientLeaveWaitTime,
204
204
  logConnectionIssue: (eventName, details) => {
205
+ const mode = this.connectionMode;
205
206
  // We get here when socket does not receive any ops on "write" connection, including
206
207
  // its own join op. Attempt recovery option.
207
- this._deltaManager.logConnectionIssue(Object.assign({ eventName, duration: performance.now() - this.connectionTransitionTimes[ConnectionState.CatchingUp] }, (details === undefined ? {} : { details: JSON.stringify(details) })));
208
+ this._deltaManager.logConnectionIssue(Object.assign({ eventName,
209
+ mode, duration: performance.now() - this.connectionTransitionTimes[ConnectionState.CatchingUp] }, (details === undefined ? {} : { details: JSON.stringify(details) })));
210
+ // If this is "write" connection, it took too long to receive join op. But in most cases that's due
211
+ // to very slow op fetches and we will eventually get there.
212
+ // For "read" connections, we get here due to self join signal not arriving on time. We will need to
213
+ // better understand when and why it may happen.
214
+ // For now, attempt to recover by reconnecting. In future, maybe we can query relay service for
215
+ // current state of audience.
216
+ // Other possible recovery path - move to connected state (i.e. ConnectionStateHandler.joinOpTimer
217
+ // to call this.applyForConnectedState("addMemberEvent") for "read" connections)
218
+ if (mode === "read") {
219
+ this.disconnect();
220
+ this.connect();
221
+ }
208
222
  },
209
223
  }, this.deltaManager, this._clientId);
210
224
  this.on(savedContainerEvent, () => {
@@ -924,10 +938,9 @@ export class Container extends EventEmitterWithErrorHandling {
924
938
  this.initializeProtocolState(attributes, quorumSnapshot);
925
939
  }
926
940
  initializeProtocolState(attributes, quorumSnapshot) {
927
- var _a, _b;
941
+ var _a;
928
942
  const protocolHandlerBuilder = (_a = this.protocolHandlerBuilder) !== null && _a !== void 0 ? _a : ((...args) => new ProtocolHandler(...args, new Audience()));
929
- const protocol = protocolHandlerBuilder(attributes, quorumSnapshot, (key, value) => this.submitMessage(MessageType.Propose, JSON.stringify({ key, value })), (_b = this._initialClients) !== null && _b !== void 0 ? _b : []);
930
- this._initialClients = undefined;
943
+ const protocol = protocolHandlerBuilder(attributes, quorumSnapshot, (key, value) => this.submitMessage(MessageType.Propose, JSON.stringify({ key, value })));
931
944
  const protocolLogger = ChildLogger.create(this.subLogger, "ProtocolHandler");
932
945
  protocol.quorum.on("error", (error) => {
933
946
  protocolLogger.sendErrorEvent(error);
@@ -1026,21 +1039,8 @@ export class Container extends EventEmitterWithErrorHandling {
1026
1039
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
1027
1040
  deltaManager.inboundSignal.pause();
1028
1041
  deltaManager.on("connect", (details, _opsBehind) => {
1029
- var _a;
1030
- if (this._protocolHandler === undefined) {
1031
- // Store the initial clients so that they can be submitted to the
1032
- // protocol handler when it is created.
1033
- this._initialClients = details.initialClients;
1034
- }
1035
- else {
1036
- // When reconnecting, the protocol handler is already created,
1037
- // so we can update the audience right now.
1038
- this._protocolHandler.audience.clear();
1039
- for (const priorClient of (_a = details.initialClients) !== null && _a !== void 0 ? _a : []) {
1040
- this._protocolHandler.audience.addMember(priorClient.clientId, priorClient.client);
1041
- }
1042
- }
1043
- this.connectionStateHandler.receivedConnectEvent(this.connectionMode, details);
1042
+ assert(this.connectionMode === details.mode, 0x4b7 /* mismatch */);
1043
+ this.connectionStateHandler.receivedConnectEvent(details);
1044
1044
  });
1045
1045
  deltaManager.on("disconnect", (reason) => {
1046
1046
  var _a;
@@ -1052,7 +1052,7 @@ export class Container extends EventEmitterWithErrorHandling {
1052
1052
  // Some "warning" events come from outside the container and are logged
1053
1053
  // elsewhere (e.g. summarizing container). We shouldn't log these here.
1054
1054
  if (warn.logged !== true) {
1055
- this.logContainerError(warn);
1055
+ this.mc.logger.sendTelemetryEvent({ eventName: "ContainerWarning" }, warn);
1056
1056
  }
1057
1057
  this.emit("warning", warn);
1058
1058
  });
@@ -1111,7 +1111,7 @@ export class Container extends EventEmitterWithErrorHandling {
1111
1111
  this.firstConnection = false;
1112
1112
  }
1113
1113
  }
1114
- propagateConnectionState(initialTransition) {
1114
+ propagateConnectionState(initialTransition, disconnectedReason) {
1115
1115
  var _a;
1116
1116
  // When container loaded, we want to propagate initial connection state.
1117
1117
  // After that, we communicate only transitions to Connected & Disconnected states, skipping all other states.
@@ -1131,7 +1131,7 @@ export class Container extends EventEmitterWithErrorHandling {
1131
1131
  // Both protocol and context should not be undefined if we got so far.
1132
1132
  this.setContextConnectedState(state, (_a = this._deltaManager.connectionManager.readOnlyInfo.readonly) !== null && _a !== void 0 ? _a : false);
1133
1133
  this.protocolHandler.setConnectionState(state, this.clientId);
1134
- raiseConnectedEvent(this.mc.logger, this, state, this.clientId);
1134
+ raiseConnectedEvent(this.mc.logger, this, state, this.clientId, disconnectedReason);
1135
1135
  if (logOpsOnReconnect) {
1136
1136
  this.mc.logger.sendTelemetryEvent({ eventName: "OpsSentOnReconnect", count: this.messageCountAfterDisconnection });
1137
1137
  }
@@ -1153,7 +1153,7 @@ export class Container extends EventEmitterWithErrorHandling {
1153
1153
  let clientSequenceNumber = -1;
1154
1154
  for (const message of batch) {
1155
1155
  clientSequenceNumber = this.submitMessage(MessageType.Operation, message.contents, true, // batch
1156
- message.metadata);
1156
+ message.metadata, message.compression);
1157
1157
  }
1158
1158
  this._deltaManager.flush();
1159
1159
  return clientSequenceNumber;
@@ -1170,7 +1170,7 @@ export class Container extends EventEmitterWithErrorHandling {
1170
1170
  this.options.summarizeProtocolTree === true;
1171
1171
  return this.submitMessage(MessageType.Summarize, JSON.stringify(summary), false /* batch */);
1172
1172
  }
1173
- submitMessage(type, contents, batch, metadata) {
1173
+ submitMessage(type, contents, batch, metadata, compression) {
1174
1174
  var _a;
1175
1175
  if (this.connectionState !== ConnectionState.Connected) {
1176
1176
  this.mc.logger.sendErrorEvent({ eventName: "SubmitMessageWithNoConnection", type });
@@ -1178,14 +1178,14 @@ export class Container extends EventEmitterWithErrorHandling {
1178
1178
  }
1179
1179
  this.messageCountAfterDisconnection += 1;
1180
1180
  (_a = this.collabWindowTracker) === null || _a === void 0 ? void 0 : _a.stopSequenceNumberUpdate();
1181
- return this._deltaManager.submit(type, contents, batch, metadata);
1181
+ return this._deltaManager.submit(type, contents, batch, metadata, compression);
1182
1182
  }
1183
1183
  processRemoteMessage(message) {
1184
1184
  const local = this.clientId === message.clientId;
1185
1185
  // Allow the protocol handler to process the message
1186
1186
  const result = this.protocolHandler.processMessage(message, local);
1187
1187
  // Forward messages to the loaded runtime for processing
1188
- this.context.process(message, local, undefined);
1188
+ this.context.process(message, local);
1189
1189
  // Inactive (not in quorum or not writers) clients don't take part in the minimum sequence number calculation.
1190
1190
  if (this.activeConnection()) {
1191
1191
  if (this.collabWindowTracker === undefined) {
@@ -1196,9 +1196,7 @@ export class Container extends EventEmitterWithErrorHandling {
1196
1196
  assert(this.serviceConfiguration !== undefined, 0x2e4 /* "there should be service config for active connection" */);
1197
1197
  this.collabWindowTracker = new CollabWindowTracker((type) => {
1198
1198
  assert(this.activeConnection(), 0x241 /* "disconnect should result in stopSequenceNumberUpdate() call" */);
1199
- // back-compat: There is a bug in 1.2 runtime where clients cannot handle
1200
- // ops whose contents are undefined
1201
- this.submitMessage(type, null);
1199
+ this.submitMessage(type);
1202
1200
  }, this.serviceConfiguration.noopTimeFrequency, this.serviceConfiguration.noopCountFrequency);
1203
1201
  }
1204
1202
  this.collabWindowTracker.scheduleSequenceNumberUpdate(message, result.immediateNoOp === true);
@@ -1260,9 +1258,6 @@ export class Container extends EventEmitterWithErrorHandling {
1260
1258
  this._dirtyContainer = dirty;
1261
1259
  this.emit(dirty ? dirtyContainerEvent : savedContainerEvent);
1262
1260
  }
1263
- logContainerError(warning) {
1264
- this.mc.logger.sendErrorEvent({ eventName: "ContainerWarning" }, warning);
1265
- }
1266
1261
  /**
1267
1262
  * Set the connected state of the ContainerContext
1268
1263
  * This controls the "connected" state of the ContainerRuntime as well