@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
package/src/containerRuntime.ts
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
} from "@fluidframework/container-runtime-definitions";
|
|
32
32
|
import {
|
|
33
33
|
assert,
|
|
34
|
+
delay,
|
|
34
35
|
LazyPromise,
|
|
35
36
|
Trace,
|
|
36
37
|
TypedEventEmitter,
|
|
@@ -88,9 +89,14 @@ import {
|
|
|
88
89
|
CreateChildSummarizerNodeParam,
|
|
89
90
|
SummarizeInternalFn,
|
|
90
91
|
channelsTreeName,
|
|
91
|
-
IAttachMessage,
|
|
92
92
|
IDataStore,
|
|
93
93
|
ITelemetryContext,
|
|
94
|
+
SerializedIdCompressorWithNoSession,
|
|
95
|
+
IIdCompressor,
|
|
96
|
+
IIdCompressorCore,
|
|
97
|
+
IdCreationRange,
|
|
98
|
+
IdCreationRangeWithStashedState,
|
|
99
|
+
IAttachMessage,
|
|
94
100
|
} from "@fluidframework/runtime-definitions";
|
|
95
101
|
import {
|
|
96
102
|
addBlobToSummary,
|
|
@@ -123,6 +129,7 @@ import {
|
|
|
123
129
|
extractSummaryMetadataMessage,
|
|
124
130
|
IContainerRuntimeMetadata,
|
|
125
131
|
ICreateContainerMetadata,
|
|
132
|
+
idCompressorBlobName,
|
|
126
133
|
IFetchSnapshotResult,
|
|
127
134
|
IRootSummarizerNodeWithGC,
|
|
128
135
|
ISummaryMetadataMessage,
|
|
@@ -168,6 +175,7 @@ import {
|
|
|
168
175
|
Outbox,
|
|
169
176
|
OpSplitter,
|
|
170
177
|
RemoteMessageProcessor,
|
|
178
|
+
OpGroupingManager,
|
|
171
179
|
} from "./opLifecycle";
|
|
172
180
|
import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy";
|
|
173
181
|
|
|
@@ -189,6 +197,13 @@ export enum ContainerMessageType {
|
|
|
189
197
|
|
|
190
198
|
// Sets the alias of a root data store
|
|
191
199
|
Alias = "alias",
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* An op containing an IdRange of Ids allocated using the runtime's IdCompressor since
|
|
203
|
+
* the last allocation op was sent.
|
|
204
|
+
* See the [IdCompressor README](./id-compressor/README.md) for more details.
|
|
205
|
+
*/
|
|
206
|
+
IdAllocation = "idAllocation",
|
|
192
207
|
}
|
|
193
208
|
|
|
194
209
|
export interface ContainerRuntimeMessage {
|
|
@@ -205,7 +220,7 @@ export interface ISummaryBaseConfiguration {
|
|
|
205
220
|
/**
|
|
206
221
|
* Defines the maximum allowed time to wait for a pending summary ack.
|
|
207
222
|
* The maximum amount of time client will wait for a summarize is the minimum of
|
|
208
|
-
* maxSummarizeAckWaitTime (currently
|
|
223
|
+
* maxSummarizeAckWaitTime (currently 3 * 60 * 1000) and maxAckWaitTime.
|
|
209
224
|
*/
|
|
210
225
|
maxAckWaitTime: number;
|
|
211
226
|
/**
|
|
@@ -301,7 +316,7 @@ export const DefaultSummaryConfiguration: ISummaryConfiguration = {
|
|
|
301
316
|
|
|
302
317
|
minOpsForLastSummaryAttempt: 10,
|
|
303
318
|
|
|
304
|
-
maxAckWaitTime:
|
|
319
|
+
maxAckWaitTime: 3 * 60 * 1000, // 3 mins.
|
|
305
320
|
|
|
306
321
|
maxOpsSinceLastSummary: 7000,
|
|
307
322
|
|
|
@@ -392,6 +407,13 @@ export interface IContainerRuntimeOptions {
|
|
|
392
407
|
* @experimental Not ready for use.
|
|
393
408
|
*/
|
|
394
409
|
readonly chunkSizeInBytes?: number;
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Enable the IdCompressor in the runtime.
|
|
413
|
+
* @experimental Not ready for use.
|
|
414
|
+
*/
|
|
415
|
+
readonly enableRuntimeIdCompressor?: boolean;
|
|
416
|
+
|
|
395
417
|
/**
|
|
396
418
|
* If enabled, the runtime will block all attempts to send an op inside the
|
|
397
419
|
* {@link ContainerRuntime#ensureNoDataModelChanges} callback. The callback is used by
|
|
@@ -402,6 +424,17 @@ export interface IContainerRuntimeOptions {
|
|
|
402
424
|
* can be used to disable it at runtime.
|
|
403
425
|
*/
|
|
404
426
|
readonly enableOpReentryCheck?: boolean;
|
|
427
|
+
/**
|
|
428
|
+
* If enabled, the runtime will group messages within a batch into a single
|
|
429
|
+
* message to be sent to the service.
|
|
430
|
+
* The grouping an ungrouping of such messages is handled by the "OpGroupingManager".
|
|
431
|
+
*
|
|
432
|
+
* By default, the feature is disabled. If enabled from options, the `Fluid.ContainerRuntime.DisableGroupedBatching`
|
|
433
|
+
* flag can be used to disable it at runtime.
|
|
434
|
+
*
|
|
435
|
+
* @experimental Not ready for use.
|
|
436
|
+
*/
|
|
437
|
+
readonly enableGroupedBatching?: boolean;
|
|
405
438
|
}
|
|
406
439
|
|
|
407
440
|
/**
|
|
@@ -496,6 +529,13 @@ const defaultCompressionConfig = {
|
|
|
496
529
|
|
|
497
530
|
const defaultChunkSizeInBytes = 204800;
|
|
498
531
|
|
|
532
|
+
/**
|
|
533
|
+
* Instead of refreshing from latest because we do not have 100% confidence in the state
|
|
534
|
+
* of the current system, we should close the summarizer and let it recover.
|
|
535
|
+
* This delay's goal is to prevent tight restart loops
|
|
536
|
+
*/
|
|
537
|
+
const defaultCloseSummarizerDelayMs = 10000; // 10 seconds
|
|
538
|
+
|
|
499
539
|
/**
|
|
500
540
|
* @deprecated - use ContainerRuntimeMessage instead
|
|
501
541
|
*/
|
|
@@ -641,8 +681,10 @@ export class ContainerRuntime
|
|
|
641
681
|
flushMode = defaultFlushMode,
|
|
642
682
|
compressionOptions = defaultCompressionConfig,
|
|
643
683
|
maxBatchSizeInBytes = defaultMaxBatchSizeInBytes,
|
|
684
|
+
enableRuntimeIdCompressor = false,
|
|
644
685
|
chunkSizeInBytes = defaultChunkSizeInBytes,
|
|
645
686
|
enableOpReentryCheck = false,
|
|
687
|
+
enableGroupedBatching = false,
|
|
646
688
|
} = runtimeOptions;
|
|
647
689
|
|
|
648
690
|
const registry = new FluidDataStoreRegistry(registryEntries);
|
|
@@ -660,12 +702,14 @@ export class ContainerRuntime
|
|
|
660
702
|
}
|
|
661
703
|
};
|
|
662
704
|
|
|
663
|
-
const [chunks, metadata, electedSummarizerData, aliases] =
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
705
|
+
const [chunks, metadata, electedSummarizerData, aliases, serializedIdCompressor] =
|
|
706
|
+
await Promise.all([
|
|
707
|
+
tryFetchBlob<[string, string[]][]>(chunksBlobName),
|
|
708
|
+
tryFetchBlob<IContainerRuntimeMetadata>(metadataBlobName),
|
|
709
|
+
tryFetchBlob<ISerializedElection>(electedSummarizerBlobName),
|
|
710
|
+
tryFetchBlob<[string, string][]>(aliasBlobName),
|
|
711
|
+
tryFetchBlob<SerializedIdCompressorWithNoSession>(idCompressorBlobName),
|
|
712
|
+
]);
|
|
669
713
|
|
|
670
714
|
const loadExisting = existing === true || context.existing === true;
|
|
671
715
|
|
|
@@ -710,6 +754,17 @@ export class ContainerRuntime
|
|
|
710
754
|
}
|
|
711
755
|
}
|
|
712
756
|
|
|
757
|
+
const idCompressorEnabled =
|
|
758
|
+
metadata?.idCompressorEnabled ?? runtimeOptions.enableRuntimeIdCompressor ?? false;
|
|
759
|
+
let idCompressor: (IIdCompressor & IIdCompressorCore) | undefined;
|
|
760
|
+
if (idCompressorEnabled) {
|
|
761
|
+
const { IdCompressor, createSessionId } = await import("./id-compressor");
|
|
762
|
+
idCompressor =
|
|
763
|
+
serializedIdCompressor !== undefined
|
|
764
|
+
? IdCompressor.deserialize(serializedIdCompressor, createSessionId())
|
|
765
|
+
: new IdCompressor(createSessionId(), logger);
|
|
766
|
+
}
|
|
767
|
+
|
|
713
768
|
const runtime = new containerRuntimeCtor(
|
|
714
769
|
context,
|
|
715
770
|
registry,
|
|
@@ -725,13 +780,16 @@ export class ContainerRuntime
|
|
|
725
780
|
compressionOptions,
|
|
726
781
|
maxBatchSizeInBytes,
|
|
727
782
|
chunkSizeInBytes,
|
|
783
|
+
enableRuntimeIdCompressor,
|
|
728
784
|
enableOpReentryCheck,
|
|
785
|
+
enableGroupedBatching,
|
|
729
786
|
},
|
|
730
787
|
containerScope,
|
|
731
788
|
logger,
|
|
732
789
|
loadExisting,
|
|
733
790
|
blobManagerSnapshot,
|
|
734
791
|
context.storage,
|
|
792
|
+
idCompressor,
|
|
735
793
|
requestHandler,
|
|
736
794
|
undefined, // summaryConfiguration
|
|
737
795
|
initializeEntryPoint,
|
|
@@ -802,6 +860,8 @@ export class ContainerRuntime
|
|
|
802
860
|
return this.context.attachState;
|
|
803
861
|
}
|
|
804
862
|
|
|
863
|
+
public idCompressor: (IIdCompressor & IIdCompressorCore) | undefined;
|
|
864
|
+
|
|
805
865
|
public get IFluidHandleContext(): IFluidHandleContext {
|
|
806
866
|
return this.handleContext;
|
|
807
867
|
}
|
|
@@ -896,6 +956,8 @@ export class ContainerRuntime
|
|
|
896
956
|
private emitDirtyDocumentEvent = true;
|
|
897
957
|
private readonly enableOpReentryCheck: boolean;
|
|
898
958
|
private readonly disableAttachReorder: boolean | undefined;
|
|
959
|
+
private readonly summaryStateUpdateMethod: string | undefined;
|
|
960
|
+
private readonly closeSummarizerDelayMs: number;
|
|
899
961
|
|
|
900
962
|
private readonly defaultTelemetrySignalSampleCount = 100;
|
|
901
963
|
private _perfSignalData: IPerfSignalReport = {
|
|
@@ -975,6 +1037,11 @@ export class ContainerRuntime
|
|
|
975
1037
|
*/
|
|
976
1038
|
private readonly telemetryDocumentId: string;
|
|
977
1039
|
|
|
1040
|
+
/**
|
|
1041
|
+
* If true, the runtime has access to an IdCompressor
|
|
1042
|
+
*/
|
|
1043
|
+
private readonly idCompressorEnabled: boolean;
|
|
1044
|
+
|
|
978
1045
|
/**
|
|
979
1046
|
* @internal
|
|
980
1047
|
*/
|
|
@@ -991,6 +1058,7 @@ export class ContainerRuntime
|
|
|
991
1058
|
existing: boolean,
|
|
992
1059
|
blobManagerSnapshot: IBlobManagerLoadInfo,
|
|
993
1060
|
private readonly _storage: IDocumentStorageService,
|
|
1061
|
+
idCompressor: (IIdCompressor & IIdCompressorCore) | undefined,
|
|
994
1062
|
private readonly requestHandler?: (
|
|
995
1063
|
request: IRequest,
|
|
996
1064
|
runtime: IContainerRuntime,
|
|
@@ -1008,6 +1076,8 @@ export class ContainerRuntime
|
|
|
1008
1076
|
this.innerDeltaManager = context.deltaManager;
|
|
1009
1077
|
this.deltaManager = new DeltaManagerSummarizerProxy(context.deltaManager);
|
|
1010
1078
|
|
|
1079
|
+
this.mc = loggerToMonitoringContext(ChildLogger.create(this.logger, "ContainerRuntime"));
|
|
1080
|
+
|
|
1011
1081
|
let loadSummaryNumber: number;
|
|
1012
1082
|
// Get the container creation metadata. For new container, we initialize these. For existing containers,
|
|
1013
1083
|
// get the values from the metadata blob.
|
|
@@ -1019,12 +1089,20 @@ export class ContainerRuntime
|
|
|
1019
1089
|
// summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
|
|
1020
1090
|
// the count is reset to 0.
|
|
1021
1091
|
loadSummaryNumber = metadata?.summaryNumber ?? 0;
|
|
1092
|
+
|
|
1093
|
+
// Enabling the IdCompressor is a one-way operation and we only want to
|
|
1094
|
+
// allow new containers to turn it on
|
|
1095
|
+
this.idCompressorEnabled = metadata?.idCompressorEnabled ?? false;
|
|
1022
1096
|
} else {
|
|
1023
1097
|
this.createContainerMetadata = {
|
|
1024
1098
|
createContainerRuntimeVersion: pkgVersion,
|
|
1025
1099
|
createContainerTimestamp: Date.now(),
|
|
1026
1100
|
};
|
|
1027
1101
|
loadSummaryNumber = 0;
|
|
1102
|
+
|
|
1103
|
+
this.idCompressorEnabled =
|
|
1104
|
+
this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled") ??
|
|
1105
|
+
idCompressor !== undefined;
|
|
1028
1106
|
}
|
|
1029
1107
|
this.nextSummaryNumber = loadSummaryNumber + 1;
|
|
1030
1108
|
|
|
@@ -1037,8 +1115,6 @@ export class ContainerRuntime
|
|
|
1037
1115
|
this.runtimeOptions.gcOptions[gcTombstoneGenerationOptionName] /* current */,
|
|
1038
1116
|
);
|
|
1039
1117
|
|
|
1040
|
-
this.mc = loggerToMonitoringContext(ChildLogger.create(this.logger, "ContainerRuntime"));
|
|
1041
|
-
|
|
1042
1118
|
this.mc.logger.sendTelemetryEvent({
|
|
1043
1119
|
eventName: "GCFeatureMatrix",
|
|
1044
1120
|
metadataValue: JSON.stringify(metadata?.gcFeatureMatrix),
|
|
@@ -1056,6 +1132,9 @@ export class ContainerRuntime
|
|
|
1056
1132
|
const disableChunking = this.mc.config.getBoolean(
|
|
1057
1133
|
"Fluid.ContainerRuntime.CompressionChunkingDisabled",
|
|
1058
1134
|
);
|
|
1135
|
+
|
|
1136
|
+
const opGroupingManager = new OpGroupingManager(this.groupedBatchingEnabled);
|
|
1137
|
+
|
|
1059
1138
|
const opSplitter = new OpSplitter(
|
|
1060
1139
|
chunks,
|
|
1061
1140
|
this.context.submitBatchFn,
|
|
@@ -1063,9 +1142,11 @@ export class ContainerRuntime
|
|
|
1063
1142
|
runtimeOptions.maxBatchSizeInBytes,
|
|
1064
1143
|
this.mc.logger,
|
|
1065
1144
|
);
|
|
1145
|
+
|
|
1066
1146
|
this.remoteMessageProcessor = new RemoteMessageProcessor(
|
|
1067
1147
|
opSplitter,
|
|
1068
1148
|
new OpDecompressor(this.mc.logger),
|
|
1149
|
+
opGroupingManager,
|
|
1069
1150
|
);
|
|
1070
1151
|
|
|
1071
1152
|
this.handleContext = new ContainerFluidHandleContext("", this);
|
|
@@ -1087,6 +1168,10 @@ export class ContainerRuntime
|
|
|
1087
1168
|
this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
|
|
1088
1169
|
this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
|
|
1089
1170
|
|
|
1171
|
+
if (this.idCompressorEnabled) {
|
|
1172
|
+
this.idCompressor = idCompressor;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1090
1175
|
this.maxConsecutiveReconnects =
|
|
1091
1176
|
this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
|
|
1092
1177
|
this.defaultMaxConsecutiveReconnects;
|
|
@@ -1203,7 +1288,7 @@ export class ContainerRuntime
|
|
|
1203
1288
|
(blobPath: string) => this.garbageCollector.isNodeDeleted(blobPath),
|
|
1204
1289
|
this,
|
|
1205
1290
|
pendingRuntimeState?.pendingAttachmentBlobs,
|
|
1206
|
-
() => this.
|
|
1291
|
+
(error?: ICriticalContainerError) => this.closeFn(error),
|
|
1207
1292
|
);
|
|
1208
1293
|
|
|
1209
1294
|
this.scheduleManager = new ScheduleManager(
|
|
@@ -1252,12 +1337,25 @@ export class ContainerRuntime
|
|
|
1252
1337
|
disablePartialFlush: disablePartialFlush === true,
|
|
1253
1338
|
},
|
|
1254
1339
|
logger: this.mc.logger,
|
|
1340
|
+
groupingManager: opGroupingManager,
|
|
1341
|
+
getCurrentSequenceNumbers: () => ({
|
|
1342
|
+
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
1343
|
+
clientSequenceNumber: this._processedClientSequenceNumber,
|
|
1344
|
+
}),
|
|
1255
1345
|
});
|
|
1256
1346
|
|
|
1257
1347
|
this.context.quorum.on("removeMember", (clientId: string) => {
|
|
1258
1348
|
this.remoteMessageProcessor.clearPartialMessagesFor(clientId);
|
|
1259
1349
|
});
|
|
1260
1350
|
|
|
1351
|
+
this.summaryStateUpdateMethod = this.mc.config.getString(
|
|
1352
|
+
"Fluid.ContainerRuntime.Test.SummaryStateUpdateMethod",
|
|
1353
|
+
);
|
|
1354
|
+
const closeSummarizerDelayOverride = this.mc.config.getNumber(
|
|
1355
|
+
"Fluid.ContainerRuntime.Test.CloseSummarizerDelayOverrideMs",
|
|
1356
|
+
);
|
|
1357
|
+
this.closeSummarizerDelayMs = closeSummarizerDelayOverride ?? defaultCloseSummarizerDelayMs;
|
|
1358
|
+
|
|
1261
1359
|
this.summaryCollection = new SummaryCollection(this.deltaManager, this.logger);
|
|
1262
1360
|
|
|
1263
1361
|
this.dirtyContainer =
|
|
@@ -1398,8 +1496,12 @@ export class ContainerRuntime
|
|
|
1398
1496
|
disableChunking,
|
|
1399
1497
|
disableAttachReorder: this.disableAttachReorder,
|
|
1400
1498
|
disablePartialFlush,
|
|
1499
|
+
idCompressorEnabled: this.idCompressorEnabled,
|
|
1500
|
+
summaryStateUpdateMethod: this.summaryStateUpdateMethod,
|
|
1501
|
+
closeSummarizerDelayOverride,
|
|
1401
1502
|
}),
|
|
1402
1503
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
1504
|
+
groupedBatchingEnabled: this.groupedBatchingEnabled,
|
|
1403
1505
|
});
|
|
1404
1506
|
|
|
1405
1507
|
ReportOpPerfTelemetry(this.context.clientId, this.deltaManager, this.logger);
|
|
@@ -1576,6 +1678,7 @@ export class ContainerRuntime
|
|
|
1576
1678
|
extractSummaryMetadataMessage(this.deltaManager.lastMessage) ??
|
|
1577
1679
|
this.messageAtLastSummary,
|
|
1578
1680
|
telemetryDocumentId: this.telemetryDocumentId,
|
|
1681
|
+
idCompressorEnabled: this.idCompressorEnabled ? true : undefined,
|
|
1579
1682
|
};
|
|
1580
1683
|
addBlobToSummary(summaryTree, metadataBlobName, JSON.stringify(metadata));
|
|
1581
1684
|
}
|
|
@@ -1588,6 +1691,15 @@ export class ContainerRuntime
|
|
|
1588
1691
|
) {
|
|
1589
1692
|
this.addMetadataToSummary(summaryTree);
|
|
1590
1693
|
|
|
1694
|
+
if (this.idCompressorEnabled) {
|
|
1695
|
+
assert(
|
|
1696
|
+
this.idCompressor !== undefined,
|
|
1697
|
+
0x67a /* IdCompressor should be defined if enabled */,
|
|
1698
|
+
);
|
|
1699
|
+
const idCompressorState = JSON.stringify(this.idCompressor.serialize(false));
|
|
1700
|
+
addBlobToSummary(summaryTree, idCompressorBlobName, idCompressorState);
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1591
1703
|
if (this.remoteMessageProcessor.partialMessages.size > 0) {
|
|
1592
1704
|
const content = JSON.stringify([...this.remoteMessageProcessor.partialMessages]);
|
|
1593
1705
|
addBlobToSummary(summaryTree, chunksBlobName, content);
|
|
@@ -1686,15 +1798,32 @@ export class ContainerRuntime
|
|
|
1686
1798
|
this.updateDocumentDirtyState(newState);
|
|
1687
1799
|
}
|
|
1688
1800
|
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1801
|
+
/**
|
|
1802
|
+
* Updates the runtime's IdCompressor with the stashed state present in the given op. This is a bit of a
|
|
1803
|
+
* hack and is unnecessarily expensive. As it stands, every locally stashed op (all ops that get stored in
|
|
1804
|
+
* the PendingStateManager) will store their serialized representation locally until ack'd. Upon receiving
|
|
1805
|
+
* this stashed state, the IdCompressor blindly deserializes to the stashed state and assumes the session.
|
|
1806
|
+
* Technically only the last stashed state is needed to do this correctly, but we would have to write some
|
|
1807
|
+
* more hacky code to modify the batch before it gets sent out.
|
|
1808
|
+
* @param content - An IdAllocationOp with "stashedState", which is a representation of un-ack'd local state.
|
|
1809
|
+
*/
|
|
1810
|
+
private async applyStashedIdAllocationOp(op: IdCreationRangeWithStashedState) {
|
|
1811
|
+
const { IdCompressor } = await import("./id-compressor");
|
|
1812
|
+
this.idCompressor = IdCompressor.deserialize(op.stashedState);
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
private async applyStashedOp(type: ContainerMessageType, contents: unknown): Promise<unknown> {
|
|
1693
1816
|
switch (type) {
|
|
1694
1817
|
case ContainerMessageType.FluidDataStoreOp:
|
|
1695
|
-
return this.dataStores.applyStashedOp(
|
|
1818
|
+
return this.dataStores.applyStashedOp(contents as IEnvelope);
|
|
1696
1819
|
case ContainerMessageType.Attach:
|
|
1697
|
-
return this.dataStores.applyStashedAttachOp(
|
|
1820
|
+
return this.dataStores.applyStashedAttachOp(contents as IAttachMessage);
|
|
1821
|
+
case ContainerMessageType.IdAllocation:
|
|
1822
|
+
assert(
|
|
1823
|
+
this.idCompressor !== undefined,
|
|
1824
|
+
0x67b /* IdCompressor should be defined if enabled */,
|
|
1825
|
+
);
|
|
1826
|
+
return this.applyStashedIdAllocationOp(contents as IdCreationRangeWithStashedState);
|
|
1698
1827
|
case ContainerMessageType.Alias:
|
|
1699
1828
|
case ContainerMessageType.BlobAttach:
|
|
1700
1829
|
return;
|
|
@@ -1814,13 +1943,25 @@ export class ContainerRuntime
|
|
|
1814
1943
|
|
|
1815
1944
|
// Do shallow copy of message, as the processing flow will modify it.
|
|
1816
1945
|
const messageCopy = { ...messageArg };
|
|
1817
|
-
const message
|
|
1946
|
+
for (const message of this.remoteMessageProcessor.process(messageCopy)) {
|
|
1947
|
+
this.processCore(message, local, runtimeMessage);
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
private _processedClientSequenceNumber: number | undefined;
|
|
1818
1952
|
|
|
1953
|
+
private processCore(
|
|
1954
|
+
message: ISequencedDocumentMessage,
|
|
1955
|
+
local: boolean,
|
|
1956
|
+
runtimeMessage: boolean,
|
|
1957
|
+
) {
|
|
1819
1958
|
// Surround the actual processing of the operation with messages to the schedule manager indicating
|
|
1820
1959
|
// the beginning and end. This allows it to emit appropriate events and/or pause the processing of new
|
|
1821
1960
|
// messages once a batch has been fully processed.
|
|
1822
1961
|
this.scheduleManager.beforeOpProcessing(message);
|
|
1823
1962
|
|
|
1963
|
+
this._processedClientSequenceNumber = message.clientSequenceNumber;
|
|
1964
|
+
|
|
1824
1965
|
try {
|
|
1825
1966
|
let localOpMetadata: unknown;
|
|
1826
1967
|
if (local && runtimeMessage && message.type !== ContainerMessageType.ChunkedOp) {
|
|
@@ -1847,6 +1988,13 @@ export class ContainerRuntime
|
|
|
1847
1988
|
case ContainerMessageType.BlobAttach:
|
|
1848
1989
|
this.blobManager.processBlobAttachOp(message, local);
|
|
1849
1990
|
break;
|
|
1991
|
+
case ContainerMessageType.IdAllocation:
|
|
1992
|
+
assert(
|
|
1993
|
+
this.idCompressor !== undefined,
|
|
1994
|
+
0x67c /* IdCompressor should be defined if enabled */,
|
|
1995
|
+
);
|
|
1996
|
+
this.idCompressor.finalizeCreationRange(message.contents as IdCreationRange);
|
|
1997
|
+
break;
|
|
1850
1998
|
case ContainerMessageType.ChunkedOp:
|
|
1851
1999
|
case ContainerMessageType.Rejoin:
|
|
1852
2000
|
break;
|
|
@@ -1870,8 +2018,7 @@ export class ContainerRuntime
|
|
|
1870
2018
|
}
|
|
1871
2019
|
}
|
|
1872
2020
|
|
|
1873
|
-
|
|
1874
|
-
if (runtimeMessage) {
|
|
2021
|
+
if (runtimeMessage || this.groupedBatchingEnabled) {
|
|
1875
2022
|
this.emit("op", message, runtimeMessage);
|
|
1876
2023
|
}
|
|
1877
2024
|
|
|
@@ -2291,31 +2438,33 @@ export class ContainerRuntime
|
|
|
2291
2438
|
runSweep,
|
|
2292
2439
|
});
|
|
2293
2440
|
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2441
|
+
try {
|
|
2442
|
+
let gcStats: IGCStats | undefined;
|
|
2443
|
+
if (runGC) {
|
|
2444
|
+
gcStats = await this.collectGarbage(
|
|
2445
|
+
{ logger: summaryLogger, runSweep, fullGC },
|
|
2446
|
+
telemetryContext,
|
|
2447
|
+
);
|
|
2448
|
+
}
|
|
2449
|
+
|
|
2450
|
+
const { stats, summary } = await this.summarizerNode.summarize(
|
|
2451
|
+
fullTree,
|
|
2452
|
+
trackState,
|
|
2298
2453
|
telemetryContext,
|
|
2299
2454
|
);
|
|
2300
|
-
}
|
|
2301
2455
|
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
);
|
|
2307
|
-
|
|
2308
|
-
this.logger.sendTelemetryEvent({
|
|
2309
|
-
eventName: "SummarizeTelemetry",
|
|
2310
|
-
details: telemetryContext.serialize(),
|
|
2311
|
-
});
|
|
2312
|
-
|
|
2313
|
-
assert(
|
|
2314
|
-
summary.type === SummaryType.Tree,
|
|
2315
|
-
0x12f /* "Container Runtime's summarize should always return a tree" */,
|
|
2316
|
-
);
|
|
2456
|
+
assert(
|
|
2457
|
+
summary.type === SummaryType.Tree,
|
|
2458
|
+
0x12f /* "Container Runtime's summarize should always return a tree" */,
|
|
2459
|
+
);
|
|
2317
2460
|
|
|
2318
|
-
|
|
2461
|
+
return { stats, summary, gcStats };
|
|
2462
|
+
} finally {
|
|
2463
|
+
this.logger.sendTelemetryEvent({
|
|
2464
|
+
eventName: "SummarizeTelemetry",
|
|
2465
|
+
details: telemetryContext.serialize(),
|
|
2466
|
+
});
|
|
2467
|
+
}
|
|
2319
2468
|
}
|
|
2320
2469
|
|
|
2321
2470
|
/**
|
|
@@ -2797,6 +2946,40 @@ export class ContainerRuntime
|
|
|
2797
2946
|
return this.blobManager.createBlob(blob);
|
|
2798
2947
|
}
|
|
2799
2948
|
|
|
2949
|
+
private maybeSubmitIdAllocationOp(type: ContainerMessageType) {
|
|
2950
|
+
if (type !== ContainerMessageType.IdAllocation) {
|
|
2951
|
+
let idAllocationBatchMessage: BatchMessage | undefined;
|
|
2952
|
+
let idRange: IdCreationRange | undefined;
|
|
2953
|
+
if (this.idCompressorEnabled) {
|
|
2954
|
+
assert(
|
|
2955
|
+
this.idCompressor !== undefined,
|
|
2956
|
+
0x67d /* IdCompressor should be defined if enabled */,
|
|
2957
|
+
);
|
|
2958
|
+
idRange = this.idCompressor.takeNextCreationRange();
|
|
2959
|
+
// Don't include the idRange if there weren't any Ids allocated
|
|
2960
|
+
idRange = idRange?.ids?.first !== undefined ? idRange : undefined;
|
|
2961
|
+
}
|
|
2962
|
+
|
|
2963
|
+
if (idRange !== undefined) {
|
|
2964
|
+
const idAllocationMessage: ContainerRuntimeMessage = {
|
|
2965
|
+
type: ContainerMessageType.IdAllocation,
|
|
2966
|
+
contents: idRange,
|
|
2967
|
+
};
|
|
2968
|
+
idAllocationBatchMessage = {
|
|
2969
|
+
contents: JSON.stringify(idAllocationMessage),
|
|
2970
|
+
deserializedContent: idAllocationMessage,
|
|
2971
|
+
referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
|
|
2972
|
+
metadata: undefined,
|
|
2973
|
+
localOpMetadata: this.idCompressor?.serialize(true),
|
|
2974
|
+
};
|
|
2975
|
+
}
|
|
2976
|
+
|
|
2977
|
+
if (idAllocationBatchMessage !== undefined) {
|
|
2978
|
+
this.outbox.submit(idAllocationBatchMessage);
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
|
|
2800
2983
|
private submit(
|
|
2801
2984
|
type: ContainerMessageType,
|
|
2802
2985
|
contents: any,
|
|
@@ -2832,6 +3015,12 @@ export class ContainerRuntime
|
|
|
2832
3015
|
};
|
|
2833
3016
|
|
|
2834
3017
|
try {
|
|
3018
|
+
// Submit an IdAllocation op if any Ids have been generated since
|
|
3019
|
+
// the last op was submitted. Don't submit another if it's an IdAllocation
|
|
3020
|
+
// op as that means we're in resubmission flow and we don't want to send
|
|
3021
|
+
// IdRanges out of order.
|
|
3022
|
+
this.maybeSubmitIdAllocationOp(type);
|
|
3023
|
+
|
|
2835
3024
|
// If this is attach message for new data store, and we are in a batch, send this op out of order
|
|
2836
3025
|
// Is it safe:
|
|
2837
3026
|
// Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
|
|
@@ -2994,6 +3183,7 @@ export class ContainerRuntime
|
|
|
2994
3183
|
break;
|
|
2995
3184
|
case ContainerMessageType.Attach:
|
|
2996
3185
|
case ContainerMessageType.Alias:
|
|
3186
|
+
case ContainerMessageType.IdAllocation:
|
|
2997
3187
|
this.submit(type, content, localOpMetadata);
|
|
2998
3188
|
break;
|
|
2999
3189
|
case ContainerMessageType.ChunkedOp:
|
|
@@ -3059,6 +3249,25 @@ export class ContainerRuntime
|
|
|
3059
3249
|
readAndParseBlob,
|
|
3060
3250
|
);
|
|
3061
3251
|
|
|
3252
|
+
/**
|
|
3253
|
+
* back-compat - Older loaders and drivers (pre 2.0.0-internal.1.4) don't have fetchSource as a param in the
|
|
3254
|
+
* getVersions API. So, they will not fetch the latest snapshot from network in the previous fetch call. For
|
|
3255
|
+
* these scenarios, fetch the snapshot corresponding to the ack handle to have the same behavior before the
|
|
3256
|
+
* change that started fetching latest snapshot always.
|
|
3257
|
+
*/
|
|
3258
|
+
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
3259
|
+
fetchResult = await this.fetchSnapshotFromStorage(
|
|
3260
|
+
summaryLogger,
|
|
3261
|
+
{
|
|
3262
|
+
eventName: "RefreshLatestSummaryAckFetchBackCompat",
|
|
3263
|
+
ackHandle,
|
|
3264
|
+
targetSequenceNumber: summaryRefSeq,
|
|
3265
|
+
},
|
|
3266
|
+
readAndParseBlob,
|
|
3267
|
+
ackHandle,
|
|
3268
|
+
);
|
|
3269
|
+
}
|
|
3270
|
+
|
|
3062
3271
|
/**
|
|
3063
3272
|
* If the fetched snapshot is older than the one for which the ack was received, close the container.
|
|
3064
3273
|
* This should never happen because an ack should be sent after the latest summary is updated in the server.
|
|
@@ -3070,32 +3279,18 @@ export class ContainerRuntime
|
|
|
3070
3279
|
* state.
|
|
3071
3280
|
*/
|
|
3072
3281
|
if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3282
|
+
const error = DataProcessingError.create(
|
|
3283
|
+
"Fetched snapshot is older than the received ack",
|
|
3284
|
+
"RefreshLatestSummaryAck",
|
|
3285
|
+
undefined /* sequencedMessage */,
|
|
3076
3286
|
{
|
|
3077
|
-
eventName: "RefreshLatestSummaryAckFetch",
|
|
3078
3287
|
ackHandle,
|
|
3079
|
-
|
|
3288
|
+
summaryRefSeq,
|
|
3289
|
+
fetchedSnapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
3080
3290
|
},
|
|
3081
|
-
readAndParseBlob,
|
|
3082
|
-
ackHandle,
|
|
3083
3291
|
);
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
const error = DataProcessingError.create(
|
|
3087
|
-
"Fetched snapshot is older than the received ack",
|
|
3088
|
-
"RefreshLatestSummaryAck",
|
|
3089
|
-
undefined /* sequencedMessage */,
|
|
3090
|
-
{
|
|
3091
|
-
ackHandle,
|
|
3092
|
-
summaryRefSeq,
|
|
3093
|
-
fetchedSnapshotRefSeq: fetchResult.latestSnapshotRefSeq,
|
|
3094
|
-
},
|
|
3095
|
-
);
|
|
3096
|
-
this.closeFn(error);
|
|
3097
|
-
throw error;
|
|
3098
|
-
}
|
|
3292
|
+
this.closeFn(error);
|
|
3293
|
+
throw error;
|
|
3099
3294
|
}
|
|
3100
3295
|
|
|
3101
3296
|
// In case we had to retrieve the latest snapshot and it is different than summaryRefSeq,
|
|
@@ -3177,7 +3372,7 @@ export class ContainerRuntime
|
|
|
3177
3372
|
readAndParseBlob: ReadAndParseBlob,
|
|
3178
3373
|
versionId: string | null,
|
|
3179
3374
|
): Promise<{ snapshotTree: ISnapshotTree; versionId: string; latestSnapshotRefSeq: number }> {
|
|
3180
|
-
|
|
3375
|
+
const snapshotResults = await PerformanceEvent.timedExecAsync(
|
|
3181
3376
|
logger,
|
|
3182
3377
|
event,
|
|
3183
3378
|
async (perfEvent: {
|
|
@@ -3223,6 +3418,33 @@ export class ContainerRuntime
|
|
|
3223
3418
|
};
|
|
3224
3419
|
},
|
|
3225
3420
|
);
|
|
3421
|
+
|
|
3422
|
+
// We choose to close the summarizer after the snapshot cache is updated to avoid
|
|
3423
|
+
// situations which the main client (which is likely to be re-elected as the leader again)
|
|
3424
|
+
// loads the summarizer from cache.
|
|
3425
|
+
if (this.summaryStateUpdateMethod === "restart") {
|
|
3426
|
+
const error = new GenericError("Restarting summarizer instead of refreshing");
|
|
3427
|
+
|
|
3428
|
+
this.mc.logger.sendTelemetryEvent(
|
|
3429
|
+
{
|
|
3430
|
+
...event,
|
|
3431
|
+
eventName: "ClosingSummarizerOnSummaryStale",
|
|
3432
|
+
codePath: event.eventName,
|
|
3433
|
+
message: "Stopping fetch from storage",
|
|
3434
|
+
versionId: versionId != null ? versionId : undefined,
|
|
3435
|
+
closeSummarizerDelayMs: this.closeSummarizerDelayMs,
|
|
3436
|
+
},
|
|
3437
|
+
error,
|
|
3438
|
+
);
|
|
3439
|
+
|
|
3440
|
+
// Delay 10 seconds before restarting summarizer to prevent the summarizer from restarting too frequently.
|
|
3441
|
+
await delay(this.closeSummarizerDelayMs);
|
|
3442
|
+
this._summarizer?.stop("latestSummaryStateStale");
|
|
3443
|
+
this.closeFn();
|
|
3444
|
+
throw error;
|
|
3445
|
+
}
|
|
3446
|
+
|
|
3447
|
+
return snapshotResults;
|
|
3226
3448
|
}
|
|
3227
3449
|
|
|
3228
3450
|
public notifyAttaching() {} // do nothing (deprecated method)
|
|
@@ -3316,6 +3538,13 @@ export class ContainerRuntime
|
|
|
3316
3538
|
);
|
|
3317
3539
|
}
|
|
3318
3540
|
}
|
|
3541
|
+
|
|
3542
|
+
private get groupedBatchingEnabled(): boolean {
|
|
3543
|
+
const killSwitch = this.mc.config.getBoolean(
|
|
3544
|
+
"Fluid.ContainerRuntime.DisableGroupedBatching",
|
|
3545
|
+
);
|
|
3546
|
+
return killSwitch !== true && this.runtimeOptions.enableGroupedBatching;
|
|
3547
|
+
}
|
|
3319
3548
|
}
|
|
3320
3549
|
|
|
3321
3550
|
/**
|
package/src/dataStoreContext.ts
CHANGED
|
@@ -48,6 +48,8 @@ import {
|
|
|
48
48
|
ISummarizerNodeWithGC,
|
|
49
49
|
SummarizeInternalFn,
|
|
50
50
|
ITelemetryContext,
|
|
51
|
+
IIdCompressor,
|
|
52
|
+
IIdCompressorCore,
|
|
51
53
|
VisibilityState,
|
|
52
54
|
} from "@fluidframework/runtime-definitions";
|
|
53
55
|
import {
|
|
@@ -193,6 +195,10 @@ export abstract class FluidDataStoreContext
|
|
|
193
195
|
return this._baseSnapshot;
|
|
194
196
|
}
|
|
195
197
|
|
|
198
|
+
public get idCompressor(): (IIdCompressorCore & IIdCompressor) | undefined {
|
|
199
|
+
return this._containerRuntime.idCompressor;
|
|
200
|
+
}
|
|
201
|
+
|
|
196
202
|
private _disposed = false;
|
|
197
203
|
public get disposed() {
|
|
198
204
|
return this._disposed;
|