@fluidframework/container-runtime 2.0.0-internal.3.0.0 → 2.0.0-internal.3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +19 -19
- package/.mocharc.js +2 -2
- package/api-extractor.json +2 -2
- package/dist/batchTracker.d.ts.map +1 -1
- package/dist/batchTracker.js +2 -1
- package/dist/batchTracker.js.map +1 -1
- package/dist/blobManager.d.ts +9 -2
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +80 -33
- package/dist/blobManager.js.map +1 -1
- package/dist/connectionTelemetry.d.ts.map +1 -1
- package/dist/connectionTelemetry.js +11 -9
- package/dist/connectionTelemetry.js.map +1 -1
- package/dist/containerHandleContext.d.ts.map +1 -1
- package/dist/containerHandleContext.js +3 -1
- package/dist/containerHandleContext.js.map +1 -1
- package/dist/containerRuntime.d.ts +10 -0
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +140 -72
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStore.d.ts.map +1 -1
- package/dist/dataStore.js +11 -9
- package/dist/dataStore.js.map +1 -1
- package/dist/dataStoreContext.d.ts +18 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +66 -15
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStoreContexts.d.ts.map +1 -1
- package/dist/dataStoreContexts.js +7 -3
- package/dist/dataStoreContexts.js.map +1 -1
- package/dist/dataStoreRegistry.d.ts.map +1 -1
- package/dist/dataStoreRegistry.js +3 -1
- package/dist/dataStoreRegistry.js.map +1 -1
- package/dist/dataStores.d.ts +26 -1
- package/dist/dataStores.d.ts.map +1 -1
- package/dist/dataStores.js +103 -18
- package/dist/dataStores.js.map +1 -1
- package/dist/deltaScheduler.d.ts.map +1 -1
- package/dist/deltaScheduler.js +8 -3
- package/dist/deltaScheduler.js.map +1 -1
- package/dist/garbageCollection.d.ts +34 -14
- package/dist/garbageCollection.d.ts.map +1 -1
- package/dist/garbageCollection.js +188 -93
- package/dist/garbageCollection.js.map +1 -1
- package/dist/garbageCollectionConstants.d.ts +3 -0
- package/dist/garbageCollectionConstants.d.ts.map +1 -1
- package/dist/garbageCollectionConstants.js +6 -1
- package/dist/garbageCollectionConstants.js.map +1 -1
- package/dist/garbageCollectionHelpers.d.ts +26 -0
- package/dist/garbageCollectionHelpers.d.ts.map +1 -0
- package/dist/garbageCollectionHelpers.js +45 -0
- package/dist/garbageCollectionHelpers.js.map +1 -0
- package/dist/gcSweepReadyUsageDetection.d.ts +5 -5
- package/dist/gcSweepReadyUsageDetection.d.ts.map +1 -1
- package/dist/gcSweepReadyUsageDetection.js +14 -10
- package/dist/gcSweepReadyUsageDetection.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +5 -5
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +19 -12
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +5 -2
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +4 -1
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +19 -17
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/dist/opProperties.d.ts.map +1 -1
- package/dist/opProperties.js +1 -3
- package/dist/opProperties.js.map +1 -1
- package/dist/orderedClientElection.d.ts.map +1 -1
- package/dist/orderedClientElection.js +10 -4
- package/dist/orderedClientElection.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/pendingStateManager.d.ts +7 -0
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +7 -4
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/dist/runWhileConnectedCoordinator.js.map +1 -1
- package/dist/runningSummarizer.d.ts.map +1 -1
- package/dist/runningSummarizer.js +34 -21
- package/dist/runningSummarizer.js.map +1 -1
- package/dist/scheduleManager.d.ts.map +1 -1
- package/dist/scheduleManager.js +3 -2
- package/dist/scheduleManager.js.map +1 -1
- package/dist/serializedSnapshotStorage.d.ts +2 -2
- package/dist/serializedSnapshotStorage.d.ts.map +1 -1
- package/dist/serializedSnapshotStorage.js +5 -3
- package/dist/serializedSnapshotStorage.js.map +1 -1
- package/dist/summarizer.d.ts +2 -2
- package/dist/summarizer.d.ts.map +1 -1
- package/dist/summarizer.js +37 -17
- package/dist/summarizer.js.map +1 -1
- package/dist/summarizerClientElection.d.ts.map +1 -1
- package/dist/summarizerClientElection.js.map +1 -1
- package/dist/summarizerHandle.d.ts.map +1 -1
- package/dist/summarizerHandle.js.map +1 -1
- package/dist/summarizerHeuristics.d.ts.map +1 -1
- package/dist/summarizerHeuristics.js +6 -9
- package/dist/summarizerHeuristics.js.map +1 -1
- package/dist/summarizerTypes.d.ts +21 -21
- package/dist/summarizerTypes.d.ts.map +1 -1
- package/dist/summarizerTypes.js.map +1 -1
- package/dist/summaryCollection.d.ts.map +1 -1
- package/dist/summaryCollection.js +18 -8
- package/dist/summaryCollection.js.map +1 -1
- package/dist/summaryFormat.d.ts +22 -0
- package/dist/summaryFormat.d.ts.map +1 -1
- package/dist/summaryFormat.js +18 -10
- package/dist/summaryFormat.js.map +1 -1
- package/dist/summaryGenerator.d.ts.map +1 -1
- package/dist/summaryGenerator.js +34 -15
- package/dist/summaryGenerator.js.map +1 -1
- package/dist/summaryManager.d.ts.map +1 -1
- package/dist/summaryManager.js +21 -9
- package/dist/summaryManager.js.map +1 -1
- package/dist/throttler.d.ts +2 -2
- package/dist/throttler.d.ts.map +1 -1
- package/dist/throttler.js +4 -4
- package/dist/throttler.js.map +1 -1
- package/garbageCollection.md +15 -2
- package/lib/batchTracker.d.ts.map +1 -1
- package/lib/batchTracker.js +2 -1
- package/lib/batchTracker.js.map +1 -1
- package/lib/blobManager.d.ts +9 -2
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +82 -35
- package/lib/blobManager.js.map +1 -1
- package/lib/connectionTelemetry.d.ts.map +1 -1
- package/lib/connectionTelemetry.js +11 -9
- package/lib/connectionTelemetry.js.map +1 -1
- package/lib/containerHandleContext.d.ts.map +1 -1
- package/lib/containerHandleContext.js +3 -1
- package/lib/containerHandleContext.js.map +1 -1
- package/lib/containerRuntime.d.ts +10 -0
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +146 -78
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStore.d.ts.map +1 -1
- package/lib/dataStore.js +11 -9
- package/lib/dataStore.js.map +1 -1
- package/lib/dataStoreContext.d.ts +18 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +68 -17
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStoreContexts.d.ts.map +1 -1
- package/lib/dataStoreContexts.js +7 -3
- package/lib/dataStoreContexts.js.map +1 -1
- package/lib/dataStoreRegistry.d.ts.map +1 -1
- package/lib/dataStoreRegistry.js +3 -1
- package/lib/dataStoreRegistry.js.map +1 -1
- package/lib/dataStores.d.ts +26 -1
- package/lib/dataStores.d.ts.map +1 -1
- package/lib/dataStores.js +109 -24
- package/lib/dataStores.js.map +1 -1
- package/lib/deltaScheduler.d.ts.map +1 -1
- package/lib/deltaScheduler.js +9 -4
- package/lib/deltaScheduler.js.map +1 -1
- package/lib/garbageCollection.d.ts +34 -14
- package/lib/garbageCollection.d.ts.map +1 -1
- package/lib/garbageCollection.js +190 -95
- package/lib/garbageCollection.js.map +1 -1
- package/lib/garbageCollectionConstants.d.ts +3 -0
- package/lib/garbageCollectionConstants.d.ts.map +1 -1
- package/lib/garbageCollectionConstants.js +5 -0
- package/lib/garbageCollectionConstants.js.map +1 -1
- package/lib/garbageCollectionHelpers.d.ts +26 -0
- package/lib/garbageCollectionHelpers.d.ts.map +1 -0
- package/lib/garbageCollectionHelpers.js +40 -0
- package/lib/garbageCollectionHelpers.js.map +1 -0
- package/lib/gcSweepReadyUsageDetection.d.ts +5 -5
- package/lib/gcSweepReadyUsageDetection.d.ts.map +1 -1
- package/lib/gcSweepReadyUsageDetection.js +14 -10
- package/lib/gcSweepReadyUsageDetection.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +5 -5
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +19 -12
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +5 -2
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +5 -2
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +19 -17
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
- package/lib/opProperties.d.ts.map +1 -1
- package/lib/opProperties.js +1 -3
- package/lib/opProperties.js.map +1 -1
- package/lib/orderedClientElection.d.ts.map +1 -1
- package/lib/orderedClientElection.js +10 -4
- package/lib/orderedClientElection.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/pendingStateManager.d.ts +7 -0
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +7 -4
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/runWhileConnectedCoordinator.d.ts.map +1 -1
- package/lib/runWhileConnectedCoordinator.js.map +1 -1
- package/lib/runningSummarizer.d.ts.map +1 -1
- package/lib/runningSummarizer.js +35 -22
- package/lib/runningSummarizer.js.map +1 -1
- package/lib/scheduleManager.d.ts.map +1 -1
- package/lib/scheduleManager.js +3 -2
- package/lib/scheduleManager.js.map +1 -1
- package/lib/serializedSnapshotStorage.d.ts +2 -2
- package/lib/serializedSnapshotStorage.d.ts.map +1 -1
- package/lib/serializedSnapshotStorage.js +5 -3
- package/lib/serializedSnapshotStorage.js.map +1 -1
- package/lib/summarizer.d.ts +2 -2
- package/lib/summarizer.d.ts.map +1 -1
- package/lib/summarizer.js +37 -17
- package/lib/summarizer.js.map +1 -1
- package/lib/summarizerClientElection.d.ts.map +1 -1
- package/lib/summarizerClientElection.js.map +1 -1
- package/lib/summarizerHandle.d.ts.map +1 -1
- package/lib/summarizerHandle.js.map +1 -1
- package/lib/summarizerHeuristics.d.ts.map +1 -1
- package/lib/summarizerHeuristics.js +6 -9
- package/lib/summarizerHeuristics.js.map +1 -1
- package/lib/summarizerTypes.d.ts +21 -21
- package/lib/summarizerTypes.d.ts.map +1 -1
- package/lib/summarizerTypes.js.map +1 -1
- package/lib/summaryCollection.d.ts.map +1 -1
- package/lib/summaryCollection.js +18 -8
- package/lib/summaryCollection.js.map +1 -1
- package/lib/summaryFormat.d.ts +22 -0
- package/lib/summaryFormat.d.ts.map +1 -1
- package/lib/summaryFormat.js +20 -12
- package/lib/summaryFormat.js.map +1 -1
- package/lib/summaryGenerator.d.ts.map +1 -1
- package/lib/summaryGenerator.js +34 -15
- package/lib/summaryGenerator.js.map +1 -1
- package/lib/summaryManager.d.ts.map +1 -1
- package/lib/summaryManager.js +21 -9
- package/lib/summaryManager.js.map +1 -1
- package/lib/throttler.d.ts +2 -2
- package/lib/throttler.d.ts.map +1 -1
- package/lib/throttler.js +4 -4
- package/lib/throttler.js.map +1 -1
- package/package.json +121 -149
- package/prettier.config.cjs +1 -1
- package/src/batchTracker.ts +54 -49
- package/src/blobManager.ts +793 -672
- package/src/connectionTelemetry.ts +280 -249
- package/src/containerHandleContext.ts +27 -29
- package/src/containerRuntime.ts +3168 -2940
- package/src/dataStore.ts +172 -159
- package/src/dataStoreContext.ts +1098 -996
- package/src/dataStoreContexts.ts +178 -161
- package/src/dataStoreRegistry.ts +25 -20
- package/src/dataStores.ts +884 -728
- package/src/deltaScheduler.ts +158 -150
- package/src/garbageCollection.ts +1883 -1692
- package/src/garbageCollectionConstants.ts +6 -0
- package/src/garbageCollectionHelpers.ts +61 -0
- package/src/gcSweepReadyUsageDetection.ts +89 -83
- package/src/index.ts +67 -66
- package/src/opLifecycle/README.md +152 -0
- package/src/opLifecycle/batchManager.ts +145 -141
- package/src/opLifecycle/definitions.ts +29 -29
- package/src/opLifecycle/index.ts +5 -5
- package/src/opLifecycle/opCompressor.ts +54 -53
- package/src/opLifecycle/opDecompressor.ts +100 -81
- package/src/opLifecycle/opSplitter.ts +214 -188
- package/src/opLifecycle/outbox.ts +204 -194
- package/src/opLifecycle/remoteMessageProcessor.ts +62 -62
- package/src/opProperties.ts +11 -9
- package/src/orderedClientElection.ts +489 -457
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +384 -338
- package/src/runWhileConnectedCoordinator.ts +78 -71
- package/src/runningSummarizer.ts +619 -581
- package/src/scheduleManager.ts +299 -269
- package/src/serializedSnapshotStorage.ts +126 -112
- package/src/summarizer.ts +417 -381
- package/src/summarizerClientElection.ts +107 -100
- package/src/summarizerHandle.ts +11 -9
- package/src/summarizerHeuristics.ts +183 -186
- package/src/summarizerTypes.ts +344 -330
- package/src/summaryCollection.ts +378 -349
- package/src/summaryFormat.ts +170 -126
- package/src/summaryGenerator.ts +465 -406
- package/src/summaryManager.ts +377 -348
- package/src/throttler.ts +131 -122
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +9 -13
- package/dist/garbageCollectionTombstoneUtils.d.ts +0 -14
- package/dist/garbageCollectionTombstoneUtils.d.ts.map +0 -1
- package/dist/garbageCollectionTombstoneUtils.js +0 -23
- package/dist/garbageCollectionTombstoneUtils.js.map +0 -1
- package/lib/garbageCollectionTombstoneUtils.d.ts +0 -14
- package/lib/garbageCollectionTombstoneUtils.d.ts.map +0 -1
- package/lib/garbageCollectionTombstoneUtils.js +0 -19
- package/lib/garbageCollectionTombstoneUtils.js.map +0 -1
- package/src/garbageCollectionTombstoneUtils.ts +0 -28
|
@@ -16,203 +16,213 @@ import { OpCompressor } from "./opCompressor";
|
|
|
16
16
|
import { OpSplitter } from "./opSplitter";
|
|
17
17
|
|
|
18
18
|
export interface IOutboxConfig {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
19
|
+
readonly compressionOptions: ICompressionRuntimeOptions;
|
|
20
|
+
// The maximum size of a batch that we can send over the wire.
|
|
21
|
+
readonly maxBatchSizeInBytes: number;
|
|
22
|
+
readonly enableOpReentryCheck?: boolean;
|
|
23
|
+
}
|
|
24
24
|
|
|
25
25
|
export interface IOutboxParameters {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
readonly shouldSend: () => boolean;
|
|
27
|
+
readonly pendingStateManager: PendingStateManager;
|
|
28
|
+
readonly containerContext: IContainerContext;
|
|
29
|
+
readonly config: IOutboxConfig;
|
|
30
|
+
readonly compressor: OpCompressor;
|
|
31
|
+
readonly splitter: OpSplitter;
|
|
32
|
+
readonly logger: ITelemetryLogger;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export class Outbox {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
36
|
+
private readonly attachFlowBatch: BatchManager;
|
|
37
|
+
private readonly mainBatch: BatchManager;
|
|
38
|
+
private readonly defaultAttachFlowSoftLimitInBytes = 64 * 1024;
|
|
39
|
+
|
|
40
|
+
constructor(private readonly params: IOutboxParameters) {
|
|
41
|
+
const isCompressionEnabled =
|
|
42
|
+
this.params.config.compressionOptions.minimumBatchSizeInBytes !==
|
|
43
|
+
Number.POSITIVE_INFINITY;
|
|
44
|
+
// We need to allow infinite size batches if we enable compression
|
|
45
|
+
const hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;
|
|
46
|
+
const softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;
|
|
47
|
+
|
|
48
|
+
this.attachFlowBatch = new BatchManager(
|
|
49
|
+
{
|
|
50
|
+
hardLimit,
|
|
51
|
+
softLimit,
|
|
52
|
+
enableOpReentryCheck: params.config.enableOpReentryCheck,
|
|
53
|
+
},
|
|
54
|
+
params.logger,
|
|
55
|
+
);
|
|
56
|
+
this.mainBatch = new BatchManager(
|
|
57
|
+
{
|
|
58
|
+
hardLimit,
|
|
59
|
+
enableOpReentryCheck: params.config.enableOpReentryCheck,
|
|
60
|
+
},
|
|
61
|
+
params.logger,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public get isEmpty(): boolean {
|
|
66
|
+
return this.attachFlowBatch.length === 0 && this.mainBatch.length === 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public submit(message: BatchMessage) {
|
|
70
|
+
if (!this.mainBatch.push(message)) {
|
|
71
|
+
throw new GenericError("BatchTooLarge", /* error */ undefined, {
|
|
72
|
+
opSize: message.contents?.length ?? 0,
|
|
73
|
+
batchSize: this.mainBatch.contentSizeInBytes,
|
|
74
|
+
count: this.mainBatch.length,
|
|
75
|
+
limit: this.mainBatch.options.hardLimit,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public submitAttach(message: BatchMessage) {
|
|
81
|
+
if (!this.attachFlowBatch.push(message)) {
|
|
82
|
+
// BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged
|
|
83
|
+
// when queue is not empty.
|
|
84
|
+
// Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit
|
|
85
|
+
this.flushInternal(this.attachFlowBatch.popBatch());
|
|
86
|
+
if (!this.attachFlowBatch.push(message)) {
|
|
87
|
+
throw new GenericError("BatchTooLarge", /* error */ undefined, {
|
|
88
|
+
opSize: message.contents?.length ?? 0,
|
|
89
|
+
batchSize: this.attachFlowBatch.contentSizeInBytes,
|
|
90
|
+
count: this.attachFlowBatch.length,
|
|
91
|
+
limit: this.attachFlowBatch.options.hardLimit,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// If compression is enabled, we will always successfully receive
|
|
97
|
+
// attach ops and compress then send them at the next JS turn, regardless
|
|
98
|
+
// of the overall size of the accumulated ops in the batch.
|
|
99
|
+
// However, it is more efficient to flush these ops faster, preferably
|
|
100
|
+
// after they reach a size which would benefit from compression.
|
|
101
|
+
if (
|
|
102
|
+
this.attachFlowBatch.contentSizeInBytes >=
|
|
103
|
+
this.params.config.compressionOptions.minimumBatchSizeInBytes
|
|
104
|
+
) {
|
|
105
|
+
this.flushInternal(this.attachFlowBatch.popBatch());
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public flush() {
|
|
110
|
+
this.flushInternal(this.attachFlowBatch.popBatch());
|
|
111
|
+
this.flushInternal(this.mainBatch.popBatch());
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private flushInternal(rawBatch: IBatch) {
|
|
115
|
+
const processedBatch = this.compressBatch(rawBatch);
|
|
116
|
+
const clientSequenceNumber = this.sendBatch(processedBatch);
|
|
117
|
+
|
|
118
|
+
this.persistBatch(clientSequenceNumber, rawBatch.content);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private compressBatch(batch: IBatch): IBatch {
|
|
122
|
+
if (
|
|
123
|
+
batch.content.length === 0 ||
|
|
124
|
+
this.params.config.compressionOptions === undefined ||
|
|
125
|
+
this.params.config.compressionOptions.minimumBatchSizeInBytes > batch.contentSizeInBytes
|
|
126
|
+
) {
|
|
127
|
+
// Nothing to do if the batch is empty or if compression is disabled or if we don't need to compress
|
|
128
|
+
return batch;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const compressedBatch = this.params.compressor.compressBatch(batch);
|
|
132
|
+
if (compressedBatch.contentSizeInBytes <= this.params.config.maxBatchSizeInBytes) {
|
|
133
|
+
// If we don't reach the maximum supported size of a batch, it can safely be sent as is
|
|
134
|
+
return compressedBatch;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (this.params.splitter.isBatchChunkingEnabled) {
|
|
138
|
+
return this.params.splitter.splitCompressedBatch(compressedBatch);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// If we've reached this point, the runtime would attempt to send a batch larger than the allowed size
|
|
142
|
+
throw new GenericError("BatchTooLarge", /* error */ undefined, {
|
|
143
|
+
batchSize: batch.contentSizeInBytes,
|
|
144
|
+
compressedBatchSize: compressedBatch.contentSizeInBytes,
|
|
145
|
+
count: compressedBatch.content.length,
|
|
146
|
+
limit: this.params.config.maxBatchSizeInBytes,
|
|
147
|
+
chunkingEnabled: this.params.splitter.isBatchChunkingEnabled,
|
|
148
|
+
compressionOptions: JSON.stringify(this.params.config.compressionOptions),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Sends the batch object to the container context to be sent over the wire.
|
|
154
|
+
*
|
|
155
|
+
* @param batch - batch to be sent
|
|
156
|
+
* @returns the client sequence number of the last batched op which was sent and
|
|
157
|
+
* -1 if there are no ops or the container cannot send ops.
|
|
158
|
+
*/
|
|
159
|
+
private sendBatch(batch: IBatch): number {
|
|
160
|
+
let clientSequenceNumber: number = -1;
|
|
161
|
+
const length = batch.content.length;
|
|
162
|
+
|
|
163
|
+
// Did we disconnect in the middle of turn-based batch?
|
|
164
|
+
// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.
|
|
165
|
+
if (length === 0 || !this.params.shouldSend()) {
|
|
166
|
+
return clientSequenceNumber;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (this.params.containerContext.submitBatchFn === undefined) {
|
|
170
|
+
// Legacy path - supporting old loader versions. Can be removed only when LTS moves above
|
|
171
|
+
// version that has support for batches (submitBatchFn)
|
|
172
|
+
for (const message of batch.content) {
|
|
173
|
+
// Legacy path doesn't support compressed payloads and will submit uncompressed payload anyways
|
|
174
|
+
if (message.metadata?.compressed) {
|
|
175
|
+
delete message.metadata.compressed;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
clientSequenceNumber = this.params.containerContext.submitFn(
|
|
179
|
+
MessageType.Operation,
|
|
180
|
+
message.deserializedContent,
|
|
181
|
+
true, // batch
|
|
182
|
+
message.metadata,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
this.params.containerContext.deltaManager.flush();
|
|
187
|
+
} else {
|
|
188
|
+
// returns clientSequenceNumber of last message in a batch
|
|
189
|
+
clientSequenceNumber = this.params.containerContext.submitBatchFn(
|
|
190
|
+
batch.content.map((message) => ({
|
|
191
|
+
contents: message.contents,
|
|
192
|
+
metadata: message.metadata,
|
|
193
|
+
compression: message.compression,
|
|
194
|
+
})),
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Convert from clientSequenceNumber of last message in the batch to clientSequenceNumber of first message.
|
|
199
|
+
clientSequenceNumber -= length - 1;
|
|
200
|
+
assert(clientSequenceNumber >= 0, 0x3d0 /* clientSequenceNumber can't be negative */);
|
|
201
|
+
return clientSequenceNumber;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private persistBatch(initialClientSequenceNumber: number, batch: BatchMessage[]) {
|
|
205
|
+
let clientSequenceNumber = initialClientSequenceNumber;
|
|
206
|
+
// Let the PendingStateManager know that a message was submitted.
|
|
207
|
+
// In future, need to shift toward keeping batch as a whole!
|
|
208
|
+
for (const message of batch) {
|
|
209
|
+
this.params.pendingStateManager.onSubmitMessage(
|
|
210
|
+
message.deserializedContent.type,
|
|
211
|
+
clientSequenceNumber,
|
|
212
|
+
message.referenceSequenceNumber,
|
|
213
|
+
message.deserializedContent.contents,
|
|
214
|
+
message.localOpMetadata,
|
|
215
|
+
message.metadata,
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
clientSequenceNumber++;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
public checkpoint() {
|
|
223
|
+
return {
|
|
224
|
+
mainBatch: this.mainBatch.checkpoint(),
|
|
225
|
+
attachFlowBatch: this.attachFlowBatch.checkpoint(),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
218
228
|
}
|
|
@@ -9,61 +9,61 @@ import { OpDecompressor } from "./opDecompressor";
|
|
|
9
9
|
import { OpSplitter } from "./opSplitter";
|
|
10
10
|
|
|
11
11
|
export class RemoteMessageProcessor {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
constructor(
|
|
13
|
+
private readonly opSplitter: OpSplitter,
|
|
14
|
+
private readonly opDecompressor: OpDecompressor,
|
|
15
|
+
) {}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
public get partialMessages(): ReadonlyMap<string, string[]> {
|
|
18
|
+
return this.opSplitter.chunks;
|
|
19
|
+
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
public clearPartialMessagesFor(clientId: string) {
|
|
22
|
+
this.opSplitter.clearPartialChunks(clientId);
|
|
23
|
+
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
public process(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage {
|
|
26
|
+
let message = copy(remoteMessage);
|
|
27
|
+
message = this.opDecompressor.processMessage(message).message;
|
|
28
|
+
unpackRuntimeMessage(message);
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
+
}
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
const decompressionAfterChunking = this.opDecompressor.processMessage(message);
|
|
39
|
+
message = decompressionAfterChunking.message;
|
|
40
|
+
if (decompressionAfterChunking.state === "Skipped") {
|
|
41
|
+
// After chunking, if the original message was not compressed,
|
|
42
|
+
// there is no need to continue processing
|
|
43
|
+
return message;
|
|
44
|
+
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
// The message needs to be unpacked after chunking + decompression
|
|
47
|
+
unpack(message);
|
|
48
|
+
return message;
|
|
49
|
+
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
const copy = (remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
// Do shallow copy of message, as the processing flow will modify it.
|
|
54
|
+
// There might be multiple container instances receiving same message
|
|
55
|
+
// We do not need to make deep copy, as each layer will just replace message.content itself,
|
|
56
|
+
// but would not modify contents details
|
|
57
|
+
const message = { ...remoteMessage };
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
// back-compat: ADO #1385: eventually should become unconditional, but only for runtime messages!
|
|
60
|
+
// System message may have no contents, or in some cases (mostly for back-compat) they may have actual objects.
|
|
61
|
+
// Old ops may contain empty string (I assume noops).
|
|
62
|
+
if (typeof message.contents === "string" && message.contents !== "") {
|
|
63
|
+
message.contents = JSON.parse(message.contents);
|
|
64
|
+
}
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
return message;
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
/**
|
|
@@ -71,9 +71,9 @@ const copy = (remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessa
|
|
|
71
71
|
*
|
|
72
72
|
*/
|
|
73
73
|
const unpack = (message: ISequencedDocumentMessage) => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
const innerContents = message.contents as ContainerRuntimeMessage;
|
|
75
|
+
message.type = innerContents.type;
|
|
76
|
+
message.contents = innerContents.contents;
|
|
77
77
|
};
|
|
78
78
|
|
|
79
79
|
/**
|
|
@@ -86,21 +86,21 @@ const unpack = (message: ISequencedDocumentMessage) => {
|
|
|
86
86
|
* @internal
|
|
87
87
|
*/
|
|
88
88
|
export function unpackRuntimeMessage(message: ISequencedDocumentMessage): boolean {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
89
|
+
if (message.type !== MessageType.Operation) {
|
|
90
|
+
// Legacy format, but it's already "unpacked",
|
|
91
|
+
// i.e. message.type is actually ContainerMessageType.
|
|
92
|
+
// Or it's non-runtime message.
|
|
93
|
+
// Nothing to do in such case.
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
97
|
+
// legacy op format?
|
|
98
|
+
if (message.contents.address !== undefined && message.contents.type === undefined) {
|
|
99
|
+
message.type = ContainerMessageType.FluidDataStoreOp;
|
|
100
|
+
} else {
|
|
101
|
+
// new format
|
|
102
|
+
unpack(message);
|
|
103
|
+
}
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
return true;
|
|
106
106
|
}
|
package/src/opProperties.ts
CHANGED
|
@@ -3,17 +3,19 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
ISequencedDocumentMessage,
|
|
8
|
+
ISequencedDocumentSystemMessage,
|
|
9
|
+
} from "@fluidframework/protocol-definitions";
|
|
7
10
|
|
|
8
11
|
export const opSize = (op: ISequencedDocumentMessage): number => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return content.length + data.length;
|
|
12
|
+
// Some messages may already have string contents,
|
|
13
|
+
// so stringifying them again will add inaccurate overhead.
|
|
14
|
+
const content =
|
|
15
|
+
typeof op.contents === "string" ? op.contents : JSON.stringify(op.contents) ?? "";
|
|
16
|
+
const data = opHasData(op) ? op.data : "";
|
|
17
|
+
return content.length + data.length;
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
const opHasData = (op: ISequencedDocumentMessage): op is ISequencedDocumentSystemMessage =>
|
|
19
|
-
|
|
21
|
+
(op as ISequencedDocumentSystemMessage).data !== undefined;
|