@fluidframework/container-runtime 2.31.1 → 2.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/container-runtime.test-files.tar +0 -0
- package/dist/channelCollection.d.ts +0 -14
- package/dist/channelCollection.d.ts.map +1 -1
- package/dist/channelCollection.js +10 -25
- package/dist/channelCollection.js.map +1 -1
- package/dist/containerRuntime.d.ts +16 -9
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +137 -103
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts +1 -5
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +0 -8
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +3 -7
- package/dist/messageTypes.d.ts.map +1 -1
- package/dist/messageTypes.js.map +1 -1
- package/dist/opLifecycle/batchManager.d.ts +4 -4
- package/dist/opLifecycle/batchManager.d.ts.map +1 -1
- package/dist/opLifecycle/batchManager.js +4 -4
- package/dist/opLifecycle/batchManager.js.map +1 -1
- package/dist/opLifecycle/definitions.d.ts +40 -6
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/index.d.ts +4 -3
- package/dist/opLifecycle/index.d.ts.map +1 -1
- package/dist/opLifecycle/index.js +4 -3
- package/dist/opLifecycle/index.js.map +1 -1
- package/dist/opLifecycle/opCompressor.d.ts +10 -11
- package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opCompressor.js +19 -18
- package/dist/opLifecycle/opCompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts +9 -5
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +18 -22
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSerialization.d.ts +20 -0
- package/dist/opLifecycle/opSerialization.d.ts.map +1 -0
- package/dist/opLifecycle/opSerialization.js +40 -0
- package/dist/opLifecycle/opSerialization.js.map +1 -0
- package/dist/opLifecycle/opSplitter.d.ts +12 -13
- package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
- package/dist/opLifecycle/opSplitter.js +13 -13
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/outbox.d.ts +16 -18
- package/dist/opLifecycle/outbox.d.ts.map +1 -1
- package/dist/opLifecycle/outbox.js +57 -43
- package/dist/opLifecycle/outbox.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +0 -7
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +1 -15
- 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 +2 -2
- package/dist/pendingStateManager.d.ts.map +1 -1
- package/dist/pendingStateManager.js +1 -1
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/runtimeLayerCompatState.d.ts.map +1 -1
- package/dist/runtimeLayerCompatState.js +6 -5
- package/dist/runtimeLayerCompatState.js.map +1 -1
- package/dist/summary/index.d.ts +5 -8
- package/dist/summary/index.d.ts.map +1 -1
- package/dist/summary/index.js +20 -21
- package/dist/summary/index.js.map +1 -1
- package/dist/summary/orderedClientElection.js +9 -9
- package/dist/summary/orderedClientElection.js.map +1 -1
- package/dist/summary/summarizerClientElection.d.ts +0 -1
- package/dist/summary/summarizerClientElection.d.ts.map +1 -1
- package/dist/summary/summarizerClientElection.js +3 -3
- package/dist/summary/summarizerClientElection.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +3 -75
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js +2 -0
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/{lib/summary/summaryGenerator.d.ts → dist/summary/summarizerUtils.d.ts} +12 -43
- package/dist/summary/summarizerUtils.d.ts.map +1 -0
- package/dist/summary/summarizerUtils.js +71 -0
- package/dist/summary/summarizerUtils.js.map +1 -0
- package/dist/summary/summaryDelayLoadedModule/index.d.ts +10 -0
- package/dist/summary/summaryDelayLoadedModule/index.d.ts.map +1 -0
- package/dist/summary/summaryDelayLoadedModule/index.js +20 -0
- package/dist/summary/summaryDelayLoadedModule/index.js.map +1 -0
- package/dist/summary/{runWhileConnectedCoordinator.d.ts → summaryDelayLoadedModule/runWhileConnectedCoordinator.d.ts} +1 -1
- package/dist/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/dist/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.js.map +1 -0
- package/dist/summary/{runningSummarizer.d.ts → summaryDelayLoadedModule/runningSummarizer.d.ts} +4 -13
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -0
- package/dist/summary/{runningSummarizer.js → summaryDelayLoadedModule/runningSummarizer.js} +17 -24
- package/dist/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -0
- package/dist/summary/{summarizer.d.ts → summaryDelayLoadedModule/summarizer.d.ts} +13 -2
- package/dist/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -0
- package/dist/summary/{summarizer.js → summaryDelayLoadedModule/summarizer.js} +13 -3
- package/dist/summary/summaryDelayLoadedModule/summarizer.js.map +1 -0
- package/{lib/summary → dist/summary/summaryDelayLoadedModule}/summarizerHeuristics.d.ts +3 -3
- package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts.map +1 -0
- package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.js.map +1 -0
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.d.ts +36 -0
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.d.ts.map +1 -0
- package/dist/summary/{summaryGenerator.js → summaryDelayLoadedModule/summaryGenerator.js} +14 -99
- package/dist/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -0
- package/dist/summary/summaryDelayLoadedModule/summaryResultBuilder.d.ts +21 -0
- package/dist/summary/summaryDelayLoadedModule/summaryResultBuilder.d.ts.map +1 -0
- package/dist/summary/summaryDelayLoadedModule/summaryResultBuilder.js +44 -0
- package/dist/summary/summaryDelayLoadedModule/summaryResultBuilder.js.map +1 -0
- package/dist/summary/summaryDelayLoadedModule/summaryResultTypes.d.ts +80 -0
- package/dist/summary/summaryDelayLoadedModule/summaryResultTypes.d.ts.map +1 -0
- package/dist/summary/summaryDelayLoadedModule/summaryResultTypes.js +7 -0
- package/dist/summary/summaryDelayLoadedModule/summaryResultTypes.js.map +1 -0
- package/dist/summary/summaryHelpers.d.ts +1 -1
- package/dist/summary/summaryHelpers.d.ts.map +1 -1
- package/dist/summary/summaryHelpers.js +2 -2
- package/dist/summary/summaryHelpers.js.map +1 -1
- package/dist/summary/summaryManager.d.ts +4 -3
- package/dist/summary/summaryManager.d.ts.map +1 -1
- package/dist/summary/summaryManager.js +2 -2
- package/dist/summary/summaryManager.js.map +1 -1
- package/lib/channelCollection.d.ts +0 -14
- package/lib/channelCollection.d.ts.map +1 -1
- package/lib/channelCollection.js +6 -21
- package/lib/channelCollection.js.map +1 -1
- package/lib/containerRuntime.d.ts +16 -9
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +140 -106
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts +1 -5
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +0 -8
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/messageTypes.d.ts +3 -7
- package/lib/messageTypes.d.ts.map +1 -1
- package/lib/messageTypes.js.map +1 -1
- package/lib/opLifecycle/batchManager.d.ts +4 -4
- package/lib/opLifecycle/batchManager.d.ts.map +1 -1
- package/lib/opLifecycle/batchManager.js +4 -4
- package/lib/opLifecycle/batchManager.js.map +1 -1
- package/lib/opLifecycle/definitions.d.ts +40 -6
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/index.d.ts +4 -3
- package/lib/opLifecycle/index.d.ts.map +1 -1
- package/lib/opLifecycle/index.js +3 -2
- package/lib/opLifecycle/index.js.map +1 -1
- package/lib/opLifecycle/opCompressor.d.ts +10 -11
- package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opCompressor.js +20 -19
- package/lib/opLifecycle/opCompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts +9 -5
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +18 -22
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSerialization.d.ts +20 -0
- package/lib/opLifecycle/opSerialization.d.ts.map +1 -0
- package/lib/opLifecycle/opSerialization.js +35 -0
- package/lib/opLifecycle/opSerialization.js.map +1 -0
- package/lib/opLifecycle/opSplitter.d.ts +12 -13
- package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
- package/lib/opLifecycle/opSplitter.js +13 -13
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/outbox.d.ts +16 -18
- package/lib/opLifecycle/outbox.d.ts.map +1 -1
- package/lib/opLifecycle/outbox.js +56 -41
- package/lib/opLifecycle/outbox.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +0 -7
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +0 -13
- 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 +2 -2
- package/lib/pendingStateManager.d.ts.map +1 -1
- package/lib/pendingStateManager.js +1 -1
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/runtimeLayerCompatState.d.ts.map +1 -1
- package/lib/runtimeLayerCompatState.js +3 -2
- package/lib/runtimeLayerCompatState.js.map +1 -1
- package/lib/summary/index.d.ts +5 -8
- package/lib/summary/index.d.ts.map +1 -1
- package/lib/summary/index.js +5 -7
- package/lib/summary/index.js.map +1 -1
- package/lib/summary/orderedClientElection.js +1 -1
- package/lib/summary/orderedClientElection.js.map +1 -1
- package/lib/summary/summarizerClientElection.d.ts +0 -1
- package/lib/summary/summarizerClientElection.d.ts.map +1 -1
- package/lib/summary/summarizerClientElection.js +1 -1
- package/lib/summary/summarizerClientElection.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +3 -75
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/{dist/summary/summaryGenerator.d.ts → lib/summary/summarizerUtils.d.ts} +12 -43
- package/lib/summary/summarizerUtils.d.ts.map +1 -0
- package/lib/summary/summarizerUtils.js +64 -0
- package/lib/summary/summarizerUtils.js.map +1 -0
- package/lib/summary/summaryDelayLoadedModule/index.d.ts +10 -0
- package/lib/summary/summaryDelayLoadedModule/index.d.ts.map +1 -0
- package/lib/summary/summaryDelayLoadedModule/index.js +9 -0
- package/lib/summary/summaryDelayLoadedModule/index.js.map +1 -0
- package/lib/summary/{runWhileConnectedCoordinator.d.ts → summaryDelayLoadedModule/runWhileConnectedCoordinator.d.ts} +1 -1
- package/lib/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.d.ts.map +1 -0
- package/lib/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.js.map +1 -0
- package/lib/summary/{runningSummarizer.d.ts → summaryDelayLoadedModule/runningSummarizer.d.ts} +4 -13
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -0
- package/lib/summary/{runningSummarizer.js → summaryDelayLoadedModule/runningSummarizer.js} +5 -12
- package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -0
- package/lib/summary/{summarizer.d.ts → summaryDelayLoadedModule/summarizer.d.ts} +13 -2
- package/lib/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -0
- package/lib/summary/{summarizer.js → summaryDelayLoadedModule/summarizer.js} +11 -1
- package/lib/summary/summaryDelayLoadedModule/summarizer.js.map +1 -0
- package/{dist/summary → lib/summary/summaryDelayLoadedModule}/summarizerHeuristics.d.ts +3 -3
- package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts.map +1 -0
- package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.js.map +1 -0
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.d.ts +36 -0
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.d.ts.map +1 -0
- package/lib/summary/{summaryGenerator.js → summaryDelayLoadedModule/summaryGenerator.js} +4 -85
- package/lib/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -0
- package/lib/summary/summaryDelayLoadedModule/summaryResultBuilder.d.ts +21 -0
- package/lib/summary/summaryDelayLoadedModule/summaryResultBuilder.d.ts.map +1 -0
- package/lib/summary/summaryDelayLoadedModule/summaryResultBuilder.js +40 -0
- package/lib/summary/summaryDelayLoadedModule/summaryResultBuilder.js.map +1 -0
- package/lib/summary/summaryDelayLoadedModule/summaryResultTypes.d.ts +80 -0
- package/lib/summary/summaryDelayLoadedModule/summaryResultTypes.d.ts.map +1 -0
- package/lib/summary/summaryDelayLoadedModule/summaryResultTypes.js +6 -0
- package/lib/summary/summaryDelayLoadedModule/summaryResultTypes.js.map +1 -0
- package/lib/summary/summaryHelpers.d.ts +1 -1
- package/lib/summary/summaryHelpers.d.ts.map +1 -1
- package/lib/summary/summaryHelpers.js +1 -1
- package/lib/summary/summaryHelpers.js.map +1 -1
- package/lib/summary/summaryManager.d.ts +4 -3
- package/lib/summary/summaryManager.d.ts.map +1 -1
- package/lib/summary/summaryManager.js +2 -2
- package/lib/summary/summaryManager.js.map +1 -1
- package/package.json +20 -19
- package/src/channelCollection.ts +5 -20
- package/src/containerRuntime.ts +220 -178
- package/src/dataStoreContext.ts +0 -11
- package/src/index.ts +0 -1
- package/src/messageTypes.ts +5 -19
- package/src/opLifecycle/batchManager.ts +19 -12
- package/src/opLifecycle/definitions.ts +45 -6
- package/src/opLifecycle/index.ts +14 -3
- package/src/opLifecycle/opCompressor.ts +25 -24
- package/src/opLifecycle/opGroupingManager.ts +27 -26
- package/src/opLifecycle/opSerialization.ts +46 -0
- package/src/opLifecycle/opSplitter.ts +20 -16
- package/src/opLifecycle/outbox.ts +101 -66
- package/src/opLifecycle/remoteMessageProcessor.ts +0 -17
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +3 -3
- package/src/runtimeLayerCompatState.ts +3 -2
- package/src/summary/index.ts +35 -31
- package/src/summary/orderedClientElection.ts +1 -1
- package/src/summary/summarizerClientElection.ts +1 -2
- package/src/summary/summarizerTypes.ts +7 -91
- package/src/summary/summarizerUtils.ts +132 -0
- package/src/summary/summaryDelayLoadedModule/index.ts +28 -0
- package/src/summary/{runWhileConnectedCoordinator.ts → summaryDelayLoadedModule/runWhileConnectedCoordinator.ts} +1 -1
- package/src/summary/{runningSummarizer.ts → summaryDelayLoadedModule/runningSummarizer.ts} +13 -28
- package/src/summary/{summarizer.ts → summaryDelayLoadedModule/summarizer.ts} +19 -8
- package/src/summary/{summarizerHeuristics.ts → summaryDelayLoadedModule/summarizerHeuristics.ts} +3 -3
- package/src/summary/{summaryGenerator.ts → summaryDelayLoadedModule/summaryGenerator.ts} +13 -179
- package/src/summary/summaryDelayLoadedModule/summaryResultBuilder.ts +70 -0
- package/src/summary/summaryDelayLoadedModule/summaryResultTypes.ts +100 -0
- package/src/summary/summaryHelpers.ts +6 -6
- package/src/summary/summaryManager.ts +8 -6
- package/dist/summary/runWhileConnectedCoordinator.d.ts.map +0 -1
- package/dist/summary/runWhileConnectedCoordinator.js.map +0 -1
- package/dist/summary/runningSummarizer.d.ts.map +0 -1
- package/dist/summary/runningSummarizer.js.map +0 -1
- package/dist/summary/summarizer.d.ts.map +0 -1
- package/dist/summary/summarizer.js.map +0 -1
- package/dist/summary/summarizerHeuristics.d.ts.map +0 -1
- package/dist/summary/summarizerHeuristics.js.map +0 -1
- package/dist/summary/summaryGenerator.d.ts.map +0 -1
- package/dist/summary/summaryGenerator.js.map +0 -1
- package/lib/summary/runWhileConnectedCoordinator.d.ts.map +0 -1
- package/lib/summary/runWhileConnectedCoordinator.js.map +0 -1
- package/lib/summary/runningSummarizer.d.ts.map +0 -1
- package/lib/summary/runningSummarizer.js.map +0 -1
- package/lib/summary/summarizer.d.ts.map +0 -1
- package/lib/summary/summarizer.js.map +0 -1
- package/lib/summary/summarizerHeuristics.d.ts.map +0 -1
- package/lib/summary/summarizerHeuristics.js.map +0 -1
- package/lib/summary/summaryGenerator.d.ts.map +0 -1
- package/lib/summary/summaryGenerator.js.map +0 -1
- /package/dist/summary/{runWhileConnectedCoordinator.js → summaryDelayLoadedModule/runWhileConnectedCoordinator.js} +0 -0
- /package/dist/summary/{summarizerHeuristics.js → summaryDelayLoadedModule/summarizerHeuristics.js} +0 -0
- /package/lib/summary/{runWhileConnectedCoordinator.js → summaryDelayLoadedModule/runWhileConnectedCoordinator.js} +0 -0
- /package/lib/summary/{summarizerHeuristics.js → summaryDelayLoadedModule/summarizerHeuristics.js} +0 -0
|
@@ -4,18 +4,10 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.Outbox = exports.getLongStack =
|
|
7
|
+
exports.Outbox = exports.getLongStack = void 0;
|
|
8
8
|
const internal_1 = require("@fluidframework/core-utils/internal");
|
|
9
9
|
const internal_2 = require("@fluidframework/telemetry-utils/internal");
|
|
10
10
|
const batchManager_js_1 = require("./batchManager.js");
|
|
11
|
-
/**
|
|
12
|
-
* Before submitting an op to the Outbox, its contents must be serialized using this function.
|
|
13
|
-
* @remarks - The deserialization on process happens via the function {@link ensureContentsDeserialized}.
|
|
14
|
-
*/
|
|
15
|
-
function serializeOpContents(contents) {
|
|
16
|
-
return JSON.stringify(contents);
|
|
17
|
-
}
|
|
18
|
-
exports.serializeOpContents = serializeOpContents;
|
|
19
11
|
/**
|
|
20
12
|
* Temporarily increase the stack limit while executing the provided action.
|
|
21
13
|
* If a negative value is provided for `length`, no stack frames will be collected.
|
|
@@ -176,7 +168,7 @@ class Outbox {
|
|
|
176
168
|
addMessageToBatchManager(batchManager, message) {
|
|
177
169
|
if (!batchManager.push(message, this.isContextReentrant(), this.params.getCurrentSequenceNumbers().clientSequenceNumber)) {
|
|
178
170
|
throw new internal_2.GenericError("BatchTooLarge", /* error */ undefined, {
|
|
179
|
-
opSize: message.
|
|
171
|
+
opSize: message.serializedOp?.length ?? 0,
|
|
180
172
|
batchSize: batchManager.contentSizeInBytes,
|
|
181
173
|
count: batchManager.length,
|
|
182
174
|
limit: batchManager.options.hardLimit,
|
|
@@ -186,15 +178,13 @@ class Outbox {
|
|
|
186
178
|
/**
|
|
187
179
|
* Flush all the batches to the ordering service.
|
|
188
180
|
* This method is expected to be called at the end of a batch.
|
|
181
|
+
*
|
|
182
|
+
* @throws If called from a reentrant context, or if the batch being flushed is too large.
|
|
189
183
|
* @param resubmittingBatchId - If defined, indicates this is a resubmission of a batch
|
|
190
184
|
* with the given Batch ID, which must be preserved
|
|
191
185
|
*/
|
|
192
186
|
flush(resubmittingBatchId) {
|
|
193
|
-
|
|
194
|
-
const error = new internal_2.UsageError("Flushing is not supported inside DDS event handlers");
|
|
195
|
-
this.params.closeContainer(error);
|
|
196
|
-
throw error;
|
|
197
|
-
}
|
|
187
|
+
(0, internal_1.assert)(!this.isContextReentrant(), 0xb7b /* Flushing must not happen while incoming changes are being processed */);
|
|
198
188
|
this.flushAll(resubmittingBatchId);
|
|
199
189
|
}
|
|
200
190
|
flushAll(resubmittingBatchId) {
|
|
@@ -219,12 +209,13 @@ class Outbox {
|
|
|
219
209
|
flushEmptyBatch(resubmittingBatchId) {
|
|
220
210
|
const referenceSequenceNumber = this.params.getCurrentSequenceNumbers().referenceSequenceNumber;
|
|
221
211
|
(0, internal_1.assert)(referenceSequenceNumber !== undefined, 0xa01 /* reference sequence number should be defined */);
|
|
222
|
-
const
|
|
212
|
+
const { outboundBatch, placeholderMessage } = this.params.groupingManager.createEmptyGroupedBatch(resubmittingBatchId, referenceSequenceNumber);
|
|
223
213
|
let clientSequenceNumber;
|
|
224
214
|
if (this.params.shouldSend()) {
|
|
225
|
-
clientSequenceNumber = this.sendBatch(
|
|
215
|
+
clientSequenceNumber = this.sendBatch(outboundBatch);
|
|
226
216
|
}
|
|
227
|
-
|
|
217
|
+
// Push the empty batch placeholder to the PendingStateManager
|
|
218
|
+
this.params.pendingStateManager.onFlushBatch([{ ...placeholderMessage, serializedOp: "", contents: undefined }], // placeholder message - serializedOp will never be used
|
|
228
219
|
clientSequenceNumber);
|
|
229
220
|
return;
|
|
230
221
|
}
|
|
@@ -233,8 +224,13 @@ class Outbox {
|
|
|
233
224
|
return;
|
|
234
225
|
}
|
|
235
226
|
const rawBatch = batchManager.popBatch(resubmittingBatchId);
|
|
236
|
-
const
|
|
237
|
-
if (batchManager.options.canRebase &&
|
|
227
|
+
const groupingEnabled = !disableGroupedBatching && this.params.groupingManager.groupedBatchingEnabled();
|
|
228
|
+
if (batchManager.options.canRebase &&
|
|
229
|
+
rawBatch.hasReentrantOps === true &&
|
|
230
|
+
// NOTE: This is too restrictive. We should rebase for any reentrant op, not just if it's going to be a grouped batch
|
|
231
|
+
// However there is some test that is depending on this behavior so we haven't removed these conditions yet. See AB#33427
|
|
232
|
+
groupingEnabled &&
|
|
233
|
+
rawBatch.messages.length > 1) {
|
|
238
234
|
(0, internal_1.assert)(!this.rebasing, 0x6fa /* A rebased batch should never have reentrant ops */);
|
|
239
235
|
// If a batch contains reentrant ops (ops created as a result from processing another op)
|
|
240
236
|
// it needs to be rebased so that we can ensure consistent reference sequence numbers
|
|
@@ -247,10 +243,8 @@ class Outbox {
|
|
|
247
243
|
// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.
|
|
248
244
|
// Because flush() is a task that executes async (on clean stack), we can get here in disconnected state.
|
|
249
245
|
if (this.params.shouldSend()) {
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
: this.compressAndChunkBatch(shouldGroup ? this.params.groupingManager.groupBatch(rawBatch) : rawBatch);
|
|
253
|
-
clientSequenceNumber = this.sendBatch(processedBatch);
|
|
246
|
+
const virtualizedBatch = this.virtualizeBatch(rawBatch, groupingEnabled);
|
|
247
|
+
clientSequenceNumber = this.sendBatch(virtualizedBatch);
|
|
254
248
|
(0, internal_1.assert)(clientSequenceNumber === undefined || clientSequenceNumber >= 0, 0x9d2 /* unexpected negative clientSequenceNumber (empty batch should yield undefined) */);
|
|
255
249
|
}
|
|
256
250
|
this.params.pendingStateManager.onFlushBatch(rawBatch.messages, clientSequenceNumber, batchManager.options.ignoreBatchId);
|
|
@@ -267,8 +261,7 @@ class Outbox {
|
|
|
267
261
|
this.rebasing = true;
|
|
268
262
|
for (const message of rawBatch.messages) {
|
|
269
263
|
this.params.reSubmit({
|
|
270
|
-
|
|
271
|
-
content: message.contents,
|
|
264
|
+
content: message.serializedOp,
|
|
272
265
|
localOpMetadata: message.localOpMetadata,
|
|
273
266
|
opMetadata: message.metadata,
|
|
274
267
|
});
|
|
@@ -288,39 +281,60 @@ class Outbox {
|
|
|
288
281
|
return this.params.opReentrancy() && !this.rebasing;
|
|
289
282
|
}
|
|
290
283
|
/**
|
|
291
|
-
* As necessary and enabled, compresses
|
|
284
|
+
* As necessary and enabled, groups / compresses / chunks the given batch.
|
|
292
285
|
*
|
|
293
286
|
* @remarks - If chunking happens, a side effect here is that 1 or more chunks are queued immediately for sending in next JS turn.
|
|
294
287
|
*
|
|
295
|
-
* @param
|
|
296
|
-
* @
|
|
297
|
-
*
|
|
288
|
+
* @param localBatch - Local Batch to be virtualized - i.e. transformed into an Outbound Batch
|
|
289
|
+
* @param groupingEnabled - If true, Grouped batching is enabled.
|
|
290
|
+
* @returns One of the following:
|
|
291
|
+
* - (A) The original batch (Based on what's enabled)
|
|
292
|
+
* - (B) A grouped batch (it's a singleton batch)
|
|
293
|
+
* - (C) A compressed singleton batch
|
|
294
|
+
* - (D) A singleton batch containing the last chunk.
|
|
298
295
|
*/
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
296
|
+
virtualizeBatch(localBatch, groupingEnabled) {
|
|
297
|
+
// Shallow copy the local batch, updating the messages to be outbound messages
|
|
298
|
+
const originalBatch = {
|
|
299
|
+
...localBatch,
|
|
300
|
+
messages: localBatch.messages.map(({ serializedOp, ...message }) => ({
|
|
301
|
+
contents: serializedOp,
|
|
302
|
+
...message,
|
|
303
|
+
})),
|
|
304
|
+
};
|
|
305
|
+
const originalOrGroupedBatch = groupingEnabled
|
|
306
|
+
? this.params.groupingManager.groupBatch(originalBatch)
|
|
307
|
+
: originalBatch;
|
|
308
|
+
if (originalOrGroupedBatch.messages.length !== 1) {
|
|
309
|
+
// Compression requires a single message, so return early otherwise.
|
|
310
|
+
return originalOrGroupedBatch;
|
|
311
|
+
}
|
|
312
|
+
// Regardless of whether we grouped or not, we now have a batch with a single message.
|
|
313
|
+
// Now proceed to compress/chunk it if necessary.
|
|
314
|
+
const singletonBatch = originalOrGroupedBatch;
|
|
315
|
+
if (this.params.config.compressionOptions === undefined ||
|
|
302
316
|
this.params.config.compressionOptions.minimumBatchSizeInBytes >
|
|
303
|
-
|
|
304
|
-
this.params.submitBatchFn === undefined
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
return batch;
|
|
317
|
+
singletonBatch.contentSizeInBytes ||
|
|
318
|
+
this.params.submitBatchFn === undefined) {
|
|
319
|
+
// Nothing to do if compression is disabled, unnecessary or unsupported.
|
|
320
|
+
return singletonBatch;
|
|
308
321
|
}
|
|
309
|
-
const compressedBatch = this.params.compressor.compressBatch(
|
|
322
|
+
const compressedBatch = this.params.compressor.compressBatch(singletonBatch);
|
|
310
323
|
if (this.params.splitter.isBatchChunkingEnabled) {
|
|
311
324
|
return compressedBatch.contentSizeInBytes <= this.params.splitter.chunkSizeInBytes
|
|
312
325
|
? compressedBatch
|
|
313
|
-
: this.params.splitter.
|
|
326
|
+
: this.params.splitter.splitSingletonBatchMessage(compressedBatch);
|
|
314
327
|
}
|
|
315
328
|
if (compressedBatch.contentSizeInBytes >= this.params.config.maxBatchSizeInBytes) {
|
|
316
|
-
throw
|
|
317
|
-
|
|
329
|
+
throw internal_2.DataProcessingError.create("BatchTooLarge", "compressionInsufficient",
|
|
330
|
+
/* sequencedMessage */ undefined, {
|
|
331
|
+
batchSize: singletonBatch.contentSizeInBytes,
|
|
318
332
|
compressedBatchSize: compressedBatch.contentSizeInBytes,
|
|
319
333
|
count: compressedBatch.messages.length,
|
|
320
334
|
limit: this.params.config.maxBatchSizeInBytes,
|
|
321
335
|
chunkingEnabled: this.params.splitter.isBatchChunkingEnabled,
|
|
322
336
|
compressionOptions: JSON.stringify(this.params.config.compressionOptions),
|
|
323
|
-
socketSize: (0, batchManager_js_1.estimateSocketSize)(
|
|
337
|
+
socketSize: (0, batchManager_js_1.estimateSocketSize)(singletonBatch),
|
|
324
338
|
});
|
|
325
339
|
}
|
|
326
340
|
return compressedBatch;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ICriticalContainerError } from \"@fluidframework/container-definitions\";\nimport { IBatchMessage } from \"@fluidframework/container-definitions/internal\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert, Lazy } from \"@fluidframework/core-utils/internal\";\nimport {\n\tDataProcessingError,\n\tGenericError,\n\tUsageError,\n\tcreateChildLogger,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { ICompressionRuntimeOptions } from \"../containerRuntime.js\";\nimport { OutboundContainerRuntimeMessage } from \"../messageTypes.js\";\nimport { PendingMessageResubmitData, PendingStateManager } from \"../pendingStateManager.js\";\n\nimport {\n\tBatchManager,\n\tBatchSequenceNumbers,\n\testimateSocketSize,\n\tsequenceNumbersMatch,\n\ttype BatchId,\n} from \"./batchManager.js\";\nimport { BatchMessage, IBatch, IBatchCheckpoint } from \"./definitions.js\";\nimport { OpCompressor } from \"./opCompressor.js\";\nimport { OpGroupingManager } from \"./opGroupingManager.js\";\nimport { OpSplitter } from \"./opSplitter.js\";\n// eslint-disable-next-line unused-imports/no-unused-imports -- Used by \"@link\" comment annotation below\nimport { ensureContentsDeserialized } from \"./remoteMessageProcessor.js\";\n\nexport interface IOutboxConfig {\n\treadonly compressionOptions: ICompressionRuntimeOptions;\n\t/**\n\t * The maximum size of a batch that we can send over the wire.\n\t */\n\treadonly maxBatchSizeInBytes: number;\n\t/**\n\t * If true, maybeFlushPartialBatch will flush the batch if the reference sequence number changed\n\t * since the batch started. Otherwise, it will throw in this case (apart from reentrancy which is handled elsewhere).\n\t * Once the new throw-based flow is proved in a production environment, this option will be removed.\n\t */\n\treadonly flushPartialBatches: boolean;\n}\n\nexport interface IOutboxParameters {\n\treadonly shouldSend: () => boolean;\n\treadonly pendingStateManager: PendingStateManager;\n\treadonly submitBatchFn:\n\t\t| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)\n\t\t| undefined;\n\treadonly legacySendBatchFn: (batch: IBatch) => number;\n\treadonly config: IOutboxConfig;\n\treadonly compressor: OpCompressor;\n\treadonly splitter: OpSplitter;\n\treadonly logger: ITelemetryBaseLogger;\n\treadonly groupingManager: OpGroupingManager;\n\treadonly getCurrentSequenceNumbers: () => BatchSequenceNumbers;\n\treadonly reSubmit: (message: PendingMessageResubmitData) => void;\n\treadonly opReentrancy: () => boolean;\n\treadonly closeContainer: (error?: ICriticalContainerError) => void;\n}\n\n/**\n * Before submitting an op to the Outbox, its contents must be serialized using this function.\n * @remarks - The deserialization on process happens via the function {@link ensureContentsDeserialized}.\n */\nexport function serializeOpContents(contents: OutboundContainerRuntimeMessage): string {\n\treturn JSON.stringify(contents);\n}\n\n/**\n * Temporarily increase the stack limit while executing the provided action.\n * If a negative value is provided for `length`, no stack frames will be collected.\n * If Infinity is provided, all frames will be collected.\n *\n * ADO:4663 - add this to the common packages.\n *\n * @param action - action which returns an error\n * @param length - number of stack frames to collect, 50 if unspecified.\n * @returns the result of the action provided\n */\nexport function getLongStack<T>(action: () => T, length: number = 50): T {\n\t// TODO: better typing here\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment\n\tconst errorObj = Error as any;\n\tif (\n\t\t/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */\n\t\t// ?? is not logically equivalent when the first clause returns false.\n\t\t(\n\t\t\tObject.getOwnPropertyDescriptor(errorObj, \"stackTraceLimit\") ||\n\t\t\tObject.getOwnPropertyDescriptor(Object.getPrototypeOf(errorObj), \"stackTraceLimit\")\n\t\t)?.writable !== true\n\t\t/* eslint-enable @typescript-eslint/prefer-nullish-coalescing */\n\t) {\n\t\treturn action();\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\tconst originalStackTraceLimit = errorObj.stackTraceLimit;\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\terrorObj.stackTraceLimit = length;\n\t\treturn action();\n\t} finally {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\t\terrorObj.stackTraceLimit = originalStackTraceLimit;\n\t}\n}\n\n/**\n * The Outbox collects messages submitted by the ContainerRuntime into a batch,\n * and then flushes the batch when requested.\n *\n * @remarks There are actually multiple independent batches (some are for a specific message type),\n * to support slight variation in semantics for each batch (e.g. support for rebasing or grouping).\n */\nexport class Outbox {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate readonly mainBatch: BatchManager;\n\tprivate readonly blobAttachBatch: BatchManager;\n\tprivate readonly idAllocationBatch: BatchManager;\n\tprivate batchRebasesToReport = 5;\n\tprivate rebasing = false;\n\n\t/**\n\t * Track the number of ops which were detected to have a mismatched\n\t * reference sequence number, in order to self-throttle the telemetry events.\n\t *\n\t * This should be removed as part of ADO:2322\n\t */\n\tprivate readonly maxMismatchedOpsToReport = 3;\n\tprivate mismatchedOpsReported = 0;\n\n\tconstructor(private readonly params: IOutboxParameters) {\n\t\tthis.logger = createChildLogger({ logger: params.logger, namespace: \"Outbox\" });\n\n\t\tconst isCompressionEnabled =\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes !==\n\t\t\tNumber.POSITIVE_INFINITY;\n\t\t// We need to allow infinite size batches if we enable compression\n\t\tconst hardLimit = isCompressionEnabled\n\t\t\t? Number.POSITIVE_INFINITY\n\t\t\t: this.params.config.maxBatchSizeInBytes;\n\n\t\tthis.mainBatch = new BatchManager({ hardLimit, canRebase: true });\n\t\tthis.blobAttachBatch = new BatchManager({ hardLimit, canRebase: true });\n\t\tthis.idAllocationBatch = new BatchManager({\n\t\t\thardLimit,\n\t\t\tcanRebase: false,\n\t\t\tignoreBatchId: true,\n\t\t});\n\t}\n\n\tpublic get messageCount(): number {\n\t\treturn this.mainBatch.length + this.blobAttachBatch.length + this.idAllocationBatch.length;\n\t}\n\n\tpublic get mainBatchMessageCount(): number {\n\t\treturn this.mainBatch.length;\n\t}\n\n\tpublic get blobAttachBatchMessageCount(): number {\n\t\treturn this.blobAttachBatch.length;\n\t}\n\n\tpublic get idAllocationBatchMessageCount(): number {\n\t\treturn this.idAllocationBatch.length;\n\t}\n\n\tpublic get isEmpty(): boolean {\n\t\treturn this.messageCount === 0;\n\t}\n\n\t/**\n\t * Detect whether batching has been interrupted by an incoming message being processed. In this case,\n\t * we will flush the accumulated messages to account for that (if allowed) and create a new batch with the new\n\t * message as the first message. If flushing partial batch is not enabled, we will throw (except for reentrant ops).\n\t * This would indicate we expected this case to be precluded by logic elsewhere.\n\t *\n\t * @remarks - To detect batch interruption, we compare both the reference sequence number\n\t * (i.e. last message processed by DeltaManager) and the client sequence number of the\n\t * last message processed by the ContainerRuntime. In the absence of op reentrancy, this\n\t * pair will remain stable during a single JS turn during which the batch is being built up.\n\t */\n\tprivate maybeFlushPartialBatch(): void {\n\t\tconst mainBatchSeqNums = this.mainBatch.sequenceNumbers;\n\t\tconst blobAttachSeqNums = this.blobAttachBatch.sequenceNumbers;\n\t\tconst idAllocSeqNums = this.idAllocationBatch.sequenceNumbers;\n\t\tassert(\n\t\t\tsequenceNumbersMatch(mainBatchSeqNums, blobAttachSeqNums) &&\n\t\t\t\tsequenceNumbersMatch(mainBatchSeqNums, idAllocSeqNums),\n\t\t\t0x58d /* Reference sequence numbers from both batches must be in sync */,\n\t\t);\n\n\t\tconst currentSequenceNumbers = this.params.getCurrentSequenceNumbers();\n\n\t\tif (\n\t\t\tsequenceNumbersMatch(mainBatchSeqNums, currentSequenceNumbers) &&\n\t\t\tsequenceNumbersMatch(blobAttachSeqNums, currentSequenceNumbers) &&\n\t\t\tsequenceNumbersMatch(idAllocSeqNums, currentSequenceNumbers)\n\t\t) {\n\t\t\t// The reference sequence numbers are stable, there is nothing to do\n\t\t\treturn;\n\t\t}\n\n\t\t// Reference and/or Client sequence number will be advancing while processing this batch,\n\t\t// so we can't use this check to detect wrongdoing. But we will still log via telemetry.\n\t\t// This is rare, and the reentrancy will be handled during Flush.\n\t\tconst expectedDueToReentrancy = this.isContextReentrant();\n\n\t\tconst errorWrapper = new Lazy(() =>\n\t\t\tgetLongStack(() =>\n\t\t\t\tDataProcessingError.create(\n\t\t\t\t\t\"Sequence numbers advanced as if ops were processed while a batch is accumulating\",\n\t\t\t\t\t\"outboxSequenceNumberCoherencyCheck\",\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t\tif (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\t// Only log error if this is truly unexpected\n\t\t\t\t\tcategory:\n\t\t\t\t\t\texpectedDueToReentrancy || this.params.config.flushPartialBatches\n\t\t\t\t\t\t\t? \"generic\"\n\t\t\t\t\t\t\t: \"error\",\n\t\t\t\t\teventName: \"ReferenceSequenceNumberMismatch\",\n\t\t\t\t\tData_details: {\n\t\t\t\t\t\texpectedDueToReentrancy,\n\t\t\t\t\t\tmainReferenceSequenceNumber: mainBatchSeqNums.referenceSequenceNumber,\n\t\t\t\t\t\tmainClientSequenceNumber: mainBatchSeqNums.clientSequenceNumber,\n\t\t\t\t\t\tblobAttachReferenceSequenceNumber: blobAttachSeqNums.referenceSequenceNumber,\n\t\t\t\t\t\tblobAttachClientSequenceNumber: blobAttachSeqNums.clientSequenceNumber,\n\t\t\t\t\t\tcurrentReferenceSequenceNumber: currentSequenceNumbers.referenceSequenceNumber,\n\t\t\t\t\t\tcurrentClientSequenceNumber: currentSequenceNumbers.clientSequenceNumber,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\terrorWrapper.value,\n\t\t\t);\n\t\t}\n\n\t\t// If we're configured to flush partial batches, do that now and return (don't throw)\n\t\tif (this.params.config.flushPartialBatches) {\n\t\t\tthis.flushAll();\n\t\t\treturn;\n\t\t}\n\n\t\t// If we are in a reentrant context, we know this can happen without causing any harm.\n\t\tif (expectedDueToReentrancy) {\n\t\t\treturn;\n\t\t}\n\n\t\tthrow errorWrapper.value;\n\t}\n\n\tpublic submit(message: BatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.mainBatch, message);\n\t}\n\n\tpublic submitBlobAttach(message: BatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.blobAttachBatch, message);\n\t}\n\n\tpublic submitIdAllocation(message: BatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.idAllocationBatch, message);\n\t}\n\n\tprivate addMessageToBatchManager(batchManager: BatchManager, message: BatchMessage): void {\n\t\tif (\n\t\t\t!batchManager.push(\n\t\t\t\tmessage,\n\t\t\t\tthis.isContextReentrant(),\n\t\t\t\tthis.params.getCurrentSequenceNumbers().clientSequenceNumber,\n\t\t\t)\n\t\t) {\n\t\t\tthrow new GenericError(\"BatchTooLarge\", /* error */ undefined, {\n\t\t\t\topSize: message.contents?.length ?? 0,\n\t\t\t\tbatchSize: batchManager.contentSizeInBytes,\n\t\t\t\tcount: batchManager.length,\n\t\t\t\tlimit: batchManager.options.hardLimit,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Flush all the batches to the ordering service.\n\t * This method is expected to be called at the end of a batch.\n\t * @param resubmittingBatchId - If defined, indicates this is a resubmission of a batch\n\t * with the given Batch ID, which must be preserved\n\t */\n\tpublic flush(resubmittingBatchId?: BatchId): void {\n\t\tif (this.isContextReentrant()) {\n\t\t\tconst error = new UsageError(\"Flushing is not supported inside DDS event handlers\");\n\t\t\tthis.params.closeContainer(error);\n\t\t\tthrow error;\n\t\t}\n\n\t\tthis.flushAll(resubmittingBatchId);\n\t}\n\n\tprivate flushAll(resubmittingBatchId?: BatchId): void {\n\t\tconst allBatchesEmpty =\n\t\t\tthis.idAllocationBatch.empty && this.blobAttachBatch.empty && this.mainBatch.empty;\n\t\tif (allBatchesEmpty) {\n\t\t\t// If we're resubmitting and all batches are empty, we need to flush an empty batch.\n\t\t\t// Note that we currently resubmit one batch at a time, so on resubmit, 2 of the 3 batches will *always* be empty.\n\t\t\t// It's theoretically possible that we don't *need* to resubmit this empty batch, and in those cases, it'll safely be ignored\n\t\t\t// by the rest of the system, including remote clients.\n\t\t\t// In some cases we *must* resubmit the empty batch (to match up with a non-empty version tracked locally by a container fork), so we do it always.\n\t\t\tif (resubmittingBatchId) {\n\t\t\t\tthis.flushEmptyBatch(resubmittingBatchId);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Don't use resubmittingBatchId for idAllocationBatch.\n\t\t// ID Allocation messages are not directly resubmitted so we don't want to reuse the batch ID.\n\t\tthis.flushInternal(this.idAllocationBatch);\n\t\tthis.flushInternal(\n\t\t\tthis.blobAttachBatch,\n\t\t\ttrue /* disableGroupedBatching */,\n\t\t\tresubmittingBatchId,\n\t\t);\n\t\tthis.flushInternal(\n\t\t\tthis.mainBatch,\n\t\t\tfalse /* disableGroupedBatching */,\n\t\t\tresubmittingBatchId,\n\t\t);\n\t}\n\n\tprivate flushEmptyBatch(resubmittingBatchId: BatchId): void {\n\t\tconst referenceSequenceNumber =\n\t\t\tthis.params.getCurrentSequenceNumbers().referenceSequenceNumber;\n\t\tassert(\n\t\t\treferenceSequenceNumber !== undefined,\n\t\t\t0xa01 /* reference sequence number should be defined */,\n\t\t);\n\t\tconst emptyGroupedBatch = this.params.groupingManager.createEmptyGroupedBatch(\n\t\t\tresubmittingBatchId,\n\t\t\treferenceSequenceNumber,\n\t\t);\n\t\tlet clientSequenceNumber: number | undefined;\n\t\tif (this.params.shouldSend()) {\n\t\t\tclientSequenceNumber = this.sendBatch(emptyGroupedBatch);\n\t\t}\n\t\tthis.params.pendingStateManager.onFlushBatch(\n\t\t\temptyGroupedBatch.messages, // This is the single empty Grouped Batch message\n\t\t\tclientSequenceNumber,\n\t\t);\n\t\treturn;\n\t}\n\n\tprivate flushInternal(\n\t\tbatchManager: BatchManager,\n\t\tdisableGroupedBatching: boolean = false,\n\t\tresubmittingBatchId?: BatchId,\n\t): void {\n\t\tif (batchManager.empty) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rawBatch = batchManager.popBatch(resubmittingBatchId);\n\t\tconst shouldGroup =\n\t\t\t!disableGroupedBatching && this.params.groupingManager.shouldGroup(rawBatch);\n\t\tif (batchManager.options.canRebase && rawBatch.hasReentrantOps === true && shouldGroup) {\n\t\t\tassert(!this.rebasing, 0x6fa /* A rebased batch should never have reentrant ops */);\n\t\t\t// If a batch contains reentrant ops (ops created as a result from processing another op)\n\t\t\t// it needs to be rebased so that we can ensure consistent reference sequence numbers\n\t\t\t// and eventual consistency at the DDS level.\n\t\t\tthis.rebase(rawBatch, batchManager);\n\t\t\treturn;\n\t\t}\n\n\t\tlet clientSequenceNumber: number | undefined;\n\t\t// Did we disconnect? (i.e. is shouldSend false?)\n\t\t// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.\n\t\t// Because flush() is a task that executes async (on clean stack), we can get here in disconnected state.\n\t\tif (this.params.shouldSend()) {\n\t\t\tconst processedBatch = disableGroupedBatching\n\t\t\t\t? rawBatch\n\t\t\t\t: this.compressAndChunkBatch(\n\t\t\t\t\t\tshouldGroup ? this.params.groupingManager.groupBatch(rawBatch) : rawBatch,\n\t\t\t\t\t);\n\t\t\tclientSequenceNumber = this.sendBatch(processedBatch);\n\t\t\tassert(\n\t\t\t\tclientSequenceNumber === undefined || clientSequenceNumber >= 0,\n\t\t\t\t0x9d2 /* unexpected negative clientSequenceNumber (empty batch should yield undefined) */,\n\t\t\t);\n\t\t}\n\n\t\tthis.params.pendingStateManager.onFlushBatch(\n\t\t\trawBatch.messages,\n\t\t\tclientSequenceNumber,\n\t\t\tbatchManager.options.ignoreBatchId,\n\t\t);\n\t}\n\n\t/**\n\t * Rebases a batch. All the ops in the batch are resubmitted to the runtime and\n\t * they will end up back in the same batch manager they were flushed from and subsequently flushed.\n\t *\n\t * @param rawBatch - the batch to be rebased\n\t */\n\tprivate rebase(rawBatch: IBatch, batchManager: BatchManager): void {\n\t\tassert(!this.rebasing, 0x6fb /* Reentrancy */);\n\t\tassert(batchManager.options.canRebase, 0x9a7 /* BatchManager does not support rebase */);\n\n\t\tthis.rebasing = true;\n\t\tfor (const message of rawBatch.messages) {\n\t\t\tthis.params.reSubmit({\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tcontent: message.contents!,\n\t\t\t\tlocalOpMetadata: message.localOpMetadata,\n\t\t\t\topMetadata: message.metadata,\n\t\t\t});\n\t\t}\n\n\t\tif (this.batchRebasesToReport > 0) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: \"BatchRebase\",\n\t\t\t\t\tlength: rawBatch.messages.length,\n\t\t\t\t\treferenceSequenceNumber: rawBatch.referenceSequenceNumber,\n\t\t\t\t},\n\t\t\t\tnew UsageError(\"BatchRebase\"),\n\t\t\t);\n\t\t\tthis.batchRebasesToReport--;\n\t\t}\n\n\t\tthis.flushInternal(batchManager);\n\t\tthis.rebasing = false;\n\t}\n\n\tprivate isContextReentrant(): boolean {\n\t\treturn this.params.opReentrancy() && !this.rebasing;\n\t}\n\n\t/**\n\t * As necessary and enabled, compresses and chunks the given batch.\n\t *\n\t * @remarks - If chunking happens, a side effect here is that 1 or more chunks are queued immediately for sending in next JS turn.\n\t *\n\t * @param batch - Raw or Grouped batch to consider for compression/chunking\n\t * @returns Either (A) the original batch, (B) a compressed batch (same length as original)\n\t * or (C) a batch containing the last chunk.\n\t */\n\tprivate compressAndChunkBatch(batch: IBatch): IBatch {\n\t\tif (\n\t\t\tbatch.messages.length === 0 ||\n\t\t\tthis.params.config.compressionOptions === undefined ||\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes >\n\t\t\t\tbatch.contentSizeInBytes ||\n\t\t\tthis.params.submitBatchFn === undefined ||\n\t\t\t!this.params.groupingManager.groupedBatchingEnabled()\n\t\t) {\n\t\t\t// Nothing to do if the batch is empty or if compression is disabled or not supported, or if we don't need to compress\n\t\t\treturn batch;\n\t\t}\n\n\t\tconst compressedBatch = this.params.compressor.compressBatch(batch);\n\n\t\tif (this.params.splitter.isBatchChunkingEnabled) {\n\t\t\treturn compressedBatch.contentSizeInBytes <= this.params.splitter.chunkSizeInBytes\n\t\t\t\t? compressedBatch\n\t\t\t\t: this.params.splitter.splitFirstBatchMessage(compressedBatch);\n\t\t}\n\n\t\tif (compressedBatch.contentSizeInBytes >= this.params.config.maxBatchSizeInBytes) {\n\t\t\tthrow new GenericError(\"BatchTooLarge\", /* error */ undefined, {\n\t\t\t\tbatchSize: batch.contentSizeInBytes,\n\t\t\t\tcompressedBatchSize: compressedBatch.contentSizeInBytes,\n\t\t\t\tcount: compressedBatch.messages.length,\n\t\t\t\tlimit: this.params.config.maxBatchSizeInBytes,\n\t\t\t\tchunkingEnabled: this.params.splitter.isBatchChunkingEnabled,\n\t\t\t\tcompressionOptions: JSON.stringify(this.params.config.compressionOptions),\n\t\t\t\tsocketSize: estimateSocketSize(batch),\n\t\t\t});\n\t\t}\n\n\t\treturn compressedBatch;\n\t}\n\n\t/**\n\t * Sends the batch object to the container context to be sent over the wire.\n\t *\n\t * @param batch - batch to be sent\n\t * @returns the clientSequenceNumber of the start of the batch, or undefined if nothing was sent\n\t */\n\tprivate sendBatch(batch: IBatch): number | undefined {\n\t\tconst length = batch.messages.length;\n\t\tif (length === 0) {\n\t\t\treturn undefined; // Nothing submitted\n\t\t}\n\n\t\tconst socketSize = estimateSocketSize(batch);\n\t\tif (socketSize >= this.params.config.maxBatchSizeInBytes) {\n\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\teventName: \"LargeBatch\",\n\t\t\t\tlength: batch.messages.length,\n\t\t\t\tsizeInBytes: batch.contentSizeInBytes,\n\t\t\t\tsocketSize,\n\t\t\t});\n\t\t}\n\n\t\tlet clientSequenceNumber: number;\n\t\tif (this.params.submitBatchFn === undefined) {\n\t\t\t// Legacy path - supporting old loader versions. Can be removed only when LTS moves above\n\t\t\t// version that has support for batches (submitBatchFn)\n\t\t\tassert(\n\t\t\t\tbatch.messages[0].compression === undefined,\n\t\t\t\t0x5a6 /* Compression should not have happened if the loader does not support it */,\n\t\t\t);\n\n\t\t\tclientSequenceNumber = this.params.legacySendBatchFn(batch);\n\t\t} else {\n\t\t\tassert(batch.referenceSequenceNumber !== undefined, 0x58e /* Batch must not be empty */);\n\t\t\tclientSequenceNumber = this.params.submitBatchFn(\n\t\t\t\tbatch.messages.map<IBatchMessage>((message) => ({\n\t\t\t\t\tcontents: message.contents,\n\t\t\t\t\tmetadata: message.metadata,\n\t\t\t\t\tcompression: message.compression,\n\t\t\t\t\treferenceSequenceNumber: message.referenceSequenceNumber,\n\t\t\t\t})),\n\t\t\t\tbatch.referenceSequenceNumber,\n\t\t\t);\n\t\t}\n\n\t\t// Convert from clientSequenceNumber of last message in the batch to clientSequenceNumber of first message.\n\t\tclientSequenceNumber -= length - 1;\n\t\tassert(clientSequenceNumber >= 0, 0x3d0 /* clientSequenceNumber can't be negative */);\n\t\treturn clientSequenceNumber;\n\t}\n\n\t/**\n\t * Gets a checkpoint object per batch that facilitates iterating over the batch messages when rolling back.\n\t */\n\tpublic getBatchCheckpoints(): {\n\t\tmainBatch: IBatchCheckpoint;\n\t\tidAllocationBatch: IBatchCheckpoint;\n\t\tblobAttachBatch: IBatchCheckpoint;\n\t} {\n\t\t// This variable is declared with a specific type so that we have a standard import of the IBatchCheckpoint type.\n\t\t// When the type is inferred, the generated .d.ts uses a dynamic import which doesn't resolve.\n\t\tconst mainBatch: IBatchCheckpoint = this.mainBatch.checkpoint();\n\t\treturn {\n\t\t\tmainBatch,\n\t\t\tidAllocationBatch: this.idAllocationBatch.checkpoint(),\n\t\t\tblobAttachBatch: this.blobAttachBatch.checkpoint(),\n\t\t};\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IBatchMessage } from \"@fluidframework/container-definitions/internal\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert, Lazy } from \"@fluidframework/core-utils/internal\";\nimport {\n\tDataProcessingError,\n\tGenericError,\n\tUsageError,\n\tcreateChildLogger,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { ICompressionRuntimeOptions } from \"../containerRuntime.js\";\nimport { PendingMessageResubmitData, PendingStateManager } from \"../pendingStateManager.js\";\n\nimport {\n\tBatchManager,\n\tBatchSequenceNumbers,\n\testimateSocketSize,\n\tsequenceNumbersMatch,\n\ttype BatchId,\n} from \"./batchManager.js\";\nimport {\n\tLocalBatchMessage,\n\tIBatchCheckpoint,\n\ttype OutboundBatchMessage,\n\ttype OutboundSingletonBatch,\n\ttype LocalBatch,\n\ttype OutboundBatch,\n} from \"./definitions.js\";\nimport { OpCompressor } from \"./opCompressor.js\";\nimport { OpGroupingManager } from \"./opGroupingManager.js\";\nimport { OpSplitter } from \"./opSplitter.js\";\n\nexport interface IOutboxConfig {\n\treadonly compressionOptions: ICompressionRuntimeOptions;\n\t/**\n\t * The maximum size of a batch that we can send over the wire.\n\t */\n\treadonly maxBatchSizeInBytes: number;\n\t/**\n\t * If true, maybeFlushPartialBatch will flush the batch if the reference sequence number changed\n\t * since the batch started. Otherwise, it will throw in this case (apart from reentrancy which is handled elsewhere).\n\t * Once the new throw-based flow is proved in a production environment, this option will be removed.\n\t */\n\treadonly flushPartialBatches: boolean;\n}\n\nexport interface IOutboxParameters {\n\treadonly shouldSend: () => boolean;\n\treadonly pendingStateManager: PendingStateManager;\n\treadonly submitBatchFn:\n\t\t| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)\n\t\t| undefined;\n\treadonly legacySendBatchFn: (batch: OutboundBatch) => number;\n\treadonly config: IOutboxConfig;\n\treadonly compressor: OpCompressor;\n\treadonly splitter: OpSplitter;\n\treadonly logger: ITelemetryBaseLogger;\n\treadonly groupingManager: OpGroupingManager;\n\treadonly getCurrentSequenceNumbers: () => BatchSequenceNumbers;\n\treadonly reSubmit: (message: PendingMessageResubmitData) => void;\n\treadonly opReentrancy: () => boolean;\n}\n\n/**\n * Temporarily increase the stack limit while executing the provided action.\n * If a negative value is provided for `length`, no stack frames will be collected.\n * If Infinity is provided, all frames will be collected.\n *\n * ADO:4663 - add this to the common packages.\n *\n * @param action - action which returns an error\n * @param length - number of stack frames to collect, 50 if unspecified.\n * @returns the result of the action provided\n */\nexport function getLongStack<T>(action: () => T, length: number = 50): T {\n\t// TODO: better typing here\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment\n\tconst errorObj = Error as any;\n\tif (\n\t\t/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */\n\t\t// ?? is not logically equivalent when the first clause returns false.\n\t\t(\n\t\t\tObject.getOwnPropertyDescriptor(errorObj, \"stackTraceLimit\") ||\n\t\t\tObject.getOwnPropertyDescriptor(Object.getPrototypeOf(errorObj), \"stackTraceLimit\")\n\t\t)?.writable !== true\n\t\t/* eslint-enable @typescript-eslint/prefer-nullish-coalescing */\n\t) {\n\t\treturn action();\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\tconst originalStackTraceLimit = errorObj.stackTraceLimit;\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\terrorObj.stackTraceLimit = length;\n\t\treturn action();\n\t} finally {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\t\terrorObj.stackTraceLimit = originalStackTraceLimit;\n\t}\n}\n\n/**\n * The Outbox collects messages submitted by the ContainerRuntime into a batch,\n * and then flushes the batch when requested.\n *\n * @remarks There are actually multiple independent batches (some are for a specific message type),\n * to support slight variation in semantics for each batch (e.g. support for rebasing or grouping).\n */\nexport class Outbox {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate readonly mainBatch: BatchManager;\n\tprivate readonly blobAttachBatch: BatchManager;\n\tprivate readonly idAllocationBatch: BatchManager;\n\tprivate batchRebasesToReport = 5;\n\tprivate rebasing = false;\n\n\t/**\n\t * Track the number of ops which were detected to have a mismatched\n\t * reference sequence number, in order to self-throttle the telemetry events.\n\t *\n\t * This should be removed as part of ADO:2322\n\t */\n\tprivate readonly maxMismatchedOpsToReport = 3;\n\tprivate mismatchedOpsReported = 0;\n\n\tconstructor(private readonly params: IOutboxParameters) {\n\t\tthis.logger = createChildLogger({ logger: params.logger, namespace: \"Outbox\" });\n\n\t\tconst isCompressionEnabled =\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes !==\n\t\t\tNumber.POSITIVE_INFINITY;\n\t\t// We need to allow infinite size batches if we enable compression\n\t\tconst hardLimit = isCompressionEnabled\n\t\t\t? Number.POSITIVE_INFINITY\n\t\t\t: this.params.config.maxBatchSizeInBytes;\n\n\t\tthis.mainBatch = new BatchManager({ hardLimit, canRebase: true });\n\t\tthis.blobAttachBatch = new BatchManager({ hardLimit, canRebase: true });\n\t\tthis.idAllocationBatch = new BatchManager({\n\t\t\thardLimit,\n\t\t\tcanRebase: false,\n\t\t\tignoreBatchId: true,\n\t\t});\n\t}\n\n\tpublic get messageCount(): number {\n\t\treturn this.mainBatch.length + this.blobAttachBatch.length + this.idAllocationBatch.length;\n\t}\n\n\tpublic get mainBatchMessageCount(): number {\n\t\treturn this.mainBatch.length;\n\t}\n\n\tpublic get blobAttachBatchMessageCount(): number {\n\t\treturn this.blobAttachBatch.length;\n\t}\n\n\tpublic get idAllocationBatchMessageCount(): number {\n\t\treturn this.idAllocationBatch.length;\n\t}\n\n\tpublic get isEmpty(): boolean {\n\t\treturn this.messageCount === 0;\n\t}\n\n\t/**\n\t * Detect whether batching has been interrupted by an incoming message being processed. In this case,\n\t * we will flush the accumulated messages to account for that (if allowed) and create a new batch with the new\n\t * message as the first message. If flushing partial batch is not enabled, we will throw (except for reentrant ops).\n\t * This would indicate we expected this case to be precluded by logic elsewhere.\n\t *\n\t * @remarks - To detect batch interruption, we compare both the reference sequence number\n\t * (i.e. last message processed by DeltaManager) and the client sequence number of the\n\t * last message processed by the ContainerRuntime. In the absence of op reentrancy, this\n\t * pair will remain stable during a single JS turn during which the batch is being built up.\n\t */\n\tprivate maybeFlushPartialBatch(): void {\n\t\tconst mainBatchSeqNums = this.mainBatch.sequenceNumbers;\n\t\tconst blobAttachSeqNums = this.blobAttachBatch.sequenceNumbers;\n\t\tconst idAllocSeqNums = this.idAllocationBatch.sequenceNumbers;\n\t\tassert(\n\t\t\tsequenceNumbersMatch(mainBatchSeqNums, blobAttachSeqNums) &&\n\t\t\t\tsequenceNumbersMatch(mainBatchSeqNums, idAllocSeqNums),\n\t\t\t0x58d /* Reference sequence numbers from both batches must be in sync */,\n\t\t);\n\n\t\tconst currentSequenceNumbers = this.params.getCurrentSequenceNumbers();\n\n\t\tif (\n\t\t\tsequenceNumbersMatch(mainBatchSeqNums, currentSequenceNumbers) &&\n\t\t\tsequenceNumbersMatch(blobAttachSeqNums, currentSequenceNumbers) &&\n\t\t\tsequenceNumbersMatch(idAllocSeqNums, currentSequenceNumbers)\n\t\t) {\n\t\t\t// The reference sequence numbers are stable, there is nothing to do\n\t\t\treturn;\n\t\t}\n\n\t\t// Reference and/or Client sequence number will be advancing while processing this batch,\n\t\t// so we can't use this check to detect wrongdoing. But we will still log via telemetry.\n\t\t// This is rare, and the reentrancy will be handled during Flush.\n\t\tconst expectedDueToReentrancy = this.isContextReentrant();\n\n\t\tconst errorWrapper = new Lazy(() =>\n\t\t\tgetLongStack(() =>\n\t\t\t\tDataProcessingError.create(\n\t\t\t\t\t\"Sequence numbers advanced as if ops were processed while a batch is accumulating\",\n\t\t\t\t\t\"outboxSequenceNumberCoherencyCheck\",\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t\tif (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\t// Only log error if this is truly unexpected\n\t\t\t\t\tcategory:\n\t\t\t\t\t\texpectedDueToReentrancy || this.params.config.flushPartialBatches\n\t\t\t\t\t\t\t? \"generic\"\n\t\t\t\t\t\t\t: \"error\",\n\t\t\t\t\teventName: \"ReferenceSequenceNumberMismatch\",\n\t\t\t\t\tData_details: {\n\t\t\t\t\t\texpectedDueToReentrancy,\n\t\t\t\t\t\tmainReferenceSequenceNumber: mainBatchSeqNums.referenceSequenceNumber,\n\t\t\t\t\t\tmainClientSequenceNumber: mainBatchSeqNums.clientSequenceNumber,\n\t\t\t\t\t\tblobAttachReferenceSequenceNumber: blobAttachSeqNums.referenceSequenceNumber,\n\t\t\t\t\t\tblobAttachClientSequenceNumber: blobAttachSeqNums.clientSequenceNumber,\n\t\t\t\t\t\tcurrentReferenceSequenceNumber: currentSequenceNumbers.referenceSequenceNumber,\n\t\t\t\t\t\tcurrentClientSequenceNumber: currentSequenceNumbers.clientSequenceNumber,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\terrorWrapper.value,\n\t\t\t);\n\t\t}\n\n\t\t// If we're configured to flush partial batches, do that now and return (don't throw)\n\t\tif (this.params.config.flushPartialBatches) {\n\t\t\tthis.flushAll();\n\t\t\treturn;\n\t\t}\n\n\t\t// If we are in a reentrant context, we know this can happen without causing any harm.\n\t\tif (expectedDueToReentrancy) {\n\t\t\treturn;\n\t\t}\n\n\t\tthrow errorWrapper.value;\n\t}\n\n\tpublic submit(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.mainBatch, message);\n\t}\n\n\tpublic submitBlobAttach(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.blobAttachBatch, message);\n\t}\n\n\tpublic submitIdAllocation(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.idAllocationBatch, message);\n\t}\n\n\tprivate addMessageToBatchManager(\n\t\tbatchManager: BatchManager,\n\t\tmessage: LocalBatchMessage,\n\t): void {\n\t\tif (\n\t\t\t!batchManager.push(\n\t\t\t\tmessage,\n\t\t\t\tthis.isContextReentrant(),\n\t\t\t\tthis.params.getCurrentSequenceNumbers().clientSequenceNumber,\n\t\t\t)\n\t\t) {\n\t\t\tthrow new GenericError(\"BatchTooLarge\", /* error */ undefined, {\n\t\t\t\topSize: message.serializedOp?.length ?? 0,\n\t\t\t\tbatchSize: batchManager.contentSizeInBytes,\n\t\t\t\tcount: batchManager.length,\n\t\t\t\tlimit: batchManager.options.hardLimit,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Flush all the batches to the ordering service.\n\t * This method is expected to be called at the end of a batch.\n\t *\n\t * @throws If called from a reentrant context, or if the batch being flushed is too large.\n\t * @param resubmittingBatchId - If defined, indicates this is a resubmission of a batch\n\t * with the given Batch ID, which must be preserved\n\t */\n\tpublic flush(resubmittingBatchId?: BatchId): void {\n\t\tassert(\n\t\t\t!this.isContextReentrant(),\n\t\t\t0xb7b /* Flushing must not happen while incoming changes are being processed */,\n\t\t);\n\n\t\tthis.flushAll(resubmittingBatchId);\n\t}\n\n\tprivate flushAll(resubmittingBatchId?: BatchId): void {\n\t\tconst allBatchesEmpty =\n\t\t\tthis.idAllocationBatch.empty && this.blobAttachBatch.empty && this.mainBatch.empty;\n\t\tif (allBatchesEmpty) {\n\t\t\t// If we're resubmitting and all batches are empty, we need to flush an empty batch.\n\t\t\t// Note that we currently resubmit one batch at a time, so on resubmit, 2 of the 3 batches will *always* be empty.\n\t\t\t// It's theoretically possible that we don't *need* to resubmit this empty batch, and in those cases, it'll safely be ignored\n\t\t\t// by the rest of the system, including remote clients.\n\t\t\t// In some cases we *must* resubmit the empty batch (to match up with a non-empty version tracked locally by a container fork), so we do it always.\n\t\t\tif (resubmittingBatchId) {\n\t\t\t\tthis.flushEmptyBatch(resubmittingBatchId);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Don't use resubmittingBatchId for idAllocationBatch.\n\t\t// ID Allocation messages are not directly resubmitted so we don't want to reuse the batch ID.\n\t\tthis.flushInternal(this.idAllocationBatch);\n\t\tthis.flushInternal(\n\t\t\tthis.blobAttachBatch,\n\t\t\ttrue /* disableGroupedBatching */,\n\t\t\tresubmittingBatchId,\n\t\t);\n\t\tthis.flushInternal(\n\t\t\tthis.mainBatch,\n\t\t\tfalse /* disableGroupedBatching */,\n\t\t\tresubmittingBatchId,\n\t\t);\n\t}\n\n\tprivate flushEmptyBatch(resubmittingBatchId: BatchId): void {\n\t\tconst referenceSequenceNumber =\n\t\t\tthis.params.getCurrentSequenceNumbers().referenceSequenceNumber;\n\t\tassert(\n\t\t\treferenceSequenceNumber !== undefined,\n\t\t\t0xa01 /* reference sequence number should be defined */,\n\t\t);\n\t\tconst { outboundBatch, placeholderMessage } =\n\t\t\tthis.params.groupingManager.createEmptyGroupedBatch(\n\t\t\t\tresubmittingBatchId,\n\t\t\t\treferenceSequenceNumber,\n\t\t\t);\n\t\tlet clientSequenceNumber: number | undefined;\n\t\tif (this.params.shouldSend()) {\n\t\t\tclientSequenceNumber = this.sendBatch(outboundBatch);\n\t\t}\n\n\t\t// Push the empty batch placeholder to the PendingStateManager\n\t\tthis.params.pendingStateManager.onFlushBatch(\n\t\t\t[{ ...placeholderMessage, serializedOp: \"\", contents: undefined }], // placeholder message - serializedOp will never be used\n\t\t\tclientSequenceNumber,\n\t\t);\n\t\treturn;\n\t}\n\n\tprivate flushInternal(\n\t\tbatchManager: BatchManager,\n\t\tdisableGroupedBatching: boolean = false,\n\t\tresubmittingBatchId?: BatchId,\n\t): void {\n\t\tif (batchManager.empty) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rawBatch = batchManager.popBatch(resubmittingBatchId);\n\t\tconst groupingEnabled =\n\t\t\t!disableGroupedBatching && this.params.groupingManager.groupedBatchingEnabled();\n\t\tif (\n\t\t\tbatchManager.options.canRebase &&\n\t\t\trawBatch.hasReentrantOps === true &&\n\t\t\t// NOTE: This is too restrictive. We should rebase for any reentrant op, not just if it's going to be a grouped batch\n\t\t\t// However there is some test that is depending on this behavior so we haven't removed these conditions yet. See AB#33427\n\t\t\tgroupingEnabled &&\n\t\t\trawBatch.messages.length > 1\n\t\t) {\n\t\t\tassert(!this.rebasing, 0x6fa /* A rebased batch should never have reentrant ops */);\n\t\t\t// If a batch contains reentrant ops (ops created as a result from processing another op)\n\t\t\t// it needs to be rebased so that we can ensure consistent reference sequence numbers\n\t\t\t// and eventual consistency at the DDS level.\n\t\t\tthis.rebase(rawBatch, batchManager);\n\t\t\treturn;\n\t\t}\n\n\t\tlet clientSequenceNumber: number | undefined;\n\t\t// Did we disconnect? (i.e. is shouldSend false?)\n\t\t// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.\n\t\t// Because flush() is a task that executes async (on clean stack), we can get here in disconnected state.\n\t\tif (this.params.shouldSend()) {\n\t\t\tconst virtualizedBatch = this.virtualizeBatch(rawBatch, groupingEnabled);\n\n\t\t\tclientSequenceNumber = this.sendBatch(virtualizedBatch);\n\t\t\tassert(\n\t\t\t\tclientSequenceNumber === undefined || clientSequenceNumber >= 0,\n\t\t\t\t0x9d2 /* unexpected negative clientSequenceNumber (empty batch should yield undefined) */,\n\t\t\t);\n\t\t}\n\n\t\tthis.params.pendingStateManager.onFlushBatch(\n\t\t\trawBatch.messages,\n\t\t\tclientSequenceNumber,\n\t\t\tbatchManager.options.ignoreBatchId,\n\t\t);\n\t}\n\n\t/**\n\t * Rebases a batch. All the ops in the batch are resubmitted to the runtime and\n\t * they will end up back in the same batch manager they were flushed from and subsequently flushed.\n\t *\n\t * @param rawBatch - the batch to be rebased\n\t */\n\tprivate rebase(rawBatch: LocalBatch, batchManager: BatchManager): void {\n\t\tassert(!this.rebasing, 0x6fb /* Reentrancy */);\n\t\tassert(batchManager.options.canRebase, 0x9a7 /* BatchManager does not support rebase */);\n\n\t\tthis.rebasing = true;\n\t\tfor (const message of rawBatch.messages) {\n\t\t\tthis.params.reSubmit({\n\t\t\t\tcontent: message.serializedOp,\n\t\t\t\tlocalOpMetadata: message.localOpMetadata,\n\t\t\t\topMetadata: message.metadata,\n\t\t\t});\n\t\t}\n\n\t\tif (this.batchRebasesToReport > 0) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: \"BatchRebase\",\n\t\t\t\t\tlength: rawBatch.messages.length,\n\t\t\t\t\treferenceSequenceNumber: rawBatch.referenceSequenceNumber,\n\t\t\t\t},\n\t\t\t\tnew UsageError(\"BatchRebase\"),\n\t\t\t);\n\t\t\tthis.batchRebasesToReport--;\n\t\t}\n\n\t\tthis.flushInternal(batchManager);\n\t\tthis.rebasing = false;\n\t}\n\n\tprivate isContextReentrant(): boolean {\n\t\treturn this.params.opReentrancy() && !this.rebasing;\n\t}\n\n\t/**\n\t * As necessary and enabled, groups / compresses / chunks the given batch.\n\t *\n\t * @remarks - If chunking happens, a side effect here is that 1 or more chunks are queued immediately for sending in next JS turn.\n\t *\n\t * @param localBatch - Local Batch to be virtualized - i.e. transformed into an Outbound Batch\n\t * @param groupingEnabled - If true, Grouped batching is enabled.\n\t * @returns One of the following:\n\t * - (A) The original batch (Based on what's enabled)\n\t * - (B) A grouped batch (it's a singleton batch)\n\t * - (C) A compressed singleton batch\n\t * - (D) A singleton batch containing the last chunk.\n\t */\n\tprivate virtualizeBatch(localBatch: LocalBatch, groupingEnabled: boolean): OutboundBatch {\n\t\t// Shallow copy the local batch, updating the messages to be outbound messages\n\t\tconst originalBatch: OutboundBatch = {\n\t\t\t...localBatch,\n\t\t\tmessages: localBatch.messages.map<OutboundBatchMessage>(\n\t\t\t\t({ serializedOp, ...message }) => ({\n\t\t\t\t\tcontents: serializedOp,\n\t\t\t\t\t...message,\n\t\t\t\t}),\n\t\t\t),\n\t\t};\n\n\t\tconst originalOrGroupedBatch = groupingEnabled\n\t\t\t? this.params.groupingManager.groupBatch(originalBatch)\n\t\t\t: originalBatch;\n\n\t\tif (originalOrGroupedBatch.messages.length !== 1) {\n\t\t\t// Compression requires a single message, so return early otherwise.\n\t\t\treturn originalOrGroupedBatch;\n\t\t}\n\n\t\t// Regardless of whether we grouped or not, we now have a batch with a single message.\n\t\t// Now proceed to compress/chunk it if necessary.\n\t\tconst singletonBatch = originalOrGroupedBatch as OutboundSingletonBatch;\n\n\t\tif (\n\t\t\tthis.params.config.compressionOptions === undefined ||\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes >\n\t\t\t\tsingletonBatch.contentSizeInBytes ||\n\t\t\tthis.params.submitBatchFn === undefined\n\t\t) {\n\t\t\t// Nothing to do if compression is disabled, unnecessary or unsupported.\n\t\t\treturn singletonBatch;\n\t\t}\n\n\t\tconst compressedBatch = this.params.compressor.compressBatch(singletonBatch);\n\n\t\tif (this.params.splitter.isBatchChunkingEnabled) {\n\t\t\treturn compressedBatch.contentSizeInBytes <= this.params.splitter.chunkSizeInBytes\n\t\t\t\t? compressedBatch\n\t\t\t\t: this.params.splitter.splitSingletonBatchMessage(compressedBatch);\n\t\t}\n\n\t\tif (compressedBatch.contentSizeInBytes >= this.params.config.maxBatchSizeInBytes) {\n\t\t\tthrow DataProcessingError.create(\n\t\t\t\t\"BatchTooLarge\",\n\t\t\t\t\"compressionInsufficient\",\n\t\t\t\t/* sequencedMessage */ undefined,\n\t\t\t\t{\n\t\t\t\t\tbatchSize: singletonBatch.contentSizeInBytes,\n\t\t\t\t\tcompressedBatchSize: compressedBatch.contentSizeInBytes,\n\t\t\t\t\tcount: compressedBatch.messages.length,\n\t\t\t\t\tlimit: this.params.config.maxBatchSizeInBytes,\n\t\t\t\t\tchunkingEnabled: this.params.splitter.isBatchChunkingEnabled,\n\t\t\t\t\tcompressionOptions: JSON.stringify(this.params.config.compressionOptions),\n\t\t\t\t\tsocketSize: estimateSocketSize(singletonBatch),\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\treturn compressedBatch;\n\t}\n\n\t/**\n\t * Sends the batch object to the container context to be sent over the wire.\n\t *\n\t * @param batch - batch to be sent\n\t * @returns the clientSequenceNumber of the start of the batch, or undefined if nothing was sent\n\t */\n\tprivate sendBatch(batch: OutboundBatch): number | undefined {\n\t\tconst length = batch.messages.length;\n\t\tif (length === 0) {\n\t\t\treturn undefined; // Nothing submitted\n\t\t}\n\n\t\tconst socketSize = estimateSocketSize(batch);\n\t\tif (socketSize >= this.params.config.maxBatchSizeInBytes) {\n\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\teventName: \"LargeBatch\",\n\t\t\t\tlength: batch.messages.length,\n\t\t\t\tsizeInBytes: batch.contentSizeInBytes,\n\t\t\t\tsocketSize,\n\t\t\t});\n\t\t}\n\n\t\tlet clientSequenceNumber: number;\n\t\tif (this.params.submitBatchFn === undefined) {\n\t\t\t// Legacy path - supporting old loader versions. Can be removed only when LTS moves above\n\t\t\t// version that has support for batches (submitBatchFn)\n\t\t\tassert(\n\t\t\t\tbatch.messages[0].compression === undefined,\n\t\t\t\t0x5a6 /* Compression should not have happened if the loader does not support it */,\n\t\t\t);\n\n\t\t\tclientSequenceNumber = this.params.legacySendBatchFn(batch);\n\t\t} else {\n\t\t\tassert(batch.referenceSequenceNumber !== undefined, 0x58e /* Batch must not be empty */);\n\t\t\tclientSequenceNumber = this.params.submitBatchFn(\n\t\t\t\tbatch.messages.map<IBatchMessage>((message) => ({\n\t\t\t\t\tcontents: message.contents,\n\t\t\t\t\tmetadata: message.metadata,\n\t\t\t\t\tcompression: message.compression,\n\t\t\t\t\treferenceSequenceNumber: message.referenceSequenceNumber,\n\t\t\t\t})),\n\t\t\t\tbatch.referenceSequenceNumber,\n\t\t\t);\n\t\t}\n\n\t\t// Convert from clientSequenceNumber of last message in the batch to clientSequenceNumber of first message.\n\t\tclientSequenceNumber -= length - 1;\n\t\tassert(clientSequenceNumber >= 0, 0x3d0 /* clientSequenceNumber can't be negative */);\n\t\treturn clientSequenceNumber;\n\t}\n\n\t/**\n\t * Gets a checkpoint object per batch that facilitates iterating over the batch messages when rolling back.\n\t */\n\tpublic getBatchCheckpoints(): {\n\t\tmainBatch: IBatchCheckpoint;\n\t\tidAllocationBatch: IBatchCheckpoint;\n\t\tblobAttachBatch: IBatchCheckpoint;\n\t} {\n\t\t// This variable is declared with a specific type so that we have a standard import of the IBatchCheckpoint type.\n\t\t// When the type is inferred, the generated .d.ts uses a dynamic import which doesn't resolve.\n\t\tconst mainBatch: IBatchCheckpoint = this.mainBatch.checkpoint();\n\t\treturn {\n\t\t\tmainBatch,\n\t\t\tidAllocationBatch: this.idAllocationBatch.checkpoint(),\n\t\t\tblobAttachBatch: this.blobAttachBatch.checkpoint(),\n\t\t};\n\t}\n}\n"]}
|
|
@@ -99,13 +99,6 @@ export declare class RemoteMessageProcessor {
|
|
|
99
99
|
*/
|
|
100
100
|
private getResultBasedOnBatchMetadata;
|
|
101
101
|
}
|
|
102
|
-
/**
|
|
103
|
-
* Takes an incoming runtime message JSON.parse's its contents in place, if needed (old Loader does this for us).
|
|
104
|
-
* Only to be used for runtine messages.
|
|
105
|
-
* @remarks - Serialization during submit happens via {@link serializeOpContents}
|
|
106
|
-
* @param mutableMessage - op message received
|
|
107
|
-
*/
|
|
108
|
-
export declare function ensureContentsDeserialized(mutableMessage: ISequencedDocumentMessage): void;
|
|
109
102
|
/**
|
|
110
103
|
* Unpacks runtime messages.
|
|
111
104
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteMessageProcessor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAEN,yBAAyB,EACzB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EAGN,KAAK,uCAAuC,EAC5C,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAkB,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAoB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"remoteMessageProcessor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAEN,yBAAyB,EACzB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EAGN,KAAK,uCAAuC,EAC5C,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAkB,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAoB,MAAM,iBAAiB,CAAC;AAC/D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,yBAAyB,CAAC;CAC/C;AAED;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAC7B;IACA,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,uCAAuC,EAAE,CAAC;IACpD,UAAU,EAAE,cAAc,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;CACrB,GACD;IACA,IAAI,EAAE,sBAAsB,CAAC;IAC7B,UAAU,EAAE,cAAc,CAAC;IAC3B,WAAW,EAAE,uCAAuC,CAAC;IACrD,MAAM,CAAC,EAAE,KAAK,CAAC;CACd,GACD;IACA,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,uCAAuC,CAAC;IACrD,MAAM,CAAC,EAAE,KAAK,CAAC;CACd,CAAC;AAWL;;;;;GAKG;AACH,qBAAa,sBAAsB;IAIjC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IALnC,OAAO,CAAC,eAAe,CAAkB;gBAGvB,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,cAAc,EAC9B,iBAAiB,EAAE,iBAAiB;IAGtD,IAAW,eAAe,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAE1D;IAEM,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAItD;;;;;;;;;;;;;;;;;;OAkBG;IACI,OAAO,CACb,iBAAiB,EAAE,yBAAyB,EAC5C,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GACvC,oBAAoB,GAAG,SAAS;IA0DnC;;;OAGG;IACH,OAAO,CAAC,6BAA6B;CAkDrC;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,yBAAyB,EAClC,aAAa,GAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAe,GAClD,OAAO,CAuBT"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.unpackRuntimeMessage = exports.
|
|
7
|
+
exports.unpackRuntimeMessage = exports.RemoteMessageProcessor = void 0;
|
|
8
8
|
const internal_1 = require("@fluidframework/core-utils/internal");
|
|
9
9
|
const internal_2 = require("@fluidframework/driver-definitions/internal");
|
|
10
10
|
const messageTypes_js_1 = require("../messageTypes.js");
|
|
@@ -149,20 +149,6 @@ class RemoteMessageProcessor {
|
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
exports.RemoteMessageProcessor = RemoteMessageProcessor;
|
|
152
|
-
/**
|
|
153
|
-
* Takes an incoming runtime message JSON.parse's its contents in place, if needed (old Loader does this for us).
|
|
154
|
-
* Only to be used for runtine messages.
|
|
155
|
-
* @remarks - Serialization during submit happens via {@link serializeOpContents}
|
|
156
|
-
* @param mutableMessage - op message received
|
|
157
|
-
*/
|
|
158
|
-
function ensureContentsDeserialized(mutableMessage) {
|
|
159
|
-
// This should become unconditional once Loader LTS reaches 2.4 or later.
|
|
160
|
-
// There will be a long time of needing both cases, until LTS advances to that point.
|
|
161
|
-
if (typeof mutableMessage.contents === "string" && mutableMessage.contents !== "") {
|
|
162
|
-
mutableMessage.contents = JSON.parse(mutableMessage.contents);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
exports.ensureContentsDeserialized = ensureContentsDeserialized;
|
|
166
152
|
/**
|
|
167
153
|
* For a given message, it moves the nested InboundContainerRuntimeMessage props one level up.
|
|
168
154
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteMessageProcessor.js","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tMessageType,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\n\nimport {\n\tContainerMessageType,\n\ttype InboundContainerRuntimeMessage,\n\ttype InboundSequencedContainerRuntimeMessage,\n} from \"../messageTypes.js\";\nimport { asBatchMetadata } from \"../metadata.js\";\n\nimport { OpDecompressor } from \"./opDecompressor.js\";\nimport { OpGroupingManager, isGroupedBatch } from \"./opGroupingManager.js\";\nimport { OpSplitter, isChunkedMessage } from \"./opSplitter.js\";\n// eslint-disable-next-line unused-imports/no-unused-imports -- Used by \"@link\" comment annotation below\nimport { serializeOpContents } from \"./outbox.js\";\n\n/**\n * Info about the batch we learn when we process the first message\n */\nexport interface BatchStartInfo {\n\t/**\n\t * Batch ID, if present\n\t */\n\treadonly batchId: string | undefined;\n\t/**\n\t * clientId that sent this batch. Used to compute Batch ID if needed\n\t */\n\treadonly clientId: string;\n\t/**\n\t * Client Sequence Number of the Grouped Batch message, or the first message in the ungrouped batch.\n\t * Used to compute Batch ID if needed\n\t *\n\t * @remarks For chunked batches, this is the CSN of the \"representative\" chunk (the final chunk).\n\t * For grouped batches, clientSequenceNumber on messages is overwritten, so we track this original value here.\n\t */\n\treadonly batchStartCsn: number;\n\t/**\n\t * The first message in the batch, or if the batch is empty, the empty grouped batch message.\n\t * Used for accessing the sequence numbers for the (start of the) batch.\n\t *\n\t * @remarks Do not use clientSequenceNumber here, use batchStartCsn instead.\n\t */\n\treadonly keyMessage: ISequencedDocumentMessage;\n}\n\n/**\n * Result of processing the next inbound message.\n * Depending on the message and configuration of RemoteMessageProcessor, the result may be:\n * - A full batch of messages (including a single-message batch)\n * - The first message of a multi-message batch\n * - The next message in a multi-message batch\n */\nexport type InboundMessageResult =\n\t| {\n\t\t\ttype: \"fullBatch\";\n\t\t\tmessages: InboundSequencedContainerRuntimeMessage[];\n\t\t\tbatchStart: BatchStartInfo;\n\t\t\tlength: number;\n\t\t\tgroupedBatch: boolean; // Messages in a grouped batches are sent to the runtime in bunches.\n\t }\n\t| {\n\t\t\ttype: \"batchStartingMessage\";\n\t\t\tbatchStart: BatchStartInfo;\n\t\t\tnextMessage: InboundSequencedContainerRuntimeMessage;\n\t\t\tlength?: never;\n\t }\n\t| {\n\t\t\ttype: \"nextBatchMessage\";\n\t\t\tbatchEnd?: boolean;\n\t\t\tnextMessage: InboundSequencedContainerRuntimeMessage;\n\t\t\tlength?: never;\n\t };\n\nfunction assertHasClientId(\n\tmessage: ISequencedDocumentMessage,\n): asserts message is ISequencedDocumentMessage & { clientId: string } {\n\tassert(\n\t\tmessage.clientId !== null,\n\t\t0xa02 /* Server-generated message should not reach RemoteMessageProcessor */,\n\t);\n}\n\n/**\n * Stateful class for processing incoming remote messages as the virtualization measures are unwrapped,\n * potentially across numerous inbound ops.\n *\n * @internal\n */\nexport class RemoteMessageProcessor {\n\tprivate batchInProgress: boolean = false;\n\n\tconstructor(\n\t\tprivate readonly opSplitter: OpSplitter,\n\t\tprivate readonly opDecompressor: OpDecompressor,\n\t\tprivate readonly opGroupingManager: OpGroupingManager,\n\t) {}\n\n\tpublic get partialMessages(): ReadonlyMap<string, string[]> {\n\t\treturn this.opSplitter.chunks;\n\t}\n\n\tpublic clearPartialMessagesFor(clientId: string): void {\n\t\tthis.opSplitter.clearPartialChunks(clientId);\n\t}\n\n\t/**\n\t * Ungroups and Unchunks the runtime ops of a batch received over the wire\n\t * @param remoteMessageCopy - A shallow copy of a message from another client, possibly virtualized\n\t * (grouped, compressed, and/or chunked).\n\t * Being a shallow copy, it's considered mutable, meaning no other Container or other parallel procedure\n\t * depends on this object instance.\n\t * Note remoteMessageCopy.contents (and other object props) MUST not be modified,\n\t * but may be overwritten (as is the case with contents).\n\t *\n\t * Incoming messages will always have compression, chunking, and grouped batching happen in a defined order and that order cannot be changed.\n\t * When processing these messages, the order is:\n\t * 1. If chunked, process the chunk and only continue if this is a final chunk\n\t * 2. If compressed, decompress the message and store for further unrolling of the decompressed content\n\t * 3. If grouped, ungroup the message\n\t * For more details, see https://github.com/microsoft/FluidFramework/blob/main/packages/runtime/container-runtime/src/opLifecycle/README.md#inbound\n\t *\n\t * @returns all the unchunked, decompressed, ungrouped, unpacked InboundSequencedContainerRuntimeMessage from a single batch\n\t * or undefined if the batch is not yet complete.\n\t */\n\tpublic process(\n\t\tremoteMessageCopy: ISequencedDocumentMessage,\n\t\tlogLegacyCase: (codePath: string) => void,\n\t): InboundMessageResult | undefined {\n\t\tlet message = remoteMessageCopy;\n\n\t\tassertHasClientId(message);\n\t\tconst clientId = message.clientId;\n\n\t\tif (isChunkedMessage(message)) {\n\t\t\tconst chunkProcessingResult = this.opSplitter.processChunk(message);\n\t\t\t// Only continue further if current chunk is the final chunk\n\t\t\tif (!chunkProcessingResult.isFinalChunk) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\t// This message will always be compressed\n\t\t\tmessage = chunkProcessingResult.message;\n\t\t}\n\n\t\tif (this.opDecompressor.isCompressedMessage(message)) {\n\t\t\tthis.opDecompressor.decompressAndStore(message);\n\t\t}\n\n\t\tif (this.opDecompressor.currentlyUnrolling) {\n\t\t\tmessage = this.opDecompressor.unroll(message);\n\t\t\t// Need to unpack after unrolling if not a groupedBatch\n\t\t\tif (!isGroupedBatch(message)) {\n\t\t\t\tunpack(message);\n\t\t\t}\n\t\t}\n\n\t\tif (isGroupedBatch(message)) {\n\t\t\t// We should be awaiting a new batch (batchInProgress false)\n\t\t\tassert(!this.batchInProgress, 0x9d3 /* Grouped batch interrupting another batch */);\n\t\t\tconst batchId = asBatchMetadata(message.metadata)?.batchId;\n\t\t\tconst groupedMessages = this.opGroupingManager\n\t\t\t\t.ungroupOp(message)\n\t\t\t\t.map((innerMessage) => unpack(innerMessage));\n\n\t\t\treturn {\n\t\t\t\ttype: \"fullBatch\",\n\t\t\t\tmessages: groupedMessages, // Will be [] for an empty batch\n\t\t\t\tbatchStart: {\n\t\t\t\t\tbatchStartCsn: message.clientSequenceNumber,\n\t\t\t\t\tclientId,\n\t\t\t\t\tbatchId,\n\t\t\t\t\tkeyMessage: groupedMessages[0] ?? message, // For an empty batch, this is the empty grouped batch message. Needed for sequence numbers for this batch\n\t\t\t\t},\n\t\t\t\tlength: groupedMessages.length, // Will be 0 for an empty batch\n\t\t\t\tgroupedBatch: true,\n\t\t\t};\n\t\t}\n\n\t\t// Do a final unpack of runtime messages in case the message was not grouped, compressed, or chunked\n\t\tunpackRuntimeMessage(message, logLegacyCase);\n\n\t\treturn this.getResultBasedOnBatchMetadata(\n\t\t\tmessage as InboundSequencedContainerRuntimeMessage & { clientId: string },\n\t\t);\n\t}\n\n\t/**\n\t * Now that the message has been \"unwrapped\" as to any virtualization (grouping, compression, chunking),\n\t * inspect the batch metadata flag and determine what kind of result to return.\n\t */\n\tprivate getResultBasedOnBatchMetadata(\n\t\tmessage: InboundSequencedContainerRuntimeMessage & { clientId: string },\n\t): InboundMessageResult {\n\t\tconst batchMetadataFlag = asBatchMetadata(message.metadata)?.batch;\n\t\tif (!this.batchInProgress) {\n\t\t\t// We are waiting for a new batch\n\t\t\tassert(batchMetadataFlag !== false, 0x9d5 /* Unexpected batch end marker */);\n\n\t\t\t// Start of a new multi-message batch\n\t\t\tif (batchMetadataFlag === true) {\n\t\t\t\tthis.batchInProgress = true;\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"batchStartingMessage\",\n\t\t\t\t\tbatchStart: {\n\t\t\t\t\t\tbatchId: asBatchMetadata(message.metadata)?.batchId,\n\t\t\t\t\t\tclientId: message.clientId,\n\t\t\t\t\t\tbatchStartCsn: message.clientSequenceNumber,\n\t\t\t\t\t\tkeyMessage: message,\n\t\t\t\t\t},\n\t\t\t\t\tnextMessage: message,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Single-message batch (Since metadata flag is undefined)\n\t\t\treturn {\n\t\t\t\ttype: \"fullBatch\",\n\t\t\t\tmessages: [message],\n\t\t\t\tbatchStart: {\n\t\t\t\t\tbatchStartCsn: message.clientSequenceNumber,\n\t\t\t\t\tclientId: message.clientId,\n\t\t\t\t\tbatchId: asBatchMetadata(message.metadata)?.batchId,\n\t\t\t\t\tkeyMessage: message,\n\t\t\t\t},\n\t\t\t\tlength: 1,\n\t\t\t\tgroupedBatch: false,\n\t\t\t};\n\t\t}\n\t\tassert(batchMetadataFlag !== true, 0x9d6 /* Unexpected batch start marker */);\n\n\t\t// Clear batchInProgress state if the batch is ending\n\t\tif (batchMetadataFlag === false) {\n\t\t\tthis.batchInProgress = false;\n\t\t}\n\n\t\treturn {\n\t\t\ttype: \"nextBatchMessage\",\n\t\t\tnextMessage: message,\n\t\t\tbatchEnd: batchMetadataFlag === false,\n\t\t};\n\t}\n}\n\n/**\n * Takes an incoming runtime message JSON.parse's its contents in place, if needed (old Loader does this for us).\n * Only to be used for runtine messages.\n * @remarks - Serialization during submit happens via {@link serializeOpContents}\n * @param mutableMessage - op message received\n */\nexport function ensureContentsDeserialized(mutableMessage: ISequencedDocumentMessage): void {\n\t// This should become unconditional once Loader LTS reaches 2.4 or later.\n\t// There will be a long time of needing both cases, until LTS advances to that point.\n\tif (typeof mutableMessage.contents === \"string\" && mutableMessage.contents !== \"\") {\n\t\tmutableMessage.contents = JSON.parse(mutableMessage.contents);\n\t}\n}\n\n/**\n * For a given message, it moves the nested InboundContainerRuntimeMessage props one level up.\n *\n * The return type illustrates the assumption that the message param\n * becomes a InboundSequencedContainerRuntimeMessage by the time the function returns\n * (but there is no runtime validation of the 'type').\n */\nfunction unpack(message: ISequencedDocumentMessage): InboundSequencedContainerRuntimeMessage {\n\t// We assume the contents is an InboundContainerRuntimeMessage (the message is \"packed\")\n\tconst contents = message.contents as InboundContainerRuntimeMessage;\n\n\t// We're going to unpack message in-place (promoting those properties of contents up to message itself)\n\tconst messageUnpacked = message as InboundSequencedContainerRuntimeMessage;\n\n\tmessageUnpacked.type = contents.type;\n\tmessageUnpacked.contents = contents.contents;\n\treturn messageUnpacked;\n}\n\n/**\n * Unpacks runtime messages.\n *\n * @remarks This API makes no promises regarding backward-compatibility. This is internal API.\n * @param message - message (as it observed in storage / service)\n * @returns whether the given message was unpacked\n *\n * @internal\n */\nexport function unpackRuntimeMessage(\n\tmessage: ISequencedDocumentMessage,\n\tlogLegacyCase: (codePath: string) => void = () => {},\n): boolean {\n\tif (message.type !== MessageType.Operation) {\n\t\t// Legacy format, but it's already \"unpacked\",\n\t\t// i.e. message.type is actually ContainerMessageType.\n\t\t// Or it's non-runtime message.\n\t\t// Nothing to do in such case.\n\t\treturn false;\n\t}\n\n\t// legacy op format?\n\t// TODO: Unsure if this is a real format we should be concerned with. There doesn't appear to be anything prepared to handle the address member.\n\tif (\n\t\t(message.contents as { address?: unknown }).address !== undefined &&\n\t\t(message.contents as { type?: unknown }).type === undefined\n\t) {\n\t\tmessage.type = ContainerMessageType.FluidDataStoreOp;\n\t\tlogLegacyCase(\"unpackRuntimeMessage_contentsWithAddress\");\n\t} else {\n\t\t// new format\n\t\tunpack(message);\n\t}\n\n\treturn true;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"remoteMessageProcessor.js","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tMessageType,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/driver-definitions/internal\";\n\nimport {\n\tContainerMessageType,\n\ttype InboundContainerRuntimeMessage,\n\ttype InboundSequencedContainerRuntimeMessage,\n} from \"../messageTypes.js\";\nimport { asBatchMetadata } from \"../metadata.js\";\n\nimport { OpDecompressor } from \"./opDecompressor.js\";\nimport { OpGroupingManager, isGroupedBatch } from \"./opGroupingManager.js\";\nimport { OpSplitter, isChunkedMessage } from \"./opSplitter.js\";\n/**\n * Info about the batch we learn when we process the first message\n */\nexport interface BatchStartInfo {\n\t/**\n\t * Batch ID, if present\n\t */\n\treadonly batchId: string | undefined;\n\t/**\n\t * clientId that sent this batch. Used to compute Batch ID if needed\n\t */\n\treadonly clientId: string;\n\t/**\n\t * Client Sequence Number of the Grouped Batch message, or the first message in the ungrouped batch.\n\t * Used to compute Batch ID if needed\n\t *\n\t * @remarks For chunked batches, this is the CSN of the \"representative\" chunk (the final chunk).\n\t * For grouped batches, clientSequenceNumber on messages is overwritten, so we track this original value here.\n\t */\n\treadonly batchStartCsn: number;\n\t/**\n\t * The first message in the batch, or if the batch is empty, the empty grouped batch message.\n\t * Used for accessing the sequence numbers for the (start of the) batch.\n\t *\n\t * @remarks Do not use clientSequenceNumber here, use batchStartCsn instead.\n\t */\n\treadonly keyMessage: ISequencedDocumentMessage;\n}\n\n/**\n * Result of processing the next inbound message.\n * Depending on the message and configuration of RemoteMessageProcessor, the result may be:\n * - A full batch of messages (including a single-message batch)\n * - The first message of a multi-message batch\n * - The next message in a multi-message batch\n */\nexport type InboundMessageResult =\n\t| {\n\t\t\ttype: \"fullBatch\";\n\t\t\tmessages: InboundSequencedContainerRuntimeMessage[];\n\t\t\tbatchStart: BatchStartInfo;\n\t\t\tlength: number;\n\t\t\tgroupedBatch: boolean; // Messages in a grouped batches are sent to the runtime in bunches.\n\t }\n\t| {\n\t\t\ttype: \"batchStartingMessage\";\n\t\t\tbatchStart: BatchStartInfo;\n\t\t\tnextMessage: InboundSequencedContainerRuntimeMessage;\n\t\t\tlength?: never;\n\t }\n\t| {\n\t\t\ttype: \"nextBatchMessage\";\n\t\t\tbatchEnd?: boolean;\n\t\t\tnextMessage: InboundSequencedContainerRuntimeMessage;\n\t\t\tlength?: never;\n\t };\n\nfunction assertHasClientId(\n\tmessage: ISequencedDocumentMessage,\n): asserts message is ISequencedDocumentMessage & { clientId: string } {\n\tassert(\n\t\tmessage.clientId !== null,\n\t\t0xa02 /* Server-generated message should not reach RemoteMessageProcessor */,\n\t);\n}\n\n/**\n * Stateful class for processing incoming remote messages as the virtualization measures are unwrapped,\n * potentially across numerous inbound ops.\n *\n * @internal\n */\nexport class RemoteMessageProcessor {\n\tprivate batchInProgress: boolean = false;\n\n\tconstructor(\n\t\tprivate readonly opSplitter: OpSplitter,\n\t\tprivate readonly opDecompressor: OpDecompressor,\n\t\tprivate readonly opGroupingManager: OpGroupingManager,\n\t) {}\n\n\tpublic get partialMessages(): ReadonlyMap<string, string[]> {\n\t\treturn this.opSplitter.chunks;\n\t}\n\n\tpublic clearPartialMessagesFor(clientId: string): void {\n\t\tthis.opSplitter.clearPartialChunks(clientId);\n\t}\n\n\t/**\n\t * Ungroups and Unchunks the runtime ops of a batch received over the wire\n\t * @param remoteMessageCopy - A shallow copy of a message from another client, possibly virtualized\n\t * (grouped, compressed, and/or chunked).\n\t * Being a shallow copy, it's considered mutable, meaning no other Container or other parallel procedure\n\t * depends on this object instance.\n\t * Note remoteMessageCopy.contents (and other object props) MUST not be modified,\n\t * but may be overwritten (as is the case with contents).\n\t *\n\t * Incoming messages will always have compression, chunking, and grouped batching happen in a defined order and that order cannot be changed.\n\t * When processing these messages, the order is:\n\t * 1. If chunked, process the chunk and only continue if this is a final chunk\n\t * 2. If compressed, decompress the message and store for further unrolling of the decompressed content\n\t * 3. If grouped, ungroup the message\n\t * For more details, see https://github.com/microsoft/FluidFramework/blob/main/packages/runtime/container-runtime/src/opLifecycle/README.md#inbound\n\t *\n\t * @returns all the unchunked, decompressed, ungrouped, unpacked InboundSequencedContainerRuntimeMessage from a single batch\n\t * or undefined if the batch is not yet complete.\n\t */\n\tpublic process(\n\t\tremoteMessageCopy: ISequencedDocumentMessage,\n\t\tlogLegacyCase: (codePath: string) => void,\n\t): InboundMessageResult | undefined {\n\t\tlet message = remoteMessageCopy;\n\n\t\tassertHasClientId(message);\n\t\tconst clientId = message.clientId;\n\n\t\tif (isChunkedMessage(message)) {\n\t\t\tconst chunkProcessingResult = this.opSplitter.processChunk(message);\n\t\t\t// Only continue further if current chunk is the final chunk\n\t\t\tif (!chunkProcessingResult.isFinalChunk) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\t// This message will always be compressed\n\t\t\tmessage = chunkProcessingResult.message;\n\t\t}\n\n\t\tif (this.opDecompressor.isCompressedMessage(message)) {\n\t\t\tthis.opDecompressor.decompressAndStore(message);\n\t\t}\n\n\t\tif (this.opDecompressor.currentlyUnrolling) {\n\t\t\tmessage = this.opDecompressor.unroll(message);\n\t\t\t// Need to unpack after unrolling if not a groupedBatch\n\t\t\tif (!isGroupedBatch(message)) {\n\t\t\t\tunpack(message);\n\t\t\t}\n\t\t}\n\n\t\tif (isGroupedBatch(message)) {\n\t\t\t// We should be awaiting a new batch (batchInProgress false)\n\t\t\tassert(!this.batchInProgress, 0x9d3 /* Grouped batch interrupting another batch */);\n\t\t\tconst batchId = asBatchMetadata(message.metadata)?.batchId;\n\t\t\tconst groupedMessages = this.opGroupingManager\n\t\t\t\t.ungroupOp(message)\n\t\t\t\t.map((innerMessage) => unpack(innerMessage));\n\n\t\t\treturn {\n\t\t\t\ttype: \"fullBatch\",\n\t\t\t\tmessages: groupedMessages, // Will be [] for an empty batch\n\t\t\t\tbatchStart: {\n\t\t\t\t\tbatchStartCsn: message.clientSequenceNumber,\n\t\t\t\t\tclientId,\n\t\t\t\t\tbatchId,\n\t\t\t\t\tkeyMessage: groupedMessages[0] ?? message, // For an empty batch, this is the empty grouped batch message. Needed for sequence numbers for this batch\n\t\t\t\t},\n\t\t\t\tlength: groupedMessages.length, // Will be 0 for an empty batch\n\t\t\t\tgroupedBatch: true,\n\t\t\t};\n\t\t}\n\n\t\t// Do a final unpack of runtime messages in case the message was not grouped, compressed, or chunked\n\t\tunpackRuntimeMessage(message, logLegacyCase);\n\n\t\treturn this.getResultBasedOnBatchMetadata(\n\t\t\tmessage as InboundSequencedContainerRuntimeMessage & { clientId: string },\n\t\t);\n\t}\n\n\t/**\n\t * Now that the message has been \"unwrapped\" as to any virtualization (grouping, compression, chunking),\n\t * inspect the batch metadata flag and determine what kind of result to return.\n\t */\n\tprivate getResultBasedOnBatchMetadata(\n\t\tmessage: InboundSequencedContainerRuntimeMessage & { clientId: string },\n\t): InboundMessageResult {\n\t\tconst batchMetadataFlag = asBatchMetadata(message.metadata)?.batch;\n\t\tif (!this.batchInProgress) {\n\t\t\t// We are waiting for a new batch\n\t\t\tassert(batchMetadataFlag !== false, 0x9d5 /* Unexpected batch end marker */);\n\n\t\t\t// Start of a new multi-message batch\n\t\t\tif (batchMetadataFlag === true) {\n\t\t\t\tthis.batchInProgress = true;\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"batchStartingMessage\",\n\t\t\t\t\tbatchStart: {\n\t\t\t\t\t\tbatchId: asBatchMetadata(message.metadata)?.batchId,\n\t\t\t\t\t\tclientId: message.clientId,\n\t\t\t\t\t\tbatchStartCsn: message.clientSequenceNumber,\n\t\t\t\t\t\tkeyMessage: message,\n\t\t\t\t\t},\n\t\t\t\t\tnextMessage: message,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Single-message batch (Since metadata flag is undefined)\n\t\t\treturn {\n\t\t\t\ttype: \"fullBatch\",\n\t\t\t\tmessages: [message],\n\t\t\t\tbatchStart: {\n\t\t\t\t\tbatchStartCsn: message.clientSequenceNumber,\n\t\t\t\t\tclientId: message.clientId,\n\t\t\t\t\tbatchId: asBatchMetadata(message.metadata)?.batchId,\n\t\t\t\t\tkeyMessage: message,\n\t\t\t\t},\n\t\t\t\tlength: 1,\n\t\t\t\tgroupedBatch: false,\n\t\t\t};\n\t\t}\n\t\tassert(batchMetadataFlag !== true, 0x9d6 /* Unexpected batch start marker */);\n\n\t\t// Clear batchInProgress state if the batch is ending\n\t\tif (batchMetadataFlag === false) {\n\t\t\tthis.batchInProgress = false;\n\t\t}\n\n\t\treturn {\n\t\t\ttype: \"nextBatchMessage\",\n\t\t\tnextMessage: message,\n\t\t\tbatchEnd: batchMetadataFlag === false,\n\t\t};\n\t}\n}\n\n/**\n * For a given message, it moves the nested InboundContainerRuntimeMessage props one level up.\n *\n * The return type illustrates the assumption that the message param\n * becomes a InboundSequencedContainerRuntimeMessage by the time the function returns\n * (but there is no runtime validation of the 'type').\n */\nfunction unpack(message: ISequencedDocumentMessage): InboundSequencedContainerRuntimeMessage {\n\t// We assume the contents is an InboundContainerRuntimeMessage (the message is \"packed\")\n\tconst contents = message.contents as InboundContainerRuntimeMessage;\n\n\t// We're going to unpack message in-place (promoting those properties of contents up to message itself)\n\tconst messageUnpacked = message as InboundSequencedContainerRuntimeMessage;\n\n\tmessageUnpacked.type = contents.type;\n\tmessageUnpacked.contents = contents.contents;\n\treturn messageUnpacked;\n}\n\n/**\n * Unpacks runtime messages.\n *\n * @remarks This API makes no promises regarding backward-compatibility. This is internal API.\n * @param message - message (as it observed in storage / service)\n * @returns whether the given message was unpacked\n *\n * @internal\n */\nexport function unpackRuntimeMessage(\n\tmessage: ISequencedDocumentMessage,\n\tlogLegacyCase: (codePath: string) => void = () => {},\n): boolean {\n\tif (message.type !== MessageType.Operation) {\n\t\t// Legacy format, but it's already \"unpacked\",\n\t\t// i.e. message.type is actually ContainerMessageType.\n\t\t// Or it's non-runtime message.\n\t\t// Nothing to do in such case.\n\t\treturn false;\n\t}\n\n\t// legacy op format?\n\t// TODO: Unsure if this is a real format we should be concerned with. There doesn't appear to be anything prepared to handle the address member.\n\tif (\n\t\t(message.contents as { address?: unknown }).address !== undefined &&\n\t\t(message.contents as { type?: unknown }).type === undefined\n\t) {\n\t\tmessage.type = ContainerMessageType.FluidDataStoreOp;\n\t\tlogLegacyCase(\"unpackRuntimeMessage_contentsWithAddress\");\n\t} else {\n\t\t// new format\n\t\tunpack(message);\n\t}\n\n\treturn true;\n}\n"]}
|
package/dist/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/container-runtime";
|
|
8
|
-
export declare const pkgVersion = "2.
|
|
8
|
+
export declare const pkgVersion = "2.32.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/dist/packageVersion.js
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.pkgVersion = exports.pkgName = void 0;
|
|
10
10
|
exports.pkgName = "@fluidframework/container-runtime";
|
|
11
|
-
exports.pkgVersion = "2.
|
|
11
|
+
exports.pkgVersion = "2.32.0";
|
|
12
12
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,mCAAmC,CAAC;AAC9C,QAAA,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-runtime\";\nexport const pkgVersion = \"2.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,mCAAmC,CAAC;AAC9C,QAAA,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/container-runtime\";\nexport const pkgVersion = \"2.32.0\";\n"]}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { IDisposable, type ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
6
6
|
import { type InboundSequencedContainerRuntimeMessage } from "./messageTypes.js";
|
|
7
|
-
import { BatchId,
|
|
7
|
+
import { BatchId, LocalBatchMessage, InboundMessageResult } from "./opLifecycle/index.js";
|
|
8
8
|
/**
|
|
9
9
|
* This represents a message that has been submitted and is added to the pending queue when `submit` is called on the
|
|
10
10
|
* ContainerRuntime. This message has either not been ack'd by the server or has not been submitted to the server yet.
|
|
@@ -123,7 +123,7 @@ export declare class PendingStateManager implements IDisposable {
|
|
|
123
123
|
* or undefined if the batch was not yet sent (e.g. by the time we flushed we lost the connection)
|
|
124
124
|
* @param ignoreBatchId - Whether to ignore the batchId in the batchStartInfo
|
|
125
125
|
*/
|
|
126
|
-
onFlushBatch(batch:
|
|
126
|
+
onFlushBatch(batch: LocalBatchMessage[], clientSequenceNumber: number | undefined, ignoreBatchId?: boolean): void;
|
|
127
127
|
/**
|
|
128
128
|
* Applies stashed ops at their reference sequence number so they are ready to be ACKed or resubmitted
|
|
129
129
|
* @param seqNum - Sequence number at which to apply ops. Will apply all ops if seqNum is undefined.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pendingStateManager.d.ts","sourceRoot":"","sources":["../src/pendingStateManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,KAAK,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAYzF,OAAO,EAEN,KAAK,uCAAuC,EAE5C,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACN,OAAO,EACP,
|
|
1
|
+
{"version":3,"file":"pendingStateManager.d.ts","sourceRoot":"","sources":["../src/pendingStateManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -178,7 +178,7 @@ class PendingStateManager {
|
|
|
178
178
|
: [(0, uuid_1.v4)(), -1]; // -1 will indicate not a real clientId/CSN pair
|
|
179
179
|
(0, internal_1.assert)(clientId !== undefined, 0xa33 /* clientId (from stateHandler) could only be undefined if we've never connected, but we have a CSN so we know that's not the case */);
|
|
180
180
|
for (const message of batch) {
|
|
181
|
-
const {
|
|
181
|
+
const { serializedOp: content, referenceSequenceNumber, localOpMetadata, metadata: opMetadata, } = message;
|
|
182
182
|
const pendingMessage = {
|
|
183
183
|
type: "message",
|
|
184
184
|
referenceSequenceNumber,
|