@fluidframework/container-runtime 2.0.0-internal.6.3.3 → 2.0.0-internal.6.4.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/dist/blobManager.d.ts +3 -2
- package/dist/blobManager.d.ts.map +1 -1
- package/dist/blobManager.js +29 -25
- package/dist/blobManager.js.map +1 -1
- package/dist/containerRuntime.d.ts +14 -69
- package/dist/containerRuntime.d.ts.map +1 -1
- package/dist/containerRuntime.js +155 -184
- package/dist/containerRuntime.js.map +1 -1
- package/dist/dataStoreContext.d.ts.map +1 -1
- package/dist/dataStoreContext.js +3 -1
- package/dist/dataStoreContext.js.map +1 -1
- package/dist/dataStores.d.ts +1 -1
- package/dist/dataStores.js +3 -3
- package/dist/dataStores.js.map +1 -1
- package/dist/gc/garbageCollection.d.ts +6 -3
- package/dist/gc/garbageCollection.d.ts.map +1 -1
- package/dist/gc/garbageCollection.js +6 -3
- package/dist/gc/garbageCollection.js.map +1 -1
- package/dist/gc/gcDefinitions.d.ts +13 -2
- package/dist/gc/gcDefinitions.d.ts.map +1 -1
- package/dist/gc/gcDefinitions.js +14 -15
- package/dist/gc/gcDefinitions.js.map +1 -1
- package/dist/gc/gcHelpers.d.ts +0 -9
- package/dist/gc/gcHelpers.d.ts.map +1 -1
- package/dist/gc/gcHelpers.js +1 -13
- package/dist/gc/gcHelpers.js.map +1 -1
- package/dist/gc/gcTelemetry.d.ts.map +1 -1
- package/dist/gc/gcTelemetry.js +1 -4
- package/dist/gc/gcTelemetry.js.map +1 -1
- package/dist/gc/index.d.ts +2 -2
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +3 -4
- package/dist/gc/index.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/messageTypes.d.ts +134 -0
- package/dist/messageTypes.d.ts.map +1 -0
- package/dist/messageTypes.js +29 -0
- package/dist/messageTypes.js.map +1 -0
- package/dist/opLifecycle/definitions.d.ts +2 -1
- package/dist/opLifecycle/definitions.d.ts.map +1 -1
- package/dist/opLifecycle/definitions.js.map +1 -1
- package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/dist/opLifecycle/opDecompressor.js +0 -4
- package/dist/opLifecycle/opDecompressor.js.map +1 -1
- package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/dist/opLifecycle/opGroupingManager.js +4 -2
- package/dist/opLifecycle/opGroupingManager.js.map +1 -1
- package/dist/opLifecycle/opSplitter.js +3 -3
- package/dist/opLifecycle/opSplitter.js.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.d.ts +17 -3
- package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/dist/opLifecycle/remoteMessageProcessor.js +38 -25
- 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 +13 -6
- package/dist/pendingStateManager.js.map +1 -1
- package/dist/summary/runningSummarizer.d.ts +1 -1
- package/dist/summary/runningSummarizer.d.ts.map +1 -1
- package/dist/summary/runningSummarizer.js +4 -2
- package/dist/summary/runningSummarizer.js.map +1 -1
- package/dist/summary/summarizer.d.ts +2 -2
- package/dist/summary/summarizer.js +2 -2
- package/dist/summary/summarizer.js.map +1 -1
- package/dist/summary/summarizerNode/summarizerNode.d.ts +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js +1 -1
- package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/dist/summary/summarizerTypes.d.ts +2 -1
- package/dist/summary/summarizerTypes.d.ts.map +1 -1
- package/dist/summary/summarizerTypes.js.map +1 -1
- package/dist/summary/summaryFormat.d.ts +3 -0
- package/dist/summary/summaryFormat.d.ts.map +1 -1
- package/dist/summary/summaryFormat.js +3 -0
- package/dist/summary/summaryFormat.js.map +1 -1
- package/lib/blobManager.d.ts +3 -2
- package/lib/blobManager.d.ts.map +1 -1
- package/lib/blobManager.js +30 -26
- package/lib/blobManager.js.map +1 -1
- package/lib/containerRuntime.d.ts +14 -69
- package/lib/containerRuntime.d.ts.map +1 -1
- package/lib/containerRuntime.js +121 -150
- package/lib/containerRuntime.js.map +1 -1
- package/lib/dataStoreContext.d.ts.map +1 -1
- package/lib/dataStoreContext.js +3 -1
- package/lib/dataStoreContext.js.map +1 -1
- package/lib/dataStores.d.ts +1 -1
- package/lib/dataStores.js +4 -4
- package/lib/dataStores.js.map +1 -1
- package/lib/gc/garbageCollection.d.ts +6 -3
- package/lib/gc/garbageCollection.d.ts.map +1 -1
- package/lib/gc/garbageCollection.js +6 -3
- package/lib/gc/garbageCollection.js.map +1 -1
- package/lib/gc/gcDefinitions.d.ts +13 -2
- package/lib/gc/gcDefinitions.d.ts.map +1 -1
- package/lib/gc/gcDefinitions.js +13 -14
- package/lib/gc/gcDefinitions.js.map +1 -1
- package/lib/gc/gcHelpers.d.ts +0 -9
- package/lib/gc/gcHelpers.d.ts.map +1 -1
- package/lib/gc/gcHelpers.js +0 -11
- package/lib/gc/gcHelpers.js.map +1 -1
- package/lib/gc/gcTelemetry.d.ts.map +1 -1
- package/lib/gc/gcTelemetry.js +1 -4
- package/lib/gc/gcTelemetry.js.map +1 -1
- package/lib/gc/index.d.ts +2 -2
- package/lib/gc/index.d.ts.map +1 -1
- package/lib/gc/index.js +2 -2
- package/lib/gc/index.js.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/messageTypes.d.ts +134 -0
- package/lib/messageTypes.d.ts.map +1 -0
- package/lib/messageTypes.js +26 -0
- package/lib/messageTypes.js.map +1 -0
- package/lib/opLifecycle/definitions.d.ts +2 -1
- package/lib/opLifecycle/definitions.d.ts.map +1 -1
- package/lib/opLifecycle/definitions.js.map +1 -1
- package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
- package/lib/opLifecycle/opDecompressor.js +0 -4
- package/lib/opLifecycle/opDecompressor.js.map +1 -1
- package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
- package/lib/opLifecycle/opGroupingManager.js +4 -2
- package/lib/opLifecycle/opGroupingManager.js.map +1 -1
- package/lib/opLifecycle/opSplitter.js +1 -1
- package/lib/opLifecycle/opSplitter.js.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.d.ts +17 -3
- package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
- package/lib/opLifecycle/remoteMessageProcessor.js +37 -24
- 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 +12 -5
- package/lib/pendingStateManager.js.map +1 -1
- package/lib/summary/runningSummarizer.d.ts +1 -1
- package/lib/summary/runningSummarizer.d.ts.map +1 -1
- package/lib/summary/runningSummarizer.js +4 -2
- package/lib/summary/runningSummarizer.js.map +1 -1
- package/lib/summary/summarizer.d.ts +2 -2
- package/lib/summary/summarizer.js +2 -2
- package/lib/summary/summarizer.js.map +1 -1
- package/lib/summary/summarizerNode/summarizerNode.d.ts +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js +1 -1
- package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
- package/lib/summary/summarizerTypes.d.ts +2 -1
- package/lib/summary/summarizerTypes.d.ts.map +1 -1
- package/lib/summary/summarizerTypes.js.map +1 -1
- package/lib/summary/summaryFormat.d.ts +3 -0
- package/lib/summary/summaryFormat.d.ts.map +1 -1
- package/lib/summary/summaryFormat.js +3 -0
- package/lib/summary/summaryFormat.js.map +1 -1
- package/package.json +16 -16
- package/src/blobManager.ts +38 -28
- package/src/containerRuntime.ts +181 -245
- package/src/dataStoreContext.ts +3 -1
- package/src/dataStores.ts +4 -4
- package/src/gc/garbageCollection.md +53 -5
- package/src/gc/garbageCollection.ts +6 -3
- package/src/gc/gcDefinitions.ts +13 -14
- package/src/gc/gcEarlyAdoption.md +145 -0
- package/src/gc/gcHelpers.ts +0 -12
- package/src/gc/gcTelemetry.ts +1 -4
- package/src/gc/index.ts +2 -3
- package/src/index.ts +7 -4
- package/src/messageTypes.ts +225 -0
- package/src/opLifecycle/README.md +40 -40
- package/src/opLifecycle/definitions.ts +2 -1
- package/src/opLifecycle/opDecompressor.ts +0 -8
- package/src/opLifecycle/opGroupingManager.ts +7 -6
- package/src/opLifecycle/opSplitter.ts +2 -2
- package/src/opLifecycle/remoteMessageProcessor.ts +54 -33
- package/src/packageVersion.ts +1 -1
- package/src/pendingStateManager.ts +23 -6
- package/src/summary/runningSummarizer.ts +4 -2
- package/src/summary/summarizer.ts +2 -2
- package/src/summary/summarizerNode/summarizerNode.ts +1 -1
- package/src/summary/summarizerTypes.ts +2 -1
- package/src/summary/summaryFormat.ts +3 -0
|
@@ -212,8 +212,6 @@ On the receiving end, the client will accumulate chunks 1 and 2 and keep them in
|
|
|
212
212
|
|
|
213
213
|
## How grouped batching works
|
|
214
214
|
|
|
215
|
-
**Note: There are plans to replace empty ops with something more efficient when doing grouped batching AB#4092**
|
|
216
|
-
|
|
217
215
|
Given the following baseline batch:
|
|
218
216
|
|
|
219
217
|
```
|
|
@@ -223,68 +221,70 @@ Given the following baseline batch:
|
|
|
223
221
|
+---------------+---------------+---------------+---------------+---------------+
|
|
224
222
|
```
|
|
225
223
|
|
|
226
|
-
|
|
224
|
+
Grouped batch:
|
|
227
225
|
|
|
228
226
|
```
|
|
229
|
-
|
|
230
|
-
| Op 1
|
|
231
|
-
|
|
|
232
|
-
|
|
|
233
|
-
|
|
227
|
+
+---------------------------------------------------------------------------------------------------------------------+
|
|
228
|
+
| Op 1 Contents: +----------------+---------------+---------------+---------------+---------------+ |
|
|
229
|
+
| Type: "groupedBatch" | Op 1 | Op 2 | Op 3 | Op 4 | Op 5 | |
|
|
230
|
+
| | Contents: "a" | Contents: "b" | Contents: "c" | Contents: "d" | Contents: "e" | |
|
|
231
|
+
| +----------------+---------------+---------------+---------------+---------------+ |
|
|
232
|
+
+---------------------------------------------------------------------------------------------------------------------+
|
|
234
233
|
```
|
|
235
234
|
|
|
236
|
-
|
|
235
|
+
Compressed batch:
|
|
237
236
|
|
|
238
237
|
```
|
|
239
|
-
|
|
240
|
-
| Op 1 Contents:
|
|
241
|
-
|
|
|
242
|
-
|
|
|
243
|
-
| |
|
|
244
|
-
|
|
|
245
|
-
|
|
238
|
+
+-------------------------------------------------------------------------------------------------------------------------+
|
|
239
|
+
| Op 1 Contents: +------------------------------------------------------------------------------------+ |
|
|
240
|
+
| Compression: 'lz4' | Type: "groupedBatch" | |
|
|
241
|
+
| | +----------------+---------------+---------------+---------------+---------------+ | |
|
|
242
|
+
| | | Op 1 | Op 2 | Op 3 | Op 4 | Op 5 | | |
|
|
243
|
+
| | | Contents: "a" | Contents: "b" | Contents: "c" | Contents: "d" | Contents: "e" | | |
|
|
244
|
+
| | +----------------+---------------+---------------+---------------+---------------+ | |
|
|
245
|
+
| +------------------------------------------------------------------------------------+ |
|
|
246
|
+
+-------------------------------------------------------------------------------------------------------------------------+
|
|
246
247
|
```
|
|
247
248
|
|
|
248
249
|
Can produce the following chunks:
|
|
249
250
|
|
|
250
251
|
```
|
|
251
|
-
|
|
252
|
-
| Chunk 1/2 Contents:
|
|
253
|
-
|
|
|
254
|
-
| |
|
|
255
|
-
| |
|
|
256
|
-
|
|
|
257
|
-
|
|
252
|
+
+------------------------------------------------+
|
|
253
|
+
| Chunk 1/2 Contents: +---------------------+ |
|
|
254
|
+
| | +-----------------+ | |
|
|
255
|
+
| | | Contents: "abc" | | |
|
|
256
|
+
| | +-----------------+ | |
|
|
257
|
+
| +---------------------+ |
|
|
258
|
+
+------------------------------------------------+
|
|
258
259
|
```
|
|
259
260
|
|
|
260
261
|
```
|
|
261
|
-
|
|
262
|
-
| Chunk 2/2 Contents:
|
|
263
|
-
|
|
|
264
|
-
| |
|
|
265
|
-
| |
|
|
266
|
-
|
|
|
267
|
-
|
|
262
|
+
+-----------------------------------------------+
|
|
263
|
+
| Chunk 2/2 Contents: +--------------------+ |
|
|
264
|
+
| | +----------------+ | |
|
|
265
|
+
| | | Contents: "de" | | |
|
|
266
|
+
| | +----------------+ | |
|
|
267
|
+
| +--------------------+ |
|
|
268
|
+
+-----------------------------------------------+
|
|
268
269
|
```
|
|
269
270
|
|
|
270
271
|
- Send to service
|
|
271
272
|
- Service acks ops sent
|
|
272
273
|
- Receive chunks from service
|
|
273
|
-
- Recompile to the
|
|
274
|
+
- Recompile to the compression step
|
|
274
275
|
|
|
275
|
-
|
|
276
|
+
Decompressed batch:
|
|
276
277
|
|
|
277
278
|
```
|
|
278
|
-
|
|
279
|
-
| Op 1
|
|
280
|
-
|
|
|
281
|
-
|
|
|
282
|
-
|
|
|
283
|
-
|
|
284
|
-
+--------------------+-----------------+-----------------+-----------------+-----------------+
|
|
279
|
+
+---------------------------------------------------------------------------------------------------------------------+
|
|
280
|
+
| Op 1 Contents: +----------------+---------------+---------------+---------------+---------------+ |
|
|
281
|
+
| SeqNum: 2 | Op 1 | Op 2 | Op 3 | Op 4 | Op 5 | |
|
|
282
|
+
| Type: "groupedBatch" | Contents: "a" | Contents: "b" | Contents: "c" | Contents: "d" | Contents: "e" | |
|
|
283
|
+
| +----------------+---------------+---------------+---------------+---------------+ |
|
|
284
|
+
+---------------------------------------------------------------------------------------------------------------------+
|
|
285
285
|
```
|
|
286
286
|
|
|
287
|
-
|
|
287
|
+
Ungrouped batch:
|
|
288
288
|
|
|
289
289
|
```
|
|
290
290
|
+-----------------+-----------------+-----------------+-----------------+-----------------+
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
import { IBatchMessage } from "@fluidframework/container-definitions";
|
|
7
7
|
import { ISequencedDocumentMessage, MessageType } from "@fluidframework/protocol-definitions";
|
|
8
|
-
import { CompressionAlgorithms
|
|
8
|
+
import { CompressionAlgorithms } from "..";
|
|
9
|
+
import { ContainerMessageType } from "../messageTypes";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Batch message type used internally by the runtime
|
|
@@ -50,14 +50,6 @@ export class OpDecompressor {
|
|
|
50
50
|
) {
|
|
51
51
|
// Beginning of a compressed batch
|
|
52
52
|
assert(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);
|
|
53
|
-
if (message.compression) {
|
|
54
|
-
// lz4 is the only supported compression algorithm for now
|
|
55
|
-
assert(
|
|
56
|
-
message.compression === CompressionAlgorithms.lz4,
|
|
57
|
-
0x4b9 /* lz4 is currently the only supported compression algorithm */,
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
53
|
this.activeBatch = true;
|
|
62
54
|
|
|
63
55
|
const contents = IsoBuffer.from(
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { assert } from "@fluidframework/core-utils";
|
|
7
7
|
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
8
|
-
import { ContainerMessageType } from "
|
|
8
|
+
import { ContainerMessageType } from "../messageTypes";
|
|
9
9
|
import { IBatch } from "./definitions";
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -22,6 +22,10 @@ interface IGroupedMessage {
|
|
|
22
22
|
compression?: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
function isGroupContents(opContents: any): opContents is IGroupedBatchMessageContents {
|
|
26
|
+
return opContents?.type === OpGroupingManager.groupedBatchOp;
|
|
27
|
+
}
|
|
28
|
+
|
|
25
29
|
export class OpGroupingManager {
|
|
26
30
|
static readonly groupedBatchOp = "groupedBatch";
|
|
27
31
|
|
|
@@ -68,14 +72,11 @@ export class OpGroupingManager {
|
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
public ungroupOp(op: ISequencedDocumentMessage): ISequencedDocumentMessage[] {
|
|
71
|
-
if (
|
|
72
|
-
(op.contents as { type?: unknown } | undefined)?.type !==
|
|
73
|
-
OpGroupingManager.groupedBatchOp
|
|
74
|
-
) {
|
|
75
|
+
if (!isGroupContents(op.contents)) {
|
|
75
76
|
return [op];
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
const messages =
|
|
79
|
+
const messages = op.contents.contents;
|
|
79
80
|
let fakeCsn = 1;
|
|
80
81
|
return messages.map((subMessage) => ({
|
|
81
82
|
...op,
|
|
@@ -12,7 +12,7 @@ import { assert } from "@fluidframework/core-utils";
|
|
|
12
12
|
import { IBatchMessage } from "@fluidframework/container-definitions";
|
|
13
13
|
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
14
14
|
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
|
|
15
|
-
import { ContainerMessageType,
|
|
15
|
+
import { ContainerMessageType, ContainerRuntimeChunkedOpMessage } from "../messageTypes";
|
|
16
16
|
import { estimateSocketSize } from "./batchManager";
|
|
17
17
|
import { BatchMessage, IBatch, IChunkedOp, IMessageProcessingResult } from "./definitions";
|
|
18
18
|
|
|
@@ -210,7 +210,7 @@ const chunkToBatchMessage = (
|
|
|
210
210
|
referenceSequenceNumber: number,
|
|
211
211
|
metadata: Record<string, unknown> | undefined = undefined,
|
|
212
212
|
): BatchMessage => {
|
|
213
|
-
const payload:
|
|
213
|
+
const payload: ContainerRuntimeChunkedOpMessage = {
|
|
214
214
|
type: ContainerMessageType.ChunkedOp,
|
|
215
215
|
contents: chunk,
|
|
216
216
|
};
|
|
@@ -6,13 +6,21 @@
|
|
|
6
6
|
import { ISequencedDocumentMessage, MessageType } from "@fluidframework/protocol-definitions";
|
|
7
7
|
import {
|
|
8
8
|
ContainerMessageType,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
type InboundContainerRuntimeMessage,
|
|
10
|
+
type InboundSequencedContainerRuntimeMessage,
|
|
11
|
+
type InboundSequencedContainerRuntimeMessageOrSystemMessage,
|
|
12
|
+
type InboundSequencedRecentlyAddedContainerRuntimeMessage,
|
|
13
|
+
} from "../messageTypes";
|
|
12
14
|
import { OpDecompressor } from "./opDecompressor";
|
|
13
15
|
import { OpGroupingManager } from "./opGroupingManager";
|
|
14
16
|
import { OpSplitter } from "./opSplitter";
|
|
15
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Stateful class for processing incoming remote messages as the virtualization measures are unwrapped,
|
|
20
|
+
* potentially across numerous inbound ops.
|
|
21
|
+
*
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
16
24
|
export class RemoteMessageProcessor {
|
|
17
25
|
constructor(
|
|
18
26
|
private readonly opSplitter: OpSplitter,
|
|
@@ -30,14 +38,25 @@ export class RemoteMessageProcessor {
|
|
|
30
38
|
|
|
31
39
|
/**
|
|
32
40
|
* Ungroups and Unchunks the runtime ops encapsulated by the single remoteMessage received over the wire
|
|
33
|
-
* @param
|
|
34
|
-
*
|
|
41
|
+
* @param remoteMessageCopy - A shallow copy of a message from another client, possibly virtualized
|
|
42
|
+
* (grouped, compressed, and/or chunked).
|
|
43
|
+
* Being a shallow copy, it's considered mutable, meaning no other Container or other parallel procedure
|
|
44
|
+
* depends on this object instance.
|
|
45
|
+
* Note remoteMessageCopy.contents (and other object props) MUST not be modified,
|
|
46
|
+
* but may be overwritten (as is the case with contents).
|
|
47
|
+
* @returns the unchunked, decompressed, ungrouped, unpacked SequencedContainerRuntimeMessages encapsulated in the remote message.
|
|
48
|
+
* For ops that weren't virtualized (e.g. System ops that the ContainerRuntime will ultimately ignore),
|
|
49
|
+
* a singleton array [remoteMessageCopy] is returned
|
|
35
50
|
*/
|
|
36
|
-
public process(
|
|
37
|
-
|
|
51
|
+
public process(
|
|
52
|
+
remoteMessageCopy: ISequencedDocumentMessage,
|
|
53
|
+
): InboundSequencedContainerRuntimeMessageOrSystemMessage[] {
|
|
54
|
+
const result: InboundSequencedContainerRuntimeMessageOrSystemMessage[] = [];
|
|
55
|
+
|
|
56
|
+
ensureContentsDeserialized(remoteMessageCopy);
|
|
38
57
|
|
|
39
58
|
// Ungroup before and after decompression for back-compat (cleanup tracked by AB#4371)
|
|
40
|
-
for (const ungroupedMessage of this.opGroupingManager.ungroupOp(
|
|
59
|
+
for (const ungroupedMessage of this.opGroupingManager.ungroupOp(remoteMessageCopy)) {
|
|
41
60
|
const message = this.opDecompressor.processMessage(ungroupedMessage).message;
|
|
42
61
|
|
|
43
62
|
for (let ungroupedMessage2 of this.opGroupingManager.ungroupOp(message)) {
|
|
@@ -50,7 +69,9 @@ export class RemoteMessageProcessor {
|
|
|
50
69
|
if (chunkProcessingResult.state !== "Processed") {
|
|
51
70
|
// If the message is not chunked or if the splitter is still rebuilding the original message,
|
|
52
71
|
// there is no need to continue processing
|
|
53
|
-
result.push(
|
|
72
|
+
result.push(
|
|
73
|
+
ungroupedMessage2 as InboundSequencedContainerRuntimeMessageOrSystemMessage,
|
|
74
|
+
);
|
|
54
75
|
continue;
|
|
55
76
|
}
|
|
56
77
|
|
|
@@ -68,7 +89,9 @@ export class RemoteMessageProcessor {
|
|
|
68
89
|
if (decompressionAfterChunking.state === "Skipped") {
|
|
69
90
|
// After chunking, if the original message was not compressed,
|
|
70
91
|
// there is no need to continue processing
|
|
71
|
-
result.push(
|
|
92
|
+
result.push(
|
|
93
|
+
ungroupedMessageAfterChunking2 as InboundSequencedContainerRuntimeMessageOrSystemMessage,
|
|
94
|
+
);
|
|
72
95
|
continue;
|
|
73
96
|
}
|
|
74
97
|
|
|
@@ -84,40 +107,38 @@ export class RemoteMessageProcessor {
|
|
|
84
107
|
}
|
|
85
108
|
}
|
|
86
109
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// There might be multiple container instances receiving same message
|
|
90
|
-
// We do not need to make deep copy, as each layer will just replace message.content itself,
|
|
91
|
-
// but would not modify contents details
|
|
92
|
-
const message = { ...remoteMessage };
|
|
93
|
-
|
|
110
|
+
/** Takes an incoming message and if the contents is a string, JSON.parse's it in place */
|
|
111
|
+
function ensureContentsDeserialized(mutableMessage: ISequencedDocumentMessage): void {
|
|
94
112
|
// back-compat: ADO #1385: eventually should become unconditional, but only for runtime messages!
|
|
95
113
|
// System message may have no contents, or in some cases (mostly for back-compat) they may have actual objects.
|
|
96
114
|
// Old ops may contain empty string (I assume noops).
|
|
97
|
-
if (typeof
|
|
98
|
-
|
|
115
|
+
if (typeof mutableMessage.contents === "string" && mutableMessage.contents !== "") {
|
|
116
|
+
mutableMessage.contents = JSON.parse(mutableMessage.contents);
|
|
99
117
|
}
|
|
100
|
-
|
|
101
|
-
return message;
|
|
102
|
-
};
|
|
118
|
+
}
|
|
103
119
|
|
|
104
120
|
/**
|
|
105
|
-
* For a given message, it moves the nested
|
|
121
|
+
* For a given message, it moves the nested InboundContainerRuntimeMessage props one level up.
|
|
106
122
|
*
|
|
107
123
|
* The return type illustrates the assumption that the message param
|
|
108
|
-
* becomes a
|
|
109
|
-
* (but there is no runtime validation of the 'type' or 'compatDetails' values)
|
|
124
|
+
* becomes a InboundSequencedContainerRuntimeMessage by the time the function returns
|
|
125
|
+
* (but there is no runtime validation of the 'type' or 'compatDetails' values).
|
|
110
126
|
*/
|
|
111
127
|
function unpack(
|
|
112
128
|
message: ISequencedDocumentMessage,
|
|
113
|
-
): asserts message is
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
): asserts message is InboundSequencedContainerRuntimeMessage {
|
|
130
|
+
// We assume the contents is an InboundContainerRuntimeMessage (the message is "packed")
|
|
131
|
+
const contents = message.contents as InboundContainerRuntimeMessage;
|
|
132
|
+
|
|
133
|
+
// We're going to unpack message in-place (promoting those properties of contents up to message itself)
|
|
134
|
+
const messageUnpacked = message as InboundSequencedContainerRuntimeMessage;
|
|
135
|
+
|
|
136
|
+
messageUnpacked.type = contents.type;
|
|
137
|
+
messageUnpacked.contents = contents.contents;
|
|
138
|
+
if ("compatDetails" in contents) {
|
|
139
|
+
(messageUnpacked as InboundSequencedRecentlyAddedContainerRuntimeMessage).compatDetails =
|
|
140
|
+
contents.compatDetails;
|
|
141
|
+
}
|
|
121
142
|
}
|
|
122
143
|
|
|
123
144
|
/**
|
package/src/packageVersion.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { ICriticalContainerError } from "@fluidframework/container-definitions";
|
|
|
11
11
|
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
12
12
|
import { DataProcessingError, ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
13
13
|
|
|
14
|
-
import { ContainerMessageType,
|
|
14
|
+
import { ContainerMessageType, InboundSequencedContainerRuntimeMessage } from "./messageTypes";
|
|
15
15
|
import { pkgVersion } from "./packageVersion";
|
|
16
16
|
import { IBatchMetadata } from "./metadata";
|
|
17
17
|
|
|
@@ -69,6 +69,26 @@ export interface IRuntimeStateHandler {
|
|
|
69
69
|
isActiveConnection: () => boolean;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/** Union of keys of T */
|
|
73
|
+
type KeysOfUnion<T extends object> = T extends T ? keyof T : never;
|
|
74
|
+
/** *Partial* type all possible combinations of properties and values of union T.
|
|
75
|
+
* This loosens typing allowing access to all possible properties without
|
|
76
|
+
* narrowing.
|
|
77
|
+
*/
|
|
78
|
+
type AnyComboFromUnion<T extends object> = { [P in KeysOfUnion<T>]?: T[P] };
|
|
79
|
+
|
|
80
|
+
function buildPendingMessageContent(
|
|
81
|
+
// AnyComboFromUnion is needed need to gain access to compatDetails that
|
|
82
|
+
// is only defined for some cases.
|
|
83
|
+
message: AnyComboFromUnion<InboundSequencedContainerRuntimeMessage>,
|
|
84
|
+
): string {
|
|
85
|
+
// IMPORTANT: Order matters here, this must match the order of the properties used
|
|
86
|
+
// when submitting the message.
|
|
87
|
+
const { type, contents, compatDetails } = message;
|
|
88
|
+
// Any properties that are not defined, won't be emitted by stringify.
|
|
89
|
+
return JSON.stringify({ type, contents, compatDetails });
|
|
90
|
+
}
|
|
91
|
+
|
|
72
92
|
/**
|
|
73
93
|
* PendingStateManager is responsible for maintaining the messages that have not been sent or have not yet been
|
|
74
94
|
* acknowledged by the server. It also maintains the batch information for both automatically and manually flushed
|
|
@@ -242,7 +262,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
242
262
|
* the batch information was preserved for batch messages.
|
|
243
263
|
* @param message - The message that got ack'd and needs to be processed.
|
|
244
264
|
*/
|
|
245
|
-
public processPendingLocalMessage(message:
|
|
265
|
+
public processPendingLocalMessage(message: InboundSequencedContainerRuntimeMessage): unknown {
|
|
246
266
|
// Pre-processing part - This may be the start of a batch.
|
|
247
267
|
this.maybeProcessBatchBegin(message);
|
|
248
268
|
|
|
@@ -256,10 +276,7 @@ export class PendingStateManager implements IDisposable {
|
|
|
256
276
|
|
|
257
277
|
this.pendingMessages.shift();
|
|
258
278
|
|
|
259
|
-
|
|
260
|
-
// when submitting the message.
|
|
261
|
-
const { type, contents, compatDetails } = message;
|
|
262
|
-
const messageContent = JSON.stringify({ type, contents, compatDetails });
|
|
279
|
+
const messageContent = buildPendingMessageContent(message);
|
|
263
280
|
|
|
264
281
|
// Stringified content should match
|
|
265
282
|
if (pendingMessage.content !== messageContent) {
|
|
@@ -308,7 +308,8 @@ export class RunningSummarizer extends TypedEventEmitter<ISummarizerEvents> impl
|
|
|
308
308
|
// latest version with which we will refresh the state. However in case of single commit
|
|
309
309
|
// summary, we might me missing a summary ack, so in that case we are still fine as the
|
|
310
310
|
// code in `submitSummary` function in container runtime, will refresh the latest state
|
|
311
|
-
// by calling `
|
|
311
|
+
// by calling `prefetchLatestSummaryThenClose`. We will load the next summarizer from the
|
|
312
|
+
// updated state and be fine.
|
|
312
313
|
const isIgnoredError =
|
|
313
314
|
isFluidError(error) &&
|
|
314
315
|
error.errorType === DriverErrorTypes.fileNotFoundOrAccessDeniedError;
|
|
@@ -407,6 +408,7 @@ export class RunningSummarizer extends TypedEventEmitter<ISummarizerEvents> impl
|
|
|
407
408
|
!this.heuristicRunnerMicroTaskExists
|
|
408
409
|
) {
|
|
409
410
|
this.heuristicRunnerMicroTaskExists = true;
|
|
411
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
410
412
|
Promise.resolve()
|
|
411
413
|
.then(() => {
|
|
412
414
|
this.heuristicRunner?.run();
|
|
@@ -519,7 +521,7 @@ export class RunningSummarizer extends TypedEventEmitter<ISummarizerEvents> impl
|
|
|
519
521
|
* @param before - set of instructions to run before running the action.
|
|
520
522
|
* @param action - action to perform.
|
|
521
523
|
* @param after - set of instructions to run after running the action.
|
|
522
|
-
* @returns
|
|
524
|
+
* @returns The result of the action.
|
|
523
525
|
*/
|
|
524
526
|
private async lockedSummaryAction<T>(
|
|
525
527
|
before: () => void,
|
|
@@ -216,7 +216,7 @@ export class Summarizer extends TypedEventEmitter<ISummarizerEvents> implements
|
|
|
216
216
|
* Should we try to run a last summary for the given stop reason?
|
|
217
217
|
* Currently only allows "parentNotConnected"
|
|
218
218
|
* @param stopReason - SummarizerStopReason
|
|
219
|
-
* @returns
|
|
219
|
+
* @returns `true` if the stop reason can run a last summary, otherwise `false`.
|
|
220
220
|
*/
|
|
221
221
|
public static stopReasonCanRunLastSummary(stopReason: SummarizerStopReason): boolean {
|
|
222
222
|
return stopReason === "parentNotConnected";
|
|
@@ -231,7 +231,7 @@ export class Summarizer extends TypedEventEmitter<ISummarizerEvents> implements
|
|
|
231
231
|
* @param onBehalfOf - ID of the client that requested that the summarizer start
|
|
232
232
|
* @param runCoordinator - cancellation token
|
|
233
233
|
* @param newConfig - Summary configuration to override the existing config when invoking the RunningSummarizer.
|
|
234
|
-
* @returns
|
|
234
|
+
* @returns A promise that is fulfilled when the RunningSummarizer is ready.
|
|
235
235
|
*/
|
|
236
236
|
private async start(
|
|
237
237
|
onBehalfOf: string,
|
|
@@ -424,7 +424,7 @@ export class SummarizerNode implements IRootSummarizerNode {
|
|
|
424
424
|
* Called when we get an ack from the server for a summary we've just sent. Updates the reference state of this node
|
|
425
425
|
* from the state in the pending summary queue.
|
|
426
426
|
* @param proposalHandle - Handle for the current proposal.
|
|
427
|
-
* @param referenceSequenceNumber -
|
|
427
|
+
* @param referenceSequenceNumber - Reference sequence number of sent summary.
|
|
428
428
|
*/
|
|
429
429
|
protected refreshLatestSummaryFromPending(
|
|
430
430
|
proposalHandle: string,
|
|
@@ -104,7 +104,8 @@ export interface ISummarizeOptions {
|
|
|
104
104
|
/**
|
|
105
105
|
* True to ask the server what the latest summary is first; defaults to false
|
|
106
106
|
*
|
|
107
|
-
* @deprecated - Summarize will not refresh latest snapshot state anymore.
|
|
107
|
+
* @deprecated - Summarize will not refresh latest snapshot state anymore. Instead it updates the cache and closes
|
|
108
|
+
* It's expected a new summarizer client will be created, likely by the same parent.
|
|
108
109
|
*/
|
|
109
110
|
readonly refreshLatestAck?: boolean;
|
|
110
111
|
}
|
|
@@ -187,7 +187,9 @@ export const dataStoreAttributesBlobName = ".component";
|
|
|
187
187
|
* @param summarizeResult - Summary tree and stats to modify
|
|
188
188
|
*
|
|
189
189
|
* @example
|
|
190
|
+
*
|
|
190
191
|
* Converts from:
|
|
192
|
+
*
|
|
191
193
|
* ```typescript
|
|
192
194
|
* {
|
|
193
195
|
* type: SummaryType.Tree,
|
|
@@ -208,6 +210,7 @@ export const dataStoreAttributesBlobName = ".component";
|
|
|
208
210
|
* },
|
|
209
211
|
* }
|
|
210
212
|
* ```
|
|
213
|
+
*
|
|
211
214
|
* And adds +1 to treeNodeCount in stats.
|
|
212
215
|
*/
|
|
213
216
|
export function wrapSummaryInChannelsTree(summarizeResult: ISummaryTreeWithStats): void {
|