@fluidframework/container-loader 2.0.0-dev.3.1.0.125672 → 2.0.0-dev.4.1.0.148229
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/README.md +7 -4
- package/closeAndGetPendingLocalState.md +51 -0
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +43 -11
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +4 -4
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +7 -0
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +44 -4
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +152 -93
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +18 -8
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js +47 -4
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +41 -2
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +87 -11
- 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/deltaManager.d.ts +3 -2
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +4 -2
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaManagerProxy.d.ts +10 -22
- package/dist/deltaManagerProxy.d.ts.map +1 -1
- package/dist/deltaManagerProxy.js +14 -50
- package/dist/deltaManagerProxy.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +10 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +22 -16
- package/dist/loader.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/protocolTreeDocumentStorageService.d.ts +6 -2
- package/dist/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/dist/protocolTreeDocumentStorageService.js +7 -4
- package/dist/protocolTreeDocumentStorageService.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +2 -1
- package/dist/utils.js.map +1 -1
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +44 -12
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +4 -4
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +7 -0
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +44 -4
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +155 -96
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +18 -8
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js +48 -5
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +41 -2
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +85 -11
- 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.map +1 -1
- package/lib/deltaManager.d.ts +3 -2
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +4 -2
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaManagerProxy.d.ts +10 -22
- package/lib/deltaManagerProxy.d.ts.map +1 -1
- package/lib/deltaManagerProxy.js +14 -50
- package/lib/deltaManagerProxy.js.map +1 -1
- package/lib/index.d.ts +3 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/loader.d.ts +10 -1
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +21 -16
- package/lib/loader.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/protocolTreeDocumentStorageService.d.ts +6 -2
- package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
- package/lib/protocolTreeDocumentStorageService.js +7 -4
- package/lib/protocolTreeDocumentStorageService.js.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +2 -1
- package/lib/utils.js.map +1 -1
- package/package.json +64 -56
- package/src/connectionManager.ts +48 -17
- package/src/connectionStateHandler.ts +17 -5
- package/src/container.ts +224 -116
- package/src/containerContext.ts +74 -11
- package/src/containerStorageAdapter.ts +113 -9
- package/src/contracts.ts +2 -2
- package/src/deltaManager.ts +9 -4
- package/src/deltaManagerProxy.ts +18 -73
- package/src/index.ts +2 -3
- package/src/loader.ts +28 -26
- package/src/packageVersion.ts +1 -1
- package/src/protocolTreeDocumentStorageService.ts +6 -3
- package/src/utils.ts +7 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/container-loader",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.4.1.0.148229",
|
|
4
4
|
"description": "Fluid container loader",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -14,34 +14,6 @@
|
|
|
14
14
|
"main": "dist/index.js",
|
|
15
15
|
"module": "lib/index.js",
|
|
16
16
|
"types": "dist/index.d.ts",
|
|
17
|
-
"scripts": {
|
|
18
|
-
"build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
|
|
19
|
-
"build:commonjs": "npm run tsc && npm run typetests:gen && npm run build:test",
|
|
20
|
-
"build:compile": "concurrently npm:build:commonjs npm:build:esnext",
|
|
21
|
-
"build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
|
|
22
|
-
"build:esnext": "tsc --project ./tsconfig.esnext.json",
|
|
23
|
-
"build:full": "npm run build",
|
|
24
|
-
"build:full:compile": "npm run build:compile",
|
|
25
|
-
"build:genver": "gen-version",
|
|
26
|
-
"build:test": "tsc --project ./src/test/tsconfig.json",
|
|
27
|
-
"ci:build:docs": "api-extractor run --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/* ../../../_api-extractor-temp/",
|
|
28
|
-
"clean": "rimraf dist lib *.tsbuildinfo *.build.log",
|
|
29
|
-
"eslint": "eslint --format stylish src",
|
|
30
|
-
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
|
|
31
|
-
"format": "npm run prettier:fix",
|
|
32
|
-
"lint": "npm run prettier && npm run eslint",
|
|
33
|
-
"lint:fix": "npm run prettier:fix && npm run eslint:fix",
|
|
34
|
-
"prettier": "prettier --check . --ignore-path ../../../.prettierignore",
|
|
35
|
-
"prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
|
|
36
|
-
"test": "npm run test:mocha",
|
|
37
|
-
"test:coverage": "nyc npm test -- --reporter xunit --reporter-option output=nyc/junit-report.xml",
|
|
38
|
-
"test:mocha": "mocha --ignore 'dist/test/types/*' --recursive dist/test -r node_modules/@fluidframework/mocha-test-setup --unhandled-rejections=strict",
|
|
39
|
-
"test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
|
|
40
|
-
"tsc": "tsc",
|
|
41
|
-
"tsc:watch": "tsc --watch",
|
|
42
|
-
"typetests:gen": "flub generate typetests --generate --dir .",
|
|
43
|
-
"typetests:prepare": "flub generate typetests --prepare --dir . --pin"
|
|
44
|
-
},
|
|
45
17
|
"nyc": {
|
|
46
18
|
"all": true,
|
|
47
19
|
"cache-dir": "nyc/.cache",
|
|
@@ -64,15 +36,15 @@
|
|
|
64
36
|
},
|
|
65
37
|
"dependencies": {
|
|
66
38
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
67
|
-
"@fluidframework/common-utils": "^1.
|
|
68
|
-
"@fluidframework/container-definitions": "
|
|
69
|
-
"@fluidframework/container-utils": "
|
|
70
|
-
"@fluidframework/core-interfaces": "
|
|
71
|
-
"@fluidframework/driver-definitions": "
|
|
72
|
-
"@fluidframework/driver-utils": "
|
|
73
|
-
"@fluidframework/protocol-base": "^0.
|
|
39
|
+
"@fluidframework/common-utils": "^1.1.1",
|
|
40
|
+
"@fluidframework/container-definitions": "2.0.0-dev.4.1.0.148229",
|
|
41
|
+
"@fluidframework/container-utils": "2.0.0-dev.4.1.0.148229",
|
|
42
|
+
"@fluidframework/core-interfaces": "2.0.0-dev.4.1.0.148229",
|
|
43
|
+
"@fluidframework/driver-definitions": "2.0.0-dev.4.1.0.148229",
|
|
44
|
+
"@fluidframework/driver-utils": "2.0.0-dev.4.1.0.148229",
|
|
45
|
+
"@fluidframework/protocol-base": "^0.1039.1000",
|
|
74
46
|
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
75
|
-
"@fluidframework/telemetry-utils": "
|
|
47
|
+
"@fluidframework/telemetry-utils": "2.0.0-dev.4.1.0.148229",
|
|
76
48
|
"abort-controller": "^3.0.0",
|
|
77
49
|
"double-ended-queue": "^2.1.0-0",
|
|
78
50
|
"events": "^3.1.0",
|
|
@@ -81,37 +53,73 @@
|
|
|
81
53
|
"uuid": "^8.3.1"
|
|
82
54
|
},
|
|
83
55
|
"devDependencies": {
|
|
84
|
-
"@fluid-
|
|
56
|
+
"@fluid-internal/test-loader-utils": "2.0.0-dev.4.1.0.148229",
|
|
57
|
+
"@fluid-tools/build-cli": "^0.13.1",
|
|
85
58
|
"@fluidframework/build-common": "^1.1.0",
|
|
86
|
-
"@fluidframework/build-tools": "^0.
|
|
87
|
-
"@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@2.0.0-internal.
|
|
59
|
+
"@fluidframework/build-tools": "^0.13.1",
|
|
60
|
+
"@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@2.0.0-internal.4.0.0",
|
|
88
61
|
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
89
|
-
"@fluidframework/mocha-test-setup": "
|
|
90
|
-
"@
|
|
91
|
-
"@microsoft/api-extractor": "^7.22.2",
|
|
92
|
-
"@rushstack/eslint-config": "^2.5.1",
|
|
62
|
+
"@fluidframework/mocha-test-setup": "2.0.0-dev.4.1.0.148229",
|
|
63
|
+
"@microsoft/api-extractor": "^7.34.4",
|
|
93
64
|
"@types/double-ended-queue": "^2.1.0",
|
|
94
65
|
"@types/events": "^3.0.0",
|
|
95
66
|
"@types/lodash": "^4.14.118",
|
|
96
67
|
"@types/mocha": "^9.1.1",
|
|
97
|
-
"@types/node": "^14.18.
|
|
68
|
+
"@types/node": "^14.18.38",
|
|
98
69
|
"@types/sinon": "^7.0.13",
|
|
99
|
-
"concurrently": "^6.
|
|
70
|
+
"concurrently": "^7.6.0",
|
|
100
71
|
"copyfiles": "^2.4.1",
|
|
101
|
-
"cross-env": "^7.0.
|
|
72
|
+
"cross-env": "^7.0.3",
|
|
102
73
|
"eslint": "~8.6.0",
|
|
103
|
-
"mocha": "^10.
|
|
104
|
-
"
|
|
74
|
+
"mocha": "^10.2.0",
|
|
75
|
+
"mocha-json-output-reporter": "^2.0.1",
|
|
76
|
+
"mocha-multi-reporters": "^1.5.1",
|
|
77
|
+
"moment": "^2.21.0",
|
|
78
|
+
"nyc": "^15.1.0",
|
|
105
79
|
"prettier": "~2.6.2",
|
|
106
|
-
"rimraf": "^
|
|
80
|
+
"rimraf": "^4.4.0",
|
|
107
81
|
"sinon": "^7.4.2",
|
|
108
82
|
"typescript": "~4.5.5"
|
|
109
83
|
},
|
|
110
84
|
"typeValidation": {
|
|
111
|
-
"
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
85
|
+
"broken": {
|
|
86
|
+
"InterfaceDeclaration_IContainerConfig": {
|
|
87
|
+
"forwardCompat": false,
|
|
88
|
+
"backCompat": false
|
|
89
|
+
},
|
|
90
|
+
"InterfaceDeclaration_IPendingContainerState": {
|
|
91
|
+
"forwardCompat": false,
|
|
92
|
+
"backCompat": false
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"scripts": {
|
|
97
|
+
"build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
|
|
98
|
+
"build:commonjs": "npm run tsc && npm run typetests:gen && npm run build:test",
|
|
99
|
+
"build:compile": "concurrently npm:build:commonjs npm:build:esnext",
|
|
100
|
+
"build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
|
|
101
|
+
"build:esnext": "tsc --project ./tsconfig.esnext.json",
|
|
102
|
+
"build:full": "npm run build",
|
|
103
|
+
"build:full:compile": "npm run build:compile",
|
|
104
|
+
"build:genver": "gen-version",
|
|
105
|
+
"build:test": "tsc --project ./src/test/tsconfig.json",
|
|
106
|
+
"ci:build:docs": "api-extractor run --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/* ../../../_api-extractor-temp/",
|
|
107
|
+
"clean": "rimraf dist lib *.tsbuildinfo *.build.log",
|
|
108
|
+
"eslint": "eslint --format stylish src",
|
|
109
|
+
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
|
|
110
|
+
"format": "npm run prettier:fix",
|
|
111
|
+
"lint": "npm run prettier && npm run eslint",
|
|
112
|
+
"lint:fix": "npm run prettier:fix && npm run eslint:fix",
|
|
113
|
+
"prettier": "prettier --check . --ignore-path ../../../.prettierignore",
|
|
114
|
+
"prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
|
|
115
|
+
"test": "npm run test:mocha",
|
|
116
|
+
"test:coverage": "nyc npm test -- --reporter xunit --reporter-option output=nyc/junit-report.xml",
|
|
117
|
+
"test:mocha": "mocha --ignore 'dist/test/types/*' --recursive dist/test -r node_modules/@fluidframework/mocha-test-setup --unhandled-rejections=strict",
|
|
118
|
+
"test:mocha:multireport": "cross-env FLUID_TEST_MULTIREPORT=1 npm run test:mocha",
|
|
119
|
+
"test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
|
|
120
|
+
"tsc": "tsc",
|
|
121
|
+
"tsc:watch": "tsc --watch",
|
|
122
|
+
"typetests:gen": "fluid-type-test-generator",
|
|
123
|
+
"typetests:prepare": "flub generate typetests --prepare --dir . --pin"
|
|
116
124
|
}
|
|
117
|
-
}
|
|
125
|
+
}
|
package/src/connectionManager.ts
CHANGED
|
@@ -13,11 +13,12 @@ import { assert, performance, TypedEventEmitter } from "@fluidframework/common-u
|
|
|
13
13
|
import {
|
|
14
14
|
IDeltaQueue,
|
|
15
15
|
ReadOnlyInfo,
|
|
16
|
-
|
|
16
|
+
IConnectionDetailsInternal,
|
|
17
17
|
ICriticalContainerError,
|
|
18
18
|
} from "@fluidframework/container-definitions";
|
|
19
19
|
import { GenericError, UsageError } from "@fluidframework/container-utils";
|
|
20
20
|
import {
|
|
21
|
+
DriverErrorType,
|
|
21
22
|
IAnyDriverError,
|
|
22
23
|
IDocumentService,
|
|
23
24
|
IDocumentDeltaConnection,
|
|
@@ -28,8 +29,6 @@ import {
|
|
|
28
29
|
createWriteError,
|
|
29
30
|
createGenericNetworkError,
|
|
30
31
|
getRetryDelayFromError,
|
|
31
|
-
waitForConnectedState,
|
|
32
|
-
DeltaStreamConnectionForbiddenError,
|
|
33
32
|
logNetworkFailure,
|
|
34
33
|
isRuntimeMessage,
|
|
35
34
|
} from "@fluidframework/driver-utils";
|
|
@@ -135,6 +134,19 @@ class NoDeltaStream
|
|
|
135
134
|
}
|
|
136
135
|
}
|
|
137
136
|
|
|
137
|
+
const waitForOnline = async (): Promise<void> => {
|
|
138
|
+
// Only wait if we have a strong signal that we're offline - otherwise assume we're online.
|
|
139
|
+
if (globalThis.navigator?.onLine === false && globalThis.addEventListener !== undefined) {
|
|
140
|
+
return new Promise<void>((resolve) => {
|
|
141
|
+
const resolveAndRemoveListener = () => {
|
|
142
|
+
resolve();
|
|
143
|
+
globalThis.removeEventListener("online", resolveAndRemoveListener);
|
|
144
|
+
};
|
|
145
|
+
globalThis.addEventListener("online", resolveAndRemoveListener);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
138
150
|
/**
|
|
139
151
|
* Interface to track the current in-progress connection attempt.
|
|
140
152
|
*/
|
|
@@ -302,11 +314,12 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
302
314
|
return { readonly: this._readonlyPermissions };
|
|
303
315
|
}
|
|
304
316
|
|
|
305
|
-
private static detailsFromConnection(
|
|
317
|
+
private static detailsFromConnection(
|
|
318
|
+
connection: IDocumentDeltaConnection,
|
|
319
|
+
): IConnectionDetailsInternal {
|
|
306
320
|
return {
|
|
307
321
|
claims: connection.claims,
|
|
308
322
|
clientId: connection.clientId,
|
|
309
|
-
existing: connection.existing,
|
|
310
323
|
checkpointSequenceNumber: connection.checkpointSequenceNumber,
|
|
311
324
|
get initialClients() {
|
|
312
325
|
return connection.initialClients;
|
|
@@ -355,10 +368,7 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
355
368
|
|
|
356
369
|
this._outbound.clear();
|
|
357
370
|
|
|
358
|
-
const disconnectReason =
|
|
359
|
-
error !== undefined
|
|
360
|
-
? `Closing DeltaManager (${error.message})`
|
|
361
|
-
: "Closing DeltaManager";
|
|
371
|
+
const disconnectReason = "Closing DeltaManager";
|
|
362
372
|
|
|
363
373
|
// This raises "disconnect" event if we have active connection.
|
|
364
374
|
this.disconnectFromDeltaStream(disconnectReason);
|
|
@@ -543,7 +553,7 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
543
553
|
if (
|
|
544
554
|
typeof origError === "object" &&
|
|
545
555
|
origError !== null &&
|
|
546
|
-
origError?.errorType ===
|
|
556
|
+
origError?.errorType === DriverErrorType.deltaStreamConnectionForbidden
|
|
547
557
|
) {
|
|
548
558
|
connection = new NoDeltaStream();
|
|
549
559
|
requestedMode = "read";
|
|
@@ -572,12 +582,25 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
572
582
|
lastError = origError;
|
|
573
583
|
|
|
574
584
|
const retryDelayFromError = getRetryDelayFromError(origError);
|
|
575
|
-
delayMs = retryDelayFromError ?? Math.min(delayMs * 2, MaxReconnectDelayInMs);
|
|
576
|
-
|
|
577
585
|
if (retryDelayFromError !== undefined) {
|
|
586
|
+
// If the error told us to wait, then we wait.
|
|
578
587
|
this.props.reconnectionDelayHandler(retryDelayFromError, origError);
|
|
588
|
+
await new Promise<void>((resolve) => {
|
|
589
|
+
setTimeout(resolve, retryDelayFromError);
|
|
590
|
+
});
|
|
591
|
+
} else if (globalThis.navigator?.onLine !== false) {
|
|
592
|
+
// If the error didn't tell us to wait, let's still wait a little bit before retrying.
|
|
593
|
+
// We skip this delay if we're confident we're offline, because we probably just need to wait to come back online.
|
|
594
|
+
await new Promise<void>((resolve) => {
|
|
595
|
+
setTimeout(resolve, delayMs);
|
|
596
|
+
delayMs = Math.min(delayMs * 2, MaxReconnectDelayInMs);
|
|
597
|
+
});
|
|
579
598
|
}
|
|
580
|
-
|
|
599
|
+
|
|
600
|
+
// If we believe we're offline, we assume there's no point in trying until we at least think we're online.
|
|
601
|
+
// NOTE: This isn't strictly true for drivers that don't require network (e.g. local driver). Really this logic
|
|
602
|
+
// should probably live in the driver.
|
|
603
|
+
await waitForOnline();
|
|
581
604
|
}
|
|
582
605
|
}
|
|
583
606
|
|
|
@@ -615,7 +638,7 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
615
638
|
* @param args - The connection arguments
|
|
616
639
|
*/
|
|
617
640
|
private triggerConnect(connectionMode: ConnectionMode) {
|
|
618
|
-
// reconnect()
|
|
641
|
+
// reconnect() includes async awaits, and that causes potential race conditions
|
|
619
642
|
// where we might already have a connection. If it were to happen, it's possible that we will connect
|
|
620
643
|
// with different mode to `connectionMode`. Glancing through the caller chains, it looks like code should be
|
|
621
644
|
// fine (if needed, reconnect flow will get triggered again). Places where new mode matters should encode it
|
|
@@ -664,10 +687,10 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
664
687
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
665
688
|
this._outbound.pause();
|
|
666
689
|
this._outbound.clear();
|
|
667
|
-
this.props.disconnectHandler(reason);
|
|
668
|
-
|
|
669
690
|
connection.dispose();
|
|
670
691
|
|
|
692
|
+
this.props.disconnectHandler(reason);
|
|
693
|
+
|
|
671
694
|
this._connectionVerboseProps = {};
|
|
672
695
|
|
|
673
696
|
return true;
|
|
@@ -888,12 +911,20 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
888
911
|
return;
|
|
889
912
|
}
|
|
890
913
|
|
|
914
|
+
// If the error tells us to wait before retrying, then do so.
|
|
891
915
|
const delayMs = getRetryDelayFromError(error);
|
|
892
916
|
if (error !== undefined && delayMs !== undefined) {
|
|
893
917
|
this.props.reconnectionDelayHandler(delayMs, error);
|
|
894
|
-
await
|
|
918
|
+
await new Promise<void>((resolve) => {
|
|
919
|
+
setTimeout(resolve, delayMs);
|
|
920
|
+
});
|
|
895
921
|
}
|
|
896
922
|
|
|
923
|
+
// If we believe we're offline, we assume there's no point in trying again until we at least think we're online.
|
|
924
|
+
// NOTE: This isn't strictly true for drivers that don't require network (e.g. local driver). Really this logic
|
|
925
|
+
// should probably live in the driver.
|
|
926
|
+
await waitForOnline();
|
|
927
|
+
|
|
897
928
|
this.triggerConnect(requestedMode);
|
|
898
929
|
}
|
|
899
930
|
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
TelemetryEventCategory,
|
|
10
10
|
} from "@fluidframework/common-definitions";
|
|
11
11
|
import { assert, Timer } from "@fluidframework/common-utils";
|
|
12
|
-
import {
|
|
12
|
+
import { IConnectionDetailsInternal, IDeltaManager } from "@fluidframework/container-definitions";
|
|
13
13
|
import { ILocalSequencedClient } from "@fluidframework/protocol-base";
|
|
14
14
|
import { ISequencedClient, IClient } from "@fluidframework/protocol-definitions";
|
|
15
15
|
import { PerformanceEvent, loggerToMonitoringContext } from "@fluidframework/telemetry-utils";
|
|
@@ -56,7 +56,7 @@ export interface IConnectionStateHandler {
|
|
|
56
56
|
containerSaved(): void;
|
|
57
57
|
dispose(): void;
|
|
58
58
|
initProtocol(protocol: IProtocolHandler): void;
|
|
59
|
-
receivedConnectEvent(details:
|
|
59
|
+
receivedConnectEvent(details: IConnectionDetailsInternal): void;
|
|
60
60
|
receivedDisconnectEvent(reason: string): void;
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -143,7 +143,7 @@ class ConnectionStateHandlerPassThrough
|
|
|
143
143
|
return this.pimpl.receivedDisconnectEvent(reason);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
public receivedConnectEvent(details:
|
|
146
|
+
public receivedConnectEvent(details: IConnectionDetailsInternal) {
|
|
147
147
|
return this.pimpl.receivedConnectEvent(details);
|
|
148
148
|
}
|
|
149
149
|
|
|
@@ -288,7 +288,7 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
288
288
|
private readonly prevClientLeftTimer: Timer;
|
|
289
289
|
private readonly joinOpTimer: Timer;
|
|
290
290
|
private protocol?: IProtocolHandler;
|
|
291
|
-
private connection?:
|
|
291
|
+
private connection?: IConnectionDetailsInternal;
|
|
292
292
|
private _clientId?: string;
|
|
293
293
|
|
|
294
294
|
private waitEvent: PerformanceEvent | undefined;
|
|
@@ -398,6 +398,18 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
398
398
|
});
|
|
399
399
|
}
|
|
400
400
|
this.applyForConnectedState("addMemberEvent");
|
|
401
|
+
} else if (clientId === this.clientId) {
|
|
402
|
+
// If we see our clientId and it's not also our pending ID, it's our own join op
|
|
403
|
+
// being replayed, so start the timer in case our previous client is still in quorum
|
|
404
|
+
assert(
|
|
405
|
+
!this.waitingForLeaveOp,
|
|
406
|
+
"Unexpected join op with current clientId while waiting",
|
|
407
|
+
);
|
|
408
|
+
assert(
|
|
409
|
+
this.connectionState !== ConnectionState.Connected,
|
|
410
|
+
"Unexpected join op with current clientId while connected",
|
|
411
|
+
);
|
|
412
|
+
this.prevClientLeftTimer.restart();
|
|
401
413
|
}
|
|
402
414
|
}
|
|
403
415
|
|
|
@@ -472,7 +484,7 @@ class ConnectionStateHandler implements IConnectionStateHandler {
|
|
|
472
484
|
* @param deltaManager - DeltaManager to be used for delaying Connected transition until caught up.
|
|
473
485
|
* If it's undefined, then don't delay and transition to Connected as soon as Leave/Join op are accounted for
|
|
474
486
|
*/
|
|
475
|
-
public receivedConnectEvent(details:
|
|
487
|
+
public receivedConnectEvent(details: IConnectionDetailsInternal) {
|
|
476
488
|
this.connection = details;
|
|
477
489
|
|
|
478
490
|
const oldState = this._connectionState;
|