@fluidframework/container-loader 2.0.0-dev.5.2.0.169897 → 2.0.0-dev.6.4.0.191258
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 +162 -0
- package/README.md +10 -6
- package/dist/audience.d.ts +1 -0
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +5 -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 +2 -2
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts +6 -6
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +97 -93
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +19 -15
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +59 -59
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +48 -38
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +447 -325
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +22 -70
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +24 -221
- 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 +47 -16
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +21 -10
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +3 -3
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.d.ts +30 -0
- package/dist/debugLogger.d.ts.map +1 -0
- package/dist/debugLogger.js +95 -0
- package/dist/debugLogger.js.map +1 -0
- package/dist/deltaManager.d.ts +21 -9
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +114 -66
- 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 +10 -10
- package/dist/deltaQueue.js.map +1 -1
- package/dist/disposal.d.ts +13 -0
- package/dist/disposal.d.ts.map +1 -0
- package/dist/disposal.js +25 -0
- package/dist/disposal.js.map +1 -0
- package/dist/error.d.ts +23 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +32 -0
- package/dist/error.js.map +1 -0
- package/dist/loader.d.ts +23 -5
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +82 -51
- package/dist/loader.js.map +1 -1
- package/dist/noopHeuristic.d.ts +23 -0
- package/dist/noopHeuristic.d.ts.map +1 -0
- package/dist/noopHeuristic.js +90 -0
- package/dist/noopHeuristic.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 +9 -12
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +26 -7
- package/dist/protocol.js.map +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts +1 -1
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/quorum.d.ts +1 -14
- package/dist/quorum.d.ts.map +1 -1
- package/dist/quorum.js +1 -29
- package/dist/quorum.js.map +1 -1
- package/dist/retriableDocumentStorageService.d.ts +1 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js +4 -4
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/utils.d.ts +8 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +30 -11
- package/dist/utils.js.map +1 -1
- package/lib/audience.d.ts +1 -0
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js +4 -2
- 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 +1 -1
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts +6 -6
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +74 -67
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +19 -15
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +36 -36
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +48 -38
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +414 -292
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +22 -70
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +24 -221
- 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 +43 -12
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +21 -10
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js +3 -3
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.d.ts +30 -0
- package/lib/debugLogger.d.ts.map +1 -0
- package/lib/debugLogger.js +91 -0
- package/lib/debugLogger.js.map +1 -0
- package/lib/deltaManager.d.ts +21 -9
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +88 -37
- 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 +3 -3
- package/lib/deltaQueue.js.map +1 -1
- package/lib/disposal.d.ts +13 -0
- package/lib/disposal.d.ts.map +1 -0
- package/lib/disposal.js +21 -0
- package/lib/disposal.js.map +1 -0
- package/lib/error.d.ts +23 -0
- package/lib/error.d.ts.map +1 -0
- package/lib/error.js +28 -0
- package/lib/error.js.map +1 -0
- package/lib/loader.d.ts +23 -5
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +82 -51
- package/lib/loader.js.map +1 -1
- package/lib/noopHeuristic.d.ts +23 -0
- package/lib/noopHeuristic.d.ts.map +1 -0
- package/lib/{collabWindowTracker.js → noopHeuristic.js} +31 -42
- package/lib/noopHeuristic.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 +9 -12
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +24 -6
- package/lib/protocol.js.map +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts +1 -1
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/quorum.d.ts +1 -14
- package/lib/quorum.d.ts.map +1 -1
- package/lib/quorum.js +0 -26
- package/lib/quorum.js.map +1 -1
- package/lib/retriableDocumentStorageService.d.ts +1 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +2 -2
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/utils.d.ts +8 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +25 -7
- package/lib/utils.js.map +1 -1
- package/package.json +26 -28
- package/src/audience.ts +7 -1
- package/src/catchUpMonitor.ts +2 -2
- package/src/connectionManager.ts +76 -52
- package/src/connectionStateHandler.ts +46 -48
- package/src/container.ts +561 -326
- package/src/containerContext.ts +31 -349
- package/src/containerStorageAdapter.ts +49 -6
- package/src/contracts.ts +27 -13
- package/src/debugLogger.ts +113 -0
- package/src/deltaManager.ts +93 -36
- package/src/deltaQueue.ts +2 -1
- package/src/disposal.ts +25 -0
- package/src/error.ts +44 -0
- package/src/loader.ts +84 -36
- package/src/{collabWindowTracker.ts → noopHeuristic.ts} +38 -47
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +26 -16
- package/src/protocolTreeDocumentStorageService.ts +1 -1
- package/src/quorum.ts +1 -40
- package/src/retriableDocumentStorageService.ts +3 -4
- package/src/utils.ts +33 -8
- package/dist/collabWindowTracker.d.ts +0 -19
- package/dist/collabWindowTracker.d.ts.map +0 -1
- package/dist/collabWindowTracker.js +0 -101
- package/dist/collabWindowTracker.js.map +0 -1
- package/dist/deltaManagerProxy.d.ts +0 -42
- package/dist/deltaManagerProxy.d.ts.map +0 -1
- package/dist/deltaManagerProxy.js +0 -79
- package/dist/deltaManagerProxy.js.map +0 -1
- package/lib/collabWindowTracker.d.ts +0 -19
- package/lib/collabWindowTracker.d.ts.map +0 -1
- package/lib/collabWindowTracker.js.map +0 -1
- package/lib/deltaManagerProxy.d.ts +0 -42
- package/lib/deltaManagerProxy.d.ts.map +0 -1
- package/lib/deltaManagerProxy.js +0 -74
- package/lib/deltaManagerProxy.js.map +0 -1
- package/src/deltaManagerProxy.ts +0 -109
package/lib/audience.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audience.js","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"audience.js","sourceRoot":"","sources":["../src/audience.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAIpD;;GAEG;AACH,MAAM,OAAO,QAAS,SAAQ,YAAY;IAGzC;QACC,KAAK,EAAE,CAAC;QAHQ,YAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;QAIrD,kHAAkH;QAClH,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IAMM,EAAE,CAAC,KAAa,EAAE,QAAkC;QAC1D,OAAO,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,QAAgB,EAAE,OAAgB;QAClD,mGAAmG;QACnG,+FAA+F;QAC/F,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC1C,MAAM,CACL,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAClD,KAAK,CAAC,wDAAwD,CAC9D,CAAC;SACF;aAAM;YACN,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;SAC1C;IACF,CAAC;IAED;;;OAGG;IACI,YAAY,CAAC,QAAgB;QACnC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,aAAa,KAAK,SAAS,EAAE;YAChC,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;SACZ;aAAM;YACN,OAAO,KAAK,CAAC;SACb;IACF,CAAC;IAED;;OAEG;IACI,UAAU;QAChB,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACI,SAAS,CAAC,QAAgB;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { EventEmitter } from \"events\";\nimport { assert } from \"@fluidframework/core-utils\";\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\tprivate readonly members = new Map<string, IClient>();\n\n\tconstructor() {\n\t\tsuper();\n\t\t// We are expecting this class to have many listeners, so we suppress noisy \"MaxListenersExceededWarning\" logging.\n\t\tsuper.setMaxListeners(0);\n\t}\n\n\tpublic on(\n\t\tevent: \"addMember\" | \"removeMember\",\n\t\tlistener: (clientId: string, client: IClient) => void,\n\t): this;\n\tpublic on(event: string, listener: (...args: any[]) => void): this {\n\t\treturn super.on(event, listener);\n\t}\n\n\t/**\n\t * Adds a new client to the audience\n\t */\n\tpublic addMember(clientId: string, details: IClient) {\n\t\t// Given that signal delivery is unreliable process, we might observe same client being added twice\n\t\t// In such case we should see exactly same payload (IClient), and should not raise event twice!\n\t\tif (this.members.has(clientId)) {\n\t\t\tconst client = this.members.get(clientId);\n\t\t\tassert(\n\t\t\t\tJSON.stringify(client) === JSON.stringify(details),\n\t\t\t\t0x4b2 /* new client has different payload from existing one */,\n\t\t\t);\n\t\t} else {\n\t\t\tthis.members.set(clientId, details);\n\t\t\tthis.emit(\"addMember\", clientId, details);\n\t\t}\n\t}\n\n\t/**\n\t * Removes a client from the audience. Only emits an event if a client is actually removed\n\t * @returns if a client was removed from the audience\n\t */\n\tpublic removeMember(clientId: string): boolean {\n\t\tconst removedClient = this.members.get(clientId);\n\t\tif (removedClient !== undefined) {\n\t\t\tthis.members.delete(clientId);\n\t\t\tthis.emit(\"removeMember\", clientId, removedClient);\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Retrieves all the members in the audience\n\t */\n\tpublic getMembers(): Map<string, IClient> {\n\t\treturn new Map(this.members);\n\t}\n\n\t/**\n\t * Retrieves a specific member of the audience\n\t */\n\tpublic getMember(clientId: string): IClient | undefined {\n\t\treturn this.members.get(clientId);\n\t}\n}\n"]}
|
package/lib/catchUpMonitor.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { IDisposable } from "@fluidframework/
|
|
5
|
+
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
6
6
|
import { IDeltaManager } from "@fluidframework/container-definitions";
|
|
7
7
|
/** @see CatchUpMonitor for usage */
|
|
8
8
|
declare type CaughtUpListener = () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catchUpMonitor.d.ts","sourceRoot":"","sources":["../src/catchUpMonitor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"catchUpMonitor.d.ts","sourceRoot":"","sources":["../src/catchUpMonitor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,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;IAepD,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAf1B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAkB;IAElC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAKxB;IAEF;;OAEG;gBAEe,YAAY,EAAE,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,EACrC,QAAQ,EAAE,gBAAgB;IAerC,QAAQ,EAAE,OAAO,CAAS;IAC1B,OAAO;CAQd"}
|
package/lib/catchUpMonitor.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { assert } from "@fluidframework/
|
|
5
|
+
import { assert } from "@fluidframework/core-utils";
|
|
6
6
|
/**
|
|
7
7
|
* Monitors a Container's DeltaManager, notifying listeners when all ops have been processed
|
|
8
8
|
* that were known at the time the monitor was created.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catchUpMonitor.js","sourceRoot":"","sources":["../src/catchUpMonitor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"catchUpMonitor.js","sourceRoot":"","sources":["../src/catchUpMonitor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAUpD;;;GAGG;AACH,MAAM,OAAO,cAAc;IAW1B;;OAEG;IACH,YACkB,YAAqC,EACrC,QAA0B;QAD1B,iBAAY,GAAZ,YAAY,CAAyB;QACrC,aAAQ,GAAR,QAAQ,CAAkB;QAdpC,aAAQ,GAAY,KAAK,CAAC;QAEjB,cAAS,GAAG,CAAC,OAA0D,EAAE,EAAE;YAC3F,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC,eAAe,EAAE;gBACrE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACrB,IAAI,CAAC,QAAQ,EAAE,CAAC;aAChB;QACF,CAAC,CAAC;QAsBK,aAAQ,GAAY,KAAK,CAAC;QAbhC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC;QAE5D,MAAM,CACL,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,YAAY,CAAC,kBAAkB,EAC5D,KAAK,CAAC,oEAAoE,CAC1E,CAAC;QAEF,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;IAC1E,CAAC;IAGM,OAAO;QACb,IAAI,IAAI,CAAC,QAAQ,EAAE;YAClB,OAAO;SACP;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QAErB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IDisposable } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-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\tprivate readonly targetSeqNumber: number;\n\tprivate caughtUp: boolean = false;\n\n\tprivate readonly opHandler = (message: Pick<ISequencedDocumentMessage, \"sequenceNumber\">) => {\n\t\tif (!this.caughtUp && message.sequenceNumber >= this.targetSeqNumber) {\n\t\t\tthis.caughtUp = true;\n\t\t\tthis.listener();\n\t\t}\n\t};\n\n\t/**\n\t * Create the CatchUpMonitor, setting the target sequence number to wait for based on DeltaManager's current state.\n\t */\n\tconstructor(\n\t\tprivate readonly deltaManager: IDeltaManager<any, any>,\n\t\tprivate readonly listener: CaughtUpListener,\n\t) {\n\t\tthis.targetSeqNumber = this.deltaManager.lastKnownSeqNumber;\n\n\t\tassert(\n\t\t\tthis.targetSeqNumber >= this.deltaManager.lastSequenceNumber,\n\t\t\t0x37c /* Cannot wait for seqNumber below last processed sequence number */,\n\t\t);\n\n\t\tthis.deltaManager.on(\"op\", this.opHandler);\n\n\t\t// Simulate the last processed op to set caughtUp in case we already are\n\t\tthis.opHandler({ sequenceNumber: this.deltaManager.lastSequenceNumber });\n\t}\n\n\tpublic disposed: boolean = false;\n\tpublic dispose() {\n\t\tif (this.disposed) {\n\t\t\treturn;\n\t\t}\n\t\tthis.disposed = true;\n\n\t\tthis.deltaManager.off(\"op\", this.opHandler);\n\t}\n}\n"]}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { ITelemetryProperties } from "@fluidframework/
|
|
6
|
-
import { IDeltaQueue, ReadOnlyInfo
|
|
5
|
+
import { ITelemetryProperties } from "@fluidframework/core-interfaces";
|
|
6
|
+
import { ICriticalContainerError, IDeltaQueue, ReadOnlyInfo } from "@fluidframework/container-definitions";
|
|
7
7
|
import { IDocumentService } from "@fluidframework/driver-definitions";
|
|
8
8
|
import { ConnectionMode, IClient, IClientConfiguration, IClientDetails, IDocumentMessage, ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
9
9
|
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
10
|
-
import { ReconnectMode, IConnectionManager, IConnectionManagerFactoryArgs } from "./contracts";
|
|
10
|
+
import { ReconnectMode, IConnectionManager, IConnectionManagerFactoryArgs, IConnectionStateChangeReason } from "./contracts";
|
|
11
11
|
/**
|
|
12
12
|
* Implementation of IConnectionManager, used by Container class
|
|
13
13
|
* Implements constant connectivity to relay service, by reconnecting in case of lost connection or error.
|
|
@@ -16,7 +16,7 @@ import { ReconnectMode, IConnectionManager, IConnectionManagerFactoryArgs } from
|
|
|
16
16
|
export declare class ConnectionManager implements IConnectionManager {
|
|
17
17
|
private readonly serviceProvider;
|
|
18
18
|
readonly containerDirty: () => boolean;
|
|
19
|
-
private client;
|
|
19
|
+
private readonly client;
|
|
20
20
|
private readonly logger;
|
|
21
21
|
private readonly props;
|
|
22
22
|
/** Connection mode used when reconnecting on error or disconnect. */
|
|
@@ -91,7 +91,7 @@ export declare class ConnectionManager implements IConnectionManager {
|
|
|
91
91
|
* Enables or disables automatic reconnecting.
|
|
92
92
|
* Will throw an error if reconnectMode set to Never.
|
|
93
93
|
*/
|
|
94
|
-
setAutoReconnect(mode: ReconnectMode): void;
|
|
94
|
+
setAutoReconnect(mode: ReconnectMode, reason: IConnectionStateChangeReason): void;
|
|
95
95
|
/**
|
|
96
96
|
* Sends signal to runtime (and data stores) to be read-only.
|
|
97
97
|
* Hosts may have read only views, indicating to data stores that no edits are allowed.
|
|
@@ -111,7 +111,7 @@ export declare class ConnectionManager implements IConnectionManager {
|
|
|
111
111
|
*/
|
|
112
112
|
forceReadonly(readonly: boolean): void;
|
|
113
113
|
private set_readonlyPermissions;
|
|
114
|
-
connect(reason:
|
|
114
|
+
connect(reason: IConnectionStateChangeReason, connectionMode?: ConnectionMode): void;
|
|
115
115
|
private connectCore;
|
|
116
116
|
/**
|
|
117
117
|
* Start the connection. Any error should result in container being closed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectionManager.d.ts","sourceRoot":"","sources":["../src/connectionManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"connectionManager.d.ts","sourceRoot":"","sources":["../src/connectionManager.ts"],"names":[],"mappings":"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"}
|
package/lib/connectionManager.js
CHANGED
|
@@ -2,17 +2,15 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { canRetryOnError, createWriteError, createGenericNetworkError, getRetryDelayFromError, logNetworkFailure, isRuntimeMessage, } from "@fluidframework/driver-utils";
|
|
5
|
+
import { assert } from "@fluidframework/core-utils";
|
|
6
|
+
import { performance, TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
|
+
import { canRetryOnError, createWriteError, createGenericNetworkError, getRetryDelayFromError, logNetworkFailure, isRuntimeMessage, calculateMaxWaitTime, } from "@fluidframework/driver-utils";
|
|
9
8
|
import { MessageType, ScopeType, } from "@fluidframework/protocol-definitions";
|
|
10
|
-
import {
|
|
11
|
-
import { ReconnectMode } from "./contracts";
|
|
9
|
+
import { formatTick, GenericError, normalizeError, UsageError, } from "@fluidframework/telemetry-utils";
|
|
10
|
+
import { ReconnectMode, } from "./contracts";
|
|
12
11
|
import { DeltaQueue } from "./deltaQueue";
|
|
13
12
|
import { SignalType } from "./protocol";
|
|
14
13
|
import { isDeltaStreamConnectionForbiddenError } from "./utils";
|
|
15
|
-
const MaxReconnectDelayInMs = 8000;
|
|
16
14
|
const InitialReconnectDelayInMs = 1000;
|
|
17
15
|
const DefaultChunkSize = 16 * 1024;
|
|
18
16
|
const fatalConnectErrorProp = { fatalConnectError: true };
|
|
@@ -83,9 +81,8 @@ function isNoDeltaStreamConnection(connection) {
|
|
|
83
81
|
return connection instanceof NoDeltaStream;
|
|
84
82
|
}
|
|
85
83
|
const waitForOnline = async () => {
|
|
86
|
-
var _a;
|
|
87
84
|
// Only wait if we have a strong signal that we're offline - otherwise assume we're online.
|
|
88
|
-
if (
|
|
85
|
+
if (globalThis.navigator?.onLine === false && globalThis.addEventListener !== undefined) {
|
|
89
86
|
return new Promise((resolve) => {
|
|
90
87
|
const resolveAndRemoveListener = () => {
|
|
91
88
|
resolve();
|
|
@@ -169,15 +166,13 @@ export class ConnectionManager {
|
|
|
169
166
|
* The current connection mode, initially read.
|
|
170
167
|
*/
|
|
171
168
|
get connectionMode() {
|
|
172
|
-
|
|
173
|
-
return (_b = (_a = this.connection) === null || _a === void 0 ? void 0 : _a.mode) !== null && _b !== void 0 ? _b : "read";
|
|
169
|
+
return this.connection?.mode ?? "read";
|
|
174
170
|
}
|
|
175
171
|
get connected() {
|
|
176
172
|
return this.connection !== undefined;
|
|
177
173
|
}
|
|
178
174
|
get clientId() {
|
|
179
|
-
|
|
180
|
-
return (_a = this.connection) === null || _a === void 0 ? void 0 : _a.clientId;
|
|
175
|
+
return this.connection?.clientId;
|
|
181
176
|
}
|
|
182
177
|
/**
|
|
183
178
|
* Automatic reconnecting enabled or disabled.
|
|
@@ -187,8 +182,7 @@ export class ConnectionManager {
|
|
|
187
182
|
return this._reconnectMode;
|
|
188
183
|
}
|
|
189
184
|
get maxMessageSize() {
|
|
190
|
-
|
|
191
|
-
return (_c = (_b = (_a = this.connection) === null || _a === void 0 ? void 0 : _a.serviceConfiguration) === null || _b === void 0 ? void 0 : _b.maxMessageSize) !== null && _c !== void 0 ? _c : DefaultChunkSize;
|
|
185
|
+
return this.connection?.serviceConfiguration?.maxMessageSize ?? DefaultChunkSize;
|
|
192
186
|
}
|
|
193
187
|
get version() {
|
|
194
188
|
if (this.connection === undefined) {
|
|
@@ -197,12 +191,10 @@ export class ConnectionManager {
|
|
|
197
191
|
return this.connection.version;
|
|
198
192
|
}
|
|
199
193
|
get serviceConfiguration() {
|
|
200
|
-
|
|
201
|
-
return (_a = this.connection) === null || _a === void 0 ? void 0 : _a.serviceConfiguration;
|
|
194
|
+
return this.connection?.serviceConfiguration;
|
|
202
195
|
}
|
|
203
196
|
get scopes() {
|
|
204
|
-
|
|
205
|
-
return (_a = this.connection) === null || _a === void 0 ? void 0 : _a.claims.scopes;
|
|
197
|
+
return this.connection?.claims.scopes;
|
|
206
198
|
}
|
|
207
199
|
get outbound() {
|
|
208
200
|
return this._outbound;
|
|
@@ -214,9 +206,11 @@ export class ConnectionManager {
|
|
|
214
206
|
get connectionProps() {
|
|
215
207
|
return this.connection !== undefined
|
|
216
208
|
? this._connectionProps
|
|
217
|
-
:
|
|
209
|
+
: {
|
|
210
|
+
...this._connectionProps,
|
|
218
211
|
// Report how many ops this client sent in last disconnected session
|
|
219
|
-
sentOps: this.clientSequenceNumber
|
|
212
|
+
sentOps: this.clientSequenceNumber,
|
|
213
|
+
};
|
|
220
214
|
}
|
|
221
215
|
shouldJoinWrite() {
|
|
222
216
|
// We don't have to wait for ack for topmost NoOps. So subtract those.
|
|
@@ -286,26 +280,30 @@ export class ConnectionManager {
|
|
|
286
280
|
// Ensure that things like triggerConnect() will short circuit
|
|
287
281
|
this._reconnectMode = ReconnectMode.Never;
|
|
288
282
|
this._outbound.clear();
|
|
289
|
-
const disconnectReason =
|
|
283
|
+
const disconnectReason = {
|
|
284
|
+
text: "Closing DeltaManager",
|
|
285
|
+
error,
|
|
286
|
+
};
|
|
287
|
+
const oldReadonlyValue = this.readonly;
|
|
290
288
|
// This raises "disconnect" event if we have active connection.
|
|
291
289
|
this.disconnectFromDeltaStream(disconnectReason);
|
|
292
290
|
if (switchToReadonly) {
|
|
293
291
|
// Notify everyone we are in read-only state.
|
|
294
292
|
// Useful for data stores in case we hit some critical error,
|
|
295
293
|
// to switch to a mode where user edits are not accepted
|
|
296
|
-
this.set_readonlyPermissions(true);
|
|
294
|
+
this.set_readonlyPermissions(true, oldReadonlyValue);
|
|
297
295
|
}
|
|
298
296
|
}
|
|
299
297
|
/**
|
|
300
298
|
* Enables or disables automatic reconnecting.
|
|
301
299
|
* Will throw an error if reconnectMode set to Never.
|
|
302
300
|
*/
|
|
303
|
-
setAutoReconnect(mode) {
|
|
301
|
+
setAutoReconnect(mode, reason) {
|
|
304
302
|
assert(mode !== ReconnectMode.Never && this._reconnectMode !== ReconnectMode.Never, 0x278 /* "API is not supported for non-connecting or closed container" */);
|
|
305
303
|
this._reconnectMode = mode;
|
|
306
304
|
if (mode !== ReconnectMode.Enabled) {
|
|
307
305
|
// immediately disconnect - do not rely on service eventually dropping connection.
|
|
308
|
-
this.disconnectFromDeltaStream(
|
|
306
|
+
this.disconnectFromDeltaStream(reason);
|
|
309
307
|
}
|
|
310
308
|
}
|
|
311
309
|
/**
|
|
@@ -348,30 +346,28 @@ export class ConnectionManager {
|
|
|
348
346
|
// host logic error.
|
|
349
347
|
this.logger.sendErrorEvent({ eventName: "ForceReadonlyPendingChanged" });
|
|
350
348
|
}
|
|
351
|
-
reconnect = this.disconnectFromDeltaStream("Force readonly");
|
|
349
|
+
reconnect = this.disconnectFromDeltaStream({ text: "Force readonly" });
|
|
352
350
|
}
|
|
353
351
|
this.props.readonlyChangeHandler(this.readonly);
|
|
354
352
|
if (reconnect) {
|
|
355
353
|
// reconnect if we disconnected from before.
|
|
356
|
-
this.triggerConnect("Force Readonly", "read");
|
|
354
|
+
this.triggerConnect({ text: "Force Readonly" }, "read");
|
|
357
355
|
}
|
|
358
356
|
}
|
|
359
357
|
}
|
|
360
|
-
set_readonlyPermissions(
|
|
361
|
-
|
|
362
|
-
this.
|
|
363
|
-
if (oldValue !== this.readonly) {
|
|
358
|
+
set_readonlyPermissions(newReadonlyValue, oldReadonlyValue) {
|
|
359
|
+
this._readonlyPermissions = newReadonlyValue;
|
|
360
|
+
if (oldReadonlyValue !== this.readonly) {
|
|
364
361
|
this.props.readonlyChangeHandler(this.readonly);
|
|
365
362
|
}
|
|
366
363
|
}
|
|
367
364
|
connect(reason, connectionMode) {
|
|
368
|
-
this.connectCore(reason, connectionMode).catch((
|
|
369
|
-
const normalizedError = normalizeError(
|
|
365
|
+
this.connectCore(reason, connectionMode).catch((e) => {
|
|
366
|
+
const normalizedError = normalizeError(e, { props: fatalConnectErrorProp });
|
|
370
367
|
this.props.closeHandler(normalizedError);
|
|
371
368
|
});
|
|
372
369
|
}
|
|
373
370
|
async connectCore(reason, connectionMode) {
|
|
374
|
-
var _a, _b, _c;
|
|
375
371
|
assert(!this._disposed, 0x26a /* "not closed" */);
|
|
376
372
|
if (this.connection !== undefined) {
|
|
377
373
|
return; // Connection attempt already completed successfully
|
|
@@ -383,7 +379,7 @@ export class ConnectionManager {
|
|
|
383
379
|
assert(this.pendingConnection === undefined, 0x344 /* this.pendingConnection should be undefined */);
|
|
384
380
|
}
|
|
385
381
|
// If there is no specified ConnectionMode, try the previous mode, if there is no previous mode use default
|
|
386
|
-
let requestedMode =
|
|
382
|
+
let requestedMode = connectionMode ?? pendingConnectionMode ?? this.defaultReconnectionMode;
|
|
387
383
|
// if we have any non-acked ops from last connection, reconnect as "write".
|
|
388
384
|
// without that we would connect in view-only mode, which will result in immediate
|
|
389
385
|
// firing of "connected" event from Container and switch of current clientId (as tracked
|
|
@@ -395,7 +391,7 @@ export class ConnectionManager {
|
|
|
395
391
|
const docService = this.serviceProvider();
|
|
396
392
|
assert(docService !== undefined, 0x2a7 /* "Container is not attached" */);
|
|
397
393
|
let connection;
|
|
398
|
-
if (
|
|
394
|
+
if (docService.policies?.storageOnly === true) {
|
|
399
395
|
connection = new NoDeltaStream();
|
|
400
396
|
this.setupNewSuccessfulConnection(connection, "read", reason);
|
|
401
397
|
assert(this.pendingConnection === undefined, 0x2b3 /* "logic error" */);
|
|
@@ -423,7 +419,7 @@ export class ConnectionManager {
|
|
|
423
419
|
this.logger.sendTelemetryEvent({
|
|
424
420
|
eventName: "ConnectionAttemptCancelled",
|
|
425
421
|
attempts: connectRepeatCount,
|
|
426
|
-
duration:
|
|
422
|
+
duration: formatTick(performance.now() - connectStartTime),
|
|
427
423
|
connectionEstablished: false,
|
|
428
424
|
});
|
|
429
425
|
return;
|
|
@@ -431,7 +427,10 @@ export class ConnectionManager {
|
|
|
431
427
|
connectRepeatCount++;
|
|
432
428
|
try {
|
|
433
429
|
this.client.mode = requestedMode;
|
|
434
|
-
connection = await docService.connectToDeltaStream(
|
|
430
|
+
connection = await docService.connectToDeltaStream({
|
|
431
|
+
...this.client,
|
|
432
|
+
mode: requestedMode,
|
|
433
|
+
});
|
|
435
434
|
if (connection.disposed) {
|
|
436
435
|
// Nobody observed this connection, so drop it on the floor and retry.
|
|
437
436
|
this.logger.sendTelemetryEvent({ eventName: "ReceivedClosedConnection" });
|
|
@@ -455,7 +454,7 @@ export class ConnectionManager {
|
|
|
455
454
|
attempts: connectRepeatCount,
|
|
456
455
|
delay: delayMs,
|
|
457
456
|
eventName: "DeltaConnectionFailureToConnect",
|
|
458
|
-
duration:
|
|
457
|
+
duration: formatTick(performance.now() - connectStartTime),
|
|
459
458
|
}, origError);
|
|
460
459
|
lastError = origError;
|
|
461
460
|
const waitStartTime = performance.now();
|
|
@@ -467,12 +466,12 @@ export class ConnectionManager {
|
|
|
467
466
|
setTimeout(resolve, retryDelayFromError);
|
|
468
467
|
});
|
|
469
468
|
}
|
|
470
|
-
else if (
|
|
469
|
+
else if (globalThis.navigator?.onLine !== false) {
|
|
471
470
|
// If the error didn't tell us to wait, let's still wait a little bit before retrying.
|
|
472
471
|
// We skip this delay if we're confident we're offline, because we probably just need to wait to come back online.
|
|
473
472
|
await new Promise((resolve) => {
|
|
474
473
|
setTimeout(resolve, delayMs);
|
|
475
|
-
delayMs = Math.min(delayMs * 2,
|
|
474
|
+
delayMs = Math.min(delayMs * 2, calculateMaxWaitTime(origError));
|
|
476
475
|
});
|
|
477
476
|
}
|
|
478
477
|
// If we believe we're offline, we assume there's no point in trying until we at least think we're online.
|
|
@@ -494,7 +493,7 @@ export class ConnectionManager {
|
|
|
494
493
|
logNetworkFailure(this.logger, {
|
|
495
494
|
eventName: "MultipleDeltaConnectionFailures",
|
|
496
495
|
attempts: connectRepeatCount,
|
|
497
|
-
duration:
|
|
496
|
+
duration: formatTick(performance.now() - connectStartTime),
|
|
498
497
|
}, lastError);
|
|
499
498
|
}
|
|
500
499
|
// Check for abort signal after while loop as well
|
|
@@ -503,7 +502,7 @@ export class ConnectionManager {
|
|
|
503
502
|
this.logger.sendTelemetryEvent({
|
|
504
503
|
eventName: "ConnectionAttemptCancelled",
|
|
505
504
|
attempts: connectRepeatCount,
|
|
506
|
-
duration:
|
|
505
|
+
duration: formatTick(performance.now() - connectStartTime),
|
|
507
506
|
connectionEstablished: true,
|
|
508
507
|
});
|
|
509
508
|
return;
|
|
@@ -533,7 +532,7 @@ export class ConnectionManager {
|
|
|
533
532
|
* @param error - Error causing the disconnect if any.
|
|
534
533
|
* @returns A boolean that indicates if there was an existing connection (or pending connection) to disconnect
|
|
535
534
|
*/
|
|
536
|
-
disconnectFromDeltaStream(reason
|
|
535
|
+
disconnectFromDeltaStream(reason) {
|
|
537
536
|
this.pendingReconnect = false;
|
|
538
537
|
if (this.connection === undefined) {
|
|
539
538
|
if (this.pendingConnection !== undefined) {
|
|
@@ -557,7 +556,7 @@ export class ConnectionManager {
|
|
|
557
556
|
this._outbound.pause();
|
|
558
557
|
this._outbound.clear();
|
|
559
558
|
connection.dispose();
|
|
560
|
-
this.props.disconnectHandler(reason
|
|
559
|
+
this.props.disconnectHandler(reason);
|
|
561
560
|
this._connectionVerboseProps = {};
|
|
562
561
|
return true;
|
|
563
562
|
}
|
|
@@ -569,7 +568,10 @@ export class ConnectionManager {
|
|
|
569
568
|
this.pendingConnection.abort();
|
|
570
569
|
this.pendingConnection = undefined;
|
|
571
570
|
this.logger.sendTelemetryEvent({ eventName: "ConnectionCancelReceived" });
|
|
572
|
-
this.props.cancelConnectionHandler(
|
|
571
|
+
this.props.cancelConnectionHandler({
|
|
572
|
+
text: `Cancel Pending Connection due to ${reason.text}`,
|
|
573
|
+
error: reason.error,
|
|
574
|
+
});
|
|
573
575
|
}
|
|
574
576
|
/**
|
|
575
577
|
* Once we've successfully gotten a connection, we need to set up state, attach event listeners, and process
|
|
@@ -577,11 +579,11 @@ export class ConnectionManager {
|
|
|
577
579
|
* @param connection - The newly established connection
|
|
578
580
|
*/
|
|
579
581
|
setupNewSuccessfulConnection(connection, requestedMode, reason) {
|
|
580
|
-
var _a;
|
|
581
582
|
// Old connection should have been cleaned up before establishing a new one
|
|
582
583
|
assert(this.connection === undefined, 0x0e6 /* "old connection exists on new connection setup" */);
|
|
583
584
|
assert(!connection.disposed, 0x28a /* "can't be disposed - Callers need to ensure that!" */);
|
|
584
585
|
this.pendingConnection = undefined;
|
|
586
|
+
const oldReadonlyValue = this.readonly;
|
|
585
587
|
this.connection = connection;
|
|
586
588
|
// Does information in scopes & mode matches?
|
|
587
589
|
// If we asked for "write" and got "read", then file is read-only
|
|
@@ -598,10 +600,10 @@ export class ConnectionManager {
|
|
|
598
600
|
// removed after those packages have released and become ubiquitous.
|
|
599
601
|
assert(requestedMode === "read" || readonly === (this.connectionMode === "read"), 0x0e7 /* "claims/connectionMode mismatch" */);
|
|
600
602
|
assert(!readonly || this.connectionMode === "read", 0x0e8 /* "readonly perf with write connection" */);
|
|
601
|
-
this.set_readonlyPermissions(readonly);
|
|
603
|
+
this.set_readonlyPermissions(readonly, oldReadonlyValue);
|
|
602
604
|
if (this._disposed) {
|
|
603
605
|
// Raise proper events, Log telemetry event and close connection.
|
|
604
|
-
this.disconnectFromDeltaStream("ConnectionManager already closed");
|
|
606
|
+
this.disconnectFromDeltaStream({ text: "ConnectionManager already closed" });
|
|
605
607
|
return;
|
|
606
608
|
}
|
|
607
609
|
this._outbound.resume();
|
|
@@ -658,7 +660,7 @@ export class ConnectionManager {
|
|
|
658
660
|
}),
|
|
659
661
|
};
|
|
660
662
|
this.props.signalHandler(clearSignal);
|
|
661
|
-
for (const priorClient of
|
|
663
|
+
for (const priorClient of connection.initialClients ?? []) {
|
|
662
664
|
const joinSignal = {
|
|
663
665
|
clientId: null,
|
|
664
666
|
content: JSON.stringify({
|
|
@@ -686,7 +688,7 @@ export class ConnectionManager {
|
|
|
686
688
|
* @returns A promise that resolves when the connection is reestablished or we stop trying
|
|
687
689
|
*/
|
|
688
690
|
reconnectOnError(requestedMode, error) {
|
|
689
|
-
this.reconnect(requestedMode, error.message, error).catch(this.props.closeHandler);
|
|
691
|
+
this.reconnect(requestedMode, { text: error.message, error }).catch(this.props.closeHandler);
|
|
690
692
|
}
|
|
691
693
|
/**
|
|
692
694
|
* Disconnect the current connection and reconnect.
|
|
@@ -695,20 +697,20 @@ export class ConnectionManager {
|
|
|
695
697
|
* @param error - Error reconnect information including whether or not to reconnect
|
|
696
698
|
* @returns A promise that resolves when the connection is reestablished or we stop trying
|
|
697
699
|
*/
|
|
698
|
-
async reconnect(requestedMode,
|
|
700
|
+
async reconnect(requestedMode, reason) {
|
|
699
701
|
// We quite often get protocol errors before / after observing nack/disconnect
|
|
700
702
|
// we do not want to run through same sequence twice.
|
|
701
703
|
// If we're already disconnected/disconnecting it's not appropriate to call this again.
|
|
702
704
|
assert(this.connection !== undefined, 0x0eb /* "Missing connection for reconnect" */);
|
|
703
|
-
this.disconnectFromDeltaStream(
|
|
705
|
+
this.disconnectFromDeltaStream(reason);
|
|
704
706
|
// We will always trigger reconnect, even if canRetry is false.
|
|
705
707
|
// Any truly fatal error state will result in container close upon attempted reconnect,
|
|
706
708
|
// which is a preferable to closing abruptly when a live connection fails.
|
|
707
|
-
if (error
|
|
709
|
+
if (reason.error?.canRetry === false) {
|
|
708
710
|
this.logger.sendTelemetryEvent({
|
|
709
711
|
eventName: "reconnectingDespiteFatalError",
|
|
710
712
|
reconnectMode: this.reconnectMode,
|
|
711
|
-
}, error);
|
|
713
|
+
}, reason.error);
|
|
712
714
|
}
|
|
713
715
|
if (this.reconnectMode === ReconnectMode.Never) {
|
|
714
716
|
// Do not raise container error if we are closing just because we lost connection.
|
|
@@ -721,9 +723,9 @@ export class ConnectionManager {
|
|
|
721
723
|
return;
|
|
722
724
|
}
|
|
723
725
|
// If the error tells us to wait before retrying, then do so.
|
|
724
|
-
const delayMs = getRetryDelayFromError(error);
|
|
725
|
-
if (error !== undefined && delayMs !== undefined) {
|
|
726
|
-
this.props.reconnectionDelayHandler(delayMs, error);
|
|
726
|
+
const delayMs = getRetryDelayFromError(reason.error);
|
|
727
|
+
if (reason.error !== undefined && delayMs !== undefined) {
|
|
728
|
+
this.props.reconnectionDelayHandler(delayMs, reason.error);
|
|
727
729
|
await new Promise((resolve) => {
|
|
728
730
|
setTimeout(resolve, delayMs);
|
|
729
731
|
});
|
|
@@ -732,12 +734,14 @@ export class ConnectionManager {
|
|
|
732
734
|
// NOTE: This isn't strictly true for drivers that don't require network (e.g. local driver). Really this logic
|
|
733
735
|
// should probably live in the driver.
|
|
734
736
|
await waitForOnline();
|
|
735
|
-
this.triggerConnect(
|
|
736
|
-
|
|
737
|
-
|
|
737
|
+
this.triggerConnect({
|
|
738
|
+
text: reason.error !== undefined
|
|
739
|
+
? "Reconnecting due to Error"
|
|
740
|
+
: `Reconnecting due to: ${reason.text}`,
|
|
741
|
+
error: reason.error,
|
|
742
|
+
}, requestedMode);
|
|
738
743
|
}
|
|
739
744
|
prepareMessageToSend(message) {
|
|
740
|
-
var _a, _b;
|
|
741
745
|
if (this.readonly === true) {
|
|
742
746
|
assert(this.readOnlyInfo.readonly === true, 0x1f0 /* "Unexpected mismatch in readonly" */);
|
|
743
747
|
const error = new GenericError("deltaManagerReadonlySubmit", undefined /* error */, {
|
|
@@ -754,8 +758,8 @@ export class ConnectionManager {
|
|
|
754
758
|
// we keep info about old connection as long as possible to be able to account for all non-acked ops
|
|
755
759
|
// that we pick up on next connection.
|
|
756
760
|
assert(!!this.connection, 0x0e4 /* "Lost old connection!" */);
|
|
757
|
-
if (this.lastSubmittedClientId !==
|
|
758
|
-
this.lastSubmittedClientId =
|
|
761
|
+
if (this.lastSubmittedClientId !== this.connection?.clientId) {
|
|
762
|
+
this.lastSubmittedClientId = this.connection?.clientId;
|
|
759
763
|
this.clientSequenceNumber = 0;
|
|
760
764
|
this.clientSequenceNumberObserved = 0;
|
|
761
765
|
}
|
|
@@ -765,7 +769,10 @@ export class ConnectionManager {
|
|
|
765
769
|
else {
|
|
766
770
|
this.localOpsToIgnore = 0;
|
|
767
771
|
}
|
|
768
|
-
return
|
|
772
|
+
return {
|
|
773
|
+
...message,
|
|
774
|
+
clientSequenceNumber: ++this.clientSequenceNumber,
|
|
775
|
+
};
|
|
769
776
|
}
|
|
770
777
|
submitSignal(content) {
|
|
771
778
|
if (this.connection !== undefined) {
|
|
@@ -791,7 +798,7 @@ export class ConnectionManager {
|
|
|
791
798
|
if (this.pendingReconnect) {
|
|
792
799
|
// still valid?
|
|
793
800
|
await this.reconnect("write", // connectionMode
|
|
794
|
-
"Switch to write");
|
|
801
|
+
{ text: "Switch to write" });
|
|
795
802
|
}
|
|
796
803
|
})
|
|
797
804
|
.catch(() => { });
|
|
@@ -824,7 +831,7 @@ export class ConnectionManager {
|
|
|
824
831
|
// Clients need to be able to transition to "read" state after some time of inactivity!
|
|
825
832
|
// Note - this may close container!
|
|
826
833
|
this.reconnect("read", // connectionMode
|
|
827
|
-
"Switch to read").catch((error) => {
|
|
834
|
+
{ text: "Switch to read" }).catch((error) => {
|
|
828
835
|
this.logger.sendErrorEvent({ eventName: "SwitchToReadConnection" }, error);
|
|
829
836
|
});
|
|
830
837
|
}
|