@fluidframework/driver-base 2.0.0-dev.3.1.0.125672 → 2.0.0-dev.4.2.0.153917
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 +5 -0
- package/README.md +37 -1
- package/dist/documentDeltaConnection.d.ts +6 -2
- package/dist/documentDeltaConnection.d.ts.map +1 -1
- package/dist/documentDeltaConnection.js +91 -25
- package/dist/documentDeltaConnection.js.map +1 -1
- package/dist/driverUtils.d.ts +24 -0
- package/dist/driverUtils.d.ts.map +1 -0
- package/dist/driverUtils.js +103 -0
- package/dist/driverUtils.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.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/lib/documentDeltaConnection.d.ts +6 -2
- package/lib/documentDeltaConnection.d.ts.map +1 -1
- package/lib/documentDeltaConnection.js +92 -26
- package/lib/documentDeltaConnection.js.map +1 -1
- package/lib/driverUtils.d.ts +24 -0
- package/lib/driverUtils.d.ts.map +1 -0
- package/lib/driverUtils.js +98 -0
- package/lib/driverUtils.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/test/types/validateDriverBasePrevious.generated.js.map +1 -1
- package/package.json +33 -35
- package/src/documentDeltaConnection.ts +108 -25
- package/src/driverUtils.ts +105 -0
- package/src/index.ts +1 -0
- package/src/packageVersion.ts +1 -1
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import { performance } from "@fluidframework/common-utils";
|
|
6
|
+
/**
|
|
7
|
+
* Extract and return the w3c data.
|
|
8
|
+
* @param url - request url for which w3c data needs to be reported.
|
|
9
|
+
* @param initiatorType - type of the network call
|
|
10
|
+
*/
|
|
11
|
+
export function getW3CData(url, initiatorType) {
|
|
12
|
+
// From: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming
|
|
13
|
+
// fetchStart: immediately before the browser starts to fetch the resource.
|
|
14
|
+
// requestStart: immediately before the browser starts requesting the resource from the server
|
|
15
|
+
// responseStart: immediately after the browser receives the first byte of the response from the server.
|
|
16
|
+
// responseEnd: immediately after the browser receives the last byte of the resource
|
|
17
|
+
// or immediately before the transport connection is closed, whichever comes first.
|
|
18
|
+
// secureConnectionStart: immediately before the browser starts the handshake process to secure the
|
|
19
|
+
// current connection. If a secure connection is not used, this property returns zero.
|
|
20
|
+
// startTime: Time when the resource fetch started. This value is equivalent to fetchStart.
|
|
21
|
+
// domainLookupStart: immediately before the browser starts the domain name lookup for the resource.
|
|
22
|
+
// domainLookupEnd: immediately after the browser finishes the domain name lookup for the resource.
|
|
23
|
+
// redirectStart: start time of the fetch which that initiates the redirect.
|
|
24
|
+
// redirectEnd: immediately after receiving the last byte of the response of the last redirect.
|
|
25
|
+
var _a, _b;
|
|
26
|
+
// Interval between start and finish of the domain name lookup for the resource.
|
|
27
|
+
let dnsLookupTime; // domainLookupEnd - domainLookupStart
|
|
28
|
+
// Interval between the first fetch until the last byte of the last redirect.
|
|
29
|
+
let redirectTime; // redirectEnd - redirectStart
|
|
30
|
+
// Time to establish the connection to the server to retrieve the resource.
|
|
31
|
+
let tcpHandshakeTime; // connectEnd - connectStart
|
|
32
|
+
// Time from the end of the connection until the inital handshake process to secure the connection.
|
|
33
|
+
// If 0, then no time is spent here.
|
|
34
|
+
let secureConnectionTime; // connectEnd - secureConnectionStart
|
|
35
|
+
// Interval to receive all (first to last) bytes form the server.
|
|
36
|
+
let responseNetworkTime; // responsEnd - responseStart
|
|
37
|
+
// Interval between the initial fetch until the last byte is received.
|
|
38
|
+
// Likely same as fetchTime + receiveContentTime.
|
|
39
|
+
let fetchStartToResponseEndTime; // responseEnd - fetchStart
|
|
40
|
+
// reqStartToResponseEndTime = fetchStartToResponseEndTime - <initial TCP handshake>
|
|
41
|
+
// Interval between starting the request for the resource until receiving the last byte.
|
|
42
|
+
let reqStartToResponseEndTime; // responseEnd - requestStart
|
|
43
|
+
let w3cStartTime; // W3C Start time = fetchStart time
|
|
44
|
+
// getEntriesByType is only available in browser performance object
|
|
45
|
+
const resources1 = (_b = (_a = performance.getEntriesByType) === null || _a === void 0 ? void 0 : _a.call(performance, "resource")) !== null && _b !== void 0 ? _b : [];
|
|
46
|
+
// Usually the latest fetch call is to the end of resources, so we start from the end.
|
|
47
|
+
for (let i = resources1.length - 1; i > 0; i--) {
|
|
48
|
+
const indResTime = resources1[i];
|
|
49
|
+
const resource_name = indResTime.name.toString();
|
|
50
|
+
const resource_initiatortype = indResTime.initiatorType;
|
|
51
|
+
if (resource_initiatortype.localeCompare(initiatorType) === 0 &&
|
|
52
|
+
resource_name.includes(url)) {
|
|
53
|
+
redirectTime = indResTime.redirectEnd - indResTime.redirectStart;
|
|
54
|
+
w3cStartTime = indResTime.fetchStart;
|
|
55
|
+
dnsLookupTime = indResTime.domainLookupEnd - indResTime.domainLookupStart;
|
|
56
|
+
tcpHandshakeTime = indResTime.connectEnd - indResTime.connectStart;
|
|
57
|
+
secureConnectionTime =
|
|
58
|
+
indResTime.secureConnectionStart > 0
|
|
59
|
+
? indResTime.connectEnd - indResTime.secureConnectionStart
|
|
60
|
+
: 0;
|
|
61
|
+
responseNetworkTime =
|
|
62
|
+
indResTime.responseStart > 0
|
|
63
|
+
? indResTime.responseEnd - indResTime.responseStart
|
|
64
|
+
: undefined;
|
|
65
|
+
fetchStartToResponseEndTime =
|
|
66
|
+
indResTime.fetchStart > 0
|
|
67
|
+
? indResTime.responseEnd - indResTime.fetchStart
|
|
68
|
+
: undefined;
|
|
69
|
+
reqStartToResponseEndTime =
|
|
70
|
+
indResTime.requestStart > 0
|
|
71
|
+
? indResTime.responseEnd - indResTime.requestStart
|
|
72
|
+
: undefined;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
dnsLookupTime,
|
|
78
|
+
w3cStartTime,
|
|
79
|
+
redirectTime,
|
|
80
|
+
tcpHandshakeTime,
|
|
81
|
+
secureConnectionTime,
|
|
82
|
+
responseNetworkTime,
|
|
83
|
+
fetchStartToResponseEndTime,
|
|
84
|
+
reqStartToResponseEndTime,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/*
|
|
88
|
+
* An implementation of Promise.race that gives you the winner of the promise race.
|
|
89
|
+
* If one of the promises is rejected before any other is resolved, this method will return the error/reason from that rejection.
|
|
90
|
+
*/
|
|
91
|
+
export async function promiseRaceWithWinner(promises) {
|
|
92
|
+
return new Promise((resolve, reject) => {
|
|
93
|
+
promises.forEach((p, index) => {
|
|
94
|
+
p.then((v) => resolve({ index, value: v })).catch(reject);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=driverUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driverUtils.js","sourceRoot":"","sources":["../src/driverUtils.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 { performance } from \"@fluidframework/common-utils\";\n\n/**\n * Extract and return the w3c data.\n * @param url - request url for which w3c data needs to be reported.\n * @param initiatorType - type of the network call\n */\nexport function getW3CData(url: string, initiatorType: string) {\n\t// From: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming\n\t// fetchStart: immediately before the browser starts to fetch the resource.\n\t// requestStart: immediately before the browser starts requesting the resource from the server\n\t// responseStart: immediately after the browser receives the first byte of the response from the server.\n\t// responseEnd: immediately after the browser receives the last byte of the resource\n\t// or immediately before the transport connection is closed, whichever comes first.\n\t// secureConnectionStart: immediately before the browser starts the handshake process to secure the\n\t// current connection. If a secure connection is not used, this property returns zero.\n\t// startTime: Time when the resource fetch started. This value is equivalent to fetchStart.\n\t// domainLookupStart: immediately before the browser starts the domain name lookup for the resource.\n\t// domainLookupEnd: immediately after the browser finishes the domain name lookup for the resource.\n\t// redirectStart: start time of the fetch which that initiates the redirect.\n\t// redirectEnd: immediately after receiving the last byte of the response of the last redirect.\n\n\t// Interval between start and finish of the domain name lookup for the resource.\n\tlet dnsLookupTime: number | undefined; // domainLookupEnd - domainLookupStart\n\t// Interval between the first fetch until the last byte of the last redirect.\n\tlet redirectTime: number | undefined; // redirectEnd - redirectStart\n\t// Time to establish the connection to the server to retrieve the resource.\n\tlet tcpHandshakeTime: number | undefined; // connectEnd - connectStart\n\t// Time from the end of the connection until the inital handshake process to secure the connection.\n\t// If 0, then no time is spent here.\n\tlet secureConnectionTime: number | undefined; // connectEnd - secureConnectionStart\n\t// Interval to receive all (first to last) bytes form the server.\n\tlet responseNetworkTime: number | undefined; // responsEnd - responseStart\n\t// Interval between the initial fetch until the last byte is received.\n\t// Likely same as fetchTime + receiveContentTime.\n\tlet fetchStartToResponseEndTime: number | undefined; // responseEnd - fetchStart\n\t// reqStartToResponseEndTime = fetchStartToResponseEndTime - <initial TCP handshake>\n\t// Interval between starting the request for the resource until receiving the last byte.\n\tlet reqStartToResponseEndTime: number | undefined; // responseEnd - requestStart\n\tlet w3cStartTime: number | undefined; // W3C Start time = fetchStart time\n\n\t// getEntriesByType is only available in browser performance object\n\tconst resources1 = performance.getEntriesByType?.(\"resource\") ?? [];\n\t// Usually the latest fetch call is to the end of resources, so we start from the end.\n\tfor (let i = resources1.length - 1; i > 0; i--) {\n\t\tconst indResTime = resources1[i] as PerformanceResourceTiming;\n\t\tconst resource_name = indResTime.name.toString();\n\t\tconst resource_initiatortype = indResTime.initiatorType;\n\t\tif (\n\t\t\tresource_initiatortype.localeCompare(initiatorType) === 0 &&\n\t\t\tresource_name.includes(url)\n\t\t) {\n\t\t\tredirectTime = indResTime.redirectEnd - indResTime.redirectStart;\n\t\t\tw3cStartTime = indResTime.fetchStart;\n\t\t\tdnsLookupTime = indResTime.domainLookupEnd - indResTime.domainLookupStart;\n\t\t\ttcpHandshakeTime = indResTime.connectEnd - indResTime.connectStart;\n\t\t\tsecureConnectionTime =\n\t\t\t\tindResTime.secureConnectionStart > 0\n\t\t\t\t\t? indResTime.connectEnd - indResTime.secureConnectionStart\n\t\t\t\t\t: 0;\n\t\t\tresponseNetworkTime =\n\t\t\t\tindResTime.responseStart > 0\n\t\t\t\t\t? indResTime.responseEnd - indResTime.responseStart\n\t\t\t\t\t: undefined;\n\t\t\tfetchStartToResponseEndTime =\n\t\t\t\tindResTime.fetchStart > 0\n\t\t\t\t\t? indResTime.responseEnd - indResTime.fetchStart\n\t\t\t\t\t: undefined;\n\t\t\treqStartToResponseEndTime =\n\t\t\t\tindResTime.requestStart > 0\n\t\t\t\t\t? indResTime.responseEnd - indResTime.requestStart\n\t\t\t\t\t: undefined;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn {\n\t\tdnsLookupTime,\n\t\tw3cStartTime,\n\t\tredirectTime,\n\t\ttcpHandshakeTime,\n\t\tsecureConnectionTime,\n\t\tresponseNetworkTime,\n\t\tfetchStartToResponseEndTime,\n\t\treqStartToResponseEndTime,\n\t};\n}\n\n/*\n * An implementation of Promise.race that gives you the winner of the promise race.\n * If one of the promises is rejected before any other is resolved, this method will return the error/reason from that rejection.\n */\nexport async function promiseRaceWithWinner<T>(\n\tpromises: Promise<T>[],\n): Promise<{ index: number; value: T }> {\n\treturn new Promise((resolve, reject) => {\n\t\tpromises.forEach((p, index) => {\n\t\t\tp.then((v) => resolve({ index, value: v })).catch(reject);\n\t\t});\n\t});\n}\n"]}
|
package/lib/index.d.ts
CHANGED
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC"}
|
package/lib/index.js
CHANGED
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { DocumentDeltaConnection } from \"./documentDeltaConnection\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { DocumentDeltaConnection } from \"./documentDeltaConnection\";\nexport { getW3CData, promiseRaceWithWinner } from \"./driverUtils\";\n"]}
|
package/lib/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/driver-base";
|
|
8
|
-
export declare const pkgVersion = "2.0.0-dev.
|
|
8
|
+
export declare const pkgVersion = "2.0.0-dev.4.2.0.153917";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/lib/packageVersion.js
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export const pkgName = "@fluidframework/driver-base";
|
|
8
|
-
export const pkgVersion = "2.0.0-dev.
|
|
8
|
+
export const pkgVersion = "2.0.0-dev.4.2.0.153917";
|
|
9
9
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,wBAAwB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/driver-base\";\nexport const pkgVersion = \"2.0.0-dev.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,wBAAwB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/driver-base\";\nexport const pkgVersion = \"2.0.0-dev.4.2.0.153917\";\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateDriverBasePrevious.generated.js","sourceRoot":"","sources":["../../../src/test/types/validateDriverBasePrevious.generated.ts"],"names":[],"mappings":"AAwBA,oDAAoD,CAChD,gDAAgD,EAAE,CAAC,CAAC;AAWxD,gDAAgD,CAC5C,oDAAoD,EAAE,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n/*\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n * Generated by fluid-type-
|
|
1
|
+
{"version":3,"file":"validateDriverBasePrevious.generated.js","sourceRoot":"","sources":["../../../src/test/types/validateDriverBasePrevious.generated.ts"],"names":[],"mappings":"AAwBA,oDAAoD,CAChD,gDAAgD,EAAE,CAAC,CAAC;AAWxD,gDAAgD,CAC5C,oDAAoD,EAAE,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n/*\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n * Generated by fluid-type-test-generator in @fluidframework/build-tools.\n */\nimport * as old from \"@fluidframework/driver-base-previous\";\nimport * as current from \"../../index\";\n\ntype TypeOnly<T> = {\n [P in keyof T]: TypeOnly<T[P]>;\n};\n\n/*\n* Validate forward compat by using old type in place of current type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"ClassDeclaration_DocumentDeltaConnection\": {\"forwardCompat\": false}\n*/\ndeclare function get_old_ClassDeclaration_DocumentDeltaConnection():\n TypeOnly<old.DocumentDeltaConnection>;\ndeclare function use_current_ClassDeclaration_DocumentDeltaConnection(\n use: TypeOnly<current.DocumentDeltaConnection>);\nuse_current_ClassDeclaration_DocumentDeltaConnection(\n get_old_ClassDeclaration_DocumentDeltaConnection());\n\n/*\n* Validate back compat by using current type in place of old type\n* If breaking change required, add in package.json under typeValidation.broken:\n* \"ClassDeclaration_DocumentDeltaConnection\": {\"backCompat\": false}\n*/\ndeclare function get_current_ClassDeclaration_DocumentDeltaConnection():\n TypeOnly<current.DocumentDeltaConnection>;\ndeclare function use_old_ClassDeclaration_DocumentDeltaConnection(\n use: TypeOnly<old.DocumentDeltaConnection>);\nuse_old_ClassDeclaration_DocumentDeltaConnection(\n get_current_ClassDeclaration_DocumentDeltaConnection());\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/driver-base",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.4.2.0.153917",
|
|
4
4
|
"description": "Shared driver code for Fluid driver implementations",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -14,9 +14,36 @@
|
|
|
14
14
|
"main": "dist/index.js",
|
|
15
15
|
"module": "lib/index.js",
|
|
16
16
|
"types": "dist/index.d.ts",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@fluidframework/common-definitions": "^0.20.1",
|
|
19
|
+
"@fluidframework/common-utils": "^1.1.1",
|
|
20
|
+
"@fluidframework/driver-definitions": "2.0.0-dev.4.2.0.153917",
|
|
21
|
+
"@fluidframework/driver-utils": "2.0.0-dev.4.2.0.153917",
|
|
22
|
+
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
23
|
+
"@fluidframework/telemetry-utils": "2.0.0-dev.4.2.0.153917"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@fluid-tools/build-cli": "^0.15.0",
|
|
27
|
+
"@fluidframework/build-common": "^1.1.0",
|
|
28
|
+
"@fluidframework/build-tools": "^0.15.0",
|
|
29
|
+
"@fluidframework/driver-base-previous": "npm:@fluidframework/driver-base@2.0.0-internal.4.0.0",
|
|
30
|
+
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
31
|
+
"@microsoft/api-extractor": "^7.34.4",
|
|
32
|
+
"@types/node": "^14.18.38",
|
|
33
|
+
"concurrently": "^7.6.0",
|
|
34
|
+
"copyfiles": "^2.4.1",
|
|
35
|
+
"eslint": "~8.6.0",
|
|
36
|
+
"prettier": "~2.6.2",
|
|
37
|
+
"rimraf": "^4.4.0",
|
|
38
|
+
"socket.io-client": "^4.4.1",
|
|
39
|
+
"typescript": "~4.5.5"
|
|
40
|
+
},
|
|
41
|
+
"typeValidation": {
|
|
42
|
+
"broken": {}
|
|
43
|
+
},
|
|
17
44
|
"scripts": {
|
|
18
45
|
"build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
|
|
19
|
-
"build:compile": "concurrently npm:tsc npm:build:esnext",
|
|
46
|
+
"build:compile": "npm run typetests:gen && concurrently npm:tsc npm:build:esnext",
|
|
20
47
|
"build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
|
|
21
48
|
"build:esnext": "tsc --project ./tsconfig.esnext.json",
|
|
22
49
|
"build:full": "npm run build",
|
|
@@ -31,37 +58,8 @@
|
|
|
31
58
|
"lint:fix": "npm run prettier:fix && npm run eslint:fix",
|
|
32
59
|
"prettier": "prettier --check . --ignore-path ../../../.prettierignore",
|
|
33
60
|
"prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
|
|
34
|
-
"tsc": "tsc"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"@fluidframework/common-definitions": "^0.20.1",
|
|
38
|
-
"@fluidframework/common-utils": "^1.0.0",
|
|
39
|
-
"@fluidframework/driver-definitions": ">=2.0.0-dev.3.1.0.125672 <2.0.0-dev.4.0.0",
|
|
40
|
-
"@fluidframework/driver-utils": ">=2.0.0-dev.3.1.0.125672 <2.0.0-dev.4.0.0",
|
|
41
|
-
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
42
|
-
"@fluidframework/telemetry-utils": ">=2.0.0-dev.3.1.0.125672 <2.0.0-dev.4.0.0"
|
|
43
|
-
},
|
|
44
|
-
"devDependencies": {
|
|
45
|
-
"@fluid-tools/build-cli": "^0.8.0",
|
|
46
|
-
"@fluidframework/build-common": "^1.1.0",
|
|
47
|
-
"@fluidframework/driver-base-previous": "npm:@fluidframework/driver-base@2.0.0-internal.3.0.0",
|
|
48
|
-
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
49
|
-
"@microsoft/api-extractor": "^7.22.2",
|
|
50
|
-
"@rushstack/eslint-config": "^2.5.1",
|
|
51
|
-
"@types/node": "^14.18.36",
|
|
52
|
-
"concurrently": "^6.2.0",
|
|
53
|
-
"copyfiles": "^2.4.1",
|
|
54
|
-
"eslint": "~8.6.0",
|
|
55
|
-
"prettier": "~2.6.2",
|
|
56
|
-
"rimraf": "^2.6.2",
|
|
57
|
-
"socket.io-client": "^4.4.1",
|
|
58
|
-
"typescript": "~4.5.5"
|
|
59
|
-
},
|
|
60
|
-
"typeValidation": {
|
|
61
|
-
"version": "2.0.0-internal.3.1.0",
|
|
62
|
-
"previousVersionStyle": "~previousMinor",
|
|
63
|
-
"baselineRange": ">=2.0.0-internal.3.0.0 <2.0.0-internal.3.1.0",
|
|
64
|
-
"baselineVersion": "2.0.0-internal.3.0.0",
|
|
65
|
-
"broken": {}
|
|
61
|
+
"tsc": "tsc",
|
|
62
|
+
"typetests:gen": "fluid-type-test-generator",
|
|
63
|
+
"typetests:prepare": "flub generate typetests --prepare --dir . --pin"
|
|
66
64
|
}
|
|
67
|
-
}
|
|
65
|
+
}
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
loggerToMonitoringContext,
|
|
31
31
|
MonitoringContext,
|
|
32
32
|
EventEmitterWithErrorHandling,
|
|
33
|
+
normalizeError,
|
|
33
34
|
} from "@fluidframework/telemetry-utils";
|
|
34
35
|
import type { Socket } from "socket.io-client";
|
|
35
36
|
// For now, this package is versioned and released in unison with the specific drivers
|
|
@@ -81,10 +82,21 @@ export class DocumentDeltaConnection
|
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
public get disposed() {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
// Increase the stack trace limit temporarily, so as to debug better in case it occurs.
|
|
86
|
+
// We are seeing this in telemetry and we are unable to figure out why it is happening, so this should help.
|
|
87
|
+
const originalStackTraceLimit = (Error as any).stackTraceLimit;
|
|
88
|
+
try {
|
|
89
|
+
(Error as any).stackTraceLimit = 50;
|
|
90
|
+
assert(
|
|
91
|
+
this._disposed || this.socket.connected,
|
|
92
|
+
0x244 /* "Socket is closed, but connection is not!" */,
|
|
93
|
+
);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
const normalizedError = this.addPropsToError(error);
|
|
96
|
+
throw normalizedError;
|
|
97
|
+
} finally {
|
|
98
|
+
(Error as any).stackTraceLimit = originalStackTraceLimit;
|
|
99
|
+
}
|
|
88
100
|
return this._disposed;
|
|
89
101
|
}
|
|
90
102
|
|
|
@@ -120,6 +132,7 @@ export class DocumentDeltaConnection
|
|
|
120
132
|
public documentId: string,
|
|
121
133
|
logger: ITelemetryLogger,
|
|
122
134
|
private readonly enableLongPollingDowngrades: boolean = false,
|
|
135
|
+
protected readonly connectionId?: string,
|
|
123
136
|
) {
|
|
124
137
|
super((name, error) => {
|
|
125
138
|
logger.sendErrorEvent(
|
|
@@ -223,7 +236,18 @@ export class DocumentDeltaConnection
|
|
|
223
236
|
}
|
|
224
237
|
|
|
225
238
|
private checkNotClosed() {
|
|
226
|
-
|
|
239
|
+
// Increase the stack trace limit temporarily, so as to debug better in case it occurs.
|
|
240
|
+
// We are seeing this in telemetry and we are unable to figure out why it is happening, so this should help.
|
|
241
|
+
const originalStackTraceLimit = (Error as any).stackTraceLimit;
|
|
242
|
+
try {
|
|
243
|
+
(Error as any).stackTraceLimit = 50;
|
|
244
|
+
assert(!this.disposed, 0x20c /* "connection disposed" */);
|
|
245
|
+
} catch (error) {
|
|
246
|
+
const normalizedError = this.addPropsToError(error);
|
|
247
|
+
throw normalizedError;
|
|
248
|
+
} finally {
|
|
249
|
+
(Error as any).stackTraceLimit = originalStackTraceLimit;
|
|
250
|
+
}
|
|
227
251
|
}
|
|
228
252
|
|
|
229
253
|
/**
|
|
@@ -318,7 +342,26 @@ export class DocumentDeltaConnection
|
|
|
318
342
|
/**
|
|
319
343
|
* Disconnect from the websocket and close the websocket too.
|
|
320
344
|
*/
|
|
321
|
-
|
|
345
|
+
private closeSocket(error: IAnyDriverError) {
|
|
346
|
+
if (this._disposed) {
|
|
347
|
+
// This would be rare situation due to complexity around socket emitting events.
|
|
348
|
+
this.logger.sendTelemetryEvent(
|
|
349
|
+
{
|
|
350
|
+
eventName: "SocketCloseOnDisposedConnection",
|
|
351
|
+
driverVersion,
|
|
352
|
+
details: JSON.stringify({
|
|
353
|
+
...this.getConnectionDetailsProps(),
|
|
354
|
+
trackedListenerCount: this.trackedListeners.size,
|
|
355
|
+
}),
|
|
356
|
+
},
|
|
357
|
+
error,
|
|
358
|
+
);
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
this.closeSocketCore(error);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
protected closeSocketCore(error: IAnyDriverError) {
|
|
322
365
|
this.disconnect(error);
|
|
323
366
|
}
|
|
324
367
|
|
|
@@ -332,8 +375,7 @@ export class DocumentDeltaConnection
|
|
|
332
375
|
eventName: "ClientClosingDeltaConnection",
|
|
333
376
|
driverVersion,
|
|
334
377
|
details: JSON.stringify({
|
|
335
|
-
|
|
336
|
-
socketConnected: this.socket.connected,
|
|
378
|
+
...this.getConnectionDetailsProps(),
|
|
337
379
|
}),
|
|
338
380
|
});
|
|
339
381
|
this.disconnect(
|
|
@@ -361,23 +403,24 @@ export class DocumentDeltaConnection
|
|
|
361
403
|
// to prevent normal messages from being emitted.
|
|
362
404
|
this._disposed = true;
|
|
363
405
|
|
|
364
|
-
//
|
|
365
|
-
//
|
|
406
|
+
// Remove all listeners listening on the socket. These are listeners on socket and not on this connection
|
|
407
|
+
// object. Anyway since we have disposed this connection object, nobody should listen to event on socket
|
|
408
|
+
// anymore.
|
|
409
|
+
this.removeTrackedListeners();
|
|
410
|
+
|
|
411
|
+
// Clear the connection/socket before letting the deltaManager/connection manager know about the disconnect.
|
|
412
|
+
this.disconnectCore();
|
|
413
|
+
|
|
414
|
+
// Let user of connection object know about disconnect.
|
|
366
415
|
this.emit("disconnect", err);
|
|
367
416
|
this.logger.sendTelemetryEvent({
|
|
368
417
|
eventName: "AfterDisconnectEvent",
|
|
369
418
|
driverVersion,
|
|
370
419
|
details: JSON.stringify({
|
|
371
|
-
|
|
420
|
+
...this.getConnectionDetailsProps(),
|
|
372
421
|
disconnectListenerCount: this.listenerCount("disconnect"),
|
|
373
422
|
}),
|
|
374
423
|
});
|
|
375
|
-
// user of DeltaConnection should have processed "disconnect" event and removed all listeners. Not clear
|
|
376
|
-
// if we want to enforce that, as some users (like LocalDocumentService) do not unregister any handlers
|
|
377
|
-
// assert(this.listenerCount("disconnect") === 0, "'disconnect` events should be processed synchronously");
|
|
378
|
-
|
|
379
|
-
this.removeTrackedListeners();
|
|
380
|
-
this.disconnectCore();
|
|
381
424
|
}
|
|
382
425
|
|
|
383
426
|
/**
|
|
@@ -403,14 +446,34 @@ export class DocumentDeltaConnection
|
|
|
403
446
|
|
|
404
447
|
this._details = await new Promise<IConnected>((resolve, reject) => {
|
|
405
448
|
const failAndCloseSocket = (err: IAnyDriverError) => {
|
|
406
|
-
|
|
449
|
+
try {
|
|
450
|
+
this.closeSocket(err);
|
|
451
|
+
} catch (failError) {
|
|
452
|
+
const normalizedError = this.addPropsToError(failError);
|
|
453
|
+
this.logger.sendErrorEvent({ eventName: "CloseSocketError" }, normalizedError);
|
|
454
|
+
}
|
|
407
455
|
reject(err);
|
|
408
456
|
};
|
|
409
457
|
|
|
410
458
|
const failConnection = (err: IAnyDriverError) => {
|
|
411
|
-
|
|
459
|
+
try {
|
|
460
|
+
this.disconnect(err);
|
|
461
|
+
} catch (failError) {
|
|
462
|
+
const normalizedError = this.addPropsToError(failError);
|
|
463
|
+
this.logger.sendErrorEvent(
|
|
464
|
+
{ eventName: "FailConnectionError" },
|
|
465
|
+
normalizedError,
|
|
466
|
+
);
|
|
467
|
+
}
|
|
412
468
|
reject(err);
|
|
413
469
|
};
|
|
470
|
+
|
|
471
|
+
// Immediately set the connection timeout.
|
|
472
|
+
// Give extra 2 seconds for handshake on top of socket connection timeout.
|
|
473
|
+
this.socketConnectionTimeout = setTimeout(() => {
|
|
474
|
+
failConnection(this.createErrorObject("orderingServiceHandshakeTimeout"));
|
|
475
|
+
}, timeout + 2000);
|
|
476
|
+
|
|
414
477
|
// Listen for connection issues
|
|
415
478
|
this.addConnectionListener("connect_error", (error) => {
|
|
416
479
|
internalSocketConnectionFailureCount++;
|
|
@@ -560,16 +623,31 @@ export class DocumentDeltaConnection
|
|
|
560
623
|
});
|
|
561
624
|
|
|
562
625
|
this.socket.emit("connect_document", connectMessage);
|
|
563
|
-
|
|
564
|
-
// Give extra 2 seconds for handshake on top of socket connection timeout
|
|
565
|
-
this.socketConnectionTimeout = setTimeout(() => {
|
|
566
|
-
failConnection(this.createErrorObject("orderingServiceHandshakeTimeout"));
|
|
567
|
-
}, timeout + 2000);
|
|
568
626
|
});
|
|
569
627
|
|
|
570
628
|
assert(!this.disposed, 0x246 /* "checking consistency of socket & _disposed flags" */);
|
|
571
629
|
}
|
|
572
630
|
|
|
631
|
+
private addPropsToError(errorToBeNormalized: unknown) {
|
|
632
|
+
const normalizedError = normalizeError(errorToBeNormalized, {
|
|
633
|
+
props: {
|
|
634
|
+
details: JSON.stringify({
|
|
635
|
+
...this.getConnectionDetailsProps(),
|
|
636
|
+
}),
|
|
637
|
+
},
|
|
638
|
+
});
|
|
639
|
+
return normalizedError;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
private getConnectionDetailsProps() {
|
|
643
|
+
return {
|
|
644
|
+
disposed: this._disposed,
|
|
645
|
+
socketConnected: this.socket?.connected,
|
|
646
|
+
clientId: this._details?.clientId,
|
|
647
|
+
connectionId: this.connectionId,
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
573
651
|
protected earlyOpHandler = (documentId: string, msgs: ISequencedDocumentMessage[]) => {
|
|
574
652
|
this.queuedMessages.push(...msgs);
|
|
575
653
|
};
|
|
@@ -654,7 +732,12 @@ export class DocumentDeltaConnection
|
|
|
654
732
|
const errorObj = createGenericNetworkError(
|
|
655
733
|
`socket.io (${handler}): ${message}`,
|
|
656
734
|
{ canRetry },
|
|
657
|
-
{
|
|
735
|
+
{
|
|
736
|
+
driverVersion,
|
|
737
|
+
details: JSON.stringify({
|
|
738
|
+
...this.getConnectionDetailsProps(),
|
|
739
|
+
}),
|
|
740
|
+
},
|
|
658
741
|
);
|
|
659
742
|
|
|
660
743
|
return errorObj;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { performance } from "@fluidframework/common-utils";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Extract and return the w3c data.
|
|
10
|
+
* @param url - request url for which w3c data needs to be reported.
|
|
11
|
+
* @param initiatorType - type of the network call
|
|
12
|
+
*/
|
|
13
|
+
export function getW3CData(url: string, initiatorType: string) {
|
|
14
|
+
// From: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming
|
|
15
|
+
// fetchStart: immediately before the browser starts to fetch the resource.
|
|
16
|
+
// requestStart: immediately before the browser starts requesting the resource from the server
|
|
17
|
+
// responseStart: immediately after the browser receives the first byte of the response from the server.
|
|
18
|
+
// responseEnd: immediately after the browser receives the last byte of the resource
|
|
19
|
+
// or immediately before the transport connection is closed, whichever comes first.
|
|
20
|
+
// secureConnectionStart: immediately before the browser starts the handshake process to secure the
|
|
21
|
+
// current connection. If a secure connection is not used, this property returns zero.
|
|
22
|
+
// startTime: Time when the resource fetch started. This value is equivalent to fetchStart.
|
|
23
|
+
// domainLookupStart: immediately before the browser starts the domain name lookup for the resource.
|
|
24
|
+
// domainLookupEnd: immediately after the browser finishes the domain name lookup for the resource.
|
|
25
|
+
// redirectStart: start time of the fetch which that initiates the redirect.
|
|
26
|
+
// redirectEnd: immediately after receiving the last byte of the response of the last redirect.
|
|
27
|
+
|
|
28
|
+
// Interval between start and finish of the domain name lookup for the resource.
|
|
29
|
+
let dnsLookupTime: number | undefined; // domainLookupEnd - domainLookupStart
|
|
30
|
+
// Interval between the first fetch until the last byte of the last redirect.
|
|
31
|
+
let redirectTime: number | undefined; // redirectEnd - redirectStart
|
|
32
|
+
// Time to establish the connection to the server to retrieve the resource.
|
|
33
|
+
let tcpHandshakeTime: number | undefined; // connectEnd - connectStart
|
|
34
|
+
// Time from the end of the connection until the inital handshake process to secure the connection.
|
|
35
|
+
// If 0, then no time is spent here.
|
|
36
|
+
let secureConnectionTime: number | undefined; // connectEnd - secureConnectionStart
|
|
37
|
+
// Interval to receive all (first to last) bytes form the server.
|
|
38
|
+
let responseNetworkTime: number | undefined; // responsEnd - responseStart
|
|
39
|
+
// Interval between the initial fetch until the last byte is received.
|
|
40
|
+
// Likely same as fetchTime + receiveContentTime.
|
|
41
|
+
let fetchStartToResponseEndTime: number | undefined; // responseEnd - fetchStart
|
|
42
|
+
// reqStartToResponseEndTime = fetchStartToResponseEndTime - <initial TCP handshake>
|
|
43
|
+
// Interval between starting the request for the resource until receiving the last byte.
|
|
44
|
+
let reqStartToResponseEndTime: number | undefined; // responseEnd - requestStart
|
|
45
|
+
let w3cStartTime: number | undefined; // W3C Start time = fetchStart time
|
|
46
|
+
|
|
47
|
+
// getEntriesByType is only available in browser performance object
|
|
48
|
+
const resources1 = performance.getEntriesByType?.("resource") ?? [];
|
|
49
|
+
// Usually the latest fetch call is to the end of resources, so we start from the end.
|
|
50
|
+
for (let i = resources1.length - 1; i > 0; i--) {
|
|
51
|
+
const indResTime = resources1[i] as PerformanceResourceTiming;
|
|
52
|
+
const resource_name = indResTime.name.toString();
|
|
53
|
+
const resource_initiatortype = indResTime.initiatorType;
|
|
54
|
+
if (
|
|
55
|
+
resource_initiatortype.localeCompare(initiatorType) === 0 &&
|
|
56
|
+
resource_name.includes(url)
|
|
57
|
+
) {
|
|
58
|
+
redirectTime = indResTime.redirectEnd - indResTime.redirectStart;
|
|
59
|
+
w3cStartTime = indResTime.fetchStart;
|
|
60
|
+
dnsLookupTime = indResTime.domainLookupEnd - indResTime.domainLookupStart;
|
|
61
|
+
tcpHandshakeTime = indResTime.connectEnd - indResTime.connectStart;
|
|
62
|
+
secureConnectionTime =
|
|
63
|
+
indResTime.secureConnectionStart > 0
|
|
64
|
+
? indResTime.connectEnd - indResTime.secureConnectionStart
|
|
65
|
+
: 0;
|
|
66
|
+
responseNetworkTime =
|
|
67
|
+
indResTime.responseStart > 0
|
|
68
|
+
? indResTime.responseEnd - indResTime.responseStart
|
|
69
|
+
: undefined;
|
|
70
|
+
fetchStartToResponseEndTime =
|
|
71
|
+
indResTime.fetchStart > 0
|
|
72
|
+
? indResTime.responseEnd - indResTime.fetchStart
|
|
73
|
+
: undefined;
|
|
74
|
+
reqStartToResponseEndTime =
|
|
75
|
+
indResTime.requestStart > 0
|
|
76
|
+
? indResTime.responseEnd - indResTime.requestStart
|
|
77
|
+
: undefined;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
dnsLookupTime,
|
|
83
|
+
w3cStartTime,
|
|
84
|
+
redirectTime,
|
|
85
|
+
tcpHandshakeTime,
|
|
86
|
+
secureConnectionTime,
|
|
87
|
+
responseNetworkTime,
|
|
88
|
+
fetchStartToResponseEndTime,
|
|
89
|
+
reqStartToResponseEndTime,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* An implementation of Promise.race that gives you the winner of the promise race.
|
|
95
|
+
* If one of the promises is rejected before any other is resolved, this method will return the error/reason from that rejection.
|
|
96
|
+
*/
|
|
97
|
+
export async function promiseRaceWithWinner<T>(
|
|
98
|
+
promises: Promise<T>[],
|
|
99
|
+
): Promise<{ index: number; value: T }> {
|
|
100
|
+
return new Promise((resolve, reject) => {
|
|
101
|
+
promises.forEach((p, index) => {
|
|
102
|
+
p.then((v) => resolve({ index, value: v })).catch(reject);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
package/src/index.ts
CHANGED
package/src/packageVersion.ts
CHANGED