@fluidframework/container-runtime 2.0.0-dev.4.1.0.148229 → 2.0.0-dev.4.3.0.157531
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 +58 -0
- package/README.md +69 -0
- package/dist/blobManager.d.ts +6 -14
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +50 -37
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +47 -4
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +203 -49
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +2 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +3 -0
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +5 -5
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +3 -6
- package/dist/dataStores.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +5 -5
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcConfigs.d.ts.map +1 -1
- package/dist/gc/gcConfigs.js +1 -3
- package/dist/gc/gcConfigs.js.map +1 -1
- package/dist/gc/gcDefinitions.js +1 -1
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +6 -6
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/id-compressor/appendOnlySortedMap.d.ts +146 -0
- package/dist/id-compressor/appendOnlySortedMap.d.ts.map +1 -0
- package/dist/id-compressor/appendOnlySortedMap.js +360 -0
- package/dist/id-compressor/appendOnlySortedMap.js.map +1 -0
- package/dist/id-compressor/idCompressor.d.ts +279 -0
- package/dist/id-compressor/idCompressor.d.ts.map +1 -0
- package/dist/id-compressor/idCompressor.js +1258 -0
- package/dist/id-compressor/idCompressor.js.map +1 -0
- package/dist/id-compressor/idRange.d.ts +11 -0
- package/dist/id-compressor/idRange.d.ts.map +1 -0
- package/dist/id-compressor/idRange.js +29 -0
- package/dist/id-compressor/idRange.js.map +1 -0
- package/dist/id-compressor/index.d.ts +14 -0
- package/dist/id-compressor/index.d.ts.map +1 -0
- package/dist/id-compressor/index.js +38 -0
- package/dist/id-compressor/index.js.map +1 -0
- package/dist/id-compressor/numericUuid.d.ts +59 -0
- package/dist/id-compressor/numericUuid.d.ts.map +1 -0
- package/dist/id-compressor/numericUuid.js +325 -0
- package/dist/id-compressor/numericUuid.js.map +1 -0
- package/dist/id-compressor/sessionIdNormalizer.d.ts +138 -0
- package/dist/id-compressor/sessionIdNormalizer.d.ts.map +1 -0
- package/dist/id-compressor/sessionIdNormalizer.js +488 -0
- package/dist/id-compressor/sessionIdNormalizer.js.map +1 -0
- package/dist/id-compressor/utils.d.ts +57 -0
- package/dist/id-compressor/utils.d.ts.map +1 -0
- package/dist/id-compressor/utils.js +90 -0
- package/dist/id-compressor/utils.js.map +1 -0
- package/dist/id-compressor/uuidUtilities.d.ts +30 -0
- package/dist/id-compressor/uuidUtilities.d.ts.map +1 -0
- package/dist/id-compressor/uuidUtilities.js +106 -0
- package/dist/id-compressor/uuidUtilities.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +9 -2
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +21 -2
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +2 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +3 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +2 -1
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +14 -0
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -0
- package/dist/opLifecycle/opGroupingManager.js +61 -0
- package/dist/opLifecycle/opGroupingManager.js.map +1 -0
- package/dist/opLifecycle/opSplitter.d.ts +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +5 -6
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +4 -2
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +37 -25
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +4 -2
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +30 -20
- package/dist/opLifecycle/remoteMessageProcessor.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 +1 -1
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +11 -3
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/summary/index.d.ts +2 -2
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js +4 -1
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.d.ts +1 -0
- package/dist/summary/orderedClientElection.d.ts.map +1 -1
- package/dist/summary/orderedClientElection.js +19 -0
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +4 -3
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +65 -66
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts.map +1 -1
- package/dist/summary/summarizer.js +1 -5
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerHeuristics.d.ts +1 -0
- package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summary/summarizerHeuristics.js +3 -0
- package/dist/summary/summarizerHeuristics.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +128 -2
- package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js +4 -3
- package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +14 -2
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +3 -0
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js +3 -1
- package/dist/summary/summaryFormat.js.map +1 -1
- package/dist/summary/summaryGenerator.d.ts +28 -2
- package/dist/summary/summaryGenerator.d.ts.map +1 -1
- package/dist/summary/summaryGenerator.js +19 -16
- package/dist/summary/summaryGenerator.js.map +1 -1
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +2 -0
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/blobManager.d.ts +6 -14
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +50 -37
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +47 -4
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +187 -52
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +2 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +3 -0
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +5 -5
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +3 -6
- package/lib/dataStores.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +5 -5
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcConfigs.d.ts.map +1 -1
- package/lib/gc/gcConfigs.js +1 -3
- package/lib/gc/gcConfigs.js.map +1 -1
- package/lib/gc/gcDefinitions.js +1 -1
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +6 -6
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/id-compressor/appendOnlySortedMap.d.ts +146 -0
- package/lib/id-compressor/appendOnlySortedMap.d.ts.map +1 -0
- package/lib/id-compressor/appendOnlySortedMap.js +355 -0
- package/lib/id-compressor/appendOnlySortedMap.js.map +1 -0
- package/lib/id-compressor/idCompressor.d.ts +279 -0
- package/lib/id-compressor/idCompressor.d.ts.map +1 -0
- package/lib/id-compressor/idCompressor.js +1248 -0
- package/lib/id-compressor/idCompressor.js.map +1 -0
- package/lib/id-compressor/idRange.d.ts +11 -0
- package/lib/id-compressor/idRange.d.ts.map +1 -0
- package/lib/id-compressor/idRange.js +25 -0
- package/lib/id-compressor/idRange.js.map +1 -0
- package/lib/id-compressor/index.d.ts +14 -0
- package/lib/id-compressor/index.d.ts.map +1 -0
- package/lib/id-compressor/index.js +14 -0
- package/lib/id-compressor/index.js.map +1 -0
- package/lib/id-compressor/numericUuid.d.ts +59 -0
- package/lib/id-compressor/numericUuid.d.ts.map +1 -0
- package/lib/id-compressor/numericUuid.js +315 -0
- package/lib/id-compressor/numericUuid.js.map +1 -0
- package/lib/id-compressor/sessionIdNormalizer.d.ts +138 -0
- package/lib/id-compressor/sessionIdNormalizer.d.ts.map +1 -0
- package/lib/id-compressor/sessionIdNormalizer.js +484 -0
- package/lib/id-compressor/sessionIdNormalizer.js.map +1 -0
- package/lib/id-compressor/utils.d.ts +57 -0
- package/lib/id-compressor/utils.d.ts.map +1 -0
- package/lib/id-compressor/utils.js +79 -0
- package/lib/id-compressor/utils.js.map +1 -0
- package/lib/id-compressor/uuidUtilities.d.ts +30 -0
- package/lib/id-compressor/uuidUtilities.d.ts.map +1 -0
- package/lib/id-compressor/uuidUtilities.js +98 -0
- package/lib/id-compressor/uuidUtilities.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/opLifecycle/batchManager.d.ts +9 -2
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +19 -1
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +2 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js +1 -0
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +2 -1
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +14 -0
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -0
- package/lib/opLifecycle/opGroupingManager.js +57 -0
- package/lib/opLifecycle/opGroupingManager.js.map +1 -0
- package/lib/opLifecycle/opSplitter.d.ts +1 -1
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +5 -6
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +4 -2
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +38 -26
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +4 -2
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +30 -20
- package/lib/opLifecycle/remoteMessageProcessor.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 +1 -1
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +11 -3
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/summary/index.d.ts +2 -2
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js +2 -1
- package/lib/summary/index.js.map +1 -1
- package/lib/summary/orderedClientElection.d.ts +1 -0
- package/lib/summary/orderedClientElection.d.ts.map +1 -1
- package/lib/summary/orderedClientElection.js +19 -0
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +4 -3
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +65 -66
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts.map +1 -1
- package/lib/summary/summarizer.js +1 -5
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerHeuristics.d.ts +1 -0
- package/lib/summary/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summary/summarizerHeuristics.js +3 -0
- package/lib/summary/summarizerHeuristics.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +128 -2
- package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js +3 -3
- package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +14 -2
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +3 -0
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js +2 -0
- package/lib/summary/summaryFormat.js.map +1 -1
- package/lib/summary/summaryGenerator.d.ts +28 -2
- package/lib/summary/summaryGenerator.d.ts.map +1 -1
- package/lib/summary/summaryGenerator.js +17 -15
- package/lib/summary/summaryGenerator.js.map +1 -1
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +2 -0
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +29 -17
- package/src/blobManager.ts +64 -41
- package/src/containerRuntime.ts +294 -65
- package/src/dataStoreContext.ts +6 -0
- package/src/dataStores.ts +4 -7
- package/src/gc/garbageCollection.ts +7 -6
- package/src/gc/gcConfigs.ts +1 -3
- package/src/gc/gcDefinitions.ts +1 -1
- package/src/gc/gcHelpers.ts +9 -6
- package/src/id-compressor/README.md +3 -0
- package/src/id-compressor/appendOnlySortedMap.ts +427 -0
- package/src/id-compressor/idCompressor.ts +1854 -0
- package/src/id-compressor/idRange.ts +35 -0
- package/src/id-compressor/index.ts +35 -0
- package/src/id-compressor/numericUuid.ts +383 -0
- package/src/id-compressor/sessionIdNormalizer.ts +609 -0
- package/src/id-compressor/utils.ts +114 -0
- package/src/id-compressor/uuidUtilities.ts +123 -0
- package/src/index.ts +1 -0
- package/src/opLifecycle/README.md +119 -0
- package/src/opLifecycle/batchManager.ts +35 -2
- package/src/opLifecycle/index.ts +2 -1
- package/src/opLifecycle/opDecompressor.ts +1 -0
- package/src/opLifecycle/opGroupingManager.ts +82 -0
- package/src/opLifecycle/opSplitter.ts +1 -5
- package/src/opLifecycle/outbox.ts +64 -26
- package/src/opLifecycle/remoteMessageProcessor.ts +38 -22
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +21 -7
- package/src/summary/index.ts +2 -1
- package/src/summary/orderedClientElection.ts +17 -1
- package/src/summary/runningSummarizer.ts +78 -77
- package/src/summary/summarizer.ts +0 -8
- package/src/summary/summarizerHeuristics.ts +4 -0
- package/src/summary/summarizerNode/summarizerNode.ts +1 -1
- package/src/summary/summarizerNode/summarizerNodeWithGc.ts +3 -3
- package/src/summary/summarizerTypes.ts +20 -3
- package/src/summary/summaryFormat.ts +4 -0
- package/src/summary/summaryGenerator.ts +22 -16
- package/src/summary/summaryManager.ts +2 -0
|
@@ -15,9 +15,15 @@ import {
|
|
|
15
15
|
} from "@fluidframework/telemetry-utils";
|
|
16
16
|
import { ICompressionRuntimeOptions } from "../containerRuntime";
|
|
17
17
|
import { PendingStateManager } from "../pendingStateManager";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
BatchManager,
|
|
20
|
+
BatchSequenceNumbers,
|
|
21
|
+
estimateSocketSize,
|
|
22
|
+
sequenceNumbersMatch,
|
|
23
|
+
} from "./batchManager";
|
|
19
24
|
import { BatchMessage, IBatch } from "./definitions";
|
|
20
25
|
import { OpCompressor } from "./opCompressor";
|
|
26
|
+
import { OpGroupingManager } from "./opGroupingManager";
|
|
21
27
|
import { OpSplitter } from "./opSplitter";
|
|
22
28
|
|
|
23
29
|
export interface IOutboxConfig {
|
|
@@ -35,6 +41,21 @@ export interface IOutboxParameters {
|
|
|
35
41
|
readonly compressor: OpCompressor;
|
|
36
42
|
readonly splitter: OpSplitter;
|
|
37
43
|
readonly logger: ITelemetryLogger;
|
|
44
|
+
readonly groupingManager: OpGroupingManager;
|
|
45
|
+
readonly getCurrentSequenceNumbers: () => BatchSequenceNumbers;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getLongStack(action: () => Error): Error {
|
|
49
|
+
// Increase the stack trace limit temporarily, so as to debug better in case it occurs.
|
|
50
|
+
try {
|
|
51
|
+
const originalStackTraceLimit = (Error as any).stackTraceLimit;
|
|
52
|
+
(Error as any).stackTraceLimit = 50;
|
|
53
|
+
const result = action();
|
|
54
|
+
(Error as any).stackTraceLimit = originalStackTraceLimit;
|
|
55
|
+
return result;
|
|
56
|
+
} catch (error) {
|
|
57
|
+
return action();
|
|
58
|
+
}
|
|
38
59
|
}
|
|
39
60
|
|
|
40
61
|
export class Outbox {
|
|
@@ -74,39 +95,39 @@ export class Outbox {
|
|
|
74
95
|
* what was already in the batch managers, this means that batching has been interrupted so
|
|
75
96
|
* we will flush the accumulated messages to account for that and create a new batch with the new
|
|
76
97
|
* message as the first message.
|
|
77
|
-
*
|
|
78
|
-
* @param message - the incoming message
|
|
79
98
|
*/
|
|
80
|
-
private maybeFlushPartialBatch(
|
|
81
|
-
const
|
|
82
|
-
const
|
|
99
|
+
private maybeFlushPartialBatch() {
|
|
100
|
+
const mainBatchSeqNums = this.mainBatch.sequenceNumbers;
|
|
101
|
+
const attachFlowBatchSeqNums = this.attachFlowBatch.sequenceNumbers;
|
|
83
102
|
assert(
|
|
84
103
|
this.params.config.disablePartialFlush ||
|
|
85
|
-
|
|
86
|
-
attachFlowBatchReference === undefined ||
|
|
87
|
-
mainBatchReference === attachFlowBatchReference,
|
|
104
|
+
sequenceNumbersMatch(mainBatchSeqNums, attachFlowBatchSeqNums),
|
|
88
105
|
0x58d /* Reference sequence numbers from both batches must be in sync */,
|
|
89
106
|
);
|
|
90
107
|
|
|
108
|
+
const currentSequenceNumbers = this.params.getCurrentSequenceNumbers();
|
|
109
|
+
|
|
91
110
|
if (
|
|
92
|
-
(
|
|
93
|
-
|
|
94
|
-
(attachFlowBatchReference === undefined ||
|
|
95
|
-
attachFlowBatchReference === message.referenceSequenceNumber)
|
|
111
|
+
sequenceNumbersMatch(mainBatchSeqNums, currentSequenceNumbers) &&
|
|
112
|
+
sequenceNumbersMatch(attachFlowBatchSeqNums, currentSequenceNumbers)
|
|
96
113
|
) {
|
|
97
114
|
// The reference sequence numbers are stable, there is nothing to do
|
|
98
115
|
return;
|
|
99
116
|
}
|
|
100
117
|
|
|
101
118
|
if (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {
|
|
102
|
-
this.mc.logger.
|
|
119
|
+
this.mc.logger.sendTelemetryEvent(
|
|
103
120
|
{
|
|
121
|
+
category: this.params.config.disablePartialFlush ? "error" : "generic",
|
|
104
122
|
eventName: "ReferenceSequenceNumberMismatch",
|
|
105
|
-
mainReferenceSequenceNumber:
|
|
106
|
-
|
|
107
|
-
|
|
123
|
+
mainReferenceSequenceNumber: mainBatchSeqNums.referenceSequenceNumber,
|
|
124
|
+
mainClientSequenceNumber: mainBatchSeqNums.clientSequenceNumber,
|
|
125
|
+
attachReferenceSequenceNumber: attachFlowBatchSeqNums.referenceSequenceNumber,
|
|
126
|
+
attachClientSequenceNumber: attachFlowBatchSeqNums.clientSequenceNumber,
|
|
127
|
+
currentReferenceSequenceNumber: currentSequenceNumbers.referenceSequenceNumber,
|
|
128
|
+
currentClientSequenceNumber: currentSequenceNumbers.clientSequenceNumber,
|
|
108
129
|
},
|
|
109
|
-
new UsageError("Submission of an out of order message"),
|
|
130
|
+
getLongStack(() => new UsageError("Submission of an out of order message")),
|
|
110
131
|
);
|
|
111
132
|
}
|
|
112
133
|
|
|
@@ -116,9 +137,14 @@ export class Outbox {
|
|
|
116
137
|
}
|
|
117
138
|
|
|
118
139
|
public submit(message: BatchMessage) {
|
|
119
|
-
this.maybeFlushPartialBatch(
|
|
140
|
+
this.maybeFlushPartialBatch();
|
|
120
141
|
|
|
121
|
-
if (
|
|
142
|
+
if (
|
|
143
|
+
!this.mainBatch.push(
|
|
144
|
+
message,
|
|
145
|
+
this.params.getCurrentSequenceNumbers().clientSequenceNumber,
|
|
146
|
+
)
|
|
147
|
+
) {
|
|
122
148
|
throw new GenericError("BatchTooLarge", /* error */ undefined, {
|
|
123
149
|
opSize: message.contents?.length ?? 0,
|
|
124
150
|
batchSize: this.mainBatch.contentSizeInBytes,
|
|
@@ -129,14 +155,24 @@ export class Outbox {
|
|
|
129
155
|
}
|
|
130
156
|
|
|
131
157
|
public submitAttach(message: BatchMessage) {
|
|
132
|
-
this.maybeFlushPartialBatch(
|
|
158
|
+
this.maybeFlushPartialBatch();
|
|
133
159
|
|
|
134
|
-
if (
|
|
160
|
+
if (
|
|
161
|
+
!this.attachFlowBatch.push(
|
|
162
|
+
message,
|
|
163
|
+
this.params.getCurrentSequenceNumbers().clientSequenceNumber,
|
|
164
|
+
)
|
|
165
|
+
) {
|
|
135
166
|
// BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged
|
|
136
167
|
// when queue is not empty.
|
|
137
168
|
// Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit
|
|
138
169
|
this.flushInternal(this.attachFlowBatch.popBatch());
|
|
139
|
-
if (
|
|
170
|
+
if (
|
|
171
|
+
!this.attachFlowBatch.push(
|
|
172
|
+
message,
|
|
173
|
+
this.params.getCurrentSequenceNumbers().clientSequenceNumber,
|
|
174
|
+
)
|
|
175
|
+
) {
|
|
140
176
|
throw new GenericError("BatchTooLarge", /* error */ undefined, {
|
|
141
177
|
opSize: message.contents?.length ?? 0,
|
|
142
178
|
batchSize: this.attachFlowBatch.contentSizeInBytes,
|
|
@@ -180,15 +216,17 @@ export class Outbox {
|
|
|
180
216
|
this.params.containerContext.submitBatchFn === undefined
|
|
181
217
|
) {
|
|
182
218
|
// Nothing to do if the batch is empty or if compression is disabled or not supported, or if we don't need to compress
|
|
183
|
-
return batch;
|
|
219
|
+
return this.params.groupingManager.groupBatch(batch);
|
|
184
220
|
}
|
|
185
221
|
|
|
186
|
-
const compressedBatch = this.params.
|
|
222
|
+
const compressedBatch = this.params.groupingManager.groupBatch(
|
|
223
|
+
this.params.compressor.compressBatch(batch),
|
|
224
|
+
);
|
|
187
225
|
|
|
188
226
|
if (this.params.splitter.isBatchChunkingEnabled) {
|
|
189
227
|
return compressedBatch.contentSizeInBytes <= this.params.splitter.chunkSizeInBytes
|
|
190
228
|
? compressedBatch
|
|
191
|
-
: this.params.splitter.
|
|
229
|
+
: this.params.splitter.splitFirstBatchMessage(compressedBatch);
|
|
192
230
|
}
|
|
193
231
|
|
|
194
232
|
if (compressedBatch.contentSizeInBytes >= this.params.config.maxBatchSizeInBytes) {
|
|
@@ -6,12 +6,14 @@
|
|
|
6
6
|
import { ISequencedDocumentMessage, MessageType } from "@fluidframework/protocol-definitions";
|
|
7
7
|
import { ContainerMessageType, ContainerRuntimeMessage } from "../containerRuntime";
|
|
8
8
|
import { OpDecompressor } from "./opDecompressor";
|
|
9
|
+
import { OpGroupingManager } from "./opGroupingManager";
|
|
9
10
|
import { OpSplitter } from "./opSplitter";
|
|
10
11
|
|
|
11
12
|
export class RemoteMessageProcessor {
|
|
12
13
|
constructor(
|
|
13
14
|
private readonly opSplitter: OpSplitter,
|
|
14
15
|
private readonly opDecompressor: OpDecompressor,
|
|
16
|
+
private readonly opGroupingManager: OpGroupingManager,
|
|
15
17
|
) {}
|
|
16
18
|
|
|
17
19
|
public get partialMessages(): ReadonlyMap<string, string[]> {
|
|
@@ -22,30 +24,44 @@ export class RemoteMessageProcessor {
|
|
|
22
24
|
this.opSplitter.clearPartialChunks(clientId);
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
public process(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage {
|
|
26
|
-
|
|
27
|
-
message = this.opDecompressor.processMessage(message).message;
|
|
28
|
-
unpackRuntimeMessage(message);
|
|
29
|
-
|
|
30
|
-
const chunkProcessingResult = this.opSplitter.processRemoteMessage(message);
|
|
31
|
-
message = chunkProcessingResult.message;
|
|
32
|
-
if (chunkProcessingResult.state !== "Processed") {
|
|
33
|
-
// If the message is not chunked or if the splitter is still rebuilding the original message,
|
|
34
|
-
// there is no need to continue processing
|
|
35
|
-
return message;
|
|
36
|
-
}
|
|
27
|
+
public process(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage[] {
|
|
28
|
+
const result: ISequencedDocumentMessage[] = [];
|
|
37
29
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// there is no need to continue processing
|
|
43
|
-
return message;
|
|
44
|
-
}
|
|
30
|
+
// Ungroup before processing chunks
|
|
31
|
+
for (let ungroupedMessage of this.opGroupingManager.ungroupOp(copy(remoteMessage))) {
|
|
32
|
+
ungroupedMessage = this.opDecompressor.processMessage(ungroupedMessage).message;
|
|
33
|
+
unpackRuntimeMessage(ungroupedMessage);
|
|
45
34
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
35
|
+
const chunkProcessingResult = this.opSplitter.processRemoteMessage(ungroupedMessage);
|
|
36
|
+
ungroupedMessage = chunkProcessingResult.message;
|
|
37
|
+
if (chunkProcessingResult.state !== "Processed") {
|
|
38
|
+
// If the message is not chunked or if the splitter is still rebuilding the original message,
|
|
39
|
+
// there is no need to continue processing
|
|
40
|
+
result.push(ungroupedMessage);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Ungroup the chunked message before decompressing
|
|
45
|
+
for (let ungroupedMessageAfterChunking of this.opGroupingManager.ungroupOp(
|
|
46
|
+
ungroupedMessage,
|
|
47
|
+
)) {
|
|
48
|
+
const decompressionAfterChunking = this.opDecompressor.processMessage(
|
|
49
|
+
ungroupedMessageAfterChunking,
|
|
50
|
+
);
|
|
51
|
+
ungroupedMessageAfterChunking = decompressionAfterChunking.message;
|
|
52
|
+
if (decompressionAfterChunking.state === "Skipped") {
|
|
53
|
+
// After chunking, if the original message was not compressed,
|
|
54
|
+
// there is no need to continue processing
|
|
55
|
+
result.push(ungroupedMessageAfterChunking);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// The message needs to be unpacked after chunking + decompression
|
|
60
|
+
unpack(ungroupedMessageAfterChunking);
|
|
61
|
+
result.push(ungroupedMessageAfterChunking);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
49
65
|
}
|
|
50
66
|
}
|
|
51
67
|
|
package/src/packageVersion.ts
CHANGED
|
@@ -49,10 +49,7 @@ export interface IRuntimeStateHandler {
|
|
|
49
49
|
connected(): boolean;
|
|
50
50
|
clientId(): string | undefined;
|
|
51
51
|
close(error?: ICriticalContainerError): void;
|
|
52
|
-
applyStashedOp: (
|
|
53
|
-
type: ContainerMessageType,
|
|
54
|
-
content: ISequencedDocumentMessage,
|
|
55
|
-
) => Promise<unknown>;
|
|
52
|
+
applyStashedOp: (type: ContainerMessageType, content: unknown) => Promise<unknown>;
|
|
56
53
|
reSubmit(
|
|
57
54
|
type: ContainerMessageType,
|
|
58
55
|
content: any,
|
|
@@ -110,9 +107,20 @@ export class PendingStateManager implements IDisposable {
|
|
|
110
107
|
return {
|
|
111
108
|
// delete localOpMetadata since it may not be serializable
|
|
112
109
|
// and will be regenerated by applyStashedOp()
|
|
113
|
-
pendingStates: this.pendingMessages
|
|
114
|
-
|
|
115
|
-
|
|
110
|
+
pendingStates: this.pendingMessages.toArray().map((message) =>
|
|
111
|
+
// IdAllocations need their localOpMetadata stashed in the contents
|
|
112
|
+
// of the op to correctly resume the session when processing stashed ops
|
|
113
|
+
message.messageType === ContainerMessageType.IdAllocation
|
|
114
|
+
? {
|
|
115
|
+
...message,
|
|
116
|
+
content: {
|
|
117
|
+
...message.content,
|
|
118
|
+
stashedState: message.localOpMetadata,
|
|
119
|
+
},
|
|
120
|
+
localOpMetadata: undefined,
|
|
121
|
+
}
|
|
122
|
+
: { ...message, localOpMetadata: undefined },
|
|
123
|
+
),
|
|
116
124
|
};
|
|
117
125
|
}
|
|
118
126
|
}
|
|
@@ -211,6 +219,12 @@ export class PendingStateManager implements IDisposable {
|
|
|
211
219
|
);
|
|
212
220
|
nextMessage.localOpMetadata = localOpMetadata;
|
|
213
221
|
|
|
222
|
+
if (nextMessage.messageType === ContainerMessageType.IdAllocation) {
|
|
223
|
+
// Remove the stashed state from the op
|
|
224
|
+
// so that it doesn't go over the wire
|
|
225
|
+
delete nextMessage.content.stashedState;
|
|
226
|
+
}
|
|
227
|
+
|
|
214
228
|
// then we push onto pendingMessages which will cause PendingStateManager to resubmit when we connect
|
|
215
229
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
216
230
|
this.pendingMessages.push(this.initialMessages.shift()!);
|
package/src/summary/index.ts
CHANGED
|
@@ -94,8 +94,9 @@ export {
|
|
|
94
94
|
rootHasIsolatedChannels,
|
|
95
95
|
WriteFluidDataStoreAttributes,
|
|
96
96
|
wrapSummaryInChannelsTree,
|
|
97
|
+
idCompressorBlobName,
|
|
97
98
|
} from "./summaryFormat";
|
|
98
|
-
export { SummarizeReason } from "./summaryGenerator";
|
|
99
|
+
export { getFailMessage, SummarizeReason } from "./summaryGenerator";
|
|
99
100
|
export {
|
|
100
101
|
IConnectedEvents,
|
|
101
102
|
IConnectedState,
|
|
@@ -336,7 +336,7 @@ export class OrderedClientElection
|
|
|
336
336
|
}
|
|
337
337
|
|
|
338
338
|
constructor(
|
|
339
|
-
logger: ITelemetryLogger,
|
|
339
|
+
private readonly logger: ITelemetryLogger,
|
|
340
340
|
private readonly orderedClientCollection: IOrderedClientCollection,
|
|
341
341
|
/** Serialized state from summary or current sequence number at time of load if new. */
|
|
342
342
|
initialState: ISerializedElection | number,
|
|
@@ -416,6 +416,14 @@ export class OrderedClientElection
|
|
|
416
416
|
change = true;
|
|
417
417
|
}
|
|
418
418
|
if (change) {
|
|
419
|
+
if (isSummarizerClient) {
|
|
420
|
+
this.logger.sendTelemetryEvent({
|
|
421
|
+
eventName: "SummarizerClientElected",
|
|
422
|
+
electedClientId: this._electedClient?.clientId,
|
|
423
|
+
electedParentId: this._electedParent?.clientId,
|
|
424
|
+
electionSequenceNumber: sequenceNumber,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
419
427
|
this.emit("election", client, sequenceNumber, prevClient);
|
|
420
428
|
}
|
|
421
429
|
}
|
|
@@ -423,6 +431,14 @@ export class OrderedClientElection
|
|
|
423
431
|
private tryElectingParent(client: ILinkedClient | undefined, sequenceNumber: number): void {
|
|
424
432
|
if (this._electedParent !== client) {
|
|
425
433
|
this._electedParent = client;
|
|
434
|
+
if (client?.client.details.type === summarizerClientType) {
|
|
435
|
+
this.logger.sendTelemetryEvent({
|
|
436
|
+
eventName: "SummarizerParentElected",
|
|
437
|
+
electedClientId: this._electedClient?.clientId,
|
|
438
|
+
electedParentId: this._electedParent?.clientId,
|
|
439
|
+
electionSequenceNumber: sequenceNumber,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
426
442
|
this.emit("election", this._electedClient, sequenceNumber, this._electedClient);
|
|
427
443
|
}
|
|
428
444
|
}
|
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
const maxSummarizeAckWaitTime = 10 * 60 * 1000; // 10 minutes
|
|
47
47
|
|
|
48
48
|
const defaultNumberSummarizationAttempts = 2; // only up to 2 attempts
|
|
49
|
+
|
|
49
50
|
/**
|
|
50
51
|
* An instance of RunningSummarizer manages the heuristics for summarizing.
|
|
51
52
|
* Until disposed, the instance of RunningSummarizer can assume that it is
|
|
@@ -61,7 +62,6 @@ export class RunningSummarizer implements IDisposable {
|
|
|
61
62
|
submitSummaryCallback: (options: ISubmitSummaryOptions) => Promise<SubmitSummaryResult>,
|
|
62
63
|
refreshLatestSummaryAckCallback: (options: IRefreshSummaryAckOptions) => Promise<void>,
|
|
63
64
|
heuristicData: ISummarizeHeuristicData,
|
|
64
|
-
raiseSummarizingError: (errorMessage: string) => void,
|
|
65
65
|
summaryCollection: SummaryCollection,
|
|
66
66
|
cancellationToken: ISummaryCancellationToken,
|
|
67
67
|
stopSummarizerCallback: (reason: SummarizerStopReason) => void,
|
|
@@ -74,7 +74,6 @@ export class RunningSummarizer implements IDisposable {
|
|
|
74
74
|
submitSummaryCallback,
|
|
75
75
|
refreshLatestSummaryAckCallback,
|
|
76
76
|
heuristicData,
|
|
77
|
-
raiseSummarizingError,
|
|
78
77
|
summaryCollection,
|
|
79
78
|
cancellationToken,
|
|
80
79
|
stopSummarizerCallback,
|
|
@@ -146,6 +145,9 @@ export class RunningSummarizer implements IDisposable {
|
|
|
146
145
|
private totalSuccessfulAttempts = 0;
|
|
147
146
|
private initialized = false;
|
|
148
147
|
|
|
148
|
+
private readonly deltaManagerListener;
|
|
149
|
+
private readonly runtimeListener;
|
|
150
|
+
|
|
149
151
|
private constructor(
|
|
150
152
|
baseLogger: ITelemetryLogger,
|
|
151
153
|
private readonly summaryWatcher: IClientSummaryWatcher,
|
|
@@ -157,7 +159,6 @@ export class RunningSummarizer implements IDisposable {
|
|
|
157
159
|
options: IRefreshSummaryAckOptions,
|
|
158
160
|
) => Promise<void>,
|
|
159
161
|
private readonly heuristicData: ISummarizeHeuristicData,
|
|
160
|
-
private readonly raiseSummarizingError: (errorMessage: string) => void,
|
|
161
162
|
private readonly summaryCollection: SummaryCollection,
|
|
162
163
|
private readonly cancellationToken: ISummaryCancellationToken,
|
|
163
164
|
private readonly stopSummarizerCallback: (reason: SummarizerStopReason) => void,
|
|
@@ -198,13 +199,12 @@ export class RunningSummarizer implements IDisposable {
|
|
|
198
199
|
const maxAckWaitTime = Math.min(this.configuration.maxAckWaitTime, maxSummarizeAckWaitTime);
|
|
199
200
|
|
|
200
201
|
this.pendingAckTimer = new PromiseTimer(maxAckWaitTime, () => {
|
|
201
|
-
// pre-0.58 error message: summaryAckWaitTimeout
|
|
202
|
-
this.raiseSummarizingError("Pending summary ack not received in time");
|
|
203
202
|
// Note: summarizeCount (from ChildLogger definition) may be 0,
|
|
204
203
|
// since this code path is hit when RunningSummarizer first starts up,
|
|
205
204
|
// before this instance has kicked off a new summarize run.
|
|
206
205
|
this.mc.logger.sendErrorEvent({
|
|
207
206
|
eventName: "SummaryAckWaitTimeout",
|
|
207
|
+
message: "Pending summary ack not received in time",
|
|
208
208
|
maxAckWaitTime,
|
|
209
209
|
referenceSequenceNumber: this.heuristicData.lastAttempt.refSequenceNumber,
|
|
210
210
|
summarySequenceNumber: this.heuristicData.lastAttempt.summarySequenceNumber,
|
|
@@ -227,7 +227,6 @@ export class RunningSummarizer implements IDisposable {
|
|
|
227
227
|
this.pendingAckTimer,
|
|
228
228
|
this.heuristicData,
|
|
229
229
|
this.submitSummaryCallback,
|
|
230
|
-
this.raiseSummarizingError,
|
|
231
230
|
() => {
|
|
232
231
|
this.totalSuccessfulAttempts++;
|
|
233
232
|
},
|
|
@@ -235,10 +234,25 @@ export class RunningSummarizer implements IDisposable {
|
|
|
235
234
|
this.mc.logger,
|
|
236
235
|
);
|
|
237
236
|
|
|
238
|
-
// Listen for ops
|
|
239
|
-
this.
|
|
240
|
-
|
|
241
|
-
|
|
237
|
+
// Listen to deltaManager for non-runtime ops
|
|
238
|
+
this.deltaManagerListener = (op) => {
|
|
239
|
+
if (!isRuntimeMessage(op)) {
|
|
240
|
+
this.handleOp(op, false);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
// Listen to runtime for runtime ops
|
|
245
|
+
this.runtimeListener = (op, runtimeMessage) => {
|
|
246
|
+
if (runtimeMessage) {
|
|
247
|
+
this.handleOp(op, true);
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
// Purpose of listening to deltaManager is for back-compat
|
|
252
|
+
// Can remove and only listen to runtime once loader version is past 2.0.0-internal.1.2.0 (https://github.com/microsoft/FluidFramework/pull/11832)
|
|
253
|
+
// Tracked by AB#3883
|
|
254
|
+
this.runtime.deltaManager.on("op", this.deltaManagerListener);
|
|
255
|
+
this.runtime.on?.("op", this.runtimeListener);
|
|
242
256
|
}
|
|
243
257
|
|
|
244
258
|
private async handleSummaryAck(): Promise<number> {
|
|
@@ -248,67 +262,54 @@ export class RunningSummarizer implements IDisposable {
|
|
|
248
262
|
if (lastAck !== undefined) {
|
|
249
263
|
refSequenceNumber = lastAck.summaryOp.referenceSequenceNumber;
|
|
250
264
|
const summaryLogger = this.tryGetCorrelatedLogger(refSequenceNumber) ?? this.mc.logger;
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
265
|
+
const summaryOpHandle = lastAck.summaryOp.contents.handle;
|
|
266
|
+
const summaryAckHandle = lastAck.summaryAck.contents.handle;
|
|
267
|
+
while (this.summarizingLock !== undefined) {
|
|
268
|
+
summaryLogger.sendTelemetryEvent({
|
|
269
|
+
eventName: "RefreshAttemptWithSummarizerRunning",
|
|
270
|
+
referenceSequenceNumber: refSequenceNumber,
|
|
271
|
+
proposalHandle: summaryOpHandle,
|
|
272
|
+
ackHandle: summaryAckHandle,
|
|
273
|
+
});
|
|
274
|
+
await this.summarizingLock;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Make sure we block any summarizer from being executed/enqueued while
|
|
278
|
+
// executing the refreshLatestSummaryAck.
|
|
279
|
+
// https://dev.azure.com/fluidframework/internal/_workitems/edit/779
|
|
280
|
+
await this.lockedSummaryAction(
|
|
281
|
+
() => {},
|
|
282
|
+
async () =>
|
|
283
|
+
this.refreshLatestSummaryAckCallback({
|
|
258
284
|
proposalHandle: summaryOpHandle,
|
|
259
285
|
ackHandle: summaryAckHandle,
|
|
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
|
-
eventName: "HandleSummaryAckErrorIgnored",
|
|
289
|
-
referenceSequenceNumber: refSequenceNumber,
|
|
290
|
-
proposalHandle: summaryOpHandle,
|
|
291
|
-
ackHandle: summaryAckHandle,
|
|
292
|
-
},
|
|
293
|
-
error,
|
|
294
|
-
);
|
|
295
|
-
} else {
|
|
296
|
-
throw error;
|
|
297
|
-
}
|
|
298
|
-
}),
|
|
299
|
-
() => {},
|
|
300
|
-
);
|
|
301
|
-
} catch (error) {
|
|
302
|
-
summaryLogger.sendErrorEvent(
|
|
303
|
-
{
|
|
304
|
-
eventName: "HandleLastSummaryAckError",
|
|
305
|
-
referenceSequenceNumber: refSequenceNumber,
|
|
306
|
-
handle: lastAck?.summaryOp?.contents?.handle,
|
|
307
|
-
ackHandle: lastAck?.summaryAck?.contents?.handle,
|
|
308
|
-
},
|
|
309
|
-
error,
|
|
310
|
-
);
|
|
311
|
-
}
|
|
286
|
+
summaryRefSeq: refSequenceNumber,
|
|
287
|
+
summaryLogger,
|
|
288
|
+
}).catch(async (error) => {
|
|
289
|
+
// If the error is 404, so maybe the fetched version no longer exists on server. We just
|
|
290
|
+
// ignore this error in that case, as that means we will have another summaryAck for the
|
|
291
|
+
// latest version with which we will refresh the state. However in case of single commit
|
|
292
|
+
// summary, we might me missing a summary ack, so in that case we are still fine as the
|
|
293
|
+
// code in `submitSummary` function in container runtime, will refresh the latest state
|
|
294
|
+
// by calling `refreshLatestSummaryAckFromServer` and we will be fine.
|
|
295
|
+
const isIgnoredError =
|
|
296
|
+
isFluidError(error) &&
|
|
297
|
+
error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError;
|
|
298
|
+
|
|
299
|
+
summaryLogger.sendTelemetryEvent(
|
|
300
|
+
{
|
|
301
|
+
eventName: isIgnoredError
|
|
302
|
+
? "HandleSummaryAckErrorIgnored"
|
|
303
|
+
: "HandleLastSummaryAckError",
|
|
304
|
+
referenceSequenceNumber: refSequenceNumber,
|
|
305
|
+
proposalHandle: summaryOpHandle,
|
|
306
|
+
ackHandle: summaryAckHandle,
|
|
307
|
+
},
|
|
308
|
+
error,
|
|
309
|
+
);
|
|
310
|
+
}),
|
|
311
|
+
() => {},
|
|
312
|
+
);
|
|
312
313
|
refSequenceNumber++;
|
|
313
314
|
}
|
|
314
315
|
return refSequenceNumber;
|
|
@@ -345,9 +346,8 @@ export class RunningSummarizer implements IDisposable {
|
|
|
345
346
|
}
|
|
346
347
|
|
|
347
348
|
public dispose(): void {
|
|
348
|
-
this.runtime.deltaManager.off("op",
|
|
349
|
-
|
|
350
|
-
});
|
|
349
|
+
this.runtime.deltaManager.off("op", this.deltaManagerListener);
|
|
350
|
+
this.runtime.off?.("op", this.runtimeListener);
|
|
351
351
|
this.summaryWatcher.dispose();
|
|
352
352
|
this.heuristicRunner?.dispose();
|
|
353
353
|
this.heuristicRunner = undefined;
|
|
@@ -372,10 +372,10 @@ export class RunningSummarizer implements IDisposable {
|
|
|
372
372
|
/** We only want a single heuristic runner micro-task (will provide better optimized grouping of ops) */
|
|
373
373
|
private heuristicRunnerMicroTaskExists = false;
|
|
374
374
|
|
|
375
|
-
public handleOp(op: ISequencedDocumentMessage) {
|
|
375
|
+
public handleOp(op: ISequencedDocumentMessage, runtimeMessage: boolean) {
|
|
376
376
|
this.heuristicData.lastOpSequenceNumber = op.sequenceNumber;
|
|
377
377
|
|
|
378
|
-
if (
|
|
378
|
+
if (runtimeMessage) {
|
|
379
379
|
this.heuristicData.numRuntimeOps++;
|
|
380
380
|
} else {
|
|
381
381
|
this.heuristicData.numNonRuntimeOps++;
|
|
@@ -386,7 +386,7 @@ export class RunningSummarizer implements IDisposable {
|
|
|
386
386
|
// Check for enqueued on-demand summaries; Intentionally do nothing otherwise
|
|
387
387
|
if (
|
|
388
388
|
this.initialized &&
|
|
389
|
-
this.opCanTriggerSummary(op) &&
|
|
389
|
+
this.opCanTriggerSummary(op, runtimeMessage) &&
|
|
390
390
|
!this.tryRunEnqueuedSummary() &&
|
|
391
391
|
!this.heuristicRunnerMicroTaskExists
|
|
392
392
|
) {
|
|
@@ -407,14 +407,14 @@ export class RunningSummarizer implements IDisposable {
|
|
|
407
407
|
* @param op - op to check
|
|
408
408
|
* @returns true if this op can trigger a summary
|
|
409
409
|
*/
|
|
410
|
-
private opCanTriggerSummary(op: ISequencedDocumentMessage): boolean {
|
|
410
|
+
private opCanTriggerSummary(op: ISequencedDocumentMessage, runtimeMessage: boolean): boolean {
|
|
411
411
|
switch (op.type) {
|
|
412
412
|
case MessageType.Summarize:
|
|
413
413
|
case MessageType.SummaryAck:
|
|
414
414
|
case MessageType.SummaryNack:
|
|
415
415
|
return false;
|
|
416
416
|
default:
|
|
417
|
-
return
|
|
417
|
+
return runtimeMessage || this.nonRuntimeOpCanTriggerSummary();
|
|
418
418
|
}
|
|
419
419
|
}
|
|
420
420
|
|
|
@@ -646,6 +646,7 @@ export class RunningSummarizer implements IDisposable {
|
|
|
646
646
|
if (result.success) {
|
|
647
647
|
return;
|
|
648
648
|
}
|
|
649
|
+
|
|
649
650
|
// Check for retryDelay that can come from summaryNack or upload summary flow.
|
|
650
651
|
// Retry the same step only once per retryAfter response.
|
|
651
652
|
overrideDelaySeconds = result.retryAfterSeconds;
|
|
@@ -263,14 +263,6 @@ export class Summarizer extends EventEmitter implements ISummarizer {
|
|
|
263
263
|
refSequenceNumber: this.runtime.deltaManager.initialSequenceNumber,
|
|
264
264
|
summaryTime: Date.now(),
|
|
265
265
|
} as const),
|
|
266
|
-
(errorMessage: string) => {
|
|
267
|
-
if (!this._disposed) {
|
|
268
|
-
this.logger.sendErrorEvent(
|
|
269
|
-
{ eventName: "summarizingError" },
|
|
270
|
-
createSummarizingWarning(errorMessage, true),
|
|
271
|
-
);
|
|
272
|
-
}
|
|
273
|
-
},
|
|
274
266
|
this.summaryCollection,
|
|
275
267
|
runCoordinator /* cancellationToken */,
|
|
276
268
|
(reason) => runCoordinator.stop(reason) /* stopSummarizerCallback */,
|
|
@@ -26,6 +26,10 @@ export class SummarizeHeuristicData implements ISummarizeHeuristicData {
|
|
|
26
26
|
return this._lastSuccessfulSummary;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
public get opsSinceLastSummary(): number {
|
|
30
|
+
return this.numSystemOpsBefore + this.numNonSystemOpsBefore;
|
|
31
|
+
}
|
|
32
|
+
|
|
29
33
|
public numNonRuntimeOps: number = 0;
|
|
30
34
|
public totalOpsSize: number = 0;
|
|
31
35
|
public hasMissingOpData: boolean = false;
|
|
@@ -164,7 +164,7 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
164
164
|
// complains if this assert isn't done this way
|
|
165
165
|
assert(
|
|
166
166
|
this.wipReferenceSequenceNumber !== undefined,
|
|
167
|
-
|
|
167
|
+
0x5df /* Summarize should not be called when not tracking the summary */,
|
|
168
168
|
);
|
|
169
169
|
const incrementalSummaryContext: IExperimentalIncrementalSummaryContext | undefined =
|
|
170
170
|
this._latestSummary !== undefined
|
|
@@ -69,7 +69,7 @@ class SummaryNodeWithGC extends SummaryNode {
|
|
|
69
69
|
* - Adds trackState param to summarize. If trackState is false, it bypasses the SummarizerNode and calls
|
|
70
70
|
* directly into summarizeInternal method.
|
|
71
71
|
*/
|
|
72
|
-
class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNodeWithGC {
|
|
72
|
+
export class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNodeWithGC {
|
|
73
73
|
// Tracks the work-in-progress used routes during summary.
|
|
74
74
|
private wipSerializedUsedRoutes: string | undefined;
|
|
75
75
|
|
|
@@ -536,8 +536,8 @@ class SummarizerNodeWithGC extends SummarizerNode implements IRootSummarizerNode
|
|
|
536
536
|
JSON.stringify(newSerializedRoutes),
|
|
537
537
|
{
|
|
538
538
|
referenceSequenceNumber: value.referenceSequenceNumber,
|
|
539
|
-
basePath:
|
|
540
|
-
localPath:
|
|
539
|
+
basePath: child.latestSummary.basePath,
|
|
540
|
+
localPath: child.latestSummary.localPath,
|
|
541
541
|
},
|
|
542
542
|
);
|
|
543
543
|
child.addPendingSummary(key, newLatestSummaryNode);
|