@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
package/src/dataStoreContext.ts
CHANGED
|
@@ -9,8 +9,6 @@ import { IDeltaManager } from "@fluidframework/container-definitions/internal";
|
|
|
9
9
|
import {
|
|
10
10
|
FluidObject,
|
|
11
11
|
IDisposable,
|
|
12
|
-
IRequest,
|
|
13
|
-
IResponse,
|
|
14
12
|
ITelemetryBaseProperties,
|
|
15
13
|
type IEvent,
|
|
16
14
|
} from "@fluidframework/core-interfaces";
|
|
@@ -796,15 +794,6 @@ export abstract class FluidDataStoreContext
|
|
|
796
794
|
this.parentContext.addedGCOutboundRoute(fromPath, toPath, messageTimestampMs);
|
|
797
795
|
}
|
|
798
796
|
|
|
799
|
-
// eslint-disable-next-line jsdoc/require-description
|
|
800
|
-
/**
|
|
801
|
-
* @deprecated 0.18.Should call request on the runtime directly
|
|
802
|
-
*/
|
|
803
|
-
public async request(request: IRequest): Promise<IResponse> {
|
|
804
|
-
const runtime = await this.realize();
|
|
805
|
-
return runtime.request(request);
|
|
806
|
-
}
|
|
807
|
-
|
|
808
797
|
public submitMessage(type: string, content: unknown, localOpMetadata: unknown): void {
|
|
809
798
|
this.verifyNotClosed("submitMessage");
|
|
810
799
|
assert(!!this.channel, 0x146 /* "Channel must exist when submitting message" */);
|
package/src/index.ts
CHANGED
|
@@ -27,7 +27,6 @@ export { IBlobManagerLoadInfo } from "./blobManager/index.js";
|
|
|
27
27
|
export { FluidDataStoreRegistry } from "./dataStoreRegistry.js";
|
|
28
28
|
export {
|
|
29
29
|
detectOutboundReferences,
|
|
30
|
-
RuntimeHeaders,
|
|
31
30
|
ChannelCollectionFactory,
|
|
32
31
|
AllowTombstoneRequestHeaderKey,
|
|
33
32
|
} from "./channelCollection.js";
|
package/src/messageTypes.ts
CHANGED
|
@@ -147,12 +147,12 @@ export type InboundContainerRuntimeMessage =
|
|
|
147
147
|
| ContainerRuntimeAliasMessage
|
|
148
148
|
| ContainerRuntimeIdAllocationMessage
|
|
149
149
|
| ContainerRuntimeGCMessage
|
|
150
|
+
| ContainerRuntimeDocumentSchemaMessage
|
|
150
151
|
// Inbound messages may include unknown types from other clients, so we include that as a special case here
|
|
151
|
-
| UnknownContainerRuntimeMessage
|
|
152
|
-
| ContainerRuntimeDocumentSchemaMessage;
|
|
152
|
+
| UnknownContainerRuntimeMessage;
|
|
153
153
|
|
|
154
154
|
/**
|
|
155
|
-
* A {@link TypedContainerRuntimeMessage} that has been generated by the container runtime
|
|
155
|
+
* A {@link TypedContainerRuntimeMessage} that has been generated by the container runtime, eventually to be sent to the ordering service.
|
|
156
156
|
* These are messages generated by the local runtime, before the outbox's op virtualization step.
|
|
157
157
|
*/
|
|
158
158
|
export type LocalContainerRuntimeMessage =
|
|
@@ -163,23 +163,9 @@ export type LocalContainerRuntimeMessage =
|
|
|
163
163
|
| ContainerRuntimeAliasMessage
|
|
164
164
|
| ContainerRuntimeIdAllocationMessage
|
|
165
165
|
| ContainerRuntimeGCMessage
|
|
166
|
+
| ContainerRuntimeDocumentSchemaMessage
|
|
166
167
|
// In rare cases (e.g. related to stashed ops) we could have a local message of an unknown type
|
|
167
|
-
| UnknownContainerRuntimeMessage
|
|
168
|
-
| ContainerRuntimeDocumentSchemaMessage;
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* A {@link TypedContainerRuntimeMessage} that is being sent to the server from the container runtime.
|
|
172
|
-
*/
|
|
173
|
-
export type OutboundContainerRuntimeMessage =
|
|
174
|
-
| ContainerRuntimeDataStoreOpMessage
|
|
175
|
-
| OutboundContainerRuntimeAttachMessage
|
|
176
|
-
| ContainerRuntimeChunkedOpMessage
|
|
177
|
-
| ContainerRuntimeBlobAttachMessage
|
|
178
|
-
| ContainerRuntimeRejoinMessage
|
|
179
|
-
| ContainerRuntimeAliasMessage
|
|
180
|
-
| ContainerRuntimeIdAllocationMessage
|
|
181
|
-
| ContainerRuntimeGCMessage
|
|
182
|
-
| ContainerRuntimeDocumentSchemaMessage;
|
|
168
|
+
| UnknownContainerRuntimeMessage;
|
|
183
169
|
|
|
184
170
|
/**
|
|
185
171
|
* An unpacked ISequencedDocumentMessage with the inner TypedContainerRuntimeMessage type/contents/etc
|
|
@@ -14,7 +14,12 @@ import { ICompressionRuntimeOptions } from "../containerRuntime.js";
|
|
|
14
14
|
import { asBatchMetadata, type IBatchMetadata } from "../metadata.js";
|
|
15
15
|
import type { IPendingMessage } from "../pendingStateManager.js";
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
LocalBatchMessage,
|
|
19
|
+
IBatchCheckpoint,
|
|
20
|
+
type LocalBatch,
|
|
21
|
+
type OutboundBatch,
|
|
22
|
+
} from "./definitions.js";
|
|
18
23
|
import type { BatchStartInfo } from "./remoteMessageProcessor.js";
|
|
19
24
|
|
|
20
25
|
export interface IBatchManagerOptions {
|
|
@@ -83,7 +88,7 @@ const opOverhead = 200;
|
|
|
83
88
|
* Helper class that manages partial batch & rollback.
|
|
84
89
|
*/
|
|
85
90
|
export class BatchManager {
|
|
86
|
-
private pendingBatch:
|
|
91
|
+
private pendingBatch: LocalBatchMessage[] = [];
|
|
87
92
|
private batchContentSize = 0;
|
|
88
93
|
private hasReentrantOps = false;
|
|
89
94
|
|
|
@@ -117,11 +122,11 @@ export class BatchManager {
|
|
|
117
122
|
constructor(public readonly options: IBatchManagerOptions) {}
|
|
118
123
|
|
|
119
124
|
public push(
|
|
120
|
-
message:
|
|
125
|
+
message: LocalBatchMessage,
|
|
121
126
|
reentrant: boolean,
|
|
122
127
|
currentClientSequenceNumber?: number,
|
|
123
128
|
): boolean {
|
|
124
|
-
const contentSize = this.batchContentSize + (message.
|
|
129
|
+
const contentSize = this.batchContentSize + (message.serializedOp?.length ?? 0);
|
|
125
130
|
const opCount = this.pendingBatch.length;
|
|
126
131
|
this.hasReentrantOps = this.hasReentrantOps || reentrant;
|
|
127
132
|
|
|
@@ -152,8 +157,8 @@ export class BatchManager {
|
|
|
152
157
|
/**
|
|
153
158
|
* Gets the pending batch and clears state for the next batch.
|
|
154
159
|
*/
|
|
155
|
-
public popBatch(batchId?: BatchId):
|
|
156
|
-
const batch:
|
|
160
|
+
public popBatch(batchId?: BatchId): LocalBatch {
|
|
161
|
+
const batch: LocalBatch = {
|
|
157
162
|
messages: this.pendingBatch,
|
|
158
163
|
contentSizeInBytes: this.batchContentSize,
|
|
159
164
|
referenceSequenceNumber: this.referenceSequenceNumber,
|
|
@@ -175,19 +180,21 @@ export class BatchManager {
|
|
|
175
180
|
const startSequenceNumber = this.clientSequenceNumber;
|
|
176
181
|
const startPoint = this.pendingBatch.length;
|
|
177
182
|
return {
|
|
178
|
-
rollback: (process: (message:
|
|
183
|
+
rollback: (process: (message: LocalBatchMessage) => void) => {
|
|
179
184
|
this.clientSequenceNumber = startSequenceNumber;
|
|
180
185
|
const rollbackOpsLifo = this.pendingBatch.splice(startPoint).reverse();
|
|
181
186
|
for (const message of rollbackOpsLifo) {
|
|
182
|
-
this.batchContentSize -= message.
|
|
187
|
+
this.batchContentSize -= message.serializedOp?.length ?? 0;
|
|
183
188
|
process(message);
|
|
184
189
|
}
|
|
185
190
|
const count = this.pendingBatch.length - startPoint;
|
|
186
191
|
if (count !== 0) {
|
|
187
|
-
throw new LoggingError("Ops generated
|
|
192
|
+
throw new LoggingError("Ops generated during rollback", {
|
|
188
193
|
count,
|
|
189
194
|
...tagData(TelemetryDataTag.UserData, {
|
|
190
|
-
ops: JSON.stringify(
|
|
195
|
+
ops: JSON.stringify(
|
|
196
|
+
this.pendingBatch.slice(startPoint).map((b) => b.serializedOp),
|
|
197
|
+
),
|
|
191
198
|
}),
|
|
192
199
|
});
|
|
193
200
|
}
|
|
@@ -196,7 +203,7 @@ export class BatchManager {
|
|
|
196
203
|
}
|
|
197
204
|
}
|
|
198
205
|
|
|
199
|
-
const addBatchMetadata = (batch:
|
|
206
|
+
const addBatchMetadata = (batch: LocalBatch, batchId?: BatchId): LocalBatch => {
|
|
200
207
|
const batchEnd = batch.messages.length - 1;
|
|
201
208
|
|
|
202
209
|
const firstMsg = batch.messages[0];
|
|
@@ -234,7 +241,7 @@ const addBatchMetadata = (batch: IBatch, batchId?: BatchId): IBatch => {
|
|
|
234
241
|
* @param batch - the batch to inspect
|
|
235
242
|
* @returns An estimate of the payload size in bytes which will be produced when the batch is sent over the wire
|
|
236
243
|
*/
|
|
237
|
-
export const estimateSocketSize = (batch:
|
|
244
|
+
export const estimateSocketSize = (batch: OutboundBatch): number => {
|
|
238
245
|
return batch.contentSizeInBytes + opOverhead * batch.messages.length;
|
|
239
246
|
};
|
|
240
247
|
|
|
@@ -3,23 +3,62 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { IBatchMessage } from "@fluidframework/container-definitions/internal";
|
|
6
|
+
import type { IBatchMessage } from "@fluidframework/container-definitions/internal";
|
|
7
7
|
|
|
8
8
|
import { CompressionAlgorithms } from "../containerRuntime.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Batch message
|
|
11
|
+
* Local Batch message, before it is virtualized and sent to the ordering service
|
|
12
12
|
*/
|
|
13
|
-
export
|
|
13
|
+
export interface LocalBatchMessage {
|
|
14
|
+
serializedOp: string;
|
|
15
|
+
metadata?: Record<string, unknown>;
|
|
14
16
|
localOpMetadata?: unknown;
|
|
15
17
|
referenceSequenceNumber: number;
|
|
16
18
|
compression?: CompressionAlgorithms;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @deprecated Use serializedOp
|
|
22
|
+
*/
|
|
23
|
+
contents?: never; // To ensure we don't leave this one when converting from OutboundBatchMessage
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Virtualized Batch message, on its way out the door to the ordering service
|
|
28
|
+
*/
|
|
29
|
+
export type OutboundBatchMessage = IBatchMessage & {
|
|
30
|
+
localOpMetadata?: unknown;
|
|
31
|
+
referenceSequenceNumber: number;
|
|
32
|
+
compression?: CompressionAlgorithms;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @deprecated Use contents
|
|
36
|
+
*/
|
|
37
|
+
serializedOp?: never; // To ensure we don't leave this one when converting from LocalBatchMessage
|
|
17
38
|
};
|
|
18
39
|
|
|
19
40
|
/**
|
|
20
|
-
*
|
|
41
|
+
* A batch of messages we have accumulated locally, but haven't sent to the ordering service yet.
|
|
42
|
+
*/
|
|
43
|
+
export type LocalBatch = IBatch<LocalBatchMessage[]>;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A batch of messages that has been virtualized as needed (grouped, compressed, chunked)
|
|
47
|
+
* and is ready to be sent to the ordering service.
|
|
48
|
+
*/
|
|
49
|
+
export type OutboundBatch = IBatch<OutboundBatchMessage[]>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* An {@link OutboundBatch} with exactly one message
|
|
53
|
+
* This type is helpful as Grouping yields this kind of batch, and Compression only operates on this type of batch.
|
|
54
|
+
*/
|
|
55
|
+
export type OutboundSingletonBatch = IBatch<[OutboundBatchMessage]>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Base batch interface used internally by the runtime.
|
|
59
|
+
* See {@link LocalBatch} and {@link OutboundBatch} for the concrete types.
|
|
21
60
|
*/
|
|
22
|
-
|
|
61
|
+
interface IBatch<TMessages extends LocalBatchMessage[] | OutboundBatchMessage[]> {
|
|
23
62
|
/**
|
|
24
63
|
* Sum of the in-memory content sizes of all messages in the batch.
|
|
25
64
|
* If the batch is compressed, this number reflects the post-compression size.
|
|
@@ -47,7 +86,7 @@ export interface IBatch<TMessages extends BatchMessage[] = BatchMessage[]> {
|
|
|
47
86
|
}
|
|
48
87
|
|
|
49
88
|
export interface IBatchCheckpoint {
|
|
50
|
-
rollback: (action: (message:
|
|
89
|
+
rollback: (action: (message: LocalBatchMessage) => void) => void;
|
|
51
90
|
}
|
|
52
91
|
|
|
53
92
|
/**
|
package/src/opLifecycle/index.ts
CHANGED
|
@@ -12,14 +12,25 @@ export {
|
|
|
12
12
|
generateBatchId,
|
|
13
13
|
IBatchManagerOptions,
|
|
14
14
|
} from "./batchManager.js";
|
|
15
|
-
export {
|
|
15
|
+
export {
|
|
16
|
+
LocalBatch,
|
|
17
|
+
LocalBatchMessage,
|
|
18
|
+
OutboundBatch,
|
|
19
|
+
OutboundBatchMessage,
|
|
20
|
+
OutboundSingletonBatch,
|
|
21
|
+
IBatchCheckpoint,
|
|
22
|
+
IChunkedOp,
|
|
23
|
+
} from "./definitions.js";
|
|
16
24
|
export { DuplicateBatchDetector } from "./duplicateBatchDetector.js";
|
|
17
|
-
export {
|
|
25
|
+
export {
|
|
26
|
+
serializeOp,
|
|
27
|
+
ensureContentsDeserialized,
|
|
28
|
+
} from "./opSerialization.js";
|
|
29
|
+
export { Outbox, getLongStack } from "./outbox.js";
|
|
18
30
|
export { OpCompressor } from "./opCompressor.js";
|
|
19
31
|
export { OpDecompressor } from "./opDecompressor.js";
|
|
20
32
|
export { OpSplitter, splitOp, isChunkedMessage } from "./opSplitter.js";
|
|
21
33
|
export {
|
|
22
|
-
ensureContentsDeserialized,
|
|
23
34
|
InboundMessageResult,
|
|
24
35
|
BatchStartInfo,
|
|
25
36
|
RemoteMessageProcessor,
|
|
@@ -7,7 +7,7 @@ import { IsoBuffer } from "@fluid-internal/client-utils";
|
|
|
7
7
|
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
8
8
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
9
9
|
import {
|
|
10
|
-
|
|
10
|
+
DataProcessingError,
|
|
11
11
|
createChildLogger,
|
|
12
12
|
type ITelemetryLoggerExt,
|
|
13
13
|
} from "@fluidframework/telemetry-utils/internal";
|
|
@@ -16,12 +16,13 @@ import { compress } from "lz4js";
|
|
|
16
16
|
import { CompressionAlgorithms } from "../containerRuntime.js";
|
|
17
17
|
|
|
18
18
|
import { estimateSocketSize } from "./batchManager.js";
|
|
19
|
-
import {
|
|
19
|
+
import { type OutboundBatchMessage, type OutboundSingletonBatch } from "./definitions.js";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* Compresses batches of ops.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
22
|
+
* Compresses batches of ops.
|
|
23
|
+
*
|
|
24
|
+
* @remarks Only single-message batches are supported
|
|
25
|
+
* Use opGroupingManager to group a batch into a singleton batch suitable for compression.
|
|
25
26
|
*/
|
|
26
27
|
export class OpCompressor {
|
|
27
28
|
private readonly logger: ITelemetryLoggerExt;
|
|
@@ -31,14 +32,12 @@ export class OpCompressor {
|
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
|
-
* Combines the contents of the batch into a single JSON string and compresses it, putting
|
|
35
|
-
* the resulting string as the
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* @param batch - The batch to compress
|
|
39
|
-
* @returns A batch of the same length as the input batch, containing a single compressed message followed by empty placeholders
|
|
35
|
+
* Combines the contents of the singleton batch into a single JSON string and compresses it, putting
|
|
36
|
+
* the resulting string as the message contents in place of the original uncompressed payload.
|
|
37
|
+
* @param batch - The batch to compress. Must have only 1 message
|
|
38
|
+
* @returns A singleton batch containing a single compressed message
|
|
40
39
|
*/
|
|
41
|
-
public compressBatch(batch:
|
|
40
|
+
public compressBatch(batch: OutboundSingletonBatch): OutboundSingletonBatch {
|
|
42
41
|
assert(
|
|
43
42
|
batch.contentSizeInBytes > 0 && batch.messages.length === 1,
|
|
44
43
|
0x5a4 /* Batch should not be empty and should contain a single message */,
|
|
@@ -50,7 +49,7 @@ export class OpCompressor {
|
|
|
50
49
|
const compressedContent = IsoBuffer.from(compressedContents).toString("base64");
|
|
51
50
|
const duration = Date.now() - compressionStart;
|
|
52
51
|
|
|
53
|
-
const messages: [
|
|
52
|
+
const messages: [OutboundBatchMessage] = [
|
|
54
53
|
{
|
|
55
54
|
...batch.messages[0],
|
|
56
55
|
contents: JSON.stringify({ packedContents: compressedContent }),
|
|
@@ -59,7 +58,7 @@ export class OpCompressor {
|
|
|
59
58
|
},
|
|
60
59
|
];
|
|
61
60
|
|
|
62
|
-
const compressedBatch = {
|
|
61
|
+
const compressedBatch: OutboundSingletonBatch = {
|
|
63
62
|
contentSizeInBytes: compressedContent.length,
|
|
64
63
|
messages,
|
|
65
64
|
referenceSequenceNumber: batch.referenceSequenceNumber,
|
|
@@ -82,27 +81,29 @@ export class OpCompressor {
|
|
|
82
81
|
/**
|
|
83
82
|
* Combine the batch's content strings into a single JSON string (a serialized array)
|
|
84
83
|
*/
|
|
85
|
-
private serializeBatchContents(batch:
|
|
84
|
+
private serializeBatchContents(batch: OutboundSingletonBatch): string {
|
|
85
|
+
const [message, ...none] = batch.messages;
|
|
86
|
+
assert(none.length === 0, 0xb78 /* Batch should only contain a single message */);
|
|
86
87
|
try {
|
|
87
|
-
//
|
|
88
|
-
return `[${
|
|
89
|
-
} catch (
|
|
90
|
-
if ((
|
|
91
|
-
// This is how
|
|
88
|
+
// This is expressed as a JSON array, for legacy reasons
|
|
89
|
+
return `[${message.contents}]`;
|
|
90
|
+
} catch (error: unknown) {
|
|
91
|
+
if ((error as Partial<Error>).message === "Invalid string length") {
|
|
92
|
+
// This is how string interpolation signals that
|
|
92
93
|
// the content size exceeds its capacity
|
|
93
|
-
const
|
|
94
|
+
const dpe = DataProcessingError.create("Payload too large", "OpCompressor");
|
|
94
95
|
this.logger.sendErrorEvent(
|
|
95
96
|
{
|
|
96
97
|
eventName: "BatchTooLarge",
|
|
97
98
|
size: batch.contentSizeInBytes,
|
|
98
99
|
length: batch.messages.length,
|
|
99
100
|
},
|
|
100
|
-
|
|
101
|
+
dpe,
|
|
101
102
|
);
|
|
102
|
-
throw
|
|
103
|
+
throw dpe;
|
|
103
104
|
}
|
|
104
105
|
|
|
105
|
-
throw
|
|
106
|
+
throw error;
|
|
106
107
|
}
|
|
107
108
|
}
|
|
108
109
|
}
|
|
@@ -11,7 +11,11 @@ import {
|
|
|
11
11
|
type ITelemetryLoggerExt,
|
|
12
12
|
} from "@fluidframework/telemetry-utils/internal";
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
type OutboundBatch,
|
|
16
|
+
type OutboundBatchMessage,
|
|
17
|
+
type OutboundSingletonBatch,
|
|
18
|
+
} from "./definitions.js";
|
|
15
19
|
|
|
16
20
|
/**
|
|
17
21
|
* Grouping makes assumptions about the shape of message contents. This interface codifies those assumptions, but does not validate them.
|
|
@@ -58,44 +62,51 @@ export class OpGroupingManager {
|
|
|
58
62
|
* This is needed as a placeholder if a batch becomes empty on resubmit, but we are tracking batch IDs.
|
|
59
63
|
* @param resubmittingBatchId - batch ID of the resubmitting batch
|
|
60
64
|
* @param referenceSequenceNumber - reference sequence number
|
|
61
|
-
* @returns -
|
|
65
|
+
* @returns - The outbound batch as well as the interior placeholder message
|
|
62
66
|
*/
|
|
63
67
|
public createEmptyGroupedBatch(
|
|
64
68
|
resubmittingBatchId: string,
|
|
65
69
|
referenceSequenceNumber: number,
|
|
66
|
-
):
|
|
70
|
+
): { outboundBatch: OutboundSingletonBatch; placeholderMessage: OutboundBatchMessage } {
|
|
67
71
|
assert(
|
|
68
72
|
this.config.groupedBatchingEnabled,
|
|
69
73
|
0xa00 /* cannot create empty grouped batch when grouped batching is disabled */,
|
|
70
74
|
);
|
|
71
|
-
const
|
|
75
|
+
const serializedOp = JSON.stringify({
|
|
72
76
|
type: OpGroupingManager.groupedBatchOp,
|
|
73
77
|
contents: [],
|
|
74
78
|
});
|
|
75
79
|
|
|
76
|
-
|
|
80
|
+
const placeholderMessage: OutboundBatchMessage = {
|
|
81
|
+
metadata: { batchId: resubmittingBatchId },
|
|
82
|
+
localOpMetadata: { emptyBatch: true },
|
|
83
|
+
referenceSequenceNumber,
|
|
84
|
+
contents: serializedOp,
|
|
85
|
+
};
|
|
86
|
+
const outboundBatch: OutboundSingletonBatch = {
|
|
77
87
|
contentSizeInBytes: 0,
|
|
78
|
-
messages: [
|
|
79
|
-
{
|
|
80
|
-
metadata: { batchId: resubmittingBatchId },
|
|
81
|
-
localOpMetadata: { emptyBatch: true },
|
|
82
|
-
referenceSequenceNumber,
|
|
83
|
-
contents: serializedContent,
|
|
84
|
-
},
|
|
85
|
-
],
|
|
88
|
+
messages: [placeholderMessage],
|
|
86
89
|
referenceSequenceNumber,
|
|
87
90
|
};
|
|
91
|
+
return { outboundBatch, placeholderMessage };
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
/**
|
|
91
95
|
* Converts the given batch into a "grouped batch" - a batch with a single message of type "groupedBatch",
|
|
92
96
|
* with contents being an array of the original batch's messages.
|
|
93
97
|
*
|
|
98
|
+
* If the batch already has only 1 message, it is returned as-is.
|
|
99
|
+
*
|
|
94
100
|
* @remarks - Remember that a BatchMessage has its content JSON serialized, so the incoming batch message contents
|
|
95
101
|
* must be parsed first, and then the type and contents mentioned above are hidden in that JSON serialization.
|
|
96
102
|
*/
|
|
97
|
-
public groupBatch(batch:
|
|
98
|
-
assert(this.
|
|
103
|
+
public groupBatch(batch: OutboundBatch): OutboundSingletonBatch {
|
|
104
|
+
assert(this.groupedBatchingEnabled(), 0xb79 /* grouping disabled! */);
|
|
105
|
+
assert(batch.messages.length > 0, 0xb7a /* Unexpected attempt to group an empty batch */);
|
|
106
|
+
|
|
107
|
+
if (batch.messages.length === 1) {
|
|
108
|
+
return batch as OutboundSingletonBatch;
|
|
109
|
+
}
|
|
99
110
|
|
|
100
111
|
if (batch.messages.length >= 1000) {
|
|
101
112
|
this.logger.sendTelemetryEvent({
|
|
@@ -126,7 +137,7 @@ export class OpGroupingManager {
|
|
|
126
137
|
})),
|
|
127
138
|
});
|
|
128
139
|
|
|
129
|
-
const groupedBatch:
|
|
140
|
+
const groupedBatch: OutboundSingletonBatch = {
|
|
130
141
|
...batch,
|
|
131
142
|
messages: [
|
|
132
143
|
{
|
|
@@ -153,16 +164,6 @@ export class OpGroupingManager {
|
|
|
153
164
|
}));
|
|
154
165
|
}
|
|
155
166
|
|
|
156
|
-
public shouldGroup(batch: IBatch): boolean {
|
|
157
|
-
return (
|
|
158
|
-
// Grouped batching must be enabled
|
|
159
|
-
this.config.groupedBatchingEnabled &&
|
|
160
|
-
// The number of ops in the batch must be 2 or more
|
|
161
|
-
// or be empty (to allow for empty batches to be grouped)
|
|
162
|
-
batch.messages.length !== 1
|
|
163
|
-
// Support for reentrant batches will be on by default
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
167
|
public groupedBatchingEnabled(): boolean {
|
|
167
168
|
return this.config.groupedBatchingEnabled;
|
|
168
169
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
|
|
7
|
+
import {
|
|
8
|
+
encodeHandleForSerialization,
|
|
9
|
+
isFluidHandle,
|
|
10
|
+
toFluidHandleInternal,
|
|
11
|
+
} from "@fluidframework/runtime-utils/internal";
|
|
12
|
+
|
|
13
|
+
import type { LocalContainerRuntimeMessage } from "../messageTypes.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Takes an incoming runtime message (outer type "op"), JSON.parses the message's contents in place,
|
|
17
|
+
* if needed (old Loader does this for us).
|
|
18
|
+
* Only to be used for runtime messages. The contents here would be the virtualized payload for a batch of ops.
|
|
19
|
+
* @remarks - Serialization during submit happens via {@link serializeOp}
|
|
20
|
+
* @param mutableMessage - op message received
|
|
21
|
+
*/
|
|
22
|
+
export function ensureContentsDeserialized(mutableMessage: ISequencedDocumentMessage): void {
|
|
23
|
+
// This should become unconditional once Loader LTS reaches 2.4 or later.
|
|
24
|
+
// There will be a long time of needing both cases, until LTS advances to that point.
|
|
25
|
+
if (typeof mutableMessage.contents === "string" && mutableMessage.contents !== "") {
|
|
26
|
+
mutableMessage.contents = JSON.parse(mutableMessage.contents);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Before submitting an op to the Outbox, its contents must be serialized using this function.
|
|
32
|
+
* @remarks - The deserialization on process happens via the function {@link ensureContentsDeserialized}.
|
|
33
|
+
*/
|
|
34
|
+
export function serializeOp(op: LocalContainerRuntimeMessage): string {
|
|
35
|
+
return JSON.stringify(
|
|
36
|
+
op,
|
|
37
|
+
// replacer:
|
|
38
|
+
(key, value: unknown) => {
|
|
39
|
+
// If 'value' is an IFluidHandle return its encoded form.
|
|
40
|
+
if (isFluidHandle(value)) {
|
|
41
|
+
return encodeHandleForSerialization(toFluidHandleInternal(value));
|
|
42
|
+
}
|
|
43
|
+
return value;
|
|
44
|
+
},
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -17,7 +17,11 @@ import {
|
|
|
17
17
|
import { ContainerMessageType, ContainerRuntimeChunkedOpMessage } from "../messageTypes.js";
|
|
18
18
|
|
|
19
19
|
import { estimateSocketSize } from "./batchManager.js";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
IChunkedOp,
|
|
22
|
+
type OutboundBatchMessage,
|
|
23
|
+
type OutboundSingletonBatch,
|
|
24
|
+
} from "./definitions.js";
|
|
21
25
|
|
|
22
26
|
export function isChunkedMessage(message: ISequencedDocumentMessage): boolean {
|
|
23
27
|
return isChunkedContents(message.contents);
|
|
@@ -96,8 +100,8 @@ export class OpSplitter {
|
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
103
|
+
* Takes a singleton batch, and splits the interior message into chunks, sending the chunks separately and
|
|
104
|
+
* returning a new singleton batch containing the last chunk.
|
|
101
105
|
*
|
|
102
106
|
* A compressed batch is formed by one large op at the first position.
|
|
103
107
|
*
|
|
@@ -108,21 +112,20 @@ export class OpSplitter {
|
|
|
108
112
|
* This will ensure that the batch semantics of the original (non-compressed) batch are preserved, as the original chunked op
|
|
109
113
|
* will be unrolled by the runtime when the first message in the batch is processed (as it is the last chunk).
|
|
110
114
|
*
|
|
111
|
-
* To handle legacy compressed batches with empty placeholders this method can attach the empty placeholder ops at the end
|
|
112
|
-
* of the result batch, ensuring that the batch semantics are preserved.
|
|
113
|
-
*
|
|
114
115
|
* To illustrate the current functionality, if the input is `[largeOp]`, `largeOp` will be split into `[chunk1, chunk2, chunk3, chunk4]`.
|
|
115
116
|
* `chunk1`, `chunk2` and `chunk3` will be sent individually and `[chunk4]` will be returned.
|
|
116
117
|
*
|
|
117
|
-
* With the legacy code, if the input is `[largeOp, emptyOp, emptyOp]`, `largeOp` will be split into `[chunk1, chunk2, chunk3, chunk4]`.
|
|
118
|
-
* `chunk1`, `chunk2` and `chunk3` will be sent individually and `[chunk4, emptyOp, emptyOp]` will be returned.
|
|
119
|
-
*
|
|
120
118
|
* @remarks - A side effect here is that 1 or more chunks are queued immediately for sending in next JS turn.
|
|
121
119
|
*
|
|
122
|
-
* @
|
|
123
|
-
*
|
|
120
|
+
* @privateRemarks
|
|
121
|
+
* This maintains support for splitting a compressed batch with multiple messages (empty placeholders after the first),
|
|
122
|
+
* but this is only used for Unit Tests so the typing has been updated to preclude that.
|
|
123
|
+
* That code should be moved out of this function into a test helper.
|
|
124
|
+
*
|
|
125
|
+
* @param batch - the compressed batch which needs to be split into chunks before being sent over the wire
|
|
126
|
+
* @returns A batch with the last chunk in place of the original complete compressed content
|
|
124
127
|
*/
|
|
125
|
-
public
|
|
128
|
+
public splitSingletonBatchMessage(batch: OutboundSingletonBatch): OutboundSingletonBatch {
|
|
126
129
|
assert(this.isBatchChunkingEnabled, 0x513 /* Chunking needs to be enabled */);
|
|
127
130
|
assert(
|
|
128
131
|
batch.contentSizeInBytes > 0 && batch.messages.length > 0,
|
|
@@ -138,13 +141,14 @@ export class OpSplitter {
|
|
|
138
141
|
0x516 /* Chunk size needs to be smaller than the max batch size */,
|
|
139
142
|
);
|
|
140
143
|
|
|
141
|
-
|
|
144
|
+
// first message is the large compressed op to split, and we expect restOfMessages to be empty
|
|
145
|
+
// (but we keep it here to support a legacy test case, wherein it contains empty placeholder messages)
|
|
146
|
+
const [firstMessage, ...restOfMessages] = batch.messages;
|
|
142
147
|
assert(
|
|
143
148
|
(firstMessage.contents?.length ?? 0) >= this.chunkSizeInBytes,
|
|
144
149
|
0x518 /* First message in the batch needs to be chunkable */,
|
|
145
150
|
);
|
|
146
151
|
|
|
147
|
-
const restOfMessages = batch.messages.slice(1); // we expect these to be empty ops, created to reserve sequence numbers
|
|
148
152
|
const socketSize = estimateSocketSize(batch);
|
|
149
153
|
const chunks = splitOp(
|
|
150
154
|
firstMessage,
|
|
@@ -243,7 +247,7 @@ const chunkToBatchMessage = (
|
|
|
243
247
|
chunk: IChunkedOp,
|
|
244
248
|
referenceSequenceNumber: number,
|
|
245
249
|
metadata: Record<string, unknown> | undefined = undefined,
|
|
246
|
-
):
|
|
250
|
+
): OutboundBatchMessage => {
|
|
247
251
|
const payload: ContainerRuntimeChunkedOpMessage = {
|
|
248
252
|
type: ContainerMessageType.ChunkedOp,
|
|
249
253
|
contents: chunk,
|
|
@@ -268,7 +272,7 @@ const chunkToBatchMessage = (
|
|
|
268
272
|
* @returns an array of chunked ops
|
|
269
273
|
*/
|
|
270
274
|
export const splitOp = (
|
|
271
|
-
op:
|
|
275
|
+
op: OutboundBatchMessage,
|
|
272
276
|
chunkSizeInBytes: number,
|
|
273
277
|
extraOp: boolean = false,
|
|
274
278
|
): IChunkedOp[] => {
|