@fluidframework/container-runtime 2.0.0-internal.3.0.0 → 2.0.0-internal.3.1.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/.eslintrc.js +19 -19
- package/.mocharc.js +2 -2
- package/api-extractor.json +2 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +2 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +9 -2
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +80 -33
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +11 -9
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +3 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +10 -0
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +140 -72
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +11 -9
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +18 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +66 -15
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +7 -3
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +3 -1
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts +26 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +103 -18
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +8 -3
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/garbageCollection.d.ts +34 -14
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +188 -93
- package/dist/garbageCollection.js.map +1 -1
- package/dist/garbageCollectionConstants.d.ts +3 -0
- package/dist/garbageCollectionConstants.d.ts.map +1 -1
- package/dist/garbageCollectionConstants.js +6 -1
- package/dist/garbageCollectionConstants.js.map +1 -1
- package/dist/garbageCollectionHelpers.d.ts +26 -0
- package/dist/garbageCollectionHelpers.d.ts.map +1 -0
- package/dist/garbageCollectionHelpers.js +45 -0
- package/dist/garbageCollectionHelpers.js.map +1 -0
- package/dist/gcSweepReadyUsageDetection.d.ts +5 -5
- package/dist/gcSweepReadyUsageDetection.d.ts.map +1 -1
- package/dist/gcSweepReadyUsageDetection.js +14 -10
- package/dist/gcSweepReadyUsageDetection.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +5 -5
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +19 -12
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +5 -2
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +4 -1
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +19 -17
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/opProperties.d.ts.map +1 -1
- package/dist/opProperties.js +1 -3
- package/dist/opProperties.js.map +1 -1
- package/dist/orderedClientElection.d.ts.map +1 -1
- package/dist/orderedClientElection.js +10 -4
- package/dist/orderedClientElection.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 +7 -0
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +7 -4
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +34 -21
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +3 -2
- package/dist/scheduleManager.js.map +1 -1
- package/dist/serializedSnapshotStorage.d.ts +2 -2
- package/dist/serializedSnapshotStorage.d.ts.map +1 -1
- package/dist/serializedSnapshotStorage.js +5 -3
- package/dist/serializedSnapshotStorage.js.map +1 -1
- package/dist/summarizer.d.ts +2 -2
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +37 -17
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerClientElection.d.ts.map +1 -1
- package/dist/summarizerClientElection.js.map +1 -1
- package/dist/summarizerHandle.d.ts.map +1 -1
- package/dist/summarizerHandle.js.map +1 -1
- package/dist/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summarizerHeuristics.js +6 -9
- package/dist/summarizerHeuristics.js.map +1 -1
- package/dist/summarizerTypes.d.ts +21 -21
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryCollection.d.ts.map +1 -1
- package/dist/summaryCollection.js +18 -8
- package/dist/summaryCollection.js.map +1 -1
- package/dist/summaryFormat.d.ts +22 -0
- package/dist/summaryFormat.d.ts.map +1 -1
- package/dist/summaryFormat.js +18 -10
- package/dist/summaryFormat.js.map +1 -1
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js +34 -15
- package/dist/summaryGenerator.js.map +1 -1
- package/dist/summaryManager.d.ts.map +1 -1
- package/dist/summaryManager.js +21 -9
- package/dist/summaryManager.js.map +1 -1
- package/dist/throttler.d.ts +2 -2
- package/dist/throttler.d.ts.map +1 -1
- package/dist/throttler.js +4 -4
- package/dist/throttler.js.map +1 -1
- package/garbageCollection.md +15 -2
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +9 -2
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +82 -35
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +11 -9
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +3 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +10 -0
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +146 -78
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +11 -9
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +18 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +68 -17
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +7 -3
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +3 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts +26 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +109 -24
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +9 -4
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/garbageCollection.d.ts +34 -14
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +190 -95
- package/lib/garbageCollection.js.map +1 -1
- package/lib/garbageCollectionConstants.d.ts +3 -0
- package/lib/garbageCollectionConstants.d.ts.map +1 -1
- package/lib/garbageCollectionConstants.js +5 -0
- package/lib/garbageCollectionConstants.js.map +1 -1
- package/lib/garbageCollectionHelpers.d.ts +26 -0
- package/lib/garbageCollectionHelpers.d.ts.map +1 -0
- package/lib/garbageCollectionHelpers.js +40 -0
- package/lib/garbageCollectionHelpers.js.map +1 -0
- package/lib/gcSweepReadyUsageDetection.d.ts +5 -5
- package/lib/gcSweepReadyUsageDetection.d.ts.map +1 -1
- package/lib/gcSweepReadyUsageDetection.js +14 -10
- package/lib/gcSweepReadyUsageDetection.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +5 -5
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +19 -12
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +5 -2
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +5 -2
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +19 -17
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/opProperties.d.ts.map +1 -1
- package/lib/opProperties.js +1 -3
- package/lib/opProperties.js.map +1 -1
- package/lib/orderedClientElection.d.ts.map +1 -1
- package/lib/orderedClientElection.js +10 -4
- package/lib/orderedClientElection.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 +7 -0
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +7 -4
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +35 -22
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +3 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/serializedSnapshotStorage.d.ts +2 -2
- package/lib/serializedSnapshotStorage.d.ts.map +1 -1
- package/lib/serializedSnapshotStorage.js +5 -3
- package/lib/serializedSnapshotStorage.js.map +1 -1
- package/lib/summarizer.d.ts +2 -2
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +37 -17
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerClientElection.d.ts.map +1 -1
- package/lib/summarizerClientElection.js.map +1 -1
- package/lib/summarizerHandle.d.ts.map +1 -1
- package/lib/summarizerHandle.js.map +1 -1
- package/lib/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summarizerHeuristics.js +6 -9
- package/lib/summarizerHeuristics.js.map +1 -1
- package/lib/summarizerTypes.d.ts +21 -21
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryCollection.d.ts.map +1 -1
- package/lib/summaryCollection.js +18 -8
- package/lib/summaryCollection.js.map +1 -1
- package/lib/summaryFormat.d.ts +22 -0
- package/lib/summaryFormat.d.ts.map +1 -1
- package/lib/summaryFormat.js +20 -12
- package/lib/summaryFormat.js.map +1 -1
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js +34 -15
- package/lib/summaryGenerator.js.map +1 -1
- package/lib/summaryManager.d.ts.map +1 -1
- package/lib/summaryManager.js +21 -9
- package/lib/summaryManager.js.map +1 -1
- package/lib/throttler.d.ts +2 -2
- package/lib/throttler.d.ts.map +1 -1
- package/lib/throttler.js +4 -4
- package/lib/throttler.js.map +1 -1
- package/package.json +121 -149
- package/prettier.config.cjs +1 -1
- package/src/batchTracker.ts +54 -49
- package/src/blobManager.ts +793 -672
- package/src/connectionTelemetry.ts +280 -249
- package/src/containerHandleContext.ts +27 -29
- package/src/containerRuntime.ts +3168 -2940
- package/src/dataStore.ts +172 -159
- package/src/dataStoreContext.ts +1098 -996
- package/src/dataStoreContexts.ts +178 -161
- package/src/dataStoreRegistry.ts +25 -20
- package/src/dataStores.ts +884 -728
- package/src/deltaScheduler.ts +158 -150
- package/src/garbageCollection.ts +1883 -1692
- package/src/garbageCollectionConstants.ts +6 -0
- package/src/garbageCollectionHelpers.ts +61 -0
- package/src/gcSweepReadyUsageDetection.ts +89 -83
- package/src/index.ts +67 -66
- package/src/opLifecycle/README.md +152 -0
- package/src/opLifecycle/batchManager.ts +145 -141
- package/src/opLifecycle/definitions.ts +29 -29
- package/src/opLifecycle/index.ts +5 -5
- package/src/opLifecycle/opCompressor.ts +54 -53
- package/src/opLifecycle/opDecompressor.ts +100 -81
- package/src/opLifecycle/opSplitter.ts +214 -188
- package/src/opLifecycle/outbox.ts +204 -194
- package/src/opLifecycle/remoteMessageProcessor.ts +62 -62
- package/src/opProperties.ts +11 -9
- package/src/orderedClientElection.ts +489 -457
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +384 -338
- package/src/runWhileConnectedCoordinator.ts +78 -71
- package/src/runningSummarizer.ts +619 -581
- package/src/scheduleManager.ts +299 -269
- package/src/serializedSnapshotStorage.ts +126 -112
- package/src/summarizer.ts +417 -381
- package/src/summarizerClientElection.ts +107 -100
- package/src/summarizerHandle.ts +11 -9
- package/src/summarizerHeuristics.ts +183 -186
- package/src/summarizerTypes.ts +344 -330
- package/src/summaryCollection.ts +378 -349
- package/src/summaryFormat.ts +170 -126
- package/src/summaryGenerator.ts +465 -406
- package/src/summaryManager.ts +377 -348
- package/src/throttler.ts +131 -122
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +9 -13
- package/dist/garbageCollectionTombstoneUtils.d.ts +0 -14
- package/dist/garbageCollectionTombstoneUtils.d.ts.map +0 -1
- package/dist/garbageCollectionTombstoneUtils.js +0 -23
- package/dist/garbageCollectionTombstoneUtils.js.map +0 -1
- package/lib/garbageCollectionTombstoneUtils.d.ts +0 -14
- package/lib/garbageCollectionTombstoneUtils.d.ts.map +0 -1
- package/lib/garbageCollectionTombstoneUtils.js +0 -19
- package/lib/garbageCollectionTombstoneUtils.js.map +0 -1
- package/src/garbageCollectionTombstoneUtils.ts +0 -28
package/src/summaryGenerator.ts
CHANGED
|
@@ -5,51 +5,53 @@
|
|
|
5
5
|
|
|
6
6
|
import { ITelemetryLogger } from "@fluidframework/common-definitions";
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
assert,
|
|
9
|
+
Deferred,
|
|
10
|
+
IPromiseTimer,
|
|
11
|
+
IPromiseTimerResult,
|
|
12
|
+
Timer,
|
|
13
13
|
} from "@fluidframework/common-utils";
|
|
14
14
|
import { MessageType } from "@fluidframework/protocol-definitions";
|
|
15
15
|
import { PerformanceEvent, LoggingError, ChildLogger } from "@fluidframework/telemetry-utils";
|
|
16
16
|
import { getRetryDelaySecondsFromError } from "@fluidframework/driver-utils";
|
|
17
17
|
import { DriverErrorType } from "@fluidframework/driver-definitions";
|
|
18
18
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
19
|
+
IAckSummaryResult,
|
|
20
|
+
INackSummaryResult,
|
|
21
|
+
ISummarizeOptions,
|
|
22
|
+
IBroadcastSummaryResult,
|
|
23
|
+
ISummarizeResults,
|
|
24
|
+
ISummarizeHeuristicData,
|
|
25
|
+
ISubmitSummaryOptions,
|
|
26
|
+
SubmitSummaryResult,
|
|
27
|
+
SummarizeResultPart,
|
|
28
|
+
ISummaryCancellationToken,
|
|
29
|
+
ISummarizeTelemetryProperties,
|
|
30
|
+
SummaryGeneratorTelemetry,
|
|
31
31
|
} from "./summarizerTypes";
|
|
32
32
|
import { IClientSummaryWatcher } from "./summaryCollection";
|
|
33
33
|
|
|
34
34
|
export type raceTimerResult<T> =
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
| { result: "done"; value: T }
|
|
36
|
+
| { result: IPromiseTimerResult["timerResult"] }
|
|
37
|
+
| { result: "cancelled" };
|
|
38
38
|
|
|
39
39
|
/** Helper function to wait for a promise or PromiseTimer to elapse. */
|
|
40
40
|
export async function raceTimer<T>(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
promise: Promise<T>,
|
|
42
|
+
timer: Promise<IPromiseTimerResult>,
|
|
43
|
+
cancellationToken?: ISummaryCancellationToken,
|
|
44
44
|
): Promise<raceTimerResult<T>> {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
45
|
+
const promises: Promise<raceTimerResult<T>>[] = [
|
|
46
|
+
promise.then((value) => ({ result: "done", value } as const)),
|
|
47
|
+
timer.then(({ timerResult: result }) => ({ result } as const)),
|
|
48
|
+
];
|
|
49
|
+
if (cancellationToken !== undefined) {
|
|
50
|
+
promises.push(
|
|
51
|
+
cancellationToken.waitCancelled.then(() => ({ result: "cancelled" } as const)),
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
return Promise.race(promises);
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
// Send some telemetry if generate summary takes too long
|
|
@@ -57,390 +59,447 @@ const maxSummarizeTimeoutTime = 20000; // 20 sec
|
|
|
57
59
|
const maxSummarizeTimeoutCount = 5; // Double and resend 5 times
|
|
58
60
|
|
|
59
61
|
export type SummarizeReason =
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Attempt to summarize after idle timeout has elapsed.
|
|
64
|
+
* Idle timer restarts whenever an op is received. So this
|
|
65
|
+
* triggers only after some amount of time has passed with
|
|
66
|
+
* no ops being received.
|
|
67
|
+
*/
|
|
68
|
+
| "idle"
|
|
69
|
+
/**
|
|
70
|
+
* Attempt to summarize after a maximum time since last
|
|
71
|
+
* successful summary has passed. This measures time since
|
|
72
|
+
* last summary ack op was processed.
|
|
73
|
+
*/
|
|
74
|
+
| "maxTime"
|
|
75
|
+
/**
|
|
76
|
+
* Attempt to summarize after a maximum number of ops have
|
|
77
|
+
* passed since the last successful summary. This compares
|
|
78
|
+
* op sequence numbers with the reference sequence number
|
|
79
|
+
* of the summarize op corresponding to the last summary
|
|
80
|
+
* ack op.
|
|
81
|
+
*/
|
|
82
|
+
| "maxOps"
|
|
83
|
+
/**
|
|
84
|
+
* Special case to attempt to summarize one last time before the
|
|
85
|
+
* summarizer client closes itself. This is to prevent cases where
|
|
86
|
+
* the summarizer client never gets a chance to summarize, because
|
|
87
|
+
* there are too many outstanding ops and/or parent client cannot
|
|
88
|
+
* stay connected long enough for summarizer client to catch up.
|
|
89
|
+
*/
|
|
90
|
+
| "lastSummary"
|
|
91
|
+
/** On-demand summary requested with specified reason. */
|
|
92
|
+
| `onDemand;${string}`
|
|
93
|
+
/** Enqueue summarize attempt with specified reason. */
|
|
94
|
+
| `enqueue;${string}`;
|
|
93
95
|
|
|
94
96
|
const summarizeErrors = {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Error encountered while generating the summary tree, uploading
|
|
99
|
+
* it to storage, or submitting the op. It could be a result of
|
|
100
|
+
* the client becoming disconnected while generating or an actual error.
|
|
101
|
+
*/
|
|
102
|
+
submitSummaryFailure: "Error while generating, uploading, or submitting summary",
|
|
103
|
+
/**
|
|
104
|
+
* The summaryAckWaitTimeout time has elapsed before receiving the summarize op
|
|
105
|
+
* sent by this summarize attempt. It is expected to be broadcast quickly.
|
|
106
|
+
*/
|
|
107
|
+
summaryOpWaitTimeout: "Timeout while waiting for summarize op broadcast",
|
|
108
|
+
/**
|
|
109
|
+
* The summaryAckWaitTimeout time has elapsed before receiving either a
|
|
110
|
+
* summaryAck or summaryNack op from the server in response to this
|
|
111
|
+
* summarize attempt. It is expected that the server should respond.
|
|
112
|
+
*/
|
|
113
|
+
summaryAckWaitTimeout: "Timeout while waiting for summaryAck/summaryNack op",
|
|
114
|
+
/**
|
|
115
|
+
* The server responded with a summaryNack op, thus rejecting this
|
|
116
|
+
* summarize attempt.
|
|
117
|
+
*/
|
|
118
|
+
summaryNack: "Server rejected summary via summaryNack op",
|
|
119
|
+
|
|
120
|
+
disconnect: "Summary cancelled due to summarizer or main client disconnect",
|
|
119
121
|
} as const;
|
|
120
122
|
|
|
121
123
|
export class SummarizeResultBuilder {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
124
|
+
public readonly summarySubmitted = new Deferred<SummarizeResultPart<SubmitSummaryResult>>();
|
|
125
|
+
public readonly summaryOpBroadcasted = new Deferred<
|
|
126
|
+
SummarizeResultPart<IBroadcastSummaryResult>
|
|
127
|
+
>();
|
|
128
|
+
public readonly receivedSummaryAckOrNack = new Deferred<
|
|
129
|
+
SummarizeResultPart<IAckSummaryResult, INackSummaryResult>
|
|
130
|
+
>();
|
|
131
|
+
|
|
132
|
+
public fail(
|
|
133
|
+
message: string,
|
|
134
|
+
error: any,
|
|
135
|
+
nackSummaryResult?: INackSummaryResult,
|
|
136
|
+
retryAfterSeconds?: number,
|
|
137
|
+
) {
|
|
138
|
+
assert(
|
|
139
|
+
!this.receivedSummaryAckOrNack.isCompleted,
|
|
140
|
+
0x25e /* "no reason to call fail if all promises have been completed" */,
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const result: SummarizeResultPart<undefined> = {
|
|
144
|
+
success: false,
|
|
145
|
+
message,
|
|
146
|
+
data: undefined,
|
|
147
|
+
error,
|
|
148
|
+
retryAfterSeconds,
|
|
149
|
+
} as const;
|
|
150
|
+
this.summarySubmitted.resolve(result);
|
|
151
|
+
this.summaryOpBroadcasted.resolve(result);
|
|
152
|
+
this.receivedSummaryAckOrNack.resolve({ ...result, data: nackSummaryResult });
|
|
153
|
+
}
|
|
154
|
+
public build(): ISummarizeResults {
|
|
155
|
+
return {
|
|
156
|
+
summarySubmitted: this.summarySubmitted.promise,
|
|
157
|
+
summaryOpBroadcasted: this.summaryOpBroadcasted.promise,
|
|
158
|
+
receivedSummaryAckOrNack: this.receivedSummaryAckOrNack.promise,
|
|
159
|
+
} as const;
|
|
160
|
+
}
|
|
144
161
|
}
|
|
145
162
|
|
|
146
163
|
/**
|
|
147
164
|
* This class generates and tracks a summary attempt.
|
|
148
165
|
*/
|
|
149
166
|
export class SummaryGenerator {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
167
|
+
private readonly summarizeTimer: Timer;
|
|
168
|
+
constructor(
|
|
169
|
+
private readonly pendingAckTimer: IPromiseTimer,
|
|
170
|
+
private readonly heuristicData: ISummarizeHeuristicData,
|
|
171
|
+
private readonly submitSummaryCallback: (
|
|
172
|
+
options: ISubmitSummaryOptions,
|
|
173
|
+
) => Promise<SubmitSummaryResult>,
|
|
174
|
+
private readonly raiseSummarizingError: (errorMessage: string) => void,
|
|
175
|
+
private readonly successfulSummaryCallback: () => void,
|
|
176
|
+
private readonly summaryWatcher: Pick<IClientSummaryWatcher, "watchSummary">,
|
|
177
|
+
private readonly logger: ITelemetryLogger,
|
|
178
|
+
) {
|
|
179
|
+
this.summarizeTimer = new Timer(maxSummarizeTimeoutTime, () =>
|
|
180
|
+
this.summarizeTimerHandler(maxSummarizeTimeoutTime, 1),
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Generates summary and listens for broadcast and ack/nack.
|
|
186
|
+
* Returns true for ack, false for nack, and undefined for failure or timeout.
|
|
187
|
+
* @param reason - reason for summarizing
|
|
188
|
+
* @param options - refreshLatestAck to fetch summary ack info from server,
|
|
189
|
+
* fullTree to generate tree without any summary handles even if unchanged
|
|
190
|
+
*/
|
|
191
|
+
public summarize(
|
|
192
|
+
summarizeProps: ISummarizeTelemetryProperties,
|
|
193
|
+
options: ISummarizeOptions,
|
|
194
|
+
cancellationToken: ISummaryCancellationToken,
|
|
195
|
+
resultsBuilder = new SummarizeResultBuilder(),
|
|
196
|
+
): ISummarizeResults {
|
|
197
|
+
this.logger.sendTelemetryEvent({
|
|
198
|
+
eventName: "Summarize_start",
|
|
199
|
+
...summarizeProps,
|
|
200
|
+
});
|
|
201
|
+
this.summarizeCore(summarizeProps, options, resultsBuilder, cancellationToken).catch(
|
|
202
|
+
(error) => {
|
|
203
|
+
const message = "UnexpectedSummarizeError";
|
|
204
|
+
this.logger.sendErrorEvent({ eventName: message, ...summarizeProps }, error);
|
|
205
|
+
resultsBuilder.fail(message, error);
|
|
206
|
+
},
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
return resultsBuilder.build();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private async summarizeCore(
|
|
213
|
+
summarizeProps: ISummarizeTelemetryProperties,
|
|
214
|
+
options: ISummarizeOptions,
|
|
215
|
+
resultsBuilder: SummarizeResultBuilder,
|
|
216
|
+
cancellationToken: ISummaryCancellationToken,
|
|
217
|
+
): Promise<void> {
|
|
218
|
+
const { refreshLatestAck, fullTree } = options;
|
|
219
|
+
const logger = ChildLogger.create(this.logger, undefined, { all: summarizeProps });
|
|
220
|
+
|
|
221
|
+
// Note: timeSinceLastAttempt and timeSinceLastSummary for the
|
|
222
|
+
// first summary are basically the time since the summarizer was loaded.
|
|
223
|
+
const timeSinceLastAttempt = Date.now() - this.heuristicData.lastAttempt.summaryTime;
|
|
224
|
+
const timeSinceLastSummary =
|
|
225
|
+
Date.now() - this.heuristicData.lastSuccessfulSummary.summaryTime;
|
|
226
|
+
let summarizeTelemetryProps: SummaryGeneratorTelemetry = {
|
|
227
|
+
fullTree,
|
|
228
|
+
timeSinceLastAttempt,
|
|
229
|
+
timeSinceLastSummary,
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
const summarizeEvent = PerformanceEvent.start(logger, {
|
|
233
|
+
eventName: "Summarize",
|
|
234
|
+
refreshLatestAck,
|
|
235
|
+
...summarizeTelemetryProps,
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Helper functions to report failures and return.
|
|
239
|
+
const getFailMessage = (errorCode: keyof typeof summarizeErrors) =>
|
|
240
|
+
`${errorCode}: ${summarizeErrors[errorCode]}`;
|
|
241
|
+
const fail = (
|
|
242
|
+
errorCode: keyof typeof summarizeErrors,
|
|
243
|
+
error?: any,
|
|
244
|
+
properties?: SummaryGeneratorTelemetry,
|
|
245
|
+
nackSummaryResult?: INackSummaryResult,
|
|
246
|
+
) => {
|
|
247
|
+
this.raiseSummarizingError(summarizeErrors[errorCode]);
|
|
248
|
+
// UploadSummary may fail with 429 and retryAfter - respect that
|
|
249
|
+
// Summary Nack also can have retryAfter, it's parsed below and comes as a property.
|
|
250
|
+
const retryAfterSeconds = getRetryDelaySecondsFromError(error);
|
|
251
|
+
|
|
252
|
+
// Report any failure as an error unless it was due to cancellation (like "disconnected" error)
|
|
253
|
+
// If failure happened on upload, we may not yet realized that socket disconnected, so check
|
|
254
|
+
// offlineError too.
|
|
255
|
+
const category =
|
|
256
|
+
cancellationToken.cancelled || error?.errorType === DriverErrorType.offlineError
|
|
257
|
+
? "generic"
|
|
258
|
+
: "error";
|
|
259
|
+
|
|
260
|
+
const message = getFailMessage(errorCode);
|
|
261
|
+
summarizeEvent.cancel(
|
|
262
|
+
{
|
|
263
|
+
...properties,
|
|
264
|
+
reason: errorCode,
|
|
265
|
+
category,
|
|
266
|
+
retryAfterSeconds,
|
|
267
|
+
},
|
|
268
|
+
error ?? message,
|
|
269
|
+
); // disconnect & summaryAckTimeout do not have proper error.
|
|
270
|
+
resultsBuilder.fail(message, error, nackSummaryResult, retryAfterSeconds);
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
// Wait to generate and send summary
|
|
274
|
+
this.summarizeTimer.start();
|
|
275
|
+
|
|
276
|
+
// Use record type to prevent unexpected value types
|
|
277
|
+
let summaryData: SubmitSummaryResult | undefined;
|
|
278
|
+
try {
|
|
279
|
+
summaryData = await this.submitSummaryCallback({
|
|
280
|
+
fullTree,
|
|
281
|
+
refreshLatestAck,
|
|
282
|
+
summaryLogger: logger,
|
|
283
|
+
cancellationToken,
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// Cumulatively add telemetry properties based on how far generateSummary went.
|
|
287
|
+
const referenceSequenceNumber = summaryData.referenceSequenceNumber;
|
|
288
|
+
const opsSinceLastSummary =
|
|
289
|
+
referenceSequenceNumber -
|
|
290
|
+
this.heuristicData.lastSuccessfulSummary.refSequenceNumber;
|
|
291
|
+
summarizeTelemetryProps = {
|
|
292
|
+
...summarizeTelemetryProps,
|
|
293
|
+
referenceSequenceNumber,
|
|
294
|
+
minimumSequenceNumber: summaryData.minimumSequenceNumber,
|
|
295
|
+
opsSinceLastAttempt:
|
|
296
|
+
referenceSequenceNumber - this.heuristicData.lastAttempt.refSequenceNumber,
|
|
297
|
+
opsSinceLastSummary,
|
|
298
|
+
};
|
|
299
|
+
summarizeTelemetryProps = this.addSummaryDataToTelemetryProps(
|
|
300
|
+
summaryData,
|
|
301
|
+
summarizeTelemetryProps,
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
if (summaryData.stage !== "submit") {
|
|
305
|
+
return fail("submitSummaryFailure", summaryData.error, summarizeTelemetryProps);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* With incremental summaries, if the full tree was not summarized, only data stores that changed should
|
|
310
|
+
* be summarized. A data store is considered changed if either or both of the following is true:
|
|
311
|
+
* - It has received an op.
|
|
312
|
+
* - Its reference state changed, i.e., it went from referenced to unreferenced or vice-versa.
|
|
313
|
+
*
|
|
314
|
+
* In the extreme case, every op can be for a different data store and each op can result in the reference
|
|
315
|
+
* state change of multiple data stores. So, the total number of data stores that are summarized should not
|
|
316
|
+
* exceed the number of ops since last summary + number of data store whose reference state changed.
|
|
317
|
+
*/
|
|
318
|
+
if (!fullTree && !summaryData.forcedFullTree) {
|
|
319
|
+
const { summarizedDataStoreCount, gcStateUpdatedDataStoreCount = 0 } =
|
|
320
|
+
summaryData.summaryStats;
|
|
321
|
+
if (summarizedDataStoreCount > gcStateUpdatedDataStoreCount + opsSinceLastSummary) {
|
|
322
|
+
logger.sendErrorEvent({
|
|
323
|
+
eventName: "IncrementalSummaryViolation",
|
|
324
|
+
summarizedDataStoreCount,
|
|
325
|
+
gcStateUpdatedDataStoreCount,
|
|
326
|
+
opsSinceLastSummary,
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Log event here on summary success only, as Summarize_cancel duplicates failure logging.
|
|
332
|
+
summarizeEvent.reportEvent("generate", { ...summarizeTelemetryProps });
|
|
333
|
+
resultsBuilder.summarySubmitted.resolve({ success: true, data: summaryData });
|
|
334
|
+
} catch (error) {
|
|
335
|
+
return fail("submitSummaryFailure", error);
|
|
336
|
+
} finally {
|
|
337
|
+
this.heuristicData.recordAttempt(summaryData?.referenceSequenceNumber);
|
|
338
|
+
this.summarizeTimer.clear();
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
try {
|
|
342
|
+
const pendingTimeoutP = this.pendingAckTimer.start();
|
|
343
|
+
const summary = this.summaryWatcher.watchSummary(summaryData.clientSequenceNumber);
|
|
344
|
+
|
|
345
|
+
// Wait for broadcast
|
|
346
|
+
const waitBroadcastResult = await raceTimer(
|
|
347
|
+
summary.waitBroadcast(),
|
|
348
|
+
pendingTimeoutP,
|
|
349
|
+
cancellationToken,
|
|
350
|
+
);
|
|
351
|
+
if (waitBroadcastResult.result === "cancelled") {
|
|
352
|
+
return fail("disconnect");
|
|
353
|
+
}
|
|
354
|
+
if (waitBroadcastResult.result !== "done") {
|
|
355
|
+
return fail("summaryOpWaitTimeout");
|
|
356
|
+
}
|
|
357
|
+
const summarizeOp = waitBroadcastResult.value;
|
|
358
|
+
|
|
359
|
+
const broadcastDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;
|
|
360
|
+
resultsBuilder.summaryOpBroadcasted.resolve({
|
|
361
|
+
success: true,
|
|
362
|
+
data: { summarizeOp, broadcastDuration },
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
this.heuristicData.lastAttempt.summarySequenceNumber = summarizeOp.sequenceNumber;
|
|
366
|
+
logger.sendTelemetryEvent({
|
|
367
|
+
eventName: "Summarize_Op",
|
|
368
|
+
duration: broadcastDuration,
|
|
369
|
+
referenceSequenceNumber: summarizeOp.referenceSequenceNumber,
|
|
370
|
+
summarySequenceNumber: summarizeOp.sequenceNumber,
|
|
371
|
+
handle: summarizeOp.contents.handle,
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
// Wait for ack/nack
|
|
375
|
+
const waitAckNackResult = await raceTimer(
|
|
376
|
+
summary.waitAckNack(),
|
|
377
|
+
pendingTimeoutP,
|
|
378
|
+
cancellationToken,
|
|
379
|
+
);
|
|
380
|
+
if (waitAckNackResult.result === "cancelled") {
|
|
381
|
+
return fail("disconnect");
|
|
382
|
+
}
|
|
383
|
+
if (waitAckNackResult.result !== "done") {
|
|
384
|
+
return fail("summaryAckWaitTimeout");
|
|
385
|
+
}
|
|
386
|
+
const ackNackOp = waitAckNackResult.value;
|
|
387
|
+
this.pendingAckTimer.clear();
|
|
388
|
+
|
|
389
|
+
// Update for success/failure
|
|
390
|
+
const ackNackDuration = Date.now() - this.heuristicData.lastAttempt.summaryTime;
|
|
391
|
+
|
|
392
|
+
// adding new properties
|
|
393
|
+
summarizeTelemetryProps = {
|
|
394
|
+
ackWaitDuration: ackNackDuration,
|
|
395
|
+
ackNackSequenceNumber: ackNackOp.sequenceNumber,
|
|
396
|
+
summarySequenceNumber: ackNackOp.contents.summaryProposal.summarySequenceNumber,
|
|
397
|
+
...summarizeTelemetryProps,
|
|
398
|
+
};
|
|
399
|
+
if (ackNackOp.type === MessageType.SummaryAck) {
|
|
400
|
+
this.heuristicData.markLastAttemptAsSuccessful();
|
|
401
|
+
this.successfulSummaryCallback();
|
|
402
|
+
summarizeEvent.end({
|
|
403
|
+
...summarizeTelemetryProps,
|
|
404
|
+
handle: ackNackOp.contents.handle,
|
|
405
|
+
});
|
|
406
|
+
resultsBuilder.receivedSummaryAckOrNack.resolve({
|
|
407
|
+
success: true,
|
|
408
|
+
data: {
|
|
409
|
+
summaryAckOp: ackNackOp,
|
|
410
|
+
ackNackDuration,
|
|
411
|
+
},
|
|
412
|
+
});
|
|
413
|
+
} else {
|
|
414
|
+
// Check for retryDelay in summaryNack response.
|
|
415
|
+
assert(ackNackOp.type === MessageType.SummaryNack, 0x274 /* "type check" */);
|
|
416
|
+
const summaryNack = ackNackOp.contents;
|
|
417
|
+
const errorMessage = summaryNack?.message;
|
|
418
|
+
const retryAfterSeconds = summaryNack?.retryAfter;
|
|
419
|
+
|
|
420
|
+
// pre-0.58 error message prefix: summaryNack
|
|
421
|
+
const error = new LoggingError(`Received summaryNack`, {
|
|
422
|
+
retryAfterSeconds,
|
|
423
|
+
errorMessage,
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
assert(
|
|
427
|
+
getRetryDelaySecondsFromError(error) === retryAfterSeconds,
|
|
428
|
+
0x25f /* "retryAfterSeconds" */,
|
|
429
|
+
);
|
|
430
|
+
// This will only set resultsBuilder.receivedSummaryAckOrNack, as other promises are already set.
|
|
431
|
+
return fail(
|
|
432
|
+
"summaryNack",
|
|
433
|
+
error,
|
|
434
|
+
{ ...summarizeTelemetryProps, nackRetryAfter: retryAfterSeconds },
|
|
435
|
+
{ summaryNackOp: ackNackOp, ackNackDuration },
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
} finally {
|
|
439
|
+
this.pendingAckTimer.clear();
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
private addSummaryDataToTelemetryProps(
|
|
444
|
+
summaryData: SubmitSummaryResult,
|
|
445
|
+
initialProps: SummaryGeneratorTelemetry,
|
|
446
|
+
): SummaryGeneratorTelemetry {
|
|
447
|
+
switch (summaryData.stage) {
|
|
448
|
+
case "base":
|
|
449
|
+
return initialProps;
|
|
450
|
+
|
|
451
|
+
case "generate":
|
|
452
|
+
return {
|
|
453
|
+
...initialProps,
|
|
454
|
+
...summaryData.summaryStats,
|
|
455
|
+
generateDuration: summaryData.generateDuration,
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
case "upload":
|
|
459
|
+
return {
|
|
460
|
+
...initialProps,
|
|
461
|
+
...summaryData.summaryStats,
|
|
462
|
+
generateDuration: summaryData.generateDuration,
|
|
463
|
+
handle: summaryData.handle,
|
|
464
|
+
uploadDuration: summaryData.uploadDuration,
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
case "submit":
|
|
468
|
+
return {
|
|
469
|
+
...initialProps,
|
|
470
|
+
...summaryData.summaryStats,
|
|
471
|
+
generateDuration: summaryData.generateDuration,
|
|
472
|
+
handle: summaryData.handle,
|
|
473
|
+
uploadDuration: summaryData.uploadDuration,
|
|
474
|
+
clientSequenceNumber: summaryData.clientSequenceNumber,
|
|
475
|
+
hasMissingOpData: this.heuristicData.hasMissingOpData,
|
|
476
|
+
opsSizesSinceLastSummary: this.heuristicData.totalOpsSize,
|
|
477
|
+
nonRuntimeOpsSinceLastSummary: this.heuristicData.numNonRuntimeOps,
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
default:
|
|
481
|
+
assert(true, 0x397 /* Unexpected summary stage */);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
return initialProps;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
private summarizeTimerHandler(time: number, count: number) {
|
|
488
|
+
this.logger.sendPerformanceEvent({
|
|
489
|
+
eventName: "SummarizeTimeout",
|
|
490
|
+
timeoutTime: time,
|
|
491
|
+
timeoutCount: count,
|
|
492
|
+
});
|
|
493
|
+
if (count < maxSummarizeTimeoutCount) {
|
|
494
|
+
// Double and start a new timer
|
|
495
|
+
const nextTime = time * 2;
|
|
496
|
+
this.summarizeTimer.start(nextTime, () =>
|
|
497
|
+
this.summarizeTimerHandler(nextTime, count + 1),
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
public dispose() {
|
|
503
|
+
this.summarizeTimer.clear();
|
|
504
|
+
}
|
|
446
505
|
}
|