@fluidframework/container-loader 2.0.0-dev.6.4.0.192049 → 2.0.0-dev.7.2.0.204906
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.
- package/CHANGELOG.md +122 -0
- package/api-extractor.json +9 -1
- package/api-report/container-loader.api.md +153 -0
- package/dist/catchUpMonitor.d.ts +2 -2
- package/dist/catchUpMonitor.d.ts.map +1 -1
- package/dist/connectionManager.d.ts +2 -15
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +117 -100
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionState.js +1 -1
- package/dist/connectionState.js.map +1 -1
- package/dist/connectionStateHandler.js +9 -9
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container-loader-alpha.d.ts +333 -0
- package/dist/container-loader-beta.d.ts +333 -0
- package/dist/container-loader-public.d.ts +333 -0
- package/dist/container-loader-untrimmed.d.ts +333 -0
- package/dist/container.d.ts +22 -2
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +235 -222
- package/dist/container.js.map +1 -1
- package/dist/containerContext.js +16 -16
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +1 -1
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +9 -11
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +5 -4
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.d.ts.map +1 -1
- package/dist/debugLogger.js +5 -4
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +92 -96
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.js +14 -14
- package/dist/deltaQueue.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +6 -9
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +26 -91
- package/dist/loader.js.map +1 -1
- package/dist/location-redirection-utilities/index.d.ts +6 -0
- package/dist/location-redirection-utilities/index.d.ts.map +1 -0
- package/dist/location-redirection-utilities/index.js +11 -0
- package/dist/location-redirection-utilities/index.js.map +1 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts +22 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js +51 -0
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/protocol.d.ts +1 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +3 -5
- package/dist/protocol.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts +3 -2
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +18 -11
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/utils.d.ts +23 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +11 -3
- package/dist/utils.js.map +1 -1
- package/lib/catchUpMonitor.d.ts +2 -2
- package/lib/catchUpMonitor.d.ts.map +1 -1
- package/lib/connectionManager.d.ts +2 -15
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +120 -101
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.js +9 -9
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +22 -2
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +236 -223
- package/lib/container.js.map +1 -1
- package/lib/containerContext.js +16 -16
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +1 -1
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +9 -11
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +5 -4
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.d.ts.map +1 -1
- package/lib/debugLogger.js +5 -4
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +92 -96
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.js +14 -14
- package/lib/deltaQueue.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/loader.d.ts +6 -9
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +27 -92
- package/lib/loader.js.map +1 -1
- package/lib/location-redirection-utilities/index.d.ts +6 -0
- package/lib/location-redirection-utilities/index.d.ts.map +1 -0
- package/lib/location-redirection-utilities/index.js +6 -0
- package/lib/location-redirection-utilities/index.js.map +1 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts +22 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js +46 -0
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -0
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/protocol.d.ts +1 -2
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +1 -3
- package/lib/protocol.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts +3 -2
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +18 -11
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/utils.d.ts +23 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +9 -1
- package/lib/utils.js.map +1 -1
- package/package.json +24 -26
- package/src/connectionManager.ts +69 -34
- package/src/container.ts +48 -30
- package/src/containerStorageAdapter.ts +3 -9
- package/src/contracts.ts +8 -4
- package/src/debugLogger.ts +5 -1
- package/src/deltaManager.ts +16 -31
- package/src/index.ts +5 -0
- package/src/loader.ts +31 -99
- package/src/location-redirection-utilities/index.ts +9 -0
- package/src/location-redirection-utilities/resolveWithLocationRedirection.ts +59 -0
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +2 -6
- package/src/retriableDocumentStorageService.ts +29 -15
- package/src/utils.ts +23 -1
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.ConnectionManager = void 0;
|
|
8
|
+
const core_interfaces_1 = require("@fluidframework/core-interfaces");
|
|
8
9
|
const core_utils_1 = require("@fluidframework/core-utils");
|
|
9
10
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
11
|
+
const driver_definitions_1 = require("@fluidframework/driver-definitions");
|
|
10
12
|
const driver_utils_1 = require("@fluidframework/driver-utils");
|
|
11
13
|
const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
12
14
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
@@ -36,9 +38,15 @@ const clientNoDeltaStream = {
|
|
|
36
38
|
};
|
|
37
39
|
const clientIdNoDeltaStream = "storage-only client";
|
|
38
40
|
class NoDeltaStream extends client_utils_1.TypedEventEmitter {
|
|
39
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Connection which is not connected to socket.
|
|
43
|
+
* @param storageOnlyReason - Reason on why the connection to delta stream is not allowed.
|
|
44
|
+
* @param readonlyConnectionReason - reason/error if any which lead to using NoDeltaStream.
|
|
45
|
+
*/
|
|
46
|
+
constructor(storageOnlyReason, readonlyConnectionReason) {
|
|
40
47
|
super();
|
|
41
48
|
this.storageOnlyReason = storageOnlyReason;
|
|
49
|
+
this.readonlyConnectionReason = readonlyConnectionReason;
|
|
42
50
|
this.clientId = clientIdNoDeltaStream;
|
|
43
51
|
this.claims = {
|
|
44
52
|
scopes: [protocol_definitions_1.ScopeType.DocRead],
|
|
@@ -101,67 +109,6 @@ const waitForOnline = async () => {
|
|
|
101
109
|
* Exposes various controls to influence this process, including manual reconnects, forced read-only mode, etc.
|
|
102
110
|
*/
|
|
103
111
|
class ConnectionManager {
|
|
104
|
-
constructor(serviceProvider, containerDirty, client, reconnectAllowed, logger, props) {
|
|
105
|
-
this.serviceProvider = serviceProvider;
|
|
106
|
-
this.containerDirty = containerDirty;
|
|
107
|
-
this.client = client;
|
|
108
|
-
this.logger = logger;
|
|
109
|
-
this.props = props;
|
|
110
|
-
/** tracks host requiring read-only mode. */
|
|
111
|
-
this._forceReadonly = false;
|
|
112
|
-
/** True if there is pending (async) reconnection from "read" to "write" */
|
|
113
|
-
this.pendingReconnect = false;
|
|
114
|
-
this.clientSequenceNumber = 0;
|
|
115
|
-
this.clientSequenceNumberObserved = 0;
|
|
116
|
-
/** Counts the number of non-runtime ops sent by the client which may not be acked. */
|
|
117
|
-
this.localOpsToIgnore = 0;
|
|
118
|
-
this.connectFirstConnection = true;
|
|
119
|
-
this._connectionVerboseProps = {};
|
|
120
|
-
this._connectionProps = {};
|
|
121
|
-
this._disposed = false;
|
|
122
|
-
this.opHandler = (documentId, messagesArg) => {
|
|
123
|
-
const messages = Array.isArray(messagesArg) ? messagesArg : [messagesArg];
|
|
124
|
-
this.props.incomingOpHandler(messages, "opHandler");
|
|
125
|
-
};
|
|
126
|
-
// Always connect in write mode after getting nacked.
|
|
127
|
-
this.nackHandler = (documentId, messages) => {
|
|
128
|
-
const message = messages[0];
|
|
129
|
-
if (this._readonlyPermissions === true) {
|
|
130
|
-
this.props.closeHandler((0, driver_utils_1.createWriteError)("writeOnReadOnlyDocument", { driverVersion: undefined }));
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
const reconnectInfo = getNackReconnectInfo(message.content);
|
|
134
|
-
// If the nack indicates we cannot retry, then close the container outright
|
|
135
|
-
if (!reconnectInfo.canRetry) {
|
|
136
|
-
this.props.closeHandler(reconnectInfo);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
this.reconnectOnError("write", reconnectInfo);
|
|
140
|
-
};
|
|
141
|
-
// Connection mode is always read on disconnect/error unless the system mode was write.
|
|
142
|
-
this.disconnectHandlerInternal = (disconnectReason) => {
|
|
143
|
-
// Note: we might get multiple disconnect calls on same socket, as early disconnect notification
|
|
144
|
-
// ("server_disconnect", ODSP-specific) is mapped to "disconnect"
|
|
145
|
-
this.reconnectOnError(this.defaultReconnectionMode, disconnectReason);
|
|
146
|
-
};
|
|
147
|
-
this.errorHandler = (error) => {
|
|
148
|
-
this.reconnectOnError(this.defaultReconnectionMode, error);
|
|
149
|
-
};
|
|
150
|
-
this.clientDetails = this.client.details;
|
|
151
|
-
this.defaultReconnectionMode = this.client.mode;
|
|
152
|
-
this._reconnectMode = reconnectAllowed ? contracts_1.ReconnectMode.Enabled : contracts_1.ReconnectMode.Never;
|
|
153
|
-
// Outbound message queue. The outbound queue is represented as a queue of an array of ops. Ops contained
|
|
154
|
-
// within an array *must* fit within the maxMessageSize and are guaranteed to be ordered sequentially.
|
|
155
|
-
this._outbound = new deltaQueue_1.DeltaQueue((messages) => {
|
|
156
|
-
if (this.connection === undefined) {
|
|
157
|
-
throw new Error("Attempted to submit an outbound message without connection");
|
|
158
|
-
}
|
|
159
|
-
this.connection.submit(messages);
|
|
160
|
-
});
|
|
161
|
-
this._outbound.on("error", (error) => {
|
|
162
|
-
this.props.closeHandler((0, telemetry_utils_1.normalizeError)(error));
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
112
|
get connectionVerboseProps() {
|
|
166
113
|
return this._connectionVerboseProps;
|
|
167
114
|
}
|
|
@@ -275,6 +222,71 @@ class ConnectionManager {
|
|
|
275
222
|
reason,
|
|
276
223
|
};
|
|
277
224
|
}
|
|
225
|
+
constructor(serviceProvider, containerDirty, client, reconnectAllowed, logger, props) {
|
|
226
|
+
this.serviceProvider = serviceProvider;
|
|
227
|
+
this.containerDirty = containerDirty;
|
|
228
|
+
this.client = client;
|
|
229
|
+
this.logger = logger;
|
|
230
|
+
this.props = props;
|
|
231
|
+
/** tracks host requiring read-only mode. */
|
|
232
|
+
this._forceReadonly = false;
|
|
233
|
+
/** True if there is pending (async) reconnection from "read" to "write" */
|
|
234
|
+
this.pendingReconnect = false;
|
|
235
|
+
this.clientSequenceNumber = 0;
|
|
236
|
+
this.clientSequenceNumberObserved = 0;
|
|
237
|
+
/** Counts the number of non-runtime ops sent by the client which may not be acked. */
|
|
238
|
+
this.localOpsToIgnore = 0;
|
|
239
|
+
this.connectFirstConnection = true;
|
|
240
|
+
this._connectionVerboseProps = {};
|
|
241
|
+
this._connectionProps = {};
|
|
242
|
+
this._disposed = false;
|
|
243
|
+
this.opHandler = (documentId, messagesArg) => {
|
|
244
|
+
const messages = Array.isArray(messagesArg) ? messagesArg : [messagesArg];
|
|
245
|
+
this.props.incomingOpHandler(messages, "opHandler");
|
|
246
|
+
};
|
|
247
|
+
this.signalHandler = (signalsArg) => {
|
|
248
|
+
const signals = Array.isArray(signalsArg) ? signalsArg : [signalsArg];
|
|
249
|
+
this.props.signalHandler(signals);
|
|
250
|
+
};
|
|
251
|
+
// Always connect in write mode after getting nacked.
|
|
252
|
+
this.nackHandler = (documentId, messages) => {
|
|
253
|
+
const message = messages[0];
|
|
254
|
+
if (this._readonlyPermissions === true) {
|
|
255
|
+
this.props.closeHandler((0, driver_utils_1.createWriteError)("writeOnReadOnlyDocument", { driverVersion: undefined }));
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
const reconnectInfo = getNackReconnectInfo(message.content);
|
|
259
|
+
// If the nack indicates we cannot retry, then close the container outright
|
|
260
|
+
if (!reconnectInfo.canRetry) {
|
|
261
|
+
this.props.closeHandler(reconnectInfo);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
this.reconnectOnError("write", reconnectInfo);
|
|
265
|
+
};
|
|
266
|
+
// Connection mode is always read on disconnect/error unless the system mode was write.
|
|
267
|
+
this.disconnectHandlerInternal = (disconnectReason) => {
|
|
268
|
+
// Note: we might get multiple disconnect calls on same socket, as early disconnect notification
|
|
269
|
+
// ("server_disconnect", ODSP-specific) is mapped to "disconnect"
|
|
270
|
+
this.reconnectOnError(this.defaultReconnectionMode, disconnectReason);
|
|
271
|
+
};
|
|
272
|
+
this.errorHandler = (error) => {
|
|
273
|
+
this.reconnectOnError(this.defaultReconnectionMode, error);
|
|
274
|
+
};
|
|
275
|
+
this.clientDetails = this.client.details;
|
|
276
|
+
this.defaultReconnectionMode = this.client.mode;
|
|
277
|
+
this._reconnectMode = reconnectAllowed ? contracts_1.ReconnectMode.Enabled : contracts_1.ReconnectMode.Never;
|
|
278
|
+
// Outbound message queue. The outbound queue is represented as a queue of an array of ops. Ops contained
|
|
279
|
+
// within an array *must* fit within the maxMessageSize and are guaranteed to be ordered sequentially.
|
|
280
|
+
this._outbound = new deltaQueue_1.DeltaQueue((messages) => {
|
|
281
|
+
if (this.connection === undefined) {
|
|
282
|
+
throw new Error("Attempted to submit an outbound message without connection");
|
|
283
|
+
}
|
|
284
|
+
this.connection.submit(messages);
|
|
285
|
+
});
|
|
286
|
+
this._outbound.on("error", (error) => {
|
|
287
|
+
this.props.closeHandler((0, telemetry_utils_1.normalizeError)(error));
|
|
288
|
+
});
|
|
289
|
+
}
|
|
278
290
|
dispose(error, switchToReadonly = true) {
|
|
279
291
|
if (this._disposed) {
|
|
280
292
|
return;
|
|
@@ -294,7 +306,7 @@ class ConnectionManager {
|
|
|
294
306
|
// Notify everyone we are in read-only state.
|
|
295
307
|
// Useful for data stores in case we hit some critical error,
|
|
296
308
|
// to switch to a mode where user edits are not accepted
|
|
297
|
-
this.set_readonlyPermissions(true, oldReadonlyValue);
|
|
309
|
+
this.set_readonlyPermissions(true, oldReadonlyValue, disconnectReason);
|
|
298
310
|
}
|
|
299
311
|
}
|
|
300
312
|
/**
|
|
@@ -310,21 +322,7 @@ class ConnectionManager {
|
|
|
310
322
|
}
|
|
311
323
|
}
|
|
312
324
|
/**
|
|
313
|
-
*
|
|
314
|
-
* Hosts may have read only views, indicating to data stores that no edits are allowed.
|
|
315
|
-
* This is independent from this._readonlyPermissions (permissions) and this.connectionMode
|
|
316
|
-
* (server can return "write" mode even when asked for "read")
|
|
317
|
-
* Leveraging same "readonly" event as runtime & data stores should behave the same in such case
|
|
318
|
-
* as in read-only permissions.
|
|
319
|
-
* But this.active can be used by some DDSes to figure out if ops can be sent
|
|
320
|
-
* (for example, read-only view still participates in code proposals / upgrades decisions)
|
|
321
|
-
*
|
|
322
|
-
* Forcing Readonly does not prevent DDS from generating ops. It is up to user code to honour
|
|
323
|
-
* the readonly flag. If ops are generated, they will accumulate locally and not be sent. If
|
|
324
|
-
* there are pending in the outbound queue, it will stop sending until force readonly is
|
|
325
|
-
* cleared.
|
|
326
|
-
*
|
|
327
|
-
* @param readonly - set or clear force readonly.
|
|
325
|
+
* {@inheritDoc Container.forceReadonly}
|
|
328
326
|
*/
|
|
329
327
|
forceReadonly(readonly) {
|
|
330
328
|
if (readonly !== this._forceReadonly) {
|
|
@@ -358,10 +356,10 @@ class ConnectionManager {
|
|
|
358
356
|
}
|
|
359
357
|
}
|
|
360
358
|
}
|
|
361
|
-
set_readonlyPermissions(newReadonlyValue, oldReadonlyValue) {
|
|
359
|
+
set_readonlyPermissions(newReadonlyValue, oldReadonlyValue, readonlyConnectionReason) {
|
|
362
360
|
this._readonlyPermissions = newReadonlyValue;
|
|
363
361
|
if (oldReadonlyValue !== this.readonly) {
|
|
364
|
-
this.props.readonlyChangeHandler(this.readonly);
|
|
362
|
+
this.props.readonlyChangeHandler(this.readonly, readonlyConnectionReason);
|
|
365
363
|
}
|
|
366
364
|
}
|
|
367
365
|
connect(reason, connectionMode) {
|
|
@@ -439,10 +437,29 @@ class ConnectionManager {
|
|
|
439
437
|
this.logger.sendTelemetryEvent({ eventName: "ReceivedClosedConnection" });
|
|
440
438
|
connection = undefined;
|
|
441
439
|
}
|
|
440
|
+
this.logger.sendTelemetryEvent({
|
|
441
|
+
eventName: "ConnectionReceived",
|
|
442
|
+
connected: connection !== undefined && connection.disposed === false,
|
|
443
|
+
}, undefined, core_interfaces_1.LogLevel.verbose);
|
|
442
444
|
}
|
|
443
445
|
catch (origError) {
|
|
444
446
|
if ((0, utils_1.isDeltaStreamConnectionForbiddenError)(origError)) {
|
|
445
|
-
connection = new NoDeltaStream(origError.storageOnlyReason
|
|
447
|
+
connection = new NoDeltaStream(origError.storageOnlyReason, {
|
|
448
|
+
text: origError.message,
|
|
449
|
+
error: origError,
|
|
450
|
+
});
|
|
451
|
+
requestedMode = "read";
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
else if ((0, telemetry_utils_1.isFluidError)(origError) &&
|
|
455
|
+
// eslint-disable-next-line import/no-deprecated
|
|
456
|
+
origError.errorType === driver_definitions_1.DriverErrorType.outOfStorageError) {
|
|
457
|
+
// If we get out of storage error from calling joinsession, then use the NoDeltaStream object so
|
|
458
|
+
// that user can at least load the container.
|
|
459
|
+
connection = new NoDeltaStream(undefined, {
|
|
460
|
+
text: origError.message,
|
|
461
|
+
error: origError,
|
|
462
|
+
});
|
|
446
463
|
requestedMode = "read";
|
|
447
464
|
break;
|
|
448
465
|
}
|
|
@@ -499,8 +516,8 @@ class ConnectionManager {
|
|
|
499
516
|
duration: (0, telemetry_utils_1.formatTick)(client_utils_1.performance.now() - connectStartTime),
|
|
500
517
|
}, lastError);
|
|
501
518
|
}
|
|
502
|
-
// Check for abort signal after while loop as well
|
|
503
|
-
if (abortSignal.aborted === true) {
|
|
519
|
+
// Check for abort signal after while loop as well or we've been disposed
|
|
520
|
+
if (abortSignal.aborted === true || this._disposed) {
|
|
504
521
|
connection.dispose();
|
|
505
522
|
this.logger.sendTelemetryEvent({
|
|
506
523
|
eventName: "ConnectionAttemptCancelled",
|
|
@@ -550,7 +567,7 @@ class ConnectionManager {
|
|
|
550
567
|
this.connection = undefined;
|
|
551
568
|
// Remove listeners first so we don't try to retrigger this flow accidentally through reconnectOnError
|
|
552
569
|
connection.off("op", this.opHandler);
|
|
553
|
-
connection.off("signal", this.
|
|
570
|
+
connection.off("signal", this.signalHandler);
|
|
554
571
|
connection.off("nack", this.nackHandler);
|
|
555
572
|
connection.off("disconnect", this.disconnectHandlerInternal);
|
|
556
573
|
connection.off("error", this.errorHandler);
|
|
@@ -603,7 +620,7 @@ class ConnectionManager {
|
|
|
603
620
|
// removed after those packages have released and become ubiquitous.
|
|
604
621
|
(0, core_utils_1.assert)(requestedMode === "read" || readonly === (this.connectionMode === "read"), 0x0e7 /* "claims/connectionMode mismatch" */);
|
|
605
622
|
(0, core_utils_1.assert)(!readonly || this.connectionMode === "read", 0x0e8 /* "readonly perf with write connection" */);
|
|
606
|
-
this.set_readonlyPermissions(readonly, oldReadonlyValue);
|
|
623
|
+
this.set_readonlyPermissions(readonly, oldReadonlyValue, isNoDeltaStreamConnection(connection) ? connection.readonlyConnectionReason : undefined);
|
|
607
624
|
if (this._disposed) {
|
|
608
625
|
// Raise proper events, Log telemetry event and close connection.
|
|
609
626
|
this.disconnectFromDeltaStream({ text: "ConnectionManager already closed" });
|
|
@@ -611,7 +628,7 @@ class ConnectionManager {
|
|
|
611
628
|
}
|
|
612
629
|
this._outbound.resume();
|
|
613
630
|
connection.on("op", this.opHandler);
|
|
614
|
-
connection.on("signal", this.
|
|
631
|
+
connection.on("signal", this.signalHandler);
|
|
615
632
|
connection.on("nack", this.nackHandler);
|
|
616
633
|
connection.on("disconnect", this.disconnectHandlerInternal);
|
|
617
634
|
connection.on("error", this.errorHandler);
|
|
@@ -662,26 +679,26 @@ class ConnectionManager {
|
|
|
662
679
|
type: protocol_1.SignalType.Clear,
|
|
663
680
|
}),
|
|
664
681
|
};
|
|
665
|
-
this
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
682
|
+
// list of signals to process due to this new connection
|
|
683
|
+
let signalsToProcess = [clearSignal];
|
|
684
|
+
const clientJoinSignals = (connection.initialClients ?? []).map((priorClient) => ({
|
|
685
|
+
clientId: null,
|
|
686
|
+
content: JSON.stringify({
|
|
687
|
+
type: protocol_1.SignalType.ClientJoin,
|
|
688
|
+
content: priorClient, // ISignalClient
|
|
689
|
+
}),
|
|
690
|
+
}));
|
|
691
|
+
if (clientJoinSignals.length > 0) {
|
|
692
|
+
signalsToProcess = signalsToProcess.concat(clientJoinSignals);
|
|
675
693
|
}
|
|
676
694
|
// Unfortunately, there is no defined order between initialSignals (including join & leave signals)
|
|
677
695
|
// and connection.initialClients. In practice, connection.initialSignals quite often contains join signal
|
|
678
696
|
// for "self" and connection.initialClients does not contain "self", so we have to process them after
|
|
679
697
|
// "clear" signal above.
|
|
680
|
-
if (connection.initialSignals !== undefined) {
|
|
681
|
-
|
|
682
|
-
this.props.signalHandler(signal);
|
|
683
|
-
}
|
|
698
|
+
if (connection.initialSignals !== undefined && connection.initialSignals.length > 0) {
|
|
699
|
+
signalsToProcess = signalsToProcess.concat(connection.initialSignals);
|
|
684
700
|
}
|
|
701
|
+
this.props.signalHandler(signalsToProcess);
|
|
685
702
|
}
|
|
686
703
|
/**
|
|
687
704
|
* Disconnect the current connection and reconnect. Closes the container if it fails.
|