@fluidframework/container-loader 1.2.7 → 2.0.0-dev.1.3.0.96595
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/.mocharc.js +12 -0
- package/dist/audience.d.ts +2 -6
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +6 -11
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.d.ts +29 -0
- package/dist/catchUpMonitor.d.ts.map +1 -0
- package/dist/catchUpMonitor.js +43 -0
- package/dist/catchUpMonitor.js.map +1 -0
- package/dist/collabWindowTracker.d.ts +1 -1
- package/dist/collabWindowTracker.d.ts.map +1 -1
- package/dist/collabWindowTracker.js +12 -4
- package/dist/collabWindowTracker.js.map +1 -1
- package/dist/connectionManager.d.ts +5 -5
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +43 -22
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionState.d.ts +0 -5
- package/dist/connectionState.d.ts.map +1 -1
- package/dist/connectionState.js +0 -5
- package/dist/connectionState.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +84 -22
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +172 -59
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +29 -17
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +181 -171
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +18 -7
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +18 -8
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +11 -25
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +51 -17
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +5 -5
- package/dist/contracts.js.map +1 -1
- package/dist/deltaManager.d.ts +4 -1
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +39 -12
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaManagerProxy.d.ts +4 -1
- package/dist/deltaManagerProxy.d.ts.map +1 -1
- package/dist/deltaQueue.d.ts +9 -2
- package/dist/deltaQueue.d.ts.map +1 -1
- package/dist/deltaQueue.js +31 -26
- package/dist/deltaQueue.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +8 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +4 -3
- package/dist/loader.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/protocol.d.ts +27 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +79 -0
- package/dist/protocol.js.map +1 -0
- package/dist/protocolTreeDocumentStorageService.d.ts +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts +2 -2
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +2 -2
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/lib/audience.d.ts +2 -6
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js +6 -11
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.d.ts +29 -0
- package/lib/catchUpMonitor.d.ts.map +1 -0
- package/lib/catchUpMonitor.js +39 -0
- package/lib/catchUpMonitor.js.map +1 -0
- package/lib/collabWindowTracker.d.ts +1 -1
- package/lib/collabWindowTracker.d.ts.map +1 -1
- package/lib/collabWindowTracker.js +13 -5
- package/lib/collabWindowTracker.js.map +1 -1
- package/lib/connectionManager.d.ts +5 -5
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +44 -25
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionState.d.ts +0 -5
- package/lib/connectionState.d.ts.map +1 -1
- package/lib/connectionState.js +0 -5
- package/lib/connectionState.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +84 -22
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +171 -59
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +29 -17
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +184 -174
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +18 -7
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +19 -9
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +11 -25
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +51 -16
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +5 -5
- package/lib/contracts.js.map +1 -1
- package/lib/deltaManager.d.ts +4 -1
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +41 -14
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaManagerProxy.d.ts +4 -1
- package/lib/deltaManagerProxy.d.ts.map +1 -1
- package/lib/deltaQueue.d.ts +9 -2
- package/lib/deltaQueue.d.ts.map +1 -1
- package/lib/deltaQueue.js +32 -27
- package/lib/deltaQueue.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/loader.d.ts +8 -1
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +4 -3
- package/lib/loader.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/protocol.d.ts +27 -0
- package/lib/protocol.d.ts.map +1 -0
- package/lib/protocol.js +75 -0
- package/lib/protocol.js.map +1 -0
- package/lib/protocolTreeDocumentStorageService.d.ts +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts +2 -2
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +2 -2
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/package.json +27 -19
- package/src/audience.ts +8 -14
- package/src/catchUpMonitor.ts +59 -0
- package/src/collabWindowTracker.ts +15 -6
- package/src/connectionManager.ts +56 -33
- package/src/connectionState.ts +0 -6
- package/src/connectionStateHandler.ts +235 -70
- package/src/container.ts +241 -218
- package/src/containerContext.ts +22 -8
- package/src/containerStorageAdapter.ts +71 -16
- package/src/contracts.ts +7 -7
- package/src/deltaManager.ts +48 -15
- package/src/deltaQueue.ts +34 -28
- package/src/index.ts +4 -0
- package/src/loader.ts +14 -3
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +120 -0
- package/src/retriableDocumentStorageService.ts +8 -2
package/.mocharc.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const getFluidTestMochaConfig = require('@fluidframework/mocha-test-setup/mocharc-common');
|
|
9
|
+
|
|
10
|
+
const packageDir = __dirname;
|
|
11
|
+
const config = getFluidTestMochaConfig(packageDir);
|
|
12
|
+
module.exports = config;
|
package/dist/audience.d.ts
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
import { EventEmitter } from "events";
|
|
7
|
-
import {
|
|
7
|
+
import { IAudienceOwner } from "@fluidframework/container-definitions";
|
|
8
8
|
import { IClient } from "@fluidframework/protocol-definitions";
|
|
9
9
|
/**
|
|
10
10
|
* Audience represents all clients connected to the op stream.
|
|
11
11
|
*/
|
|
12
|
-
export declare class Audience extends EventEmitter implements
|
|
12
|
+
export declare class Audience extends EventEmitter implements IAudienceOwner {
|
|
13
13
|
private readonly members;
|
|
14
14
|
on(event: "addMember" | "removeMember", listener: (clientId: string, client: IClient) => void): this;
|
|
15
15
|
/**
|
|
@@ -29,9 +29,5 @@ export declare class Audience extends EventEmitter implements IAudience {
|
|
|
29
29
|
* Retrieves a specific member of the audience
|
|
30
30
|
*/
|
|
31
31
|
getMember(clientId: string): IClient | undefined;
|
|
32
|
-
/**
|
|
33
|
-
* Clears the audience
|
|
34
|
-
*/
|
|
35
|
-
clear(): void;
|
|
36
32
|
}
|
|
37
33
|
//# sourceMappingURL=audience.d.ts.map
|
package/dist/audience.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audience.d.ts","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":";AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"audience.d.ts","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":";AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,sCAAsC,CAAC;AAE/D;;GAEG;AACH,qBAAa,QAAS,SAAQ,YAAa,YAAW,cAAc;IAChE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IAE/C,EAAE,CAAC,KAAK,EAAE,WAAW,GAAG,cAAc,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAK3G;;OAEG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IASnD;;;OAGG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAW9C;;OAEG;IACI,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAIzC;;OAEG;IACI,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;CAG1D"}
|
package/dist/audience.js
CHANGED
|
@@ -21,8 +21,12 @@ class Audience extends events_1.EventEmitter {
|
|
|
21
21
|
* Adds a new client to the audience
|
|
22
22
|
*/
|
|
23
23
|
addMember(clientId, details) {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
// Given that signal delivery is unreliable process, we might observe same client being added twice
|
|
25
|
+
// In such case we should see exactly same payload (IClient), and should not raise event twice!
|
|
26
|
+
if (!this.members.has(clientId)) {
|
|
27
|
+
this.members.set(clientId, details);
|
|
28
|
+
this.emit("addMember", clientId, details);
|
|
29
|
+
}
|
|
26
30
|
}
|
|
27
31
|
/**
|
|
28
32
|
* Removes a client from the audience. Only emits an event if a client is actually removed
|
|
@@ -51,15 +55,6 @@ class Audience extends events_1.EventEmitter {
|
|
|
51
55
|
getMember(clientId) {
|
|
52
56
|
return this.members.get(clientId);
|
|
53
57
|
}
|
|
54
|
-
/**
|
|
55
|
-
* Clears the audience
|
|
56
|
-
*/
|
|
57
|
-
clear() {
|
|
58
|
-
const clientIds = this.members.keys();
|
|
59
|
-
for (const clientId of clientIds) {
|
|
60
|
-
this.removeMember(clientId);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
58
|
}
|
|
64
59
|
exports.Audience = Audience;
|
|
65
60
|
//# sourceMappingURL=audience.js.map
|
package/dist/audience.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audience.js","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,mCAAsC;AAItC;;GAEG;AACH,MAAa,QAAS,SAAQ,qBAAY;IAA1C;;QACqB,YAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"audience.js","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,mCAAsC;AAItC;;GAEG;AACH,MAAa,QAAS,SAAQ,qBAAY;IAA1C;;QACqB,YAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;IA+C1D,CAAC;IA5CU,EAAE,CAAC,KAAa,EAAE,QAAkC;QACvD,OAAO,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,QAAgB,EAAE,OAAgB;QAC/C,mGAAmG;QACnG,+FAA+F;QAC/F,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YAC7B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;SAC7C;IACL,CAAC;IAED;;;OAGG;IACI,YAAY,CAAC,QAAgB;QAChC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,aAAa,KAAK,SAAS,EAAE;YAC7B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC;SACf;aAAM;YACH,OAAO,KAAK,CAAC;SAChB;IACL,CAAC;IAED;;OAEG;IACI,UAAU;QACb,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,QAAgB;QAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;CACJ;AAhDD,4BAgDC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { EventEmitter } from \"events\";\nimport { IAudienceOwner } from \"@fluidframework/container-definitions\";\nimport { IClient } from \"@fluidframework/protocol-definitions\";\n\n/**\n * Audience represents all clients connected to the op stream.\n */\nexport class Audience extends EventEmitter implements IAudienceOwner {\n private readonly members = new Map<string, IClient>();\n\n public on(event: \"addMember\" | \"removeMember\", listener: (clientId: string, client: IClient) => void): this;\n public on(event: string, listener: (...args: any[]) => void): this {\n return super.on(event, listener);\n }\n\n /**\n * Adds a new client to the audience\n */\n public addMember(clientId: string, details: IClient) {\n // Given that signal delivery is unreliable process, we might observe same client being added twice\n // In such case we should see exactly same payload (IClient), and should not raise event twice!\n if (!this.members.has(clientId)) {\n this.members.set(clientId, details);\n this.emit(\"addMember\", clientId, details);\n }\n }\n\n /**\n * Removes a client from the audience. Only emits an event if a client is actually removed\n * @returns if a client was removed from the audience\n */\n public removeMember(clientId: string): boolean {\n const removedClient = this.members.get(clientId);\n if (removedClient !== undefined) {\n this.members.delete(clientId);\n this.emit(\"removeMember\", clientId, removedClient);\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * Retrieves all the members in the audience\n */\n public getMembers(): Map<string, IClient> {\n return new Map(this.members);\n }\n\n /**\n * Retrieves a specific member of the audience\n */\n public getMember(clientId: string): IClient | undefined {\n return this.members.get(clientId);\n }\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { IDisposable } from "@fluidframework/common-definitions";
|
|
6
|
+
import { IDeltaManager } from "@fluidframework/container-definitions";
|
|
7
|
+
/** @see CatchUpMonitor for usage */
|
|
8
|
+
declare type CaughtUpListener = () => void;
|
|
9
|
+
/** Monitor that emits an event when a Container has caught up to a given point in the op stream */
|
|
10
|
+
export declare type ICatchUpMonitor = IDisposable;
|
|
11
|
+
/**
|
|
12
|
+
* Monitors a Container's DeltaManager, notifying listeners when all ops have been processed
|
|
13
|
+
* that were known at the time the monitor was created.
|
|
14
|
+
*/
|
|
15
|
+
export declare class CatchUpMonitor implements ICatchUpMonitor {
|
|
16
|
+
private readonly deltaManager;
|
|
17
|
+
private readonly listener;
|
|
18
|
+
private readonly targetSeqNumber;
|
|
19
|
+
private caughtUp;
|
|
20
|
+
private readonly opHandler;
|
|
21
|
+
/**
|
|
22
|
+
* Create the CatchUpMonitor, setting the target sequence number to wait for based on DeltaManager's current state.
|
|
23
|
+
*/
|
|
24
|
+
constructor(deltaManager: IDeltaManager<any, any>, listener: CaughtUpListener);
|
|
25
|
+
disposed: boolean;
|
|
26
|
+
dispose(): void;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=catchUpMonitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catchUpMonitor.d.ts","sourceRoot":"","sources":["../src/catchUpMonitor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAEjE,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAGtE,oCAAoC;AACpC,aAAK,gBAAgB,GAAG,MAAM,IAAI,CAAC;AAEnC,mGAAmG;AACnG,oBAAY,eAAe,GAAG,WAAW,CAAC;AAE1C;;;GAGG;AACH,qBAAa,cAAe,YAAW,eAAe;IAe9C,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAf7B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAkB;IAElC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAKxB;IAEF;;OAEG;gBAEkB,YAAY,EAAE,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,EACrC,QAAQ,EAAE,gBAAgB;IAaxC,QAAQ,EAAE,OAAO,CAAS;IAC1B,OAAO;CAQjB"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.CatchUpMonitor = void 0;
|
|
8
|
+
const common_utils_1 = require("@fluidframework/common-utils");
|
|
9
|
+
/**
|
|
10
|
+
* Monitors a Container's DeltaManager, notifying listeners when all ops have been processed
|
|
11
|
+
* that were known at the time the monitor was created.
|
|
12
|
+
*/
|
|
13
|
+
class CatchUpMonitor {
|
|
14
|
+
/**
|
|
15
|
+
* Create the CatchUpMonitor, setting the target sequence number to wait for based on DeltaManager's current state.
|
|
16
|
+
*/
|
|
17
|
+
constructor(deltaManager, listener) {
|
|
18
|
+
this.deltaManager = deltaManager;
|
|
19
|
+
this.listener = listener;
|
|
20
|
+
this.caughtUp = false;
|
|
21
|
+
this.opHandler = (message) => {
|
|
22
|
+
if (!this.caughtUp && message.sequenceNumber >= this.targetSeqNumber) {
|
|
23
|
+
this.caughtUp = true;
|
|
24
|
+
this.listener();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
this.disposed = false;
|
|
28
|
+
this.targetSeqNumber = this.deltaManager.lastKnownSeqNumber;
|
|
29
|
+
(0, common_utils_1.assert)(this.targetSeqNumber >= this.deltaManager.lastSequenceNumber, 0x37c /* Cannot wait for seqNumber below last processed sequence number */);
|
|
30
|
+
this.deltaManager.on("op", this.opHandler);
|
|
31
|
+
// Simulate the last processed op to set caughtUp in case we already are
|
|
32
|
+
this.opHandler({ sequenceNumber: this.deltaManager.lastSequenceNumber });
|
|
33
|
+
}
|
|
34
|
+
dispose() {
|
|
35
|
+
if (this.disposed) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this.disposed = true;
|
|
39
|
+
this.deltaManager.off("op", this.opHandler);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.CatchUpMonitor = CatchUpMonitor;
|
|
43
|
+
//# sourceMappingURL=catchUpMonitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catchUpMonitor.js","sourceRoot":"","sources":["../src/catchUpMonitor.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,+DAAsD;AAUtD;;;GAGG;AACH,MAAa,cAAc;IAWvB;;OAEG;IACH,YACqB,YAAqC,EACrC,QAA0B;QAD1B,iBAAY,GAAZ,YAAY,CAAyB;QACrC,aAAQ,GAAR,QAAQ,CAAkB;QAdvC,aAAQ,GAAY,KAAK,CAAC;QAEjB,cAAS,GAAG,CAAC,OAA0D,EAAE,EAAE;YACxF,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC,eAAe,EAAE;gBAClE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACrB,IAAI,CAAC,QAAQ,EAAE,CAAC;aACnB;QACL,CAAC,CAAC;QAoBK,aAAQ,GAAY,KAAK,CAAC;QAX7B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC;QAE5D,IAAA,qBAAM,EAAC,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,YAAY,CAAC,kBAAkB,EAC/D,KAAK,CAAC,oEAAoE,CAAC,CAAC;QAEhF,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAE3C,wEAAwE;QACxE,IAAI,CAAC,SAAS,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAC7E,CAAC;IAGM,OAAO;QACV,IAAI,IAAI,CAAC,QAAQ,EAAE;YACf,OAAO;SACV;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QAErB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAChD,CAAC;CACJ;AAtCD,wCAsCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IDisposable } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IDeltaManager } from \"@fluidframework/container-definitions\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\n\n/** @see CatchUpMonitor for usage */\ntype CaughtUpListener = () => void;\n\n/** Monitor that emits an event when a Container has caught up to a given point in the op stream */\nexport type ICatchUpMonitor = IDisposable;\n\n/**\n * Monitors a Container's DeltaManager, notifying listeners when all ops have been processed\n * that were known at the time the monitor was created.\n */\nexport class CatchUpMonitor implements ICatchUpMonitor {\n private readonly targetSeqNumber: number;\n private caughtUp: boolean = false;\n\n private readonly opHandler = (message: Pick<ISequencedDocumentMessage, \"sequenceNumber\">) => {\n if (!this.caughtUp && message.sequenceNumber >= this.targetSeqNumber) {\n this.caughtUp = true;\n this.listener();\n }\n };\n\n /**\n * Create the CatchUpMonitor, setting the target sequence number to wait for based on DeltaManager's current state.\n */\n constructor(\n private readonly deltaManager: IDeltaManager<any, any>,\n private readonly listener: CaughtUpListener,\n ) {\n this.targetSeqNumber = this.deltaManager.lastKnownSeqNumber;\n\n assert(this.targetSeqNumber >= this.deltaManager.lastSequenceNumber,\n 0x37c /* Cannot wait for seqNumber below last processed sequence number */);\n\n this.deltaManager.on(\"op\", this.opHandler);\n\n // Simulate the last processed op to set caughtUp in case we already are\n this.opHandler({ sequenceNumber: this.deltaManager.lastSequenceNumber });\n }\n\n public disposed: boolean = false;\n public dispose() {\n if (this.disposed) {\n return;\n }\n this.disposed = true;\n\n this.deltaManager.off(\"op\", this.opHandler);\n }\n}\n"]}
|
|
@@ -8,7 +8,7 @@ export declare class CollabWindowTracker {
|
|
|
8
8
|
private readonly NoopCountFrequency;
|
|
9
9
|
private opsCountSinceNoop;
|
|
10
10
|
private readonly timer;
|
|
11
|
-
constructor(submit: (type: MessageType
|
|
11
|
+
constructor(submit: (type: MessageType) => void, NoopTimeFrequency?: number, NoopCountFrequency?: number);
|
|
12
12
|
/**
|
|
13
13
|
* Schedules as ack to the server to update the reference sequence number
|
|
14
14
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collabWindowTracker.d.ts","sourceRoot":"","sources":["../src/collabWindowTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAyB9F,qBAAa,mBAAmB;IAKxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IANvC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;gBAGrB,MAAM,EAAE,CAAC,IAAI,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"collabWindowTracker.d.ts","sourceRoot":"","sources":["../src/collabWindowTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAyB9F,qBAAa,mBAAmB;IAKxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IANvC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;gBAGrB,MAAM,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,EACpD,iBAAiB,GAAE,MAAiC,EACnC,kBAAkB,GAAE,MAAkC;IAa3E;;OAEG;IACI,4BAA4B,CAAC,OAAO,EAAE,yBAAyB,EAAE,aAAa,EAAE,OAAO,GAAG,IAAI;IAuCrG,OAAO,CAAC,UAAU;IAQX,wBAAwB,IAAI,IAAI;CAS1C"}
|
|
@@ -62,9 +62,16 @@ class CollabWindowTracker {
|
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
64
|
this.opsCountSinceNoop++;
|
|
65
|
-
if (this.opsCountSinceNoop
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
if (this.opsCountSinceNoop === this.NoopCountFrequency) {
|
|
66
|
+
// Ensure we only send noop after a batch of many ops is processed
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
68
|
+
Promise.resolve().then(() => {
|
|
69
|
+
(0, common_utils_1.assert)(this.opsCountSinceNoop >= this.NoopCountFrequency, 0x3ae /* not enough ops were sent to reach the noop frequency */);
|
|
70
|
+
this.submitNoop(false /* immediate */);
|
|
71
|
+
// reset count now that all ops are processed
|
|
72
|
+
this.opsCountSinceNoop = 0;
|
|
73
|
+
return;
|
|
74
|
+
});
|
|
68
75
|
}
|
|
69
76
|
if (this.timer !== undefined) {
|
|
70
77
|
if (this.opsCountSinceNoop === 1) {
|
|
@@ -75,7 +82,8 @@ class CollabWindowTracker {
|
|
|
75
82
|
}
|
|
76
83
|
submitNoop(immediate) {
|
|
77
84
|
// Anything other than null is immediate noop
|
|
78
|
-
|
|
85
|
+
// ADO:1385: Remove cast and use MessageType once definition changes propagate
|
|
86
|
+
this.submit(immediate ? driver_utils_1.MessageType2.Accept : protocol_definitions_1.MessageType.NoOp);
|
|
79
87
|
(0, common_utils_1.assert)(this.opsCountSinceNoop === 0, 0x243 /* "stopSequenceNumberUpdate should be called as result of sending any op!" */);
|
|
80
88
|
}
|
|
81
89
|
stopSequenceNumberUpdate() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collabWindowTracker.js","sourceRoot":"","sources":["../src/collabWindowTracker.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAA6D;AAC7D,+EAA8F;AAC9F,+
|
|
1
|
+
{"version":3,"file":"collabWindowTracker.js","sourceRoot":"","sources":["../src/collabWindowTracker.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert, Timer } from \"@fluidframework/common-utils\";\nimport { ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { isRuntimeMessage, MessageType2 } from \"@fluidframework/driver-utils\";\n\nconst defaultNoopTimeFrequency = 2000;\nconst defaultNoopCountFrequency = 50;\n\n// Here are key considerations when deciding conditions for when to send non-immediate noops:\n// 1. Sending them too often results in increase in file size and bandwidth, as well as catch up performance\n// 2. Sending too infrequently ensures that collab window is large, and as result Sequence DDS would have\n// large catchUp blobs - see Issue #6364\n// 3. Similarly, processes that rely on \"core\" snapshot (and can't parse trailing ops, including above), like search\n// parser in SPO, will result in non-accurate results due to presence of catch up blobs.\n// 4. Ordering service used 250ms timeout to coalesce non-immediate noops. It was changed to 2000 ms to allow more\n// aggressive noop sending from client side.\n// 5. Number of ops sent by all clients is proportional to number of \"write\" clients (every client sends noops),\n// but number of sequenced noops is a function of time (one op per 2 seconds at most).\n// We should consider impact to both outbound traffic (might be huge, depends on number of clients) and file size.\n// Please also see Issue #5629 for more discussions.\n//\n// With that, the current algorithm is as follows:\n// 1. Sent noop 2000 ms of receiving an op if no ops were sent by this client within this timeframe.\n// This will ensure that MSN moves forward with reasonable speed. If that results in too many sequenced noops,\n// server timeout of 2000ms should be reconsidered to be increased.\n// 2. If there are more than 50 ops received without sending any ops, send noop to keep collab window small.\n// Note that system ops (including noops themselves) are excluded, so it's 1 noop per 50 real ops.\nexport class CollabWindowTracker {\n private opsCountSinceNoop = 0;\n private readonly timer: Timer | undefined;\n\n constructor(\n private readonly submit: (type: MessageType) => void,\n NoopTimeFrequency: number = defaultNoopTimeFrequency,\n private readonly NoopCountFrequency: number = defaultNoopCountFrequency,\n ) {\n if (NoopTimeFrequency !== Infinity) {\n this.timer = new Timer(NoopTimeFrequency, () => {\n // Can get here due to this.stopSequenceNumberUpdate() not resetting timer.\n // Also timer callback can fire even after timer cancellation if it was queued before cancellation.\n if (this.opsCountSinceNoop !== 0) {\n this.submitNoop(false /* immediate */);\n }\n });\n }\n }\n\n /**\n * Schedules as ack to the server to update the reference sequence number\n */\n public scheduleSequenceNumberUpdate(message: ISequencedDocumentMessage, immediateNoOp: boolean): void {\n // While processing a message, an immediate no-op can be requested.\n // i.e. to expedite approve or commit phase of quorum.\n if (immediateNoOp) {\n this.submitNoop(true /* immediate */);\n return;\n }\n\n // We don't acknowledge no-ops to avoid acknowledgement cycles (i.e. ack the MSN\n // update, which updates the MSN, then ack the update, etc...).\n // Intent here is for runtime (and DDSes) not to keep too much tracking state / memory\n // due to runtime ops from other clients.\n if (!isRuntimeMessage(message)) {\n return;\n }\n\n this.opsCountSinceNoop++;\n if (this.opsCountSinceNoop === this.NoopCountFrequency) {\n // Ensure we only send noop after a batch of many ops is processed\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n Promise.resolve().then(() => {\n assert(this.opsCountSinceNoop >= this.NoopCountFrequency,\n 0x3ae /* not enough ops were sent to reach the noop frequency */);\n this.submitNoop(false /* immediate */);\n // reset count now that all ops are processed\n this.opsCountSinceNoop = 0;\n return;\n });\n }\n\n if (this.timer !== undefined) {\n if (this.opsCountSinceNoop === 1) {\n this.timer.restart();\n }\n\n assert(this.timer.hasTimer, 0x242 /* \"has timer\" */);\n }\n }\n\n private submitNoop(immediate: boolean) {\n // Anything other than null is immediate noop\n // ADO:1385: Remove cast and use MessageType once definition changes propagate\n this.submit(immediate ? (MessageType2.Accept as unknown as MessageType) : MessageType.NoOp);\n assert(this.opsCountSinceNoop === 0,\n 0x243 /* \"stopSequenceNumberUpdate should be called as result of sending any op!\" */);\n }\n\n public stopSequenceNumberUpdate(): void {\n this.opsCountSinceNoop = 0;\n // Ideally, we cancel timer here. But that will result in too often set/reset cycle if this client\n // keeps sending ops. In most cases it's actually better to let it expire (at most - 4 times per second)\n // for nothing, then have a ton of set/reset cycles.\n // Note that Timer.restart() is smart and will not change timer expiration if we keep extending timer\n // expiration - it will restart the timer instead when it fires with adjusted expiration.\n // this.timer.clear();\n }\n}\n"]}
|
|
@@ -9,8 +9,8 @@ import { ConnectionMode, IClient, IClientConfiguration, IClientDetails, IDocumen
|
|
|
9
9
|
import { ReconnectMode, IConnectionManager, IConnectionManagerFactoryArgs } from "./contracts";
|
|
10
10
|
/**
|
|
11
11
|
* Implementation of IConnectionManager, used by Container class
|
|
12
|
-
* Implements constant connectivity to relay service, by reconnecting in case of
|
|
13
|
-
* Exposes various controls to
|
|
12
|
+
* Implements constant connectivity to relay service, by reconnecting in case of lost connection or error.
|
|
13
|
+
* Exposes various controls to influence this process, including manual reconnects, forced read-only mode, etc.
|
|
14
14
|
*/
|
|
15
15
|
export declare class ConnectionManager implements IConnectionManager {
|
|
16
16
|
private readonly serviceProvider;
|
|
@@ -39,7 +39,7 @@ export declare class ConnectionManager implements IConnectionManager {
|
|
|
39
39
|
private clientSequenceNumber;
|
|
40
40
|
private clientSequenceNumberObserved;
|
|
41
41
|
/** Counts the number of noops sent by the client which may not be acked. */
|
|
42
|
-
private
|
|
42
|
+
private localOpsToIgnore;
|
|
43
43
|
/** track clientId used last time when we sent any ops */
|
|
44
44
|
private lastSubmittedClientId;
|
|
45
45
|
private connectFirstConnection;
|
|
@@ -112,8 +112,8 @@ export declare class ConnectionManager implements IConnectionManager {
|
|
|
112
112
|
connect(connectionMode?: ConnectionMode): void;
|
|
113
113
|
private connectCore;
|
|
114
114
|
/**
|
|
115
|
-
* Start the connection. Any error should result in container being
|
|
116
|
-
* And report the error if it
|
|
115
|
+
* Start the connection. Any error should result in container being closed.
|
|
116
|
+
* And report the error if it escapes for any reason.
|
|
117
117
|
* @param args - The connection arguments
|
|
118
118
|
*/
|
|
119
119
|
private triggerConnect;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectionManager.d.ts","sourceRoot":"","sources":["../src/connectionManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAEH,gBAAgB,EAChB,oBAAoB,EACvB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EACH,WAAW,EACX,YAAY,EAEZ,uBAAuB,EAC1B,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EACH,gBAAgB,EAGnB,MAAM,oCAAoC,CAAC;AAY5C,OAAO,EACH,cAAc,EACd,OAAO,EACP,oBAAoB,EACpB,cAAc,EACd,gBAAgB,EAGhB,yBAAyB,EAO5B,MAAM,sCAAsC,CAAC;AAK9C,OAAO,EACH,aAAa,EACb,kBAAkB,EAClB,6BAA6B,EAChC,MAAM,aAAa,CAAC;AA8ErB;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,kBAAkB;
|
|
1
|
+
{"version":3,"file":"connectionManager.d.ts","sourceRoot":"","sources":["../src/connectionManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,7 @@ const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
|
16
16
|
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
17
17
|
const contracts_1 = require("./contracts");
|
|
18
18
|
const deltaQueue_1 = require("./deltaQueue");
|
|
19
|
+
const protocol_1 = require("./protocol");
|
|
19
20
|
const MaxReconnectDelayInMs = 8000;
|
|
20
21
|
const InitialReconnectDelayInMs = 1000;
|
|
21
22
|
const DefaultChunkSize = 16 * 1024;
|
|
@@ -47,7 +48,6 @@ class NoDeltaStream extends common_utils_1.TypedEventEmitter {
|
|
|
47
48
|
this.serviceConfiguration = {
|
|
48
49
|
maxMessageSize: 0,
|
|
49
50
|
blockSize: 0,
|
|
50
|
-
summary: undefined,
|
|
51
51
|
};
|
|
52
52
|
this.checkpointSequenceNumber = undefined;
|
|
53
53
|
this._disposed = false;
|
|
@@ -71,8 +71,8 @@ class NoDeltaStream extends common_utils_1.TypedEventEmitter {
|
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
73
|
* Implementation of IConnectionManager, used by Container class
|
|
74
|
-
* Implements constant connectivity to relay service, by reconnecting in case of
|
|
75
|
-
* Exposes various controls to
|
|
74
|
+
* Implements constant connectivity to relay service, by reconnecting in case of lost connection or error.
|
|
75
|
+
* Exposes various controls to influence this process, including manual reconnects, forced read-only mode, etc.
|
|
76
76
|
*/
|
|
77
77
|
class ConnectionManager {
|
|
78
78
|
constructor(serviceProvider, client, reconnectAllowed, logger, props) {
|
|
@@ -87,7 +87,7 @@ class ConnectionManager {
|
|
|
87
87
|
this.clientSequenceNumber = 0;
|
|
88
88
|
this.clientSequenceNumberObserved = 0;
|
|
89
89
|
/** Counts the number of noops sent by the client which may not be acked. */
|
|
90
|
-
this.
|
|
90
|
+
this.localOpsToIgnore = 0;
|
|
91
91
|
this.connectFirstConnection = true;
|
|
92
92
|
this._connectionVerboseProps = {};
|
|
93
93
|
this._connectionProps = {};
|
|
@@ -178,18 +178,15 @@ class ConnectionManager {
|
|
|
178
178
|
* about current or last connection (if there is no connection at the moment)
|
|
179
179
|
*/
|
|
180
180
|
get connectionProps() {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
else {
|
|
185
|
-
return Object.assign(Object.assign({}, this._connectionProps), {
|
|
181
|
+
return this.connection !== undefined
|
|
182
|
+
? this._connectionProps
|
|
183
|
+
: Object.assign(Object.assign({}, this._connectionProps), {
|
|
186
184
|
// Report how many ops this client sent in last disconnected session
|
|
187
185
|
sentOps: this.clientSequenceNumber });
|
|
188
|
-
}
|
|
189
186
|
}
|
|
190
187
|
shouldJoinWrite() {
|
|
191
188
|
// We don't have to wait for ack for topmost NoOps. So subtract those.
|
|
192
|
-
return this.clientSequenceNumberObserved < (this.clientSequenceNumber - this.
|
|
189
|
+
return this.clientSequenceNumberObserved < (this.clientSequenceNumber - this.localOpsToIgnore);
|
|
193
190
|
}
|
|
194
191
|
/**
|
|
195
192
|
* Tells if container is in read-only mode.
|
|
@@ -436,8 +433,8 @@ class ConnectionManager {
|
|
|
436
433
|
this.setupNewSuccessfulConnection(connection, requestedMode);
|
|
437
434
|
}
|
|
438
435
|
/**
|
|
439
|
-
* Start the connection. Any error should result in container being
|
|
440
|
-
* And report the error if it
|
|
436
|
+
* Start the connection. Any error should result in container being closed.
|
|
437
|
+
* And report the error if it escapes for any reason.
|
|
441
438
|
* @param args - The connection arguments
|
|
442
439
|
*/
|
|
443
440
|
triggerConnect(connectionMode) {
|
|
@@ -495,6 +492,7 @@ class ConnectionManager {
|
|
|
495
492
|
* @param connection - The newly established connection
|
|
496
493
|
*/
|
|
497
494
|
setupNewSuccessfulConnection(connection, requestedMode) {
|
|
495
|
+
var _a;
|
|
498
496
|
// Old connection should have been cleaned up before establishing a new one
|
|
499
497
|
(0, common_utils_1.assert)(this.connection === undefined, 0x0e6 /* "old connection exists on new connection setup" */);
|
|
500
498
|
(0, common_utils_1.assert)(!connection.disposed, 0x28a /* "can't be disposed - Callers need to ensure that!" */);
|
|
@@ -553,15 +551,39 @@ class ConnectionManager {
|
|
|
553
551
|
}
|
|
554
552
|
}
|
|
555
553
|
this.props.incomingOpHandler(initialMessages, this.connectFirstConnection ? "InitialOps" : "ReconnectOps");
|
|
554
|
+
const details = ConnectionManager.detailsFromConnection(connection);
|
|
555
|
+
details.checkpointSequenceNumber = checkpointSequenceNumber;
|
|
556
|
+
this.props.connectHandler(details);
|
|
557
|
+
this.connectFirstConnection = false;
|
|
558
|
+
// Synthesize clear & join signals out of initialClients state.
|
|
559
|
+
// This allows us to have single way to process signals, and makes it simpler to initialize
|
|
560
|
+
// protocol in Container.
|
|
561
|
+
const clearSignal = {
|
|
562
|
+
clientId: null,
|
|
563
|
+
content: JSON.stringify({
|
|
564
|
+
type: protocol_1.SignalType.Clear,
|
|
565
|
+
}),
|
|
566
|
+
};
|
|
567
|
+
this.props.signalHandler(clearSignal);
|
|
568
|
+
for (const priorClient of (_a = connection.initialClients) !== null && _a !== void 0 ? _a : []) {
|
|
569
|
+
const joinSignal = {
|
|
570
|
+
clientId: null,
|
|
571
|
+
content: JSON.stringify({
|
|
572
|
+
type: protocol_1.SignalType.ClientJoin,
|
|
573
|
+
content: priorClient, // ISignalClient
|
|
574
|
+
}),
|
|
575
|
+
};
|
|
576
|
+
this.props.signalHandler(joinSignal);
|
|
577
|
+
}
|
|
578
|
+
// Unfortunately, there is no defined order between initialSignals (including join & leave signals)
|
|
579
|
+
// and connection.initialClients. In practice, connection.initialSignals quite often contains join signal
|
|
580
|
+
// for "self" and connection.initialClients does not contain "self", so we have to process them after
|
|
581
|
+
// "clear" signal above.
|
|
556
582
|
if (connection.initialSignals !== undefined) {
|
|
557
583
|
for (const signal of connection.initialSignals) {
|
|
558
584
|
this.props.signalHandler(signal);
|
|
559
585
|
}
|
|
560
586
|
}
|
|
561
|
-
const details = ConnectionManager.detailsFromConnection(connection);
|
|
562
|
-
details.checkpointSequenceNumber = checkpointSequenceNumber;
|
|
563
|
-
this.props.connectHandler(details);
|
|
564
|
-
this.connectFirstConnection = false;
|
|
565
587
|
}
|
|
566
588
|
/**
|
|
567
589
|
* Disconnect the current connection and reconnect. Closes the container if it fails.
|
|
@@ -635,11 +657,11 @@ class ConnectionManager {
|
|
|
635
657
|
this.clientSequenceNumber = 0;
|
|
636
658
|
this.clientSequenceNumberObserved = 0;
|
|
637
659
|
}
|
|
638
|
-
if (
|
|
639
|
-
this.
|
|
660
|
+
if (!(0, driver_utils_1.isRuntimeMessage)(message)) {
|
|
661
|
+
this.localOpsToIgnore++;
|
|
640
662
|
}
|
|
641
663
|
else {
|
|
642
|
-
this.
|
|
664
|
+
this.localOpsToIgnore = 0;
|
|
643
665
|
}
|
|
644
666
|
return Object.assign(Object.assign({}, message), { clientSequenceNumber: ++this.clientSequenceNumber });
|
|
645
667
|
}
|
|
@@ -667,8 +689,7 @@ class ConnectionManager {
|
|
|
667
689
|
await this.reconnect("write", // connectionMode
|
|
668
690
|
"Switch to write");
|
|
669
691
|
}
|
|
670
|
-
})
|
|
671
|
-
.catch(() => { });
|
|
692
|
+
}).catch(() => { });
|
|
672
693
|
}
|
|
673
694
|
return;
|
|
674
695
|
}
|