@fluidframework/container-loader 2.0.0-internal.6.0.0 → 2.0.0-internal.6.1.0

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 (59) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/connectionManager.d.ts +3 -3
  3. package/dist/connectionManager.d.ts.map +1 -1
  4. package/dist/connectionManager.js +33 -24
  5. package/dist/connectionManager.js.map +1 -1
  6. package/dist/connectionStateHandler.d.ts +14 -14
  7. package/dist/connectionStateHandler.d.ts.map +1 -1
  8. package/dist/connectionStateHandler.js +17 -12
  9. package/dist/connectionStateHandler.js.map +1 -1
  10. package/dist/container.d.ts.map +1 -1
  11. package/dist/container.js +26 -38
  12. package/dist/container.js.map +1 -1
  13. package/dist/contracts.d.ts +11 -7
  14. package/dist/contracts.d.ts.map +1 -1
  15. package/dist/contracts.js.map +1 -1
  16. package/dist/deltaManager.d.ts +4 -4
  17. package/dist/deltaManager.d.ts.map +1 -1
  18. package/dist/deltaManager.js +5 -4
  19. package/dist/deltaManager.js.map +1 -1
  20. package/dist/packageVersion.d.ts +1 -1
  21. package/dist/packageVersion.js +1 -1
  22. package/dist/packageVersion.js.map +1 -1
  23. package/dist/protocol.d.ts +4 -2
  24. package/dist/protocol.d.ts.map +1 -1
  25. package/dist/protocol.js +23 -1
  26. package/dist/protocol.js.map +1 -1
  27. package/lib/connectionManager.d.ts +3 -3
  28. package/lib/connectionManager.d.ts.map +1 -1
  29. package/lib/connectionManager.js +33 -24
  30. package/lib/connectionManager.js.map +1 -1
  31. package/lib/connectionStateHandler.d.ts +14 -14
  32. package/lib/connectionStateHandler.d.ts.map +1 -1
  33. package/lib/connectionStateHandler.js +17 -12
  34. package/lib/connectionStateHandler.js.map +1 -1
  35. package/lib/container.d.ts.map +1 -1
  36. package/lib/container.js +27 -39
  37. package/lib/container.js.map +1 -1
  38. package/lib/contracts.d.ts +11 -7
  39. package/lib/contracts.d.ts.map +1 -1
  40. package/lib/contracts.js.map +1 -1
  41. package/lib/deltaManager.d.ts +4 -4
  42. package/lib/deltaManager.d.ts.map +1 -1
  43. package/lib/deltaManager.js +5 -4
  44. package/lib/deltaManager.js.map +1 -1
  45. package/lib/packageVersion.d.ts +1 -1
  46. package/lib/packageVersion.js +1 -1
  47. package/lib/packageVersion.js.map +1 -1
  48. package/lib/protocol.d.ts +4 -2
  49. package/lib/protocol.d.ts.map +1 -1
  50. package/lib/protocol.js +23 -1
  51. package/lib/protocol.js.map +1 -1
  52. package/package.json +13 -17
  53. package/src/connectionManager.ts +46 -31
  54. package/src/connectionStateHandler.ts +28 -36
  55. package/src/container.ts +46 -51
  56. package/src/contracts.ts +12 -6
  57. package/src/deltaManager.ts +19 -13
  58. package/src/packageVersion.ts +1 -1
  59. package/src/protocol.ts +33 -1
package/dist/container.js CHANGED
@@ -194,7 +194,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
194
194
  this.scope = scope;
195
195
  this.detachedBlobStorage = detachedBlobStorage;
196
196
  this.protocolHandlerBuilder =
197
- protocolHandlerBuilder ?? ((...args) => new protocol_1.ProtocolHandler(...args, new audience_1.Audience()));
197
+ protocolHandlerBuilder ??
198
+ ((attributes, quorumSnapshot, sendProposal) => new protocol_1.ProtocolHandler(attributes, quorumSnapshot, sendProposal, new audience_1.Audience(), (clientId) => this.clientsWhoShouldHaveLeft.has(clientId)));
198
199
  // Note that we capture the createProps here so we can replicate the creation call when we want to clone.
199
200
  this.clone = async (_loadProps, createParamOverrides) => {
200
201
  return Container.load(_loadProps, {
@@ -247,11 +248,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
247
248
  this._deltaManager = this.createDeltaManager();
248
249
  this.connectionStateHandler = (0, connectionStateHandler_1.createConnectionStateHandler)({
249
250
  logger: this.mc.logger,
250
- connectionStateChanged: (value, oldState, reason, error) => {
251
+ connectionStateChanged: (value, oldState, reason) => {
251
252
  if (value === connectionState_1.ConnectionState.Connected) {
252
253
  this._clientId = this.connectionStateHandler.pendingClientId;
253
254
  }
254
- this.logConnectionStateChangeTelemetry(value, oldState, reason, error);
255
+ this.logConnectionStateChangeTelemetry(value, oldState, reason);
255
256
  if (this._lifecycleState === "loaded") {
256
257
  this.propagateConnectionState(false /* initial transition */, value === connectionState_1.ConnectionState.Disconnected
257
258
  ? reason
@@ -284,8 +285,9 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
284
285
  // Other possible recovery path - move to connected state (i.e. ConnectionStateHandler.joinOpTimer
285
286
  // to call this.applyForConnectedState("addMemberEvent") for "read" connections)
286
287
  if (mode === "read") {
287
- this.disconnect();
288
- this.connect();
288
+ const reason = { text: "NoJoinSignal" };
289
+ this.disconnectInternal(reason);
290
+ this.connectInternal({ reason, fetchOpsFromStorage: false });
289
291
  }
290
292
  },
291
293
  clientShouldHaveLeft: (clientId) => {
@@ -620,7 +622,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
620
622
  // runtime matches pending ops to successful ones by clientId and client seq num, so we need to close the
621
623
  // container at the same time we get pending state, otherwise this container could reconnect and resubmit with
622
624
  // a new clientId and a future container using stale pending state without the new clientId would resubmit them
623
- this.disconnect(); // TODO https://dev.azure.com/fluidframework/internal/_workitems/edit/5127
625
+ this.disconnectInternal({ text: "closeAndGetPendingLocalState" }); // TODO https://dev.azure.com/fluidframework/internal/_workitems/edit/5127
624
626
  const pendingState = await this.getPendingLocalStateCore({ notifyImminentClosure: true });
625
627
  this.close();
626
628
  return pendingState;
@@ -754,7 +756,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
754
756
  if (!this.closed) {
755
757
  this.resumeInternal({
756
758
  fetchOpsFromStorage: false,
757
- reason: "createDetached",
759
+ reason: { text: "createDetached" },
758
760
  });
759
761
  }
760
762
  }
@@ -770,7 +772,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
770
772
  async request(path) {
771
773
  return telemetry_utils_1.PerformanceEvent.timedExecAsync(this.mc.logger, { eventName: "Request" }, async () => this.runtime.request(path), { end: true, cancel: "error" });
772
774
  }
773
- setAutoReconnectInternal(mode) {
775
+ setAutoReconnectInternal(mode, reason) {
774
776
  const currentMode = this._deltaManager.connectionManager.reconnectMode;
775
777
  if (currentMode === mode) {
776
778
  return;
@@ -784,7 +786,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
784
786
  connectionState: connectionState_1.ConnectionState[this.connectionState],
785
787
  duration,
786
788
  });
787
- this._deltaManager.connectionManager.setAutoReconnect(mode);
789
+ this._deltaManager.connectionManager.setAutoReconnect(mode, reason);
788
790
  }
789
791
  connect() {
790
792
  if (this.closed) {
@@ -797,7 +799,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
797
799
  // Note: no need to fetch ops as we do it preemptively as part of DeltaManager.attachOpHandler().
798
800
  // If there is gap, we will learn about it once connected, but the gap should be small (if any),
799
801
  // assuming that connect() is called quickly after initial container boot.
800
- this.connectInternal({ reason: "DocumentConnect", fetchOpsFromStorage: false });
802
+ this.connectInternal({
803
+ reason: { text: "DocumentConnect" },
804
+ fetchOpsFromStorage: false,
805
+ });
801
806
  }
802
807
  }
803
808
  connectInternal(args) {
@@ -807,21 +812,21 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
807
812
  this.resumeInternal(args);
808
813
  // Set Auto Reconnect Mode
809
814
  const mode = contracts_1.ReconnectMode.Enabled;
810
- this.setAutoReconnectInternal(mode);
815
+ this.setAutoReconnectInternal(mode, args.reason);
811
816
  }
812
817
  disconnect() {
813
818
  if (this.closed) {
814
819
  throw new container_utils_1.UsageError(`The Container is closed and cannot be disconnected`);
815
820
  }
816
821
  else {
817
- this.disconnectInternal();
822
+ this.disconnectInternal({ text: "DocumentDisconnect" });
818
823
  }
819
824
  }
820
- disconnectInternal() {
825
+ disconnectInternal(reason) {
821
826
  (0, common_utils_1.assert)(!this.closed, 0x2c7 /* "Attempting to disconnect() a closed Container" */);
822
827
  // Set Auto Reconnect Mode
823
828
  const mode = contracts_1.ReconnectMode.Disabled;
824
- this.setAutoReconnectInternal(mode);
829
+ this.setAutoReconnectInternal(mode, reason);
825
830
  }
826
831
  resumeInternal(args) {
827
832
  (0, common_utils_1.assert)(!this.closed, 0x0d9 /* "Attempting to connect() a closed DeltaManager" */);
@@ -923,7 +928,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
923
928
  // A) creation flow breaks (as one of the clients "sees" file as existing, and hits #2 above)
924
929
  // B) Once file is created, transition from view-only connection to write does not work - some bugs to be fixed.
925
930
  const connectionArgs = {
926
- reason: "DocumentOpen",
931
+ reason: { text: "DocumentOpen" },
927
932
  mode: "write",
928
933
  fetchOpsFromStorage: false,
929
934
  };
@@ -1285,10 +1290,10 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1285
1290
  deltaManager.on("cancelEstablishingConnection", (reason) => {
1286
1291
  this.connectionStateHandler.cancelEstablishingConnection(reason);
1287
1292
  });
1288
- deltaManager.on("disconnect", (reason, error) => {
1293
+ deltaManager.on("disconnect", (reason) => {
1289
1294
  this.noopHeuristic?.notifyDisconnect();
1290
1295
  if (!this.closed) {
1291
- this.connectionStateHandler.receivedDisconnectEvent(reason, error);
1296
+ this.connectionStateHandler.receivedDisconnectEvent(reason);
1292
1297
  }
1293
1298
  });
1294
1299
  deltaManager.on("throttled", (warning) => {
@@ -1320,7 +1325,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1320
1325
  },
1321
1326
  }, prefetchType);
1322
1327
  }
1323
- logConnectionStateChangeTelemetry(value, oldState, reason, error) {
1328
+ logConnectionStateChangeTelemetry(value, oldState, reason) {
1324
1329
  // Log actual event
1325
1330
  const time = common_utils_1.performance.now();
1326
1331
  this.connectionTransitionTimes[value] = time;
@@ -1355,7 +1360,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1355
1360
  from: connectionState_1.ConnectionState[oldState],
1356
1361
  duration,
1357
1362
  durationFromDisconnected,
1358
- reason,
1363
+ reason: reason?.text,
1359
1364
  connectionInitiationReason,
1360
1365
  pendingClientId: this.connectionStateHandler.pendingClientId,
1361
1366
  clientId: this.clientId,
@@ -1369,7 +1374,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1369
1374
  quorumSize: this._protocolHandler?.quorum.getMembers().size,
1370
1375
  isDirty: this.isDirty,
1371
1376
  ...this._deltaManager.connectionProps,
1372
- }, error);
1377
+ }, reason?.error);
1373
1378
  if (value === connectionState_1.ConnectionState.Connected) {
1374
1379
  this.firstConnection = false;
1375
1380
  }
@@ -1387,7 +1392,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1387
1392
  // Both protocol and context should not be undefined if we got so far.
1388
1393
  this.setContextConnectedState(state, this.readOnlyInfo.readonly ?? false);
1389
1394
  this.protocolHandler.setConnectionState(state, this.clientId);
1390
- (0, telemetry_utils_1.raiseConnectedEvent)(this.mc.logger, this, state, this.clientId, disconnectedReason);
1395
+ (0, telemetry_utils_1.raiseConnectedEvent)(this.mc.logger, this, state, this.clientId, disconnectedReason?.text);
1391
1396
  }
1392
1397
  // back-compat: ADO #1385: Remove in the future, summary op should come through submitSummaryMessage()
1393
1398
  submitContainerMessage(type, contents, batch, metadata) {
@@ -1437,23 +1442,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1437
1442
  this.savedOps.push(message);
1438
1443
  }
1439
1444
  const local = this.clientId === message.clientId;
1440
- // Check and report if we're getting messages from a clientId that we previously
1441
- // flagged should have left, or from a client that's not in the quorum but should be
1442
- if (message.clientId != null) {
1443
- const client = this.protocolHandler.quorum.getMember(message.clientId);
1444
- if (client === undefined && message.type !== protocol_definitions_1.MessageType.ClientJoin) {
1445
- // pre-0.58 error message: messageClientIdMissingFromQuorum
1446
- throw new Error("Remote message's clientId is missing from the quorum");
1447
- }
1448
- // Here checking canBeCoalescedByService is used as an approximation of "is benign to process despite being unexpected".
1449
- // It's still not good to see these messages from unexpected clientIds, but since they don't harm the integrity of the
1450
- // document we don't need to blow up aggressively.
1451
- if (this.clientsWhoShouldHaveLeft.has(message.clientId) &&
1452
- !(0, driver_utils_1.canBeCoalescedByService)(message)) {
1453
- // pre-0.58 error message: messageClientIdShouldHaveLeft
1454
- throw new Error("Remote message's clientId already should have left");
1455
- }
1456
- }
1457
1445
  // Allow the protocol handler to process the message
1458
1446
  const result = this.protocolHandler.processMessage(message, local);
1459
1447
  // Forward messages to the loaded runtime for processing