@fluidframework/container-runtime 2.0.0-internal.7.0.0 → 2.0.0-internal.7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/api-extractor.json +1 -1
- package/api-report/container-runtime.api.md +864 -0
- package/dist/blobManager.d.ts +4 -6
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +42 -56
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +75 -42
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerRuntime.d.ts +90 -36
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +125 -59
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.js +2 -2
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +8 -2
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +15 -8
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts +3 -0
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +3 -0
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts +0 -2
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +2 -7
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaManagerProxyBase.d.ts +1 -1
- package/dist/deltaManagerProxyBase.d.ts.map +1 -1
- package/dist/deltaManagerProxyBase.js +2 -2
- package/dist/deltaManagerProxyBase.js.map +1 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +6 -0
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +16 -3
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts +1 -0
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +12 -2
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +42 -11
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +4 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcSummaryDefinitions.d.ts +1 -1
- package/dist/gc/gcSummaryDefinitions.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts +2 -3
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +7 -8
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/index.d.ts +2 -2
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +1 -5
- package/dist/gc/index.js.map +1 -1
- package/dist/id-compressor/utilities.d.ts +3 -0
- package/dist/id-compressor/utilities.d.ts.map +1 -1
- package/dist/id-compressor/utilities.js +3 -0
- package/dist/id-compressor/utilities.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +4 -1
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js +3 -0
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +3 -0
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +7 -2
- package/dist/opLifecycle/outbox.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/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +3 -1
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/scheduleManager.js +6 -2
- package/dist/scheduleManager.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +4 -1
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.d.ts +5 -0
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/summary/runWhileConnectedCoordinator.js +1 -0
- package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/summary/summarizer.d.ts +2 -0
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +15 -7
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +94 -10
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryCollection.d.ts +16 -0
- package/dist/summary/summaryCollection.d.ts.map +1 -1
- package/dist/summary/summaryCollection.js +2 -0
- package/dist/summary/summaryCollection.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +10 -1
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +2 -2
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +3 -3
- package/dist/summary/summaryManager.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/blobManager.d.ts +4 -6
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +44 -58
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +76 -43
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerRuntime.d.ts +90 -36
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +125 -62
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.js +2 -2
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +8 -2
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +16 -9
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts +3 -0
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +3 -0
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts +0 -2
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +3 -8
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaManagerProxyBase.d.ts +1 -1
- package/lib/deltaManagerProxyBase.d.ts.map +1 -1
- package/lib/deltaManagerProxyBase.js +2 -2
- package/lib/deltaManagerProxyBase.js.map +1 -1
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +6 -0
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +16 -3
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts +1 -0
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +14 -4
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +42 -11
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js +4 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcSummaryDefinitions.d.ts +1 -1
- package/lib/gc/gcSummaryDefinitions.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts +2 -3
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +7 -8
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/index.d.ts +2 -2
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +2 -2
- package/lib/gc/index.js.map +1 -1
- package/lib/id-compressor/utilities.d.ts +3 -0
- package/lib/id-compressor/utilities.d.ts.map +1 -1
- package/lib/id-compressor/utilities.js +3 -0
- package/lib/id-compressor/utilities.js.map +1 -1
- package/lib/index.d.ts +4 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/messageTypes.d.ts +4 -1
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js +3 -0
- package/lib/messageTypes.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +3 -0
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +7 -2
- package/lib/opLifecycle/outbox.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/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +3 -1
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/scheduleManager.js +6 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +4 -1
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts +5 -0
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/summary/runWhileConnectedCoordinator.js +1 -0
- package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/summary/summarizer.d.ts +2 -0
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +16 -8
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +94 -10
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryCollection.d.ts +16 -0
- package/lib/summary/summaryCollection.d.ts.map +1 -1
- package/lib/summary/summaryCollection.js +2 -0
- package/lib/summary/summaryCollection.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +10 -1
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +2 -2
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +3 -3
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +26 -58
- package/src/blobManager.ts +61 -74
- package/src/connectionTelemetry.ts +97 -52
- package/src/containerRuntime.ts +173 -93
- package/src/dataStore.ts +2 -2
- package/src/dataStoreContext.ts +16 -9
- package/src/dataStoreRegistry.ts +3 -0
- package/src/dataStores.ts +4 -16
- package/src/deltaManagerProxyBase.ts +2 -2
- package/src/error.ts +4 -1
- package/src/gc/garbageCollection.ts +18 -3
- package/src/gc/gcConfigs.ts +22 -4
- package/src/gc/gcDefinitions.ts +43 -11
- package/src/gc/gcSummaryDefinitions.ts +1 -1
- package/src/gc/gcTelemetry.ts +8 -8
- package/src/gc/index.ts +0 -4
- package/src/id-compressor/utilities.ts +3 -0
- package/src/index.ts +14 -1
- package/src/messageTypes.ts +4 -1
- package/src/opLifecycle/README.md +53 -28
- package/src/opLifecycle/definitions.ts +3 -0
- package/src/opLifecycle/outbox.ts +3 -0
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +1 -0
- package/src/scheduleManager.ts +2 -0
- package/src/summary/orderedClientElection.ts +4 -1
- package/src/summary/runWhileConnectedCoordinator.ts +5 -1
- package/src/summary/summarizer.ts +21 -9
- package/src/summary/summarizerTypes.ts +95 -11
- package/src/summary/summaryCollection.ts +19 -1
- package/src/summary/summaryFormat.ts +11 -1
- package/src/summary/summaryGenerator.ts +3 -3
- package/src/summary/summaryManager.ts +2 -2
- package/src/gc/gcEarlyAdoption.md +0 -145
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/container-runtime",
|
|
3
|
-
"version": "2.0.0-internal.7.
|
|
3
|
+
"version": "2.0.0-internal.7.2.0",
|
|
4
4
|
"description": "Fluid container runtime",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -35,18 +35,18 @@
|
|
|
35
35
|
"temp-directory": "nyc/.nyc_output"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@fluid-internal/client-utils": ">=2.0.0-internal.7.
|
|
39
|
-
"@fluidframework/container-definitions": ">=2.0.0-internal.7.
|
|
40
|
-
"@fluidframework/container-runtime-definitions": ">=2.0.0-internal.7.
|
|
41
|
-
"@fluidframework/core-interfaces": ">=2.0.0-internal.7.
|
|
42
|
-
"@fluidframework/core-utils": ">=2.0.0-internal.7.
|
|
43
|
-
"@fluidframework/datastore": ">=2.0.0-internal.7.
|
|
44
|
-
"@fluidframework/driver-definitions": ">=2.0.0-internal.7.
|
|
45
|
-
"@fluidframework/driver-utils": ">=2.0.0-internal.7.
|
|
38
|
+
"@fluid-internal/client-utils": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
39
|
+
"@fluidframework/container-definitions": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
40
|
+
"@fluidframework/container-runtime-definitions": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
41
|
+
"@fluidframework/core-interfaces": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
42
|
+
"@fluidframework/core-utils": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
43
|
+
"@fluidframework/datastore": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
44
|
+
"@fluidframework/driver-definitions": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
45
|
+
"@fluidframework/driver-utils": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
46
46
|
"@fluidframework/protocol-definitions": "^3.0.0",
|
|
47
|
-
"@fluidframework/runtime-definitions": ">=2.0.0-internal.7.
|
|
48
|
-
"@fluidframework/runtime-utils": ">=2.0.0-internal.7.
|
|
49
|
-
"@fluidframework/telemetry-utils": ">=2.0.0-internal.7.
|
|
47
|
+
"@fluidframework/runtime-definitions": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
48
|
+
"@fluidframework/runtime-utils": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
49
|
+
"@fluidframework/telemetry-utils": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
50
50
|
"double-ended-queue": "^2.1.0-0",
|
|
51
51
|
"events": "^3.1.0",
|
|
52
52
|
"lz4js": "^0.2.0",
|
|
@@ -54,15 +54,15 @@
|
|
|
54
54
|
"uuid": "^9.0.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@fluid-internal/stochastic-test-utils": ">=2.0.0-internal.7.
|
|
57
|
+
"@fluid-internal/stochastic-test-utils": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
58
58
|
"@fluid-tools/benchmark": "^0.48.0",
|
|
59
|
-
"@fluid-tools/build-cli": "^0.
|
|
60
|
-
"@fluidframework/build-common": "^2.0.
|
|
61
|
-
"@fluidframework/build-tools": "^0.
|
|
62
|
-
"@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.0.0-internal.
|
|
63
|
-
"@fluidframework/eslint-config-fluid": "^
|
|
64
|
-
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.7.
|
|
65
|
-
"@fluidframework/test-runtime-utils": ">=2.0.0-internal.7.
|
|
59
|
+
"@fluid-tools/build-cli": "^0.26.1",
|
|
60
|
+
"@fluidframework/build-common": "^2.0.3",
|
|
61
|
+
"@fluidframework/build-tools": "^0.26.1",
|
|
62
|
+
"@fluidframework/container-runtime-previous": "npm:@fluidframework/container-runtime@2.0.0-internal.7.1.0",
|
|
63
|
+
"@fluidframework/eslint-config-fluid": "^3.0.0",
|
|
64
|
+
"@fluidframework/mocha-test-setup": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
65
|
+
"@fluidframework/test-runtime-utils": ">=2.0.0-internal.7.2.0 <2.0.0-internal.7.3.0",
|
|
66
66
|
"@microsoft/api-extractor": "^7.37.0",
|
|
67
67
|
"@types/double-ended-queue": "^2.1.0",
|
|
68
68
|
"@types/events": "^3.0.0",
|
|
@@ -70,14 +70,13 @@
|
|
|
70
70
|
"@types/sinon": "^7.0.13",
|
|
71
71
|
"@types/uuid": "^9.0.2",
|
|
72
72
|
"c8": "^7.7.1",
|
|
73
|
-
"copyfiles": "^2.4.1",
|
|
74
73
|
"cross-env": "^7.0.3",
|
|
75
|
-
"eslint": "~8.
|
|
74
|
+
"eslint": "~8.50.0",
|
|
76
75
|
"mocha": "^10.2.0",
|
|
77
76
|
"mocha-json-output-reporter": "^2.0.1",
|
|
78
77
|
"mocha-multi-reporters": "^1.5.1",
|
|
79
78
|
"moment": "^2.21.0",
|
|
80
|
-
"prettier": "~
|
|
79
|
+
"prettier": "~3.0.3",
|
|
81
80
|
"rimraf": "^4.4.0",
|
|
82
81
|
"sinon": "^7.4.2",
|
|
83
82
|
"typescript": "~5.1.6"
|
|
@@ -85,38 +84,7 @@
|
|
|
85
84
|
"typeValidation": {
|
|
86
85
|
"broken": {
|
|
87
86
|
"ClassDeclaration_ContainerRuntime": {
|
|
88
|
-
"forwardCompat": false
|
|
89
|
-
"backCompat": false
|
|
90
|
-
},
|
|
91
|
-
"InterfaceDeclaration_IAckedSummary": {
|
|
92
|
-
"backCompat": false
|
|
93
|
-
},
|
|
94
|
-
"InterfaceDeclaration_IAckSummaryResult": {
|
|
95
|
-
"backCompat": false
|
|
96
|
-
},
|
|
97
|
-
"InterfaceDeclaration_IBroadcastSummaryResult": {
|
|
98
|
-
"backCompat": false
|
|
99
|
-
},
|
|
100
|
-
"InterfaceDeclaration_ISummaryOpMessage": {
|
|
101
|
-
"backCompat": false
|
|
102
|
-
},
|
|
103
|
-
"InterfaceDeclaration_ISummaryNackMessage": {
|
|
104
|
-
"backCompat": false
|
|
105
|
-
},
|
|
106
|
-
"ClassDeclaration_Summarizer": {
|
|
107
|
-
"backCompat": false
|
|
108
|
-
},
|
|
109
|
-
"ClassDeclaration_SummaryCollection": {
|
|
110
|
-
"backCompat": false
|
|
111
|
-
},
|
|
112
|
-
"InterfaceDeclaration_ISummarizerRuntime": {
|
|
113
|
-
"backCompat": false
|
|
114
|
-
},
|
|
115
|
-
"InterfaceDeclaration_INackSummaryResult": {
|
|
116
|
-
"backCompat": false
|
|
117
|
-
},
|
|
118
|
-
"InterfaceDeclaration_ISummaryAckMessage": {
|
|
119
|
-
"backCompat": false
|
|
87
|
+
"forwardCompat": false
|
|
120
88
|
}
|
|
121
89
|
}
|
|
122
90
|
},
|
|
@@ -124,12 +92,12 @@
|
|
|
124
92
|
"build": "fluid-build . --task build",
|
|
125
93
|
"build:commonjs": "fluid-build . --task commonjs",
|
|
126
94
|
"build:compile": "fluid-build . --task compile",
|
|
127
|
-
"build:docs": "api-extractor run --local
|
|
95
|
+
"build:docs": "api-extractor run --local",
|
|
128
96
|
"build:esnext": "tsc --project ./tsconfig.esnext.json",
|
|
129
97
|
"build:genver": "gen-version",
|
|
130
98
|
"build:test": "tsc --project ./src/test/tsconfig.json",
|
|
131
|
-
"ci:build:docs": "api-extractor run
|
|
132
|
-
"clean": "rimraf --glob
|
|
99
|
+
"ci:build:docs": "api-extractor run",
|
|
100
|
+
"clean": "rimraf --glob dist lib \"*.tsbuildinfo\" \"*.build.log\" _api-extractor-temp nyc",
|
|
133
101
|
"eslint": "eslint --format stylish src",
|
|
134
102
|
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
|
|
135
103
|
"format": "npm run prettier:fix",
|
package/src/blobManager.ts
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
LoggingError,
|
|
31
31
|
MonitoringContext,
|
|
32
32
|
PerformanceEvent,
|
|
33
|
+
wrapError,
|
|
33
34
|
} from "@fluidframework/telemetry-utils";
|
|
34
35
|
import {
|
|
35
36
|
IGarbageCollectionData,
|
|
@@ -37,14 +38,9 @@ import {
|
|
|
37
38
|
ITelemetryContext,
|
|
38
39
|
} from "@fluidframework/runtime-definitions";
|
|
39
40
|
|
|
41
|
+
import { canRetryOnError, runWithRetry } from "@fluidframework/driver-utils";
|
|
40
42
|
import { ContainerRuntime, TombstoneResponseHeaderKey } from "./containerRuntime";
|
|
41
|
-
import {
|
|
42
|
-
sendGCUnexpectedUsageEvent,
|
|
43
|
-
disableAttachmentBlobSweepKey,
|
|
44
|
-
throwOnTombstoneLoadKey,
|
|
45
|
-
} from "./gc";
|
|
46
|
-
import { Throttler, formExponentialFn, IThrottler } from "./throttler";
|
|
47
|
-
import { summarizerClientType } from "./summary";
|
|
43
|
+
import { sendGCUnexpectedUsageEvent, disableAttachmentBlobSweepKey } from "./gc";
|
|
48
44
|
import { IBlobMetadata } from "./metadata";
|
|
49
45
|
|
|
50
46
|
/**
|
|
@@ -88,25 +84,9 @@ export class BlobHandle implements IFluidHandle<ArrayBufferLike> {
|
|
|
88
84
|
}
|
|
89
85
|
}
|
|
90
86
|
|
|
91
|
-
class CancellableThrottler {
|
|
92
|
-
constructor(private readonly throttler: IThrottler) {}
|
|
93
|
-
private cancelP = new Deferred<void>();
|
|
94
|
-
|
|
95
|
-
public async getDelay(): Promise<void> {
|
|
96
|
-
return Promise.race([
|
|
97
|
-
this.cancelP.promise,
|
|
98
|
-
new Promise<void>((resolve) => setTimeout(resolve, this.throttler.getDelay())),
|
|
99
|
-
]);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
public cancel() {
|
|
103
|
-
this.cancelP.resolve();
|
|
104
|
-
this.cancelP = new Deferred<void>();
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
87
|
/**
|
|
109
88
|
* Information from a snapshot needed to load BlobManager
|
|
89
|
+
* @public
|
|
110
90
|
*/
|
|
111
91
|
export interface IBlobManagerLoadInfo {
|
|
112
92
|
ids?: string[];
|
|
@@ -119,7 +99,7 @@ export type IBlobManagerRuntime = Pick<
|
|
|
119
99
|
IContainerRuntime,
|
|
120
100
|
"attachState" | "connected" | "logger" | "clientDetails"
|
|
121
101
|
> &
|
|
122
|
-
Pick<ContainerRuntime, "gcTombstoneEnforcementAllowed"> &
|
|
102
|
+
Pick<ContainerRuntime, "gcTombstoneEnforcementAllowed" | "gcThrowOnTombstoneLoad"> &
|
|
123
103
|
TypedEventEmitter<IContainerRuntimeEvents>;
|
|
124
104
|
|
|
125
105
|
type ICreateBlobResponseWithTTL = ICreateBlobResponse & Partial<Record<"minTTLInSeconds", number>>;
|
|
@@ -180,17 +160,6 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
180
160
|
*/
|
|
181
161
|
private readonly opsInFlight: Map<string, string[]> = new Map();
|
|
182
162
|
|
|
183
|
-
private readonly retryThrottler = new CancellableThrottler(
|
|
184
|
-
new Throttler(
|
|
185
|
-
60 * 1000, // 60 sec delay window
|
|
186
|
-
30 * 1000, // 30 sec max delay
|
|
187
|
-
// throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
|
|
188
|
-
formExponentialFn({ coefficient: 20, initialDelay: 0 }),
|
|
189
|
-
),
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
/** If true, throw an error when a tombstone attachment blob is retrieved. */
|
|
193
|
-
private readonly throwOnTombstoneLoad: boolean;
|
|
194
163
|
/**
|
|
195
164
|
* This stores IDs of tombstoned blobs.
|
|
196
165
|
* Tombstone is a temporary feature that imitates a blob getting swept by garbage collection.
|
|
@@ -198,6 +167,7 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
198
167
|
private readonly tombstonedBlobs: Set<string> = new Set();
|
|
199
168
|
|
|
200
169
|
private readonly sendBlobAttachOp: (localId: string, storageId?: string) => void;
|
|
170
|
+
private stopAttaching: boolean = false;
|
|
201
171
|
|
|
202
172
|
constructor(
|
|
203
173
|
private readonly routeContext: IFluidHandleContext,
|
|
@@ -229,11 +199,6 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
229
199
|
logger: this.runtime.logger,
|
|
230
200
|
namespace: "BlobManager",
|
|
231
201
|
});
|
|
232
|
-
// Read the feature flag that tells whether to throw when a tombstone blob is requested.
|
|
233
|
-
this.throwOnTombstoneLoad =
|
|
234
|
-
this.mc.config.getBoolean(throwOnTombstoneLoadKey) === true &&
|
|
235
|
-
this.runtime.gcTombstoneEnforcementAllowed &&
|
|
236
|
-
this.runtime.clientDetails.type !== summarizerClientType;
|
|
237
202
|
|
|
238
203
|
this.redirectTable = this.load(snapshot);
|
|
239
204
|
|
|
@@ -339,7 +304,6 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
339
304
|
* Upload blobs added while offline. This must be completed before connecting and resubmitting ops.
|
|
340
305
|
*/
|
|
341
306
|
public async processStashedChanges() {
|
|
342
|
-
this.retryThrottler.cancel();
|
|
343
307
|
const pendingUploads = Array.from(this.pendingBlobs.values())
|
|
344
308
|
.filter((e) => e.pendingStashed === true)
|
|
345
309
|
.map(async (e) => e.uploadP);
|
|
@@ -493,14 +457,39 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
493
457
|
localId: string,
|
|
494
458
|
blob: ArrayBufferLike,
|
|
495
459
|
): Promise<ICreateBlobResponse | void> {
|
|
496
|
-
return
|
|
460
|
+
return runWithRetry(
|
|
461
|
+
async () => {
|
|
462
|
+
try {
|
|
463
|
+
return await this.getStorage().createBlob(blob);
|
|
464
|
+
} catch (error) {
|
|
465
|
+
const entry = this.pendingBlobs.get(localId);
|
|
466
|
+
assert(
|
|
467
|
+
!!entry,
|
|
468
|
+
0x387 /* Must have pending blob entry for blob which failed to upload */,
|
|
469
|
+
);
|
|
470
|
+
if (entry.opsent && !canRetryOnError(error)) {
|
|
471
|
+
throw wrapError(
|
|
472
|
+
error,
|
|
473
|
+
() => new LoggingError(`uploadBlob error`, { canRetry: true }),
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
throw error;
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
"createBlob",
|
|
497
480
|
this.mc.logger,
|
|
498
|
-
{
|
|
499
|
-
|
|
500
|
-
|
|
481
|
+
{
|
|
482
|
+
cancel: this.pendingBlobs.get(localId)?.abortSignal,
|
|
483
|
+
},
|
|
501
484
|
).then(
|
|
502
485
|
(response) => this.onUploadResolve(localId, response),
|
|
503
|
-
|
|
486
|
+
(error) => {
|
|
487
|
+
// it will only reject if we haven't sent an op
|
|
488
|
+
// and is a non-retriable error. It will only reject
|
|
489
|
+
// the promise but not throw any error outside.
|
|
490
|
+
this.pendingBlobs.get(localId)?.handleP.reject(error);
|
|
491
|
+
this.deletePendingBlob(localId);
|
|
492
|
+
},
|
|
504
493
|
);
|
|
505
494
|
}
|
|
506
495
|
|
|
@@ -530,7 +519,7 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
530
519
|
private onUploadResolve(localId: string, response: ICreateBlobResponseWithTTL) {
|
|
531
520
|
const entry = this.pendingBlobs.get(localId);
|
|
532
521
|
assert(entry !== undefined, 0x6c8 /* pending blob entry not found for uploaded blob */);
|
|
533
|
-
if (entry.abortSignal?.aborted === true && !entry.opsent) {
|
|
522
|
+
if ((entry.abortSignal?.aborted === true && !entry.opsent) || this.stopAttaching) {
|
|
534
523
|
this.deletePendingBlob(localId);
|
|
535
524
|
return;
|
|
536
525
|
}
|
|
@@ -568,25 +557,6 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
568
557
|
return response;
|
|
569
558
|
}
|
|
570
559
|
|
|
571
|
-
private async onUploadReject(localId: string, error: any) {
|
|
572
|
-
const entry = this.pendingBlobs.get(localId);
|
|
573
|
-
assert(!!entry, 0x387 /* Must have pending blob entry for blob which failed to upload */);
|
|
574
|
-
if (entry.abortSignal?.aborted === true && !entry.opsent) {
|
|
575
|
-
this.deletePendingBlob(localId);
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
578
|
-
if (!this.runtime.connected) {
|
|
579
|
-
// we are probably not connected to storage but start another upload request in case we are
|
|
580
|
-
entry.uploadP = this.retryThrottler
|
|
581
|
-
.getDelay()
|
|
582
|
-
.then(async () => this.uploadBlob(localId, entry.blob));
|
|
583
|
-
return entry.uploadP;
|
|
584
|
-
} else {
|
|
585
|
-
entry.handleP.reject(error);
|
|
586
|
-
throw error;
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
560
|
/**
|
|
591
561
|
* Resubmit a BlobAttach op. Used to add storage IDs to ops that were
|
|
592
562
|
* submitted to runtime while disconnected.
|
|
@@ -881,7 +851,7 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
881
851
|
|
|
882
852
|
// If the blob is deleted or throw on tombstone load is enabled, throw an error which will fail any attempt
|
|
883
853
|
// to load the blob.
|
|
884
|
-
const shouldFail = state === "deleted" || this.
|
|
854
|
+
const shouldFail = state === "deleted" || this.runtime.gcThrowOnTombstoneLoad;
|
|
885
855
|
const request = { url: blobId };
|
|
886
856
|
const error = responseToException(
|
|
887
857
|
createResponseError(
|
|
@@ -930,7 +900,9 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
930
900
|
}
|
|
931
901
|
}
|
|
932
902
|
|
|
933
|
-
public async attachAndGetPendingBlobs(
|
|
903
|
+
public async attachAndGetPendingBlobs(
|
|
904
|
+
stopBlobAttachingSignal?: AbortSignal,
|
|
905
|
+
): Promise<IPendingBlobs | undefined> {
|
|
934
906
|
return PerformanceEvent.timedExecAsync(
|
|
935
907
|
this.mc.logger,
|
|
936
908
|
{ eventName: "GetPendingBlobs" },
|
|
@@ -945,12 +917,17 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
945
917
|
for (const [id, entry] of this.pendingBlobs) {
|
|
946
918
|
if (!localBlobs.has(entry)) {
|
|
947
919
|
localBlobs.add(entry);
|
|
948
|
-
if (!entry.opsent) {
|
|
949
|
-
this.sendBlobAttachOp(id, entry.storageId);
|
|
950
|
-
}
|
|
951
920
|
entry.handleP.resolve(this.getBlobHandle(id));
|
|
952
921
|
attachBlobsP.push(
|
|
953
|
-
new Promise<void>((resolve) => {
|
|
922
|
+
new Promise<void>((resolve, reject) => {
|
|
923
|
+
stopBlobAttachingSignal?.addEventListener(
|
|
924
|
+
"abort",
|
|
925
|
+
() => {
|
|
926
|
+
this.stopAttaching = true;
|
|
927
|
+
reject(new Error("Operation aborted"));
|
|
928
|
+
},
|
|
929
|
+
{ once: true },
|
|
930
|
+
);
|
|
954
931
|
const onBlobAttached = (attachedEntry) => {
|
|
955
932
|
if (attachedEntry === entry) {
|
|
956
933
|
this.off("blobAttached", onBlobAttached);
|
|
@@ -966,11 +943,21 @@ export class BlobManager extends TypedEventEmitter<IBlobManagerEvents> {
|
|
|
966
943
|
);
|
|
967
944
|
}
|
|
968
945
|
}
|
|
969
|
-
await Promise.
|
|
946
|
+
await Promise.allSettled(attachBlobsP).catch(() => {});
|
|
970
947
|
}
|
|
971
948
|
|
|
972
949
|
for (const [id, entry] of this.pendingBlobs) {
|
|
950
|
+
if (stopBlobAttachingSignal?.aborted && !entry.attached) {
|
|
951
|
+
this.mc.logger.sendTelemetryEvent({
|
|
952
|
+
eventName: "UnableToStashBlob",
|
|
953
|
+
id,
|
|
954
|
+
});
|
|
955
|
+
continue;
|
|
956
|
+
}
|
|
973
957
|
assert(entry.attached === true, 0x790 /* stashed blob should be attached */);
|
|
958
|
+
if (!entry.opsent) {
|
|
959
|
+
this.sendBlobAttachOp(id, entry.storageId);
|
|
960
|
+
}
|
|
974
961
|
blobs[id] = {
|
|
975
962
|
blob: bufferToString(entry.blob, "base64"),
|
|
976
963
|
storageId: entry.storageId,
|
|
@@ -4,8 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
+
IEventSampler,
|
|
8
|
+
ISampledTelemetryLogger,
|
|
7
9
|
ITelemetryLoggerExt,
|
|
8
10
|
createChildLogger,
|
|
11
|
+
createSampledLogger,
|
|
9
12
|
formatTick,
|
|
10
13
|
} from "@fluidframework/telemetry-utils";
|
|
11
14
|
import { IDeltaManager } from "@fluidframework/container-definitions";
|
|
@@ -53,7 +56,6 @@ interface IOpPerfTimings {
|
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
class OpPerfTelemetry {
|
|
56
|
-
private pongCount: number = 0;
|
|
57
59
|
private pingLatency: number | undefined;
|
|
58
60
|
|
|
59
61
|
// Collab window tracking. This is timestamp of %1000 message.
|
|
@@ -61,11 +63,14 @@ class OpPerfTelemetry {
|
|
|
61
63
|
private msnTrackingTimestamp: number = 0;
|
|
62
64
|
// To track round trip time for every %500 client message.
|
|
63
65
|
private clientSequenceNumberForLatencyStatistics: number | undefined;
|
|
64
|
-
|
|
65
|
-
private opProcessingTimes: Partial<IOpPerfTimings> = {};
|
|
66
|
-
|
|
67
66
|
// Performance Data to be reported for ops round trips and processing.
|
|
68
|
-
private
|
|
67
|
+
private readonly latencyStatistics = new Map<
|
|
68
|
+
number,
|
|
69
|
+
{
|
|
70
|
+
opProcessingTimes: Partial<IOpPerfTimings>;
|
|
71
|
+
opPerfData: Partial<IOpPerfTelemetryProperties>;
|
|
72
|
+
}
|
|
73
|
+
>();
|
|
69
74
|
|
|
70
75
|
private firstConnection = true;
|
|
71
76
|
private connectionOpSeqNumber: number | undefined;
|
|
@@ -75,6 +80,12 @@ class OpPerfTelemetry {
|
|
|
75
80
|
|
|
76
81
|
private readonly logger: ITelemetryLoggerExt;
|
|
77
82
|
|
|
83
|
+
private static readonly OP_LATENCY_SAMPLE_RATE = 500;
|
|
84
|
+
private readonly opLatencyLogger: ISampledTelemetryLogger;
|
|
85
|
+
|
|
86
|
+
private static readonly DELTA_LATENCY_SAMPLE_RATE = 100;
|
|
87
|
+
private readonly deltaLatencyLogger: ISampledTelemetryLogger;
|
|
88
|
+
|
|
78
89
|
public constructor(
|
|
79
90
|
private clientId: string | undefined,
|
|
80
91
|
private readonly deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
|
|
@@ -82,6 +93,28 @@ class OpPerfTelemetry {
|
|
|
82
93
|
) {
|
|
83
94
|
this.logger = createChildLogger({ logger, namespace: "OpPerf" });
|
|
84
95
|
|
|
96
|
+
const deltaLatencyEventSampler: IEventSampler = (() => {
|
|
97
|
+
let eventCount = -1;
|
|
98
|
+
return {
|
|
99
|
+
sample: () => {
|
|
100
|
+
eventCount++;
|
|
101
|
+
const shouldSample =
|
|
102
|
+
eventCount % OpPerfTelemetry.DELTA_LATENCY_SAMPLE_RATE === 0;
|
|
103
|
+
if (shouldSample) {
|
|
104
|
+
eventCount = 0;
|
|
105
|
+
}
|
|
106
|
+
return shouldSample;
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
})();
|
|
110
|
+
|
|
111
|
+
this.deltaLatencyLogger = createSampledLogger(logger, deltaLatencyEventSampler);
|
|
112
|
+
|
|
113
|
+
// The SampledLogger here is used get access to the isSamplingDisabled property dervied from
|
|
114
|
+
// telemetry config properties. The actual sampling logic for op messages happens outside this SampledLogger
|
|
115
|
+
// due to complexity of the different asynchronus scenarios of the op message lifecycle.
|
|
116
|
+
this.opLatencyLogger = createSampledLogger(logger);
|
|
117
|
+
|
|
85
118
|
this.deltaManager.on("pong", (latency) => this.recordPingTime(latency));
|
|
86
119
|
this.deltaManager.on("submitOp", (message) => this.beforeOpSubmit(message));
|
|
87
120
|
|
|
@@ -103,42 +136,47 @@ class OpPerfTelemetry {
|
|
|
103
136
|
this.deltaManager.on("disconnect", () => {
|
|
104
137
|
this.sequenceNumberForMsnTracking = undefined;
|
|
105
138
|
this.clientSequenceNumberForLatencyStatistics = undefined;
|
|
106
|
-
this.opProcessingTimes = {};
|
|
107
|
-
this.opPerfData = {};
|
|
108
139
|
this.connectionOpSeqNumber = undefined;
|
|
109
140
|
this.firstConnection = false;
|
|
110
|
-
this.
|
|
141
|
+
this.latencyStatistics.clear();
|
|
111
142
|
});
|
|
112
143
|
|
|
113
144
|
this.deltaManager.outbound.on("push", (messages) => {
|
|
114
145
|
for (const msg of messages) {
|
|
115
146
|
if (
|
|
116
147
|
msg.type === MessageType.Operation &&
|
|
117
|
-
this.
|
|
148
|
+
(this.opLatencyLogger.isSamplingDisabled ||
|
|
149
|
+
this.clientSequenceNumberForLatencyStatistics === msg.clientSequenceNumber)
|
|
118
150
|
) {
|
|
151
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
152
|
+
const latencyStats = this.latencyStatistics.get(msg.clientSequenceNumber)!;
|
|
153
|
+
assert(
|
|
154
|
+
latencyStats !== undefined,
|
|
155
|
+
0x7c2 /* Latency stats for op should exist */,
|
|
156
|
+
);
|
|
119
157
|
assert(
|
|
120
|
-
|
|
158
|
+
latencyStats.opProcessingTimes.outboundPushEventTime === undefined,
|
|
121
159
|
0x2c8 /* "outboundPushEventTime should be undefined" */,
|
|
122
160
|
);
|
|
123
161
|
assert(
|
|
124
|
-
|
|
162
|
+
latencyStats.opPerfData.durationNetwork === undefined,
|
|
125
163
|
0x2c9 /* "durationNetwork should be undefined" */,
|
|
126
164
|
);
|
|
127
|
-
|
|
165
|
+
latencyStats.opProcessingTimes.outboundPushEventTime = Date.now();
|
|
128
166
|
|
|
129
167
|
assert(
|
|
130
|
-
|
|
168
|
+
latencyStats.opPerfData.durationOutboundBatching === undefined,
|
|
131
169
|
0x2ca /* "durationOutboundBatching should be undefined" */,
|
|
132
170
|
);
|
|
133
171
|
|
|
134
172
|
assert(
|
|
135
|
-
|
|
173
|
+
latencyStats.opProcessingTimes.submitOpEventTime !== undefined,
|
|
136
174
|
0x2cb /* "submitOpEventTime should be undefined" */,
|
|
137
175
|
);
|
|
138
176
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
177
|
+
latencyStats.opPerfData.durationOutboundBatching =
|
|
178
|
+
latencyStats.opProcessingTimes.outboundPushEventTime -
|
|
179
|
+
latencyStats.opProcessingTimes.submitOpEventTime;
|
|
142
180
|
}
|
|
143
181
|
}
|
|
144
182
|
});
|
|
@@ -147,15 +185,20 @@ class OpPerfTelemetry {
|
|
|
147
185
|
if (
|
|
148
186
|
this.clientId === message.clientId &&
|
|
149
187
|
message.type === MessageType.Operation &&
|
|
150
|
-
this.
|
|
151
|
-
|
|
188
|
+
(this.opLatencyLogger.isSamplingDisabled ||
|
|
189
|
+
this.clientSequenceNumberForLatencyStatistics === message.clientSequenceNumber)
|
|
152
190
|
) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
191
|
+
// We do an explicit check for undefined right after this
|
|
192
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
193
|
+
const latencyStats = this.latencyStatistics.get(message.clientSequenceNumber)!;
|
|
194
|
+
assert(latencyStats !== undefined, 0x7c3 /* Latency stats for op should exist */);
|
|
195
|
+
if (latencyStats.opProcessingTimes.outboundPushEventTime !== undefined) {
|
|
196
|
+
latencyStats.opProcessingTimes.inboundPushEventTime = Date.now();
|
|
197
|
+
latencyStats.opPerfData.durationNetwork =
|
|
198
|
+
latencyStats.opProcessingTimes.inboundPushEventTime -
|
|
199
|
+
latencyStats.opProcessingTimes.outboundPushEventTime;
|
|
200
|
+
latencyStats.opPerfData.lengthInboundQueue = this.deltaManager.inbound.length;
|
|
201
|
+
}
|
|
159
202
|
}
|
|
160
203
|
});
|
|
161
204
|
|
|
@@ -201,32 +244,33 @@ class OpPerfTelemetry {
|
|
|
201
244
|
});
|
|
202
245
|
}
|
|
203
246
|
|
|
204
|
-
// logging one in every
|
|
205
|
-
if (this.
|
|
206
|
-
this.
|
|
247
|
+
// logging one in every DELTA_LATENCY_SAMPLE_RATE pongs, including the first time, if it is a "write" client.
|
|
248
|
+
if (this.deltaManager.active) {
|
|
249
|
+
this.deltaLatencyLogger.sendPerformanceEvent({
|
|
207
250
|
eventName: "DeltaLatency",
|
|
208
251
|
duration: latency,
|
|
209
252
|
});
|
|
210
253
|
}
|
|
211
|
-
this.pongCount++;
|
|
212
254
|
}
|
|
213
255
|
|
|
214
256
|
private beforeOpSubmit(message: IDocumentMessage) {
|
|
215
257
|
// start with first client op and measure latency every 500 client ops
|
|
216
258
|
if (
|
|
217
|
-
this.
|
|
218
|
-
|
|
259
|
+
this.opLatencyLogger.isSamplingDisabled ||
|
|
260
|
+
(this.clientSequenceNumberForLatencyStatistics === undefined &&
|
|
261
|
+
message.clientSequenceNumber % OpPerfTelemetry.OP_LATENCY_SAMPLE_RATE === 1)
|
|
219
262
|
) {
|
|
220
263
|
assert(
|
|
221
|
-
this.
|
|
222
|
-
|
|
223
|
-
);
|
|
224
|
-
assert(
|
|
225
|
-
this.opPerfData.durationNetwork === undefined,
|
|
226
|
-
0x2cd /* "durationNetwork should be undefined" */,
|
|
264
|
+
this.latencyStatistics.get(message.clientSequenceNumber) === undefined,
|
|
265
|
+
0x7c4 /* Existing op perf data for client sequence number */,
|
|
227
266
|
);
|
|
228
|
-
this.opProcessingTimes.submitOpEventTime = Date.now();
|
|
229
267
|
this.clientSequenceNumberForLatencyStatistics = message.clientSequenceNumber;
|
|
268
|
+
this.latencyStatistics.set(message.clientSequenceNumber, {
|
|
269
|
+
opProcessingTimes: {
|
|
270
|
+
submitOpEventTime: Date.now(),
|
|
271
|
+
},
|
|
272
|
+
opPerfData: {},
|
|
273
|
+
});
|
|
230
274
|
}
|
|
231
275
|
}
|
|
232
276
|
|
|
@@ -261,20 +305,23 @@ class OpPerfTelemetry {
|
|
|
261
305
|
|
|
262
306
|
if (
|
|
263
307
|
this.clientId === message.clientId &&
|
|
264
|
-
this.
|
|
308
|
+
(this.opLatencyLogger.isSamplingDisabled ||
|
|
309
|
+
this.clientSequenceNumberForLatencyStatistics === message.clientSequenceNumber)
|
|
265
310
|
) {
|
|
311
|
+
// We do an explicit check for undefined right after this
|
|
312
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
313
|
+
const latencyData = this.latencyStatistics.get(message.clientSequenceNumber)!;
|
|
314
|
+
assert(latencyData !== undefined, 0x7c5 /* Undefined latency statistics for op */);
|
|
266
315
|
assert(
|
|
267
|
-
|
|
268
|
-
0x120 /* "Undefined latency statistics (op send time)" */,
|
|
316
|
+
latencyData.opProcessingTimes.submitOpEventTime !== undefined,
|
|
317
|
+
0x120 /* "Undefined latency statistics for op (op send time)" */,
|
|
269
318
|
);
|
|
270
319
|
const currentTime = Date.now();
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
currentTime - this.opProcessingTimes.inboundPushEventTime;
|
|
320
|
+
if (latencyData.opProcessingTimes.inboundPushEventTime !== undefined) {
|
|
321
|
+
latencyData.opPerfData.durationInboundToProcessing =
|
|
322
|
+
currentTime - latencyData.opProcessingTimes.inboundPushEventTime;
|
|
275
323
|
}
|
|
276
|
-
|
|
277
|
-
const duration = currentTime - this.opProcessingTimes.submitOpEventTime;
|
|
324
|
+
const duration = currentTime - latencyData.opProcessingTimes.submitOpEventTime;
|
|
278
325
|
|
|
279
326
|
// One of the core expectations for Fluid service is to be fast.
|
|
280
327
|
// When it's not the case, we want to learn about it and be able to investigate, so
|
|
@@ -284,8 +331,7 @@ class OpPerfTelemetry {
|
|
|
284
331
|
// The threshold could be adjusted, but ideally it stays workload-agnostic, as service
|
|
285
332
|
// performance impacts all workloads relying on service.
|
|
286
333
|
const category = duration > latencyThreshold ? "error" : "performance";
|
|
287
|
-
|
|
288
|
-
this.logger.sendPerformanceEvent({
|
|
334
|
+
this.opLatencyLogger.sendPerformanceEvent({
|
|
289
335
|
eventName: "OpRoundtripTime",
|
|
290
336
|
sequenceNumber,
|
|
291
337
|
referenceSequenceNumber: message.referenceSequenceNumber,
|
|
@@ -294,11 +340,10 @@ class OpPerfTelemetry {
|
|
|
294
340
|
pingLatency: this.pingLatency,
|
|
295
341
|
msnDistance:
|
|
296
342
|
this.deltaManager.lastSequenceNumber - this.deltaManager.minimumSequenceNumber,
|
|
297
|
-
...
|
|
343
|
+
...latencyData.opPerfData,
|
|
298
344
|
});
|
|
299
345
|
this.clientSequenceNumberForLatencyStatistics = undefined;
|
|
300
|
-
this.
|
|
301
|
-
this.opProcessingTimes = {};
|
|
346
|
+
this.latencyStatistics.delete(message.clientSequenceNumber);
|
|
302
347
|
}
|
|
303
348
|
}
|
|
304
349
|
}
|