@fluidframework/container-loader 1.2.0 → 2.0.0-internal.1.0.0.81589

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 (105) hide show
  1. package/dist/audience.d.ts +2 -2
  2. package/dist/audience.d.ts.map +1 -1
  3. package/dist/audience.js.map +1 -1
  4. package/dist/catchUpMonitor.d.ts +40 -0
  5. package/dist/catchUpMonitor.d.ts.map +1 -0
  6. package/dist/catchUpMonitor.js +74 -0
  7. package/dist/catchUpMonitor.js.map +1 -0
  8. package/dist/connectionManager.d.ts.map +1 -1
  9. package/dist/connectionManager.js +0 -1
  10. package/dist/connectionManager.js.map +1 -1
  11. package/dist/connectionState.d.ts +0 -5
  12. package/dist/connectionState.d.ts.map +1 -1
  13. package/dist/connectionState.js +0 -5
  14. package/dist/connectionState.js.map +1 -1
  15. package/dist/connectionStateHandler.d.ts +12 -4
  16. package/dist/connectionStateHandler.d.ts.map +1 -1
  17. package/dist/connectionStateHandler.js +47 -15
  18. package/dist/connectionStateHandler.js.map +1 -1
  19. package/dist/container.d.ts +8 -6
  20. package/dist/container.d.ts.map +1 -1
  21. package/dist/container.js +82 -46
  22. package/dist/container.js.map +1 -1
  23. package/dist/deltaManager.d.ts.map +1 -1
  24. package/dist/deltaManager.js +6 -6
  25. package/dist/deltaManager.js.map +1 -1
  26. package/dist/deltaManagerProxy.d.ts +4 -1
  27. package/dist/deltaManagerProxy.d.ts.map +1 -1
  28. package/dist/deltaQueue.d.ts +9 -2
  29. package/dist/deltaQueue.d.ts.map +1 -1
  30. package/dist/deltaQueue.js +31 -26
  31. package/dist/deltaQueue.js.map +1 -1
  32. package/dist/index.d.ts +1 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/loader.d.ts +7 -0
  36. package/dist/loader.d.ts.map +1 -1
  37. package/dist/loader.js +4 -3
  38. package/dist/loader.js.map +1 -1
  39. package/dist/packageVersion.d.ts +1 -1
  40. package/dist/packageVersion.d.ts.map +1 -1
  41. package/dist/packageVersion.js +1 -1
  42. package/dist/packageVersion.js.map +1 -1
  43. package/dist/protocol.d.ts +22 -0
  44. package/dist/protocol.d.ts.map +1 -0
  45. package/dist/protocol.js +52 -0
  46. package/dist/protocol.js.map +1 -0
  47. package/lib/audience.d.ts +2 -2
  48. package/lib/audience.d.ts.map +1 -1
  49. package/lib/audience.js.map +1 -1
  50. package/lib/catchUpMonitor.d.ts +40 -0
  51. package/lib/catchUpMonitor.d.ts.map +1 -0
  52. package/lib/catchUpMonitor.js +69 -0
  53. package/lib/catchUpMonitor.js.map +1 -0
  54. package/lib/connectionManager.d.ts.map +1 -1
  55. package/lib/connectionManager.js +0 -1
  56. package/lib/connectionManager.js.map +1 -1
  57. package/lib/connectionState.d.ts +0 -5
  58. package/lib/connectionState.d.ts.map +1 -1
  59. package/lib/connectionState.js +0 -5
  60. package/lib/connectionState.js.map +1 -1
  61. package/lib/connectionStateHandler.d.ts +12 -4
  62. package/lib/connectionStateHandler.d.ts.map +1 -1
  63. package/lib/connectionStateHandler.js +47 -15
  64. package/lib/connectionStateHandler.js.map +1 -1
  65. package/lib/container.d.ts +8 -6
  66. package/lib/container.d.ts.map +1 -1
  67. package/lib/container.js +82 -46
  68. package/lib/container.js.map +1 -1
  69. package/lib/deltaManager.d.ts.map +1 -1
  70. package/lib/deltaManager.js +6 -6
  71. package/lib/deltaManager.js.map +1 -1
  72. package/lib/deltaManagerProxy.d.ts +4 -1
  73. package/lib/deltaManagerProxy.d.ts.map +1 -1
  74. package/lib/deltaQueue.d.ts +9 -2
  75. package/lib/deltaQueue.d.ts.map +1 -1
  76. package/lib/deltaQueue.js +32 -27
  77. package/lib/deltaQueue.js.map +1 -1
  78. package/lib/index.d.ts +1 -0
  79. package/lib/index.d.ts.map +1 -1
  80. package/lib/index.js.map +1 -1
  81. package/lib/loader.d.ts +7 -0
  82. package/lib/loader.d.ts.map +1 -1
  83. package/lib/loader.js +4 -3
  84. package/lib/loader.js.map +1 -1
  85. package/lib/packageVersion.d.ts +1 -1
  86. package/lib/packageVersion.d.ts.map +1 -1
  87. package/lib/packageVersion.js +1 -1
  88. package/lib/packageVersion.js.map +1 -1
  89. package/lib/protocol.d.ts +22 -0
  90. package/lib/protocol.d.ts.map +1 -0
  91. package/lib/protocol.js +48 -0
  92. package/lib/protocol.js.map +1 -0
  93. package/package.json +23 -15
  94. package/src/audience.ts +2 -2
  95. package/src/catchUpMonitor.ts +99 -0
  96. package/src/connectionManager.ts +0 -1
  97. package/src/connectionState.ts +0 -6
  98. package/src/connectionStateHandler.ts +55 -15
  99. package/src/container.ts +115 -63
  100. package/src/deltaManager.ts +6 -4
  101. package/src/deltaQueue.ts +34 -28
  102. package/src/index.ts +4 -0
  103. package/src/loader.ts +13 -2
  104. package/src/packageVersion.ts +1 -1
  105. package/src/protocol.ts +96 -0
package/dist/container.js CHANGED
@@ -15,7 +15,6 @@ const common_utils_1 = require("@fluidframework/common-utils");
15
15
  const container_definitions_1 = require("@fluidframework/container-definitions");
16
16
  const container_utils_1 = require("@fluidframework/container-utils");
17
17
  const driver_utils_1 = require("@fluidframework/driver-utils");
18
- const protocol_base_1 = require("@fluidframework/protocol-base");
19
18
  const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
20
19
  const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
21
20
  const audience_1 = require("./audience");
@@ -34,6 +33,7 @@ const quorum_1 = require("./quorum");
34
33
  const collabWindowTracker_1 = require("./collabWindowTracker");
35
34
  const connectionManager_1 = require("./connectionManager");
36
35
  const connectionState_1 = require("./connectionState");
36
+ const protocol_1 = require("./protocol");
37
37
  const detachedContainerRefSeqNumber = 0;
38
38
  const dirtyContainerEvent = "dirty";
39
39
  const savedContainerEvent = "saved";
@@ -63,6 +63,10 @@ async function waitContainerToCatchUp(container) {
63
63
  : new container_utils_1.GenericError(baseMessage));
64
64
  };
65
65
  container.on("closed", closedCallback);
66
+ // Depending on config, transition to "connected" state may include the guarantee
67
+ // that all known ops have been processed. If so, we may introduce additional wait here.
68
+ // Waiting for "connected" state in either case gets us at least to our own Join op
69
+ // which is a reasonable approximation of "caught up"
66
70
  const waitForOps = () => {
67
71
  (0, common_utils_1.assert)(container.connectionState === connectionState_1.ConnectionState.CatchingUp
68
72
  || container.connectionState === connectionState_1.ConnectionState.Connected, 0x0cd /* "Container disconnected while waiting for ops!" */);
@@ -105,9 +109,22 @@ exports.waitContainerToCatchUp = waitContainerToCatchUp;
105
109
  const getCodeProposal =
106
110
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
107
111
  (quorum) => { var _a; return (_a = quorum.get("code")) !== null && _a !== void 0 ? _a : quorum.get("code2"); };
112
+ /**
113
+ * Helper function to report to telemetry cases where operation takes longer than expected (1s)
114
+ * @param logger - logger to use
115
+ * @param eventName - event name
116
+ * @param action - functor to call and measure
117
+ */
118
+ async function ReportIfTooLong(logger, eventName, action) {
119
+ const event = telemetry_utils_1.PerformanceEvent.start(logger, { eventName });
120
+ const props = await action();
121
+ if (event.duration > 1000) {
122
+ event.end(props);
123
+ }
124
+ }
108
125
  const summarizerClientType = "summarizer";
109
126
  class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
110
- constructor(loader, config) {
127
+ constructor(loader, config, protocolHandlerBuilder) {
111
128
  var _a, _b;
112
129
  super((name, error) => {
113
130
  this.mc.logger.sendErrorEvent({
@@ -116,6 +133,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
116
133
  }, error);
117
134
  });
118
135
  this.loader = loader;
136
+ this.protocolHandlerBuilder = protocolHandlerBuilder;
119
137
  // Tells if container can reconnect on losing fist connection
120
138
  // If false, container gets closed on loss of connection.
121
139
  this._canReconnect = true;
@@ -129,7 +147,6 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
129
147
  this.attachStarted = false;
130
148
  this._dirtyContainer = false;
131
149
  this.setAutoReconnectTime = common_utils_1.performance.now();
132
- this._audience = new audience_1.Audience();
133
150
  this.clientDetailsOverride = config.clientDetailsOverride;
134
151
  this._resolvedUrl = config.resolvedUrl;
135
152
  if (config.canReconnect !== undefined) {
@@ -149,6 +166,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
149
166
  containerAttachState: () => this._attachState,
150
167
  containerLifecycleState: () => this._lifecycleState,
151
168
  containerConnectionState: () => connectionState_1.ConnectionState[this.connectionState],
169
+ serializedContainer: config.serializedContainerState !== undefined,
152
170
  },
153
171
  // we need to be judicious with our logging here to avoid generating too much data
154
172
  // all data logged here should be broadly applicable, and not specific to a
@@ -161,6 +179,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
161
179
  containerLoadedFromVersionId: () => { var _a; return (_a = this.loadedFromVersion) === null || _a === void 0 ? void 0 : _a.id; },
162
180
  containerLoadedFromVersionDate: () => { var _a; return (_a = this.loadedFromVersion) === null || _a === void 0 ? void 0 : _a.date; },
163
181
  // message information to associate errors with the specific execution state
182
+ // dmLastMsqSeqNumber: if present, same as dmLastProcessedSeqNumber
164
183
  dmLastMsqSeqNumber: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.sequenceNumber; },
165
184
  dmLastMsqSeqTimestamp: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.timestamp; },
166
185
  dmLastMsqSeqClientId: () => { var _a, _b; return (_b = (_a = this.deltaManager) === null || _a === void 0 ? void 0 : _a.lastMessage) === null || _b === void 0 ? void 0 : _b.clientId; },
@@ -260,13 +279,13 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
260
279
  /**
261
280
  * Load an existing container.
262
281
  */
263
- static async load(loader, loadOptions, pendingLocalState) {
282
+ static async load(loader, loadOptions, pendingLocalState, protocolHandlerBuilder) {
264
283
  const container = new Container(loader, {
265
284
  clientDetailsOverride: loadOptions.clientDetailsOverride,
266
285
  resolvedUrl: loadOptions.resolvedUrl,
267
286
  canReconnect: loadOptions.canReconnect,
268
287
  serializedContainerState: pendingLocalState,
269
- });
288
+ }, protocolHandlerBuilder);
270
289
  return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "Load" }, async (event) => new Promise((resolve, reject) => {
271
290
  var _a, _b;
272
291
  const version = loadOptions.version;
@@ -300,8 +319,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
300
319
  /**
301
320
  * Create a new container in a detached state.
302
321
  */
303
- static async createDetached(loader, codeDetails) {
304
- const container = new Container(loader, {});
322
+ static async createDetached(loader, codeDetails, protocolHandlerBuilder) {
323
+ const container = new Container(loader, {}, protocolHandlerBuilder);
305
324
  return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "CreateDetached" }, async (_event) => {
306
325
  await container.createDetached(codeDetails);
307
326
  return container;
@@ -311,8 +330,8 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
311
330
  * Create a new container in a detached state that is initialized with a
312
331
  * snapshot from a previous detached container.
313
332
  */
314
- static async rehydrateDetachedFromSnapshot(loader, snapshot) {
315
- const container = new Container(loader, {});
333
+ static async rehydrateDetachedFromSnapshot(loader, snapshot, protocolHandlerBuilder) {
334
+ const container = new Container(loader, {}, protocolHandlerBuilder);
316
335
  return telemetry_utils_1.PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "RehydrateDetachedFromSnapshot" }, async (_event) => {
317
336
  const deserializedSummary = JSON.parse(snapshot);
318
337
  await container.rehydrateDetachedFromSnapshot(deserializedSummary);
@@ -425,12 +444,12 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
425
444
  * Retrieves the audience associated with the document
426
445
  */
427
446
  get audience() {
428
- return this._audience;
447
+ return this.protocolHandler.audience;
429
448
  }
430
449
  /**
431
450
  * Returns true if container is dirty.
432
451
  * Which means data loss if container is closed at that same moment
433
- * Most likely that happens when there is no network connection to ordering service
452
+ * Most likely that happens when there is no network connection to Relay Service
434
453
  */
435
454
  get isDirty() {
436
455
  return this._dirtyContainer;
@@ -496,7 +515,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
496
515
  (0, common_utils_1.assert)(this.attachState === container_definitions_1.AttachState.Attached, 0x0d1 /* "Container should be attached before close" */);
497
516
  (0, common_utils_1.assert)(this.resolvedUrl !== undefined && this.resolvedUrl.type === "fluid", 0x0d2 /* "resolved url should be valid Fluid url" */);
498
517
  (0, common_utils_1.assert)(!!this._protocolHandler, 0x2e3 /* "Must have a valid protocol handler instance" */);
499
- (0, common_utils_1.assert)(this._protocolHandler.attributes.term !== undefined, 0x30b /* Must have a valid protocol handler instance */);
518
+ (0, common_utils_1.assert)(this._protocolHandler.attributes.term !== undefined, "Must have a valid protocol handler instance");
500
519
  const pendingState = {
501
520
  pendingRuntimeState: this.context.getPendingLocalState(),
502
521
  url: this.resolvedUrl.url,
@@ -795,20 +814,21 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
795
814
  // ...load in the existing quorum
796
815
  // Initialize the protocol handler
797
816
  this._protocolHandler = pendingLocalState === undefined
798
- ? await this.initializeProtocolStateFromSnapshot(attributes, this.storageService, snapshot)
799
- : await this.initializeProtocolState(attributes, pendingLocalState.protocol.members, pendingLocalState.protocol.proposals, pendingLocalState.protocol.values);
817
+ ? await this.initializeProtocolStateFromSnapshot(attributes, this.storageService, snapshot) : await this.initializeProtocolState(attributes, {
818
+ members: pendingLocalState.protocol.members,
819
+ proposals: pendingLocalState.protocol.proposals,
820
+ values: pendingLocalState.protocol.values,
821
+ });
800
822
  const codeDetails = this.getCodeDetailsFromQuorum();
801
823
  await this.instantiateContext(true, // existing
802
824
  codeDetails, snapshot, pendingLocalState === null || pendingLocalState === void 0 ? void 0 : pendingLocalState.pendingRuntimeState);
803
- // Internal context is fully loaded at this point
804
- this.setLoaded();
805
825
  // We might have hit some failure that did not manifest itself in exception in this flow,
806
826
  // do not start op processing in such case - static version of Container.load() will handle it correctly.
807
827
  if (!this.closed) {
808
828
  if (opsBeforeReturnP !== undefined) {
809
829
  this._deltaManager.inbound.resume();
810
- await opsBeforeReturnP;
811
- await this._deltaManager.inbound.waitTillProcessingDone();
830
+ await ReportIfTooLong(this.mc.logger, "WaitOps", async () => { await opsBeforeReturnP; return {}; });
831
+ await ReportIfTooLong(this.mc.logger, "WaitOpProcessing", async () => this._deltaManager.inbound.waitTillProcessingDone());
812
832
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
813
833
  this._deltaManager.inbound.pause();
814
834
  }
@@ -834,9 +854,13 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
834
854
  if (this.closed) {
835
855
  throw new Error("Container was closed while load()");
836
856
  }
857
+ // Internal context is fully loaded at this point
858
+ this.setLoaded();
837
859
  return {
838
860
  sequenceNumber: attributes.sequenceNumber,
839
861
  version: versionId,
862
+ dmLastProcessedSeqNumber: this._deltaManager.lastSequenceNumber,
863
+ dmLastKnownSeqNumber: this._deltaManager.lastKnownSeqNumber,
840
864
  };
841
865
  }
842
866
  async createDetached(source) {
@@ -848,9 +872,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
848
872
  await this.attachDeltaManagerOpHandler(attributes);
849
873
  // Need to just seed the source data in the code quorum. Quorum itself is empty
850
874
  const qValues = (0, quorum_1.initQuorumValuesFromCodeDetails)(source);
851
- this._protocolHandler = await this.initializeProtocolState(attributes, [], // members
852
- [], // proposals
853
- qValues);
875
+ this._protocolHandler = await this.initializeProtocolState(attributes, {
876
+ members: [],
877
+ proposals: [],
878
+ values: qValues,
879
+ });
854
880
  // The load context - given we seeded the quorum - will be great
855
881
  await this.instantiateContextDetached(false);
856
882
  this.setLoaded();
@@ -869,9 +895,11 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
869
895
  const qValues = await (0, driver_utils_1.readAndParse)(this._storage, baseTree.blobs.quorumValues);
870
896
  const codeDetails = (0, quorum_1.getCodeDetailsFromQuorumValues)(qValues);
871
897
  this._protocolHandler =
872
- await this.initializeProtocolState(attributes, [], // members
873
- [], // proposals
874
- codeDetails !== undefined ? (0, quorum_1.initQuorumValuesFromCodeDetails)(codeDetails) : []);
898
+ await this.initializeProtocolState(attributes, {
899
+ members: [],
900
+ proposals: [],
901
+ values: codeDetails !== undefined ? (0, quorum_1.initQuorumValuesFromCodeDetails)(codeDetails) : [],
902
+ });
875
903
  await this.instantiateContextDetached(true, // existing
876
904
  snapshotTree);
877
905
  this.setLoaded();
@@ -913,22 +941,27 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
913
941
  return attributes;
914
942
  }
915
943
  async initializeProtocolStateFromSnapshot(attributes, storage, snapshot) {
916
- let members = [];
917
- let proposals = [];
918
- let values = [];
944
+ const quorumSnapshot = {
945
+ members: [],
946
+ proposals: [],
947
+ values: [],
948
+ };
919
949
  if (snapshot !== undefined) {
920
950
  const baseTree = (0, utils_1.getProtocolSnapshotTree)(snapshot);
921
- [members, proposals, values] = await Promise.all([
951
+ [quorumSnapshot.members, quorumSnapshot.proposals, quorumSnapshot.values] = await Promise.all([
922
952
  (0, driver_utils_1.readAndParse)(storage, baseTree.blobs.quorumMembers),
923
953
  (0, driver_utils_1.readAndParse)(storage, baseTree.blobs.quorumProposals),
924
954
  (0, driver_utils_1.readAndParse)(storage, baseTree.blobs.quorumValues),
925
955
  ]);
926
956
  }
927
- const protocolHandler = await this.initializeProtocolState(attributes, members, proposals, values);
957
+ const protocolHandler = await this.initializeProtocolState(attributes, quorumSnapshot);
928
958
  return protocolHandler;
929
959
  }
930
- async initializeProtocolState(attributes, members, proposals, values) {
931
- const protocol = new protocol_base_1.ProtocolOpHandlerWithClientValidation(attributes.minimumSequenceNumber, attributes.sequenceNumber, attributes.term, members, proposals, values, (key, value) => this.submitMessage(protocol_definitions_1.MessageType.Propose, { key, value }));
960
+ async initializeProtocolState(attributes, quorumSnapshot) {
961
+ var _a, _b;
962
+ const protocolHandlerBuilder = (_a = this.protocolHandlerBuilder) !== null && _a !== void 0 ? _a : ((...args) => new protocol_1.ProtocolHandler(...args, new audience_1.Audience()));
963
+ const protocol = protocolHandlerBuilder(attributes, quorumSnapshot, (key, value) => this.submitMessage(protocol_definitions_1.MessageType.Propose, { key, value }), (_b = this._initialClients) !== null && _b !== void 0 ? _b : []);
964
+ this._initialClients = undefined;
932
965
  const protocolLogger = telemetry_utils_1.ChildLogger.create(this.subLogger, "ProtocolHandler");
933
966
  protocol.quorum.on("error", (error) => {
934
967
  protocolLogger.sendErrorEvent(error);
@@ -1022,14 +1055,25 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1022
1055
  deltaManager.inbound.pause();
1023
1056
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
1024
1057
  deltaManager.inboundSignal.pause();
1025
- deltaManager.on("connect", (details, opsBehind) => {
1058
+ deltaManager.on("connect", (details, _opsBehind) => {
1026
1059
  var _a;
1027
- // Back-compat for new client and old server.
1028
- this._audience.clear();
1029
- for (const priorClient of (_a = details.initialClients) !== null && _a !== void 0 ? _a : []) {
1030
- this._audience.addMember(priorClient.clientId, priorClient.client);
1060
+ if (this._protocolHandler === undefined) {
1061
+ // Store the initial clients so that they can be submitted to the
1062
+ // protocol handler when it is created.
1063
+ this._initialClients = details.initialClients;
1031
1064
  }
1032
- this.connectionStateHandler.receivedConnectEvent(this.connectionMode, details);
1065
+ else {
1066
+ // When reconnecting, the protocol handler is already created,
1067
+ // so we can update the audience right now.
1068
+ this._protocolHandler.audience.clear();
1069
+ for (const priorClient of (_a = details.initialClients) !== null && _a !== void 0 ? _a : []) {
1070
+ this._protocolHandler.audience.addMember(priorClient.clientId, priorClient.client);
1071
+ }
1072
+ }
1073
+ const deltaManagerForCatchingUp = this.mc.config.getBoolean("Fluid.Container.CatchUpBeforeDeclaringConnected") === true ?
1074
+ this.deltaManager
1075
+ : undefined;
1076
+ this.connectionStateHandler.receivedConnectEvent(this.connectionMode, details, deltaManagerForCatchingUp);
1033
1077
  });
1034
1078
  deltaManager.on("disconnect", (reason) => {
1035
1079
  var _a;
@@ -1201,15 +1245,7 @@ class Container extends telemetry_utils_1.EventEmitterWithErrorHandling {
1201
1245
  processSignal(message) {
1202
1246
  // No clientId indicates a system signal message.
1203
1247
  if (message.clientId === null) {
1204
- const innerContent = message.content;
1205
- if (innerContent.type === protocol_definitions_1.MessageType.ClientJoin) {
1206
- const newClient = innerContent.content;
1207
- this._audience.addMember(newClient.clientId, newClient.client);
1208
- }
1209
- else if (innerContent.type === protocol_definitions_1.MessageType.ClientLeave) {
1210
- const leftClientId = innerContent.content;
1211
- this._audience.removeMember(leftClientId);
1212
- }
1248
+ this.protocolHandler.processSignal(message);
1213
1249
  }
1214
1250
  else {
1215
1251
  const local = this.clientId === message.clientId;