@fluidframework/container-loader 2.0.0-rc.3.0.3 → 2.0.0-rc.4.0.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.
- package/CHANGELOG.md +17 -0
- package/api-report/container-loader.api.md +5 -1
- package/dist/attachment.d.ts +3 -2
- package/dist/attachment.d.ts.map +1 -1
- package/dist/attachment.js +5 -5
- package/dist/attachment.js.map +1 -1
- package/dist/audience.d.ts +6 -4
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +18 -3
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.d.ts +1 -1
- package/dist/catchUpMonitor.d.ts.map +1 -1
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts +7 -3
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +57 -38
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +31 -10
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +49 -36
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +22 -13
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +145 -117
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +3 -3
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +12 -3
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +42 -4
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +2 -2
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.d.ts +1 -2
- package/dist/debugLogger.d.ts.map +1 -1
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts +5 -6
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +29 -24
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.d.ts +1 -1
- package/dist/deltaQueue.d.ts.map +1 -1
- package/dist/deltaQueue.js.map +1 -1
- package/dist/error.d.ts +1 -2
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +2 -2
- package/dist/loadPaused.d.ts +35 -0
- package/dist/loadPaused.d.ts.map +1 -0
- package/dist/loadPaused.js +115 -0
- package/dist/loadPaused.js.map +1 -0
- package/dist/loader.d.ts +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +1 -14
- package/dist/loader.js.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js +4 -4
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
- 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.map +1 -1
- package/dist/protocol.js +3 -0
- package/dist/protocol.js.map +1 -1
- package/dist/public.d.ts +1 -1
- package/dist/retriableDocumentStorageService.d.ts +1 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/serializedStateManager.d.ts +89 -9
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +150 -34
- package/dist/serializedStateManager.js.map +1 -1
- package/dist/utils.d.ts +11 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +29 -14
- package/dist/utils.js.map +1 -1
- package/lib/attachment.d.ts +3 -2
- package/lib/attachment.d.ts.map +1 -1
- package/lib/attachment.js +5 -5
- package/lib/attachment.js.map +1 -1
- package/lib/audience.d.ts +6 -4
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js +19 -4
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.d.ts +1 -1
- package/lib/catchUpMonitor.d.ts.map +1 -1
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts +7 -3
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +36 -17
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +31 -10
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +49 -36
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +22 -13
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +146 -118
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +3 -3
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +12 -3
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +42 -4
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +2 -2
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.d.ts +1 -2
- package/lib/debugLogger.d.ts.map +1 -1
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts +5 -6
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +10 -5
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.d.ts +1 -1
- package/lib/deltaQueue.d.ts.map +1 -1
- package/lib/deltaQueue.js.map +1 -1
- package/lib/error.d.ts +1 -2
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +2 -2
- package/lib/loadPaused.d.ts +35 -0
- package/lib/loadPaused.d.ts.map +1 -0
- package/lib/loadPaused.js +111 -0
- package/lib/loadPaused.js.map +1 -0
- package/lib/loader.d.ts +1 -1
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +3 -16
- package/lib/loader.js.map +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
- 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.map +1 -1
- package/lib/protocol.js +3 -0
- package/lib/protocol.js.map +1 -1
- package/lib/public.d.ts +1 -1
- package/lib/retriableDocumentStorageService.d.ts +1 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +1 -1
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/serializedStateManager.d.ts +89 -9
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +146 -30
- package/lib/serializedStateManager.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/lib/utils.d.ts +11 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +15 -1
- package/lib/utils.js.map +1 -1
- package/package.json +24 -21
- package/src/attachment.ts +12 -13
- package/src/audience.ts +30 -9
- package/src/catchUpMonitor.ts +1 -1
- package/src/connectionManager.ts +45 -22
- package/src/connectionStateHandler.ts +78 -45
- package/src/container.ts +181 -160
- package/src/containerContext.ts +2 -2
- package/src/containerStorageAdapter.ts +61 -6
- package/src/contracts.ts +5 -4
- package/src/debugLogger.ts +1 -1
- package/src/deltaManager.ts +15 -8
- package/src/deltaQueue.ts +1 -1
- package/src/error.ts +1 -1
- package/src/index.ts +1 -0
- package/src/loadPaused.ts +140 -0
- package/src/loader.ts +6 -23
- package/src/location-redirection-utilities/resolveWithLocationRedirection.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +4 -0
- package/src/retriableDocumentStorageService.ts +5 -2
- package/src/serializedStateManager.ts +215 -48
- package/src/utils.ts +19 -1
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { IDeltaManager } from "@fluidframework/container-definitions";
|
|
6
|
+
import { IDeltaManager } from "@fluidframework/container-definitions/internal";
|
|
7
7
|
import { ITelemetryBaseProperties } from "@fluidframework/core-interfaces";
|
|
8
8
|
import { assert, Timer } from "@fluidframework/core-utils/internal";
|
|
9
|
-
import { IAnyDriverError } from "@fluidframework/driver-definitions";
|
|
9
|
+
import { IAnyDriverError } from "@fluidframework/driver-definitions/internal";
|
|
10
10
|
import { IClient, ISequencedClient } from "@fluidframework/protocol-definitions";
|
|
11
|
-
import { ITelemetryLoggerExt, type TelemetryEventCategory } from "@fluidframework/telemetry-utils";
|
|
12
11
|
import {
|
|
12
|
+
type TelemetryEventCategory,
|
|
13
|
+
ITelemetryLoggerExt,
|
|
13
14
|
PerformanceEvent,
|
|
14
15
|
loggerToMonitoringContext,
|
|
15
16
|
} from "@fluidframework/telemetry-utils/internal";
|
|
@@ -25,7 +26,7 @@ import { IProtocolHandler } from "./protocol.js";
|
|
|
25
26
|
const JoinOpTimeoutMs = 45000;
|
|
26
27
|
|
|
27
28
|
// Timeout waiting for "self" join signal, before giving up
|
|
28
|
-
const JoinSignalTimeoutMs =
|
|
29
|
+
const JoinSignalTimeoutMs = 10000;
|
|
29
30
|
|
|
30
31
|
/** Constructor parameter type for passing in dependencies needed by the ConnectionStateHandler */
|
|
31
32
|
export interface IConnectionStateHandlerInputs {
|
|
@@ -48,6 +49,9 @@ export interface IConnectionStateHandlerInputs {
|
|
|
48
49
|
) => void;
|
|
49
50
|
/** Callback to note that an old local client ID is still present in the Quorum that should have left and should now be considered invalid */
|
|
50
51
|
clientShouldHaveLeft: (clientId: string) => void;
|
|
52
|
+
|
|
53
|
+
/** Some critical error was hit. Container should be closed and error logged. */
|
|
54
|
+
onCriticalError: (error: unknown) => void;
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
/**
|
|
@@ -55,7 +59,19 @@ export interface IConnectionStateHandlerInputs {
|
|
|
55
59
|
*/
|
|
56
60
|
export interface IConnectionStateHandler {
|
|
57
61
|
readonly connectionState: ConnectionState;
|
|
62
|
+
/**
|
|
63
|
+
* Pending clientID.
|
|
64
|
+
* Changes whenever socket connection is established.
|
|
65
|
+
* Resets to undefined when connection is lost
|
|
66
|
+
*/
|
|
58
67
|
readonly pendingClientId: string | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* clientId of a last established connection.
|
|
70
|
+
* Does not reset on disconnect.
|
|
71
|
+
* Changes only when new connection is established, client is fully caught up, and
|
|
72
|
+
* there is no chance to ops from previous connection (i.e. if needed, we have waited and observed leave op from previous connection)
|
|
73
|
+
*/
|
|
74
|
+
readonly clientId: string | undefined;
|
|
59
75
|
|
|
60
76
|
containerSaved(): void;
|
|
61
77
|
dispose(): void;
|
|
@@ -78,8 +94,8 @@ export function createConnectionStateHandler(
|
|
|
78
94
|
) {
|
|
79
95
|
const mc = loggerToMonitoringContext(inputs.logger);
|
|
80
96
|
return createConnectionStateHandlerCore(
|
|
81
|
-
mc.config.getBoolean("Fluid.Container.
|
|
82
|
-
mc.config.getBoolean("Fluid.Container.
|
|
97
|
+
mc.config.getBoolean("Fluid.Container.DisableCatchUpBeforeDeclaringConnected") !== true, // connectedRaisedWhenCaughtUp
|
|
98
|
+
mc.config.getBoolean("Fluid.Container.DisableJoinSignalWait") !== true, // readClientsWaitForJoinSignal
|
|
83
99
|
inputs,
|
|
84
100
|
deltaManager,
|
|
85
101
|
clientId,
|
|
@@ -93,15 +109,12 @@ export function createConnectionStateHandlerCore(
|
|
|
93
109
|
deltaManager: IDeltaManager<any, any>,
|
|
94
110
|
clientId?: string,
|
|
95
111
|
) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return
|
|
100
|
-
inputs,
|
|
101
|
-
|
|
102
|
-
new ConnectionStateHandler(handler, readClientsWaitForJoinSignal, clientId),
|
|
103
|
-
deltaManager,
|
|
104
|
-
);
|
|
112
|
+
const factory = (handler: IConnectionStateHandlerInputs) =>
|
|
113
|
+
new ConnectionStateHandler(handler, readClientsWaitForJoinSignal, clientId);
|
|
114
|
+
|
|
115
|
+
return connectedRaisedWhenCaughtUp
|
|
116
|
+
? new ConnectionStateCatchup(inputs, factory, deltaManager)
|
|
117
|
+
: factory(inputs);
|
|
105
118
|
}
|
|
106
119
|
|
|
107
120
|
/**
|
|
@@ -140,6 +153,9 @@ class ConnectionStateHandlerPassThrough
|
|
|
140
153
|
public get pendingClientId() {
|
|
141
154
|
return this.pimpl.pendingClientId;
|
|
142
155
|
}
|
|
156
|
+
public get clientId() {
|
|
157
|
+
return this.pimpl.clientId;
|
|
158
|
+
}
|
|
143
159
|
|
|
144
160
|
public containerSaved() {
|
|
145
161
|
return this.pimpl.containerSaved();
|
|
@@ -196,6 +212,10 @@ class ConnectionStateHandlerPassThrough
|
|
|
196
212
|
public clientShouldHaveLeft(clientId: string) {
|
|
197
213
|
return this.inputs.clientShouldHaveLeft(clientId);
|
|
198
214
|
}
|
|
215
|
+
|
|
216
|
+
public onCriticalError(error: unknown) {
|
|
217
|
+
return this.inputs.onCriticalError(error);
|
|
218
|
+
}
|
|
199
219
|
}
|
|
200
220
|
|
|
201
221
|
/**
|
|
@@ -325,7 +345,7 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
325
345
|
/**
|
|
326
346
|
* Tracks that we observe our own "join" op within the timeout after receiving a "connected" event from the DeltaManager
|
|
327
347
|
*/
|
|
328
|
-
private readonly
|
|
348
|
+
private readonly joinTimer: Timer;
|
|
329
349
|
|
|
330
350
|
private protocol?: IProtocolHandler;
|
|
331
351
|
private connection?: IConnectionDetailsInternal;
|
|
@@ -338,7 +358,7 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
338
358
|
return this._connectionState;
|
|
339
359
|
}
|
|
340
360
|
|
|
341
|
-
|
|
361
|
+
public get clientId(): string | undefined {
|
|
342
362
|
return this._clientId;
|
|
343
363
|
}
|
|
344
364
|
|
|
@@ -352,6 +372,7 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
352
372
|
clientIdFromPausedSession?: string,
|
|
353
373
|
) {
|
|
354
374
|
this._clientId = clientIdFromPausedSession;
|
|
375
|
+
const errorHandler = (error) => this.handler.onCriticalError(error);
|
|
355
376
|
this.prevClientLeftTimer = new Timer(
|
|
356
377
|
// Default is 5 min for which we are going to wait for its own "leave" message. This is same as
|
|
357
378
|
// the max time on server after which leave op is sent.
|
|
@@ -363,10 +384,11 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
363
384
|
);
|
|
364
385
|
this.applyForConnectedState("timeout");
|
|
365
386
|
},
|
|
387
|
+
errorHandler,
|
|
366
388
|
);
|
|
367
389
|
|
|
368
|
-
this.
|
|
369
|
-
0, // default value is not used -
|
|
390
|
+
this.joinTimer = new Timer(
|
|
391
|
+
0, // default value is not used - startjoinTimer() explicitly provides timeout
|
|
370
392
|
() => {
|
|
371
393
|
// I've observed timer firing within couple ms from disconnect event, looks like
|
|
372
394
|
// queued timer callback is not cancelled if timer is cancelled while callback sits in the queue.
|
|
@@ -379,22 +401,27 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
379
401
|
clientJoined: this.hasMember(this.pendingClientId),
|
|
380
402
|
waitingForLeaveOp: this.waitingForLeaveOp,
|
|
381
403
|
};
|
|
382
|
-
this.handler.logConnectionIssue(
|
|
404
|
+
this.handler.logConnectionIssue(
|
|
405
|
+
this.connection?.mode === "read" ? "NoJoinSignal" : "NoJoinOp", // eventName
|
|
406
|
+
"error", // category
|
|
407
|
+
details,
|
|
408
|
+
);
|
|
383
409
|
},
|
|
410
|
+
errorHandler,
|
|
384
411
|
);
|
|
385
412
|
}
|
|
386
413
|
|
|
387
|
-
private
|
|
388
|
-
assert(!this.
|
|
414
|
+
private startjoinTimer() {
|
|
415
|
+
assert(!this.joinTimer.hasTimer, 0x234 /* "has joinTimer" */);
|
|
389
416
|
assert(this.connection !== undefined, 0x4b3 /* have connection */);
|
|
390
|
-
this.
|
|
417
|
+
this.joinTimer.start(
|
|
391
418
|
this.connection.mode === "write" ? JoinOpTimeoutMs : JoinSignalTimeoutMs,
|
|
392
419
|
);
|
|
393
420
|
}
|
|
394
421
|
|
|
395
|
-
private
|
|
396
|
-
assert(this.
|
|
397
|
-
this.
|
|
422
|
+
private stopjoinTimer() {
|
|
423
|
+
assert(this.joinTimer.hasTimer, 0x235 /* "no joinTimer" */);
|
|
424
|
+
this.joinTimer.clear();
|
|
398
425
|
}
|
|
399
426
|
|
|
400
427
|
private get waitingForLeaveOp() {
|
|
@@ -402,7 +429,7 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
402
429
|
}
|
|
403
430
|
|
|
404
431
|
public dispose() {
|
|
405
|
-
assert(!this.
|
|
432
|
+
assert(!this.joinTimer.hasTimer, 0x2a5 /* "join timer" */);
|
|
406
433
|
this.prevClientLeftTimer.clear();
|
|
407
434
|
}
|
|
408
435
|
|
|
@@ -418,15 +445,18 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
418
445
|
private receivedAddMemberEvent(clientId: string) {
|
|
419
446
|
// This is the only one that requires the pending client ID
|
|
420
447
|
if (clientId === this.pendingClientId) {
|
|
421
|
-
if (this.
|
|
422
|
-
this.
|
|
423
|
-
} else if (this.
|
|
448
|
+
if (this.joinTimer.hasTimer) {
|
|
449
|
+
this.stopjoinTimer();
|
|
450
|
+
} else if (this.shouldWaitForSelf()) {
|
|
424
451
|
// timer has already fired, meaning it took too long to get join op/signal.
|
|
425
452
|
// Record how long it actually took to recover.
|
|
426
453
|
// This is generic event, as it by itself is not an error.
|
|
427
454
|
// We also have a case where NoJoinOp happens during container boot (we do not report it as error in such case),
|
|
428
455
|
// if this log statement happens after boot - we do not want to consider it error case.
|
|
429
|
-
this.handler.logConnectionIssue(
|
|
456
|
+
this.handler.logConnectionIssue(
|
|
457
|
+
this.connection?.mode === "read" ? "ReceivedJoinSignal" : "ReceivedJoinOp", // eventName
|
|
458
|
+
"generic", // category
|
|
459
|
+
);
|
|
430
460
|
}
|
|
431
461
|
// Start the event in case we are waiting for leave or timeout.
|
|
432
462
|
if (this.waitingForLeaveOp) {
|
|
@@ -514,7 +544,7 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
514
544
|
this._connectionState === ConnectionState.EstablishingConnection,
|
|
515
545
|
0x6d3 /* Connection state should be EstablishingConnection */,
|
|
516
546
|
);
|
|
517
|
-
assert(this.connection === undefined, 0x6d4 /* No
|
|
547
|
+
assert(this.connection === undefined, 0x6d4 /* No connection should be present */);
|
|
518
548
|
const oldState = this._connectionState;
|
|
519
549
|
this._connectionState = ConnectionState.Disconnected;
|
|
520
550
|
this.handler.connectionStateChanged(ConnectionState.Disconnected, oldState, reason);
|
|
@@ -529,7 +559,12 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
529
559
|
});
|
|
530
560
|
}
|
|
531
561
|
|
|
532
|
-
|
|
562
|
+
/**
|
|
563
|
+
* Tells if need to wait for "self" to show up in audience.
|
|
564
|
+
* @returns - true if we should wait for "self" to appear in audience.
|
|
565
|
+
* false is returned only for "read" connections, and only if this.readClientsWaitForJoinSignal is false.
|
|
566
|
+
*/
|
|
567
|
+
private shouldWaitForSelf() {
|
|
533
568
|
assert(
|
|
534
569
|
this.connection !== undefined,
|
|
535
570
|
0x4b4 /* all callers call here with active connection */,
|
|
@@ -576,10 +611,10 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
576
611
|
// We are fetching ops from storage in parallel to connecting to Relay Service,
|
|
577
612
|
// and given async processes, it's possible that we have already processed our own join message before
|
|
578
613
|
// connection was fully established.
|
|
579
|
-
if (!this.hasMember(this._pendingClientId) && this.
|
|
614
|
+
if (!this.hasMember(this._pendingClientId) && this.shouldWaitForSelf()) {
|
|
580
615
|
// We are waiting for our own join op / signal. When it is processed
|
|
581
616
|
// we'll attempt to transition to Connected state via receivedAddMemberEvent() flow.
|
|
582
|
-
this.
|
|
617
|
+
this.startjoinTimer();
|
|
583
618
|
} else if (!this.waitingForLeaveOp) {
|
|
584
619
|
// We're not waiting for Join or Leave op (if read-only connection those don't even apply),
|
|
585
620
|
// go ahead and declare the state to be Connected!
|
|
@@ -628,8 +663,8 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
628
663
|
// Clear pending state immediately to prepare for reconnect
|
|
629
664
|
this._pendingClientId = undefined;
|
|
630
665
|
|
|
631
|
-
if (this.
|
|
632
|
-
this.
|
|
666
|
+
if (this.joinTimer.hasTimer) {
|
|
667
|
+
this.stopjoinTimer();
|
|
633
668
|
}
|
|
634
669
|
|
|
635
670
|
// Only wait for "leave" message if the connected client exists in the quorum and had some non-acked ops
|
|
@@ -660,15 +695,10 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
660
695
|
this.handler.connectionStateChanged(this._connectionState, oldState, reason);
|
|
661
696
|
}
|
|
662
697
|
|
|
663
|
-
// Helper method to switch between quorum and audience.
|
|
664
|
-
// Old design was checking only quorum for "write" clients.
|
|
665
|
-
// Latest change checks audience for all types of connections.
|
|
666
698
|
protected get membership(): IMembership | undefined {
|
|
667
|
-
// We could always use audience here
|
|
668
|
-
//
|
|
669
|
-
//
|
|
670
|
-
// It's safer to assume that we have bugs and engaging kill-bit switch should bring us back to well-known
|
|
671
|
-
// and tested state!
|
|
699
|
+
// We could always use audience here.
|
|
700
|
+
// This is true because Audience is a superset of quorum, i.e. when we filter Audience to "write" clients,
|
|
701
|
+
// it is exactly the same as quorum! Please see asserts in Audience callbacks setup by initProtocol() enforcing that.
|
|
672
702
|
return this.readClientsWaitForJoinSignal ? this.protocol?.audience : this.protocol?.quorum;
|
|
673
703
|
}
|
|
674
704
|
|
|
@@ -676,6 +706,9 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
676
706
|
this.protocol = protocol;
|
|
677
707
|
|
|
678
708
|
this.membership?.on("addMember", (clientId, details) => {
|
|
709
|
+
// This is very important constrain. We rely on it when testing presence of "self" in Audience.
|
|
710
|
+
// We do not want to move to "connected" state for "write" connections when JoinSignal shows up
|
|
711
|
+
// for "self" - we want to move to "connected" state only when "join" op is received.
|
|
679
712
|
assert(
|
|
680
713
|
(details as IClient).mode === "read" ||
|
|
681
714
|
protocol.quorum.getMember(clientId) !== undefined,
|