@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.
Files changed (188) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/blobManager.d.ts +3 -2
  3. package/dist/blobManager.d.ts.map +1 -1
  4. package/dist/blobManager.js +29 -25
  5. package/dist/blobManager.js.map +1 -1
  6. package/dist/containerRuntime.d.ts +14 -69
  7. package/dist/containerRuntime.d.ts.map +1 -1
  8. package/dist/containerRuntime.js +155 -184
  9. package/dist/containerRuntime.js.map +1 -1
  10. package/dist/dataStoreContext.d.ts.map +1 -1
  11. package/dist/dataStoreContext.js +3 -1
  12. package/dist/dataStoreContext.js.map +1 -1
  13. package/dist/dataStores.d.ts +1 -1
  14. package/dist/dataStores.js +3 -3
  15. package/dist/dataStores.js.map +1 -1
  16. package/dist/gc/garbageCollection.d.ts +6 -3
  17. package/dist/gc/garbageCollection.d.ts.map +1 -1
  18. package/dist/gc/garbageCollection.js +6 -3
  19. package/dist/gc/garbageCollection.js.map +1 -1
  20. package/dist/gc/gcDefinitions.d.ts +13 -2
  21. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  22. package/dist/gc/gcDefinitions.js +14 -15
  23. package/dist/gc/gcDefinitions.js.map +1 -1
  24. package/dist/gc/gcHelpers.d.ts +0 -9
  25. package/dist/gc/gcHelpers.d.ts.map +1 -1
  26. package/dist/gc/gcHelpers.js +1 -13
  27. package/dist/gc/gcHelpers.js.map +1 -1
  28. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  29. package/dist/gc/gcTelemetry.js +1 -4
  30. package/dist/gc/gcTelemetry.js.map +1 -1
  31. package/dist/gc/index.d.ts +2 -2
  32. package/dist/gc/index.d.ts.map +1 -1
  33. package/dist/gc/index.js +3 -4
  34. package/dist/gc/index.js.map +1 -1
  35. package/dist/index.d.ts +2 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +3 -2
  38. package/dist/index.js.map +1 -1
  39. package/dist/messageTypes.d.ts +134 -0
  40. package/dist/messageTypes.d.ts.map +1 -0
  41. package/dist/messageTypes.js +29 -0
  42. package/dist/messageTypes.js.map +1 -0
  43. package/dist/opLifecycle/definitions.d.ts +2 -1
  44. package/dist/opLifecycle/definitions.d.ts.map +1 -1
  45. package/dist/opLifecycle/definitions.js.map +1 -1
  46. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  47. package/dist/opLifecycle/opDecompressor.js +0 -4
  48. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  49. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  50. package/dist/opLifecycle/opGroupingManager.js +4 -2
  51. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  52. package/dist/opLifecycle/opSplitter.js +3 -3
  53. package/dist/opLifecycle/opSplitter.js.map +1 -1
  54. package/dist/opLifecycle/remoteMessageProcessor.d.ts +17 -3
  55. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  56. package/dist/opLifecycle/remoteMessageProcessor.js +38 -25
  57. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  58. package/dist/packageVersion.d.ts +1 -1
  59. package/dist/packageVersion.js +1 -1
  60. package/dist/packageVersion.js.map +1 -1
  61. package/dist/pendingStateManager.d.ts +2 -2
  62. package/dist/pendingStateManager.d.ts.map +1 -1
  63. package/dist/pendingStateManager.js +13 -6
  64. package/dist/pendingStateManager.js.map +1 -1
  65. package/dist/summary/runningSummarizer.d.ts +1 -1
  66. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  67. package/dist/summary/runningSummarizer.js +4 -2
  68. package/dist/summary/runningSummarizer.js.map +1 -1
  69. package/dist/summary/summarizer.d.ts +2 -2
  70. package/dist/summary/summarizer.js +2 -2
  71. package/dist/summary/summarizer.js.map +1 -1
  72. package/dist/summary/summarizerNode/summarizerNode.d.ts +1 -1
  73. package/dist/summary/summarizerNode/summarizerNode.js +1 -1
  74. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  75. package/dist/summary/summarizerTypes.d.ts +2 -1
  76. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  77. package/dist/summary/summarizerTypes.js.map +1 -1
  78. package/dist/summary/summaryFormat.d.ts +3 -0
  79. package/dist/summary/summaryFormat.d.ts.map +1 -1
  80. package/dist/summary/summaryFormat.js +3 -0
  81. package/dist/summary/summaryFormat.js.map +1 -1
  82. package/lib/blobManager.d.ts +3 -2
  83. package/lib/blobManager.d.ts.map +1 -1
  84. package/lib/blobManager.js +30 -26
  85. package/lib/blobManager.js.map +1 -1
  86. package/lib/containerRuntime.d.ts +14 -69
  87. package/lib/containerRuntime.d.ts.map +1 -1
  88. package/lib/containerRuntime.js +121 -150
  89. package/lib/containerRuntime.js.map +1 -1
  90. package/lib/dataStoreContext.d.ts.map +1 -1
  91. package/lib/dataStoreContext.js +3 -1
  92. package/lib/dataStoreContext.js.map +1 -1
  93. package/lib/dataStores.d.ts +1 -1
  94. package/lib/dataStores.js +4 -4
  95. package/lib/dataStores.js.map +1 -1
  96. package/lib/gc/garbageCollection.d.ts +6 -3
  97. package/lib/gc/garbageCollection.d.ts.map +1 -1
  98. package/lib/gc/garbageCollection.js +6 -3
  99. package/lib/gc/garbageCollection.js.map +1 -1
  100. package/lib/gc/gcDefinitions.d.ts +13 -2
  101. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  102. package/lib/gc/gcDefinitions.js +13 -14
  103. package/lib/gc/gcDefinitions.js.map +1 -1
  104. package/lib/gc/gcHelpers.d.ts +0 -9
  105. package/lib/gc/gcHelpers.d.ts.map +1 -1
  106. package/lib/gc/gcHelpers.js +0 -11
  107. package/lib/gc/gcHelpers.js.map +1 -1
  108. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  109. package/lib/gc/gcTelemetry.js +1 -4
  110. package/lib/gc/gcTelemetry.js.map +1 -1
  111. package/lib/gc/index.d.ts +2 -2
  112. package/lib/gc/index.d.ts.map +1 -1
  113. package/lib/gc/index.js +2 -2
  114. package/lib/gc/index.js.map +1 -1
  115. package/lib/index.d.ts +2 -1
  116. package/lib/index.d.ts.map +1 -1
  117. package/lib/index.js +2 -1
  118. package/lib/index.js.map +1 -1
  119. package/lib/messageTypes.d.ts +134 -0
  120. package/lib/messageTypes.d.ts.map +1 -0
  121. package/lib/messageTypes.js +26 -0
  122. package/lib/messageTypes.js.map +1 -0
  123. package/lib/opLifecycle/definitions.d.ts +2 -1
  124. package/lib/opLifecycle/definitions.d.ts.map +1 -1
  125. package/lib/opLifecycle/definitions.js.map +1 -1
  126. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  127. package/lib/opLifecycle/opDecompressor.js +0 -4
  128. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  129. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
  130. package/lib/opLifecycle/opGroupingManager.js +4 -2
  131. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  132. package/lib/opLifecycle/opSplitter.js +1 -1
  133. package/lib/opLifecycle/opSplitter.js.map +1 -1
  134. package/lib/opLifecycle/remoteMessageProcessor.d.ts +17 -3
  135. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  136. package/lib/opLifecycle/remoteMessageProcessor.js +37 -24
  137. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  138. package/lib/packageVersion.d.ts +1 -1
  139. package/lib/packageVersion.js +1 -1
  140. package/lib/packageVersion.js.map +1 -1
  141. package/lib/pendingStateManager.d.ts +2 -2
  142. package/lib/pendingStateManager.d.ts.map +1 -1
  143. package/lib/pendingStateManager.js +12 -5
  144. package/lib/pendingStateManager.js.map +1 -1
  145. package/lib/summary/runningSummarizer.d.ts +1 -1
  146. package/lib/summary/runningSummarizer.d.ts.map +1 -1
  147. package/lib/summary/runningSummarizer.js +4 -2
  148. package/lib/summary/runningSummarizer.js.map +1 -1
  149. package/lib/summary/summarizer.d.ts +2 -2
  150. package/lib/summary/summarizer.js +2 -2
  151. package/lib/summary/summarizer.js.map +1 -1
  152. package/lib/summary/summarizerNode/summarizerNode.d.ts +1 -1
  153. package/lib/summary/summarizerNode/summarizerNode.js +1 -1
  154. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  155. package/lib/summary/summarizerTypes.d.ts +2 -1
  156. package/lib/summary/summarizerTypes.d.ts.map +1 -1
  157. package/lib/summary/summarizerTypes.js.map +1 -1
  158. package/lib/summary/summaryFormat.d.ts +3 -0
  159. package/lib/summary/summaryFormat.d.ts.map +1 -1
  160. package/lib/summary/summaryFormat.js +3 -0
  161. package/lib/summary/summaryFormat.js.map +1 -1
  162. package/package.json +16 -16
  163. package/src/blobManager.ts +38 -28
  164. package/src/containerRuntime.ts +181 -245
  165. package/src/dataStoreContext.ts +3 -1
  166. package/src/dataStores.ts +4 -4
  167. package/src/gc/garbageCollection.md +53 -5
  168. package/src/gc/garbageCollection.ts +6 -3
  169. package/src/gc/gcDefinitions.ts +13 -14
  170. package/src/gc/gcEarlyAdoption.md +145 -0
  171. package/src/gc/gcHelpers.ts +0 -12
  172. package/src/gc/gcTelemetry.ts +1 -4
  173. package/src/gc/index.ts +2 -3
  174. package/src/index.ts +7 -4
  175. package/src/messageTypes.ts +225 -0
  176. package/src/opLifecycle/README.md +40 -40
  177. package/src/opLifecycle/definitions.ts +2 -1
  178. package/src/opLifecycle/opDecompressor.ts +0 -8
  179. package/src/opLifecycle/opGroupingManager.ts +7 -6
  180. package/src/opLifecycle/opSplitter.ts +2 -2
  181. package/src/opLifecycle/remoteMessageProcessor.ts +54 -33
  182. package/src/packageVersion.ts +1 -1
  183. package/src/pendingStateManager.ts +23 -6
  184. package/src/summary/runningSummarizer.ts +4 -2
  185. package/src/summary/summarizer.ts +2 -2
  186. package/src/summary/summarizerNode/summarizerNode.ts +1 -1
  187. package/src/summary/summarizerTypes.ts +2 -1
  188. 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
- Compressed batch:
224
+ Grouped batch:
227
225
 
228
226
  ```
229
- +--------------------+-----------------+-----------------+-----------------+-----------------+
230
- | Op 1 | Op 2 | Op 3 | Op 4 | Op 5 |
231
- | Contents: "abcde" | Contents: empty | Contents: empty | Contents: empty | Contents: empty |
232
- | Compression: 'lz4' | | | | |
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
- Grouped batch:
235
+ Compressed batch:
237
236
 
238
237
  ```
239
- +---------------------------------------------------------------------------------------------------------------------------------+
240
- | Op 1 Contents: +--------------------+-----------------+-----------------+-----------------+-----------------+ |
241
- | SeqNum: 1 | Op 1 | Op 2 | Op 3 | Op 4 | Op 5 | |
242
- | Type: "groupedBatch" | Contents: "abcde" | Contents: empty | Contents: empty | Contents: empty | Contents: empty | |
243
- | | Compression: 'lz4' | | | | | |
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
- | SeqNum: 1 | +-----------------+ | |
254
- | | | Contents: "abc" | | |
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
- | SeqNum: 2 | +----------------+-----------------+-----------------+-----------------+-----------------+ | | |
264
- | | | Contents: "de" | Contents: empty | Contents: empty | Contents: empty | Contents: empty | | | |
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 grouped batch step
274
+ - Recompile to the compression step
274
275
 
275
- Ungrouped batch:
276
+ Decompressed batch:
276
277
 
277
278
  ```
278
- +--------------------+-----------------+-----------------+-----------------+-----------------+
279
- | Op 1 | Op 2 | Op 3 | Op 4 | Op 5 |
280
- | Contents: "abcde" | Contents: empty | Contents: empty | Contents: empty | Contents: empty |
281
- | SeqNum: 2 | SeqNum: 2 | SeqNum: 2 | SeqNum: 2 | SeqNum: 2 |
282
- | ClientSeqNum: 1 | ClientSeqNum: 2 | ClientSeqNum: 3 | ClientSeqNum: 4 | ClientSeqNum: 5 |
283
- | Compression: 'lz4' | | | | |
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
- Uncompressed batch:
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, ContainerMessageType } from "..";
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 = (op.contents as IGroupedBatchMessageContents).contents;
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, ContainerRuntimeMessage } from "../containerRuntime";
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: ContainerRuntimeMessage = {
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
- ContainerRuntimeMessage,
10
- SequencedContainerRuntimeMessage,
11
- } from "../containerRuntime";
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 remoteMessage - A message from another client, likely a chunked/grouped op
34
- * @returns the ungrouped, unchunked, unpacked SequencedContainerRuntimeMessage encapsulated in the remote message
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(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage[] {
37
- const result: ISequencedDocumentMessage[] = [];
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(copy(remoteMessage))) {
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(ungroupedMessage2);
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(ungroupedMessageAfterChunking2);
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
- const copy = (remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage => {
88
- // Do shallow copy of message, as the processing flow will modify it.
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 message.contents === "string" && message.contents !== "") {
98
- message.contents = JSON.parse(message.contents);
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 ContainerRuntimeMessage props one level up.
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 ContainerRuntimeMessage by the time the function returns
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 SequencedContainerRuntimeMessage {
114
- const innerContents = message.contents as ContainerRuntimeMessage;
115
-
116
- // We're going to turn message into a SequencedContainerRuntimeMessage in-place
117
- const sequencedContainerRuntimeMessage = message as SequencedContainerRuntimeMessage;
118
- sequencedContainerRuntimeMessage.type = innerContents.type;
119
- sequencedContainerRuntimeMessage.contents = innerContents.contents;
120
- sequencedContainerRuntimeMessage.compatDetails = innerContents.compatDetails;
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
  /**
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "2.0.0-internal.6.3.3";
9
+ export const pkgVersion = "2.0.0-internal.6.4.0";
@@ -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, SequencedContainerRuntimeMessage } from "./containerRuntime";
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: SequencedContainerRuntimeMessage): unknown {
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
- // IMPORTANT: Order matters here, this must match the order of the properties used
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 `refreshLatestSummaryAckFromServer` and we will be fine.
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 - result of action.
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 - true if the stop reason can run a last summary
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 - Promise that is fulfilled when the RunningSummarizer is ready
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 - reference sequence number of sent summary.
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 {