@fluidframework/container-runtime 2.1.0-281041 → 2.2.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 (207) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +6 -6
  3. package/api-report/container-runtime.legacy.alpha.api.md +4 -3
  4. package/container-runtime.test-files.tar +0 -0
  5. package/dist/batchTracker.d.ts.map +1 -1
  6. package/dist/batchTracker.js.map +1 -1
  7. package/dist/blobManager/blobManager.d.ts.map +1 -1
  8. package/dist/blobManager/blobManager.js +9 -0
  9. package/dist/blobManager/blobManager.js.map +1 -1
  10. package/dist/channelCollection.d.ts +0 -14
  11. package/dist/channelCollection.d.ts.map +1 -1
  12. package/dist/channelCollection.js +2 -12
  13. package/dist/channelCollection.js.map +1 -1
  14. package/dist/containerRuntime.d.ts +34 -6
  15. package/dist/containerRuntime.d.ts.map +1 -1
  16. package/dist/containerRuntime.js +177 -74
  17. package/dist/containerRuntime.js.map +1 -1
  18. package/dist/dataStoreContext.d.ts +9 -18
  19. package/dist/dataStoreContext.d.ts.map +1 -1
  20. package/dist/dataStoreContext.js +40 -78
  21. package/dist/dataStoreContext.js.map +1 -1
  22. package/dist/gc/garbageCollection.d.ts +0 -6
  23. package/dist/gc/garbageCollection.d.ts.map +1 -1
  24. package/dist/gc/garbageCollection.js +23 -66
  25. package/dist/gc/garbageCollection.js.map +1 -1
  26. package/dist/gc/gcConfigs.d.ts.map +1 -1
  27. package/dist/gc/gcConfigs.js +11 -34
  28. package/dist/gc/gcConfigs.js.map +1 -1
  29. package/dist/gc/gcDefinitions.d.ts +9 -52
  30. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  31. package/dist/gc/gcDefinitions.js +3 -23
  32. package/dist/gc/gcDefinitions.js.map +1 -1
  33. package/dist/gc/gcHelpers.d.ts.map +1 -1
  34. package/dist/gc/gcHelpers.js +2 -6
  35. package/dist/gc/gcHelpers.js.map +1 -1
  36. package/dist/gc/gcSummaryStateTracker.d.ts +1 -1
  37. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
  38. package/dist/gc/gcSummaryStateTracker.js +4 -8
  39. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  40. package/dist/gc/gcTelemetry.d.ts +1 -9
  41. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  42. package/dist/gc/gcTelemetry.js +3 -25
  43. package/dist/gc/gcTelemetry.js.map +1 -1
  44. package/dist/gc/index.d.ts +2 -2
  45. package/dist/gc/index.d.ts.map +1 -1
  46. package/dist/gc/index.js +2 -7
  47. package/dist/gc/index.js.map +1 -1
  48. package/dist/index.d.ts +1 -1
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +1 -2
  51. package/dist/index.js.map +1 -1
  52. package/dist/messageTypes.d.ts +6 -5
  53. package/dist/messageTypes.d.ts.map +1 -1
  54. package/dist/messageTypes.js.map +1 -1
  55. package/dist/metadata.d.ts +9 -1
  56. package/dist/metadata.d.ts.map +1 -1
  57. package/dist/metadata.js +6 -1
  58. package/dist/metadata.js.map +1 -1
  59. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  60. package/dist/opLifecycle/batchManager.js +1 -1
  61. package/dist/opLifecycle/batchManager.js.map +1 -1
  62. package/dist/opLifecycle/index.d.ts +1 -1
  63. package/dist/opLifecycle/index.d.ts.map +1 -1
  64. package/dist/opLifecycle/index.js +2 -1
  65. package/dist/opLifecycle/index.js.map +1 -1
  66. package/dist/opLifecycle/opGroupingManager.d.ts +8 -0
  67. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  68. package/dist/opLifecycle/opGroupingManager.js +34 -2
  69. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  70. package/dist/opLifecycle/outbox.d.ts +1 -0
  71. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  72. package/dist/opLifecycle/outbox.js +21 -1
  73. package/dist/opLifecycle/outbox.js.map +1 -1
  74. package/dist/opLifecycle/remoteMessageProcessor.d.ts +35 -14
  75. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  76. package/dist/opLifecycle/remoteMessageProcessor.js +71 -46
  77. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  78. package/dist/packageVersion.d.ts +1 -1
  79. package/dist/packageVersion.d.ts.map +1 -1
  80. package/dist/packageVersion.js +1 -1
  81. package/dist/packageVersion.js.map +1 -1
  82. package/dist/pendingStateManager.d.ts +28 -27
  83. package/dist/pendingStateManager.d.ts.map +1 -1
  84. package/dist/pendingStateManager.js +143 -112
  85. package/dist/pendingStateManager.js.map +1 -1
  86. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  87. package/dist/summary/summarizerNode/summarizerNode.js +5 -1
  88. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  89. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -4
  90. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  91. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +16 -15
  92. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  93. package/lib/batchTracker.d.ts.map +1 -1
  94. package/lib/batchTracker.js.map +1 -1
  95. package/lib/blobManager/blobManager.d.ts.map +1 -1
  96. package/lib/blobManager/blobManager.js +9 -0
  97. package/lib/blobManager/blobManager.js.map +1 -1
  98. package/lib/channelCollection.d.ts +0 -14
  99. package/lib/channelCollection.d.ts.map +1 -1
  100. package/lib/channelCollection.js +2 -11
  101. package/lib/channelCollection.js.map +1 -1
  102. package/lib/containerRuntime.d.ts +34 -6
  103. package/lib/containerRuntime.d.ts.map +1 -1
  104. package/lib/containerRuntime.js +178 -75
  105. package/lib/containerRuntime.js.map +1 -1
  106. package/lib/dataStoreContext.d.ts +9 -18
  107. package/lib/dataStoreContext.d.ts.map +1 -1
  108. package/lib/dataStoreContext.js +27 -65
  109. package/lib/dataStoreContext.js.map +1 -1
  110. package/lib/gc/garbageCollection.d.ts +0 -6
  111. package/lib/gc/garbageCollection.d.ts.map +1 -1
  112. package/lib/gc/garbageCollection.js +25 -68
  113. package/lib/gc/garbageCollection.js.map +1 -1
  114. package/lib/gc/gcConfigs.d.ts.map +1 -1
  115. package/lib/gc/gcConfigs.js +12 -35
  116. package/lib/gc/gcConfigs.js.map +1 -1
  117. package/lib/gc/gcDefinitions.d.ts +9 -52
  118. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  119. package/lib/gc/gcDefinitions.js +2 -22
  120. package/lib/gc/gcDefinitions.js.map +1 -1
  121. package/lib/gc/gcHelpers.d.ts.map +1 -1
  122. package/lib/gc/gcHelpers.js +2 -6
  123. package/lib/gc/gcHelpers.js.map +1 -1
  124. package/lib/gc/gcSummaryStateTracker.d.ts +1 -1
  125. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
  126. package/lib/gc/gcSummaryStateTracker.js +4 -8
  127. package/lib/gc/gcSummaryStateTracker.js.map +1 -1
  128. package/lib/gc/gcTelemetry.d.ts +1 -9
  129. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  130. package/lib/gc/gcTelemetry.js +3 -24
  131. package/lib/gc/gcTelemetry.js.map +1 -1
  132. package/lib/gc/index.d.ts +2 -2
  133. package/lib/gc/index.d.ts.map +1 -1
  134. package/lib/gc/index.js +2 -2
  135. package/lib/gc/index.js.map +1 -1
  136. package/lib/index.d.ts +1 -1
  137. package/lib/index.d.ts.map +1 -1
  138. package/lib/index.js +1 -1
  139. package/lib/index.js.map +1 -1
  140. package/lib/messageTypes.d.ts +6 -5
  141. package/lib/messageTypes.d.ts.map +1 -1
  142. package/lib/messageTypes.js.map +1 -1
  143. package/lib/metadata.d.ts +9 -1
  144. package/lib/metadata.d.ts.map +1 -1
  145. package/lib/metadata.js +4 -0
  146. package/lib/metadata.js.map +1 -1
  147. package/lib/opLifecycle/batchManager.d.ts.map +1 -1
  148. package/lib/opLifecycle/batchManager.js +1 -1
  149. package/lib/opLifecycle/batchManager.js.map +1 -1
  150. package/lib/opLifecycle/index.d.ts +1 -1
  151. package/lib/opLifecycle/index.d.ts.map +1 -1
  152. package/lib/opLifecycle/index.js +1 -1
  153. package/lib/opLifecycle/index.js.map +1 -1
  154. package/lib/opLifecycle/opGroupingManager.d.ts +8 -0
  155. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
  156. package/lib/opLifecycle/opGroupingManager.js +34 -2
  157. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  158. package/lib/opLifecycle/outbox.d.ts +1 -0
  159. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  160. package/lib/opLifecycle/outbox.js +21 -1
  161. package/lib/opLifecycle/outbox.js.map +1 -1
  162. package/lib/opLifecycle/remoteMessageProcessor.d.ts +35 -14
  163. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  164. package/lib/opLifecycle/remoteMessageProcessor.js +69 -45
  165. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  166. package/lib/packageVersion.d.ts +1 -1
  167. package/lib/packageVersion.d.ts.map +1 -1
  168. package/lib/packageVersion.js +1 -1
  169. package/lib/packageVersion.js.map +1 -1
  170. package/lib/pendingStateManager.d.ts +28 -27
  171. package/lib/pendingStateManager.d.ts.map +1 -1
  172. package/lib/pendingStateManager.js +144 -113
  173. package/lib/pendingStateManager.js.map +1 -1
  174. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  175. package/lib/summary/summarizerNode/summarizerNode.js +5 -1
  176. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  177. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -4
  178. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  179. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +16 -15
  180. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  181. package/package.json +23 -32
  182. package/src/batchTracker.ts +4 -2
  183. package/src/blobManager/blobManager.ts +9 -0
  184. package/src/channelCollection.ts +2 -11
  185. package/src/containerRuntime.ts +214 -100
  186. package/src/dataStoreContext.ts +29 -93
  187. package/src/gc/garbageCollection.ts +26 -79
  188. package/src/gc/gcConfigs.ts +12 -45
  189. package/src/gc/gcDefinitions.ts +10 -55
  190. package/src/gc/gcHelpers.ts +10 -8
  191. package/src/gc/gcSummaryStateTracker.ts +6 -9
  192. package/src/gc/gcTelemetry.ts +3 -38
  193. package/src/gc/index.ts +2 -6
  194. package/src/index.ts +0 -1
  195. package/src/messageTypes.ts +12 -11
  196. package/src/metadata.ts +16 -2
  197. package/src/opLifecycle/batchManager.ts +4 -1
  198. package/src/opLifecycle/index.ts +6 -1
  199. package/src/opLifecycle/opGroupingManager.ts +42 -3
  200. package/src/opLifecycle/outbox.ts +31 -1
  201. package/src/opLifecycle/remoteMessageProcessor.ts +116 -57
  202. package/src/packageVersion.ts +1 -1
  203. package/src/pendingStateManager.ts +199 -177
  204. package/src/summary/README.md +31 -28
  205. package/src/summary/summarizerNode/summarizerNode.ts +6 -1
  206. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +20 -43
  207. package/src/summary/summaryFormats.md +25 -22
@@ -21,6 +21,35 @@ import { OpDecompressor } from "./opDecompressor.js";
21
21
  import { OpGroupingManager, isGroupedBatch } from "./opGroupingManager.js";
22
22
  import { OpSplitter, isChunkedMessage } from "./opSplitter.js";
23
23
 
24
+ /** Messages being received as a batch, with details needed to process the batch */
25
+ export interface InboundBatch {
26
+ /** Messages in this batch */
27
+ readonly messages: InboundSequencedContainerRuntimeMessage[];
28
+ /** Batch ID, if present */
29
+ readonly batchId: string | undefined;
30
+ /** clientId that sent this batch. Used to compute Batch ID if needed */
31
+ readonly clientId: string;
32
+ /**
33
+ * Client Sequence Number of the first message in the batch.
34
+ * Used to compute Batch ID if needed
35
+ *
36
+ * @remarks For chunked batches, this is the CSN of the "representative" chunk (the final chunk).
37
+ * For grouped batches, clientSequenceNumber on messages is overwritten, so we track this original value here.
38
+ */
39
+ readonly batchStartCsn: number;
40
+ /** For an empty batch (with no messages), we need to remember the empty grouped batch's sequence number */
41
+ readonly emptyBatchSequenceNumber?: number;
42
+ }
43
+
44
+ function assertHasClientId(
45
+ message: ISequencedDocumentMessage,
46
+ ): asserts message is ISequencedDocumentMessage & { clientId: string } {
47
+ assert(
48
+ message.clientId !== null,
49
+ 0xa02 /* Server-generated message should not reach RemoteMessageProcessor */,
50
+ );
51
+ }
52
+
24
53
  /**
25
54
  * Stateful class for processing incoming remote messages as the virtualization measures are unwrapped,
26
55
  * potentially across numerous inbound ops.
@@ -29,13 +58,11 @@ import { OpSplitter, isChunkedMessage } from "./opSplitter.js";
29
58
  */
30
59
  export class RemoteMessageProcessor {
31
60
  /**
32
- * Client Sequence Number of the first message in the current batch being processed.
33
- * If undefined, we are expecting the next message to start a new batch.
61
+ * The current batch being received, with details needed to process it.
34
62
  *
35
- * @remarks For chunked batches, this is the CSN of the "representative" chunk (the final chunk)
63
+ * @remarks If undefined, we are expecting the next message to start a new batch.
36
64
  */
37
- private batchStartCsn: number | undefined;
38
- private readonly processorBatch: InboundSequencedContainerRuntimeMessage[] = [];
65
+ private batchInProgress: InboundBatch | undefined;
39
66
 
40
67
  constructor(
41
68
  private readonly opSplitter: OpSplitter,
@@ -70,21 +97,20 @@ export class RemoteMessageProcessor {
70
97
  * @returns all the unchunked, decompressed, ungrouped, unpacked InboundSequencedContainerRuntimeMessage from a single batch
71
98
  * or undefined if the batch is not yet complete.
72
99
  */
73
- public process(remoteMessageCopy: ISequencedDocumentMessage):
74
- | {
75
- messages: InboundSequencedContainerRuntimeMessage[];
76
- batchStartCsn: number;
77
- }
78
- | undefined {
100
+ public process(
101
+ remoteMessageCopy: ISequencedDocumentMessage,
102
+ logLegacyCase: (codePath: string) => void,
103
+ ): InboundBatch | undefined {
79
104
  let message = remoteMessageCopy;
80
105
 
81
- ensureContentsDeserialized(message);
106
+ assertHasClientId(message);
107
+ const clientId = message.clientId;
82
108
 
83
109
  if (isChunkedMessage(message)) {
84
110
  const chunkProcessingResult = this.opSplitter.processChunk(message);
85
111
  // Only continue further if current chunk is the final chunk
86
112
  if (!chunkProcessingResult.isFinalChunk) {
87
- return;
113
+ return undefined;
88
114
  }
89
115
  // This message will always be compressed
90
116
  message = chunkProcessingResult.message;
@@ -103,82 +129,111 @@ export class RemoteMessageProcessor {
103
129
  }
104
130
 
105
131
  if (isGroupedBatch(message)) {
106
- // We should be awaiting a new batch (batchStartCsn undefined)
107
- assert(this.batchStartCsn === undefined, "Grouped batch interrupting another batch");
132
+ // We should be awaiting a new batch (batchInProgress undefined)
108
133
  assert(
109
- this.processorBatch.length === 0,
110
- "Processor batch should be empty on grouped batch",
134
+ this.batchInProgress === undefined,
135
+ 0x9d3 /* Grouped batch interrupting another batch */,
111
136
  );
137
+ const batchId = asBatchMetadata(message.metadata)?.batchId;
138
+ const groupedMessages = this.opGroupingManager.ungroupOp(message).map(unpack);
112
139
  return {
113
- messages: this.opGroupingManager.ungroupOp(message).map(unpack),
140
+ messages: groupedMessages, // Will be [] for an empty batch
114
141
  batchStartCsn: message.clientSequenceNumber,
142
+ clientId,
143
+ batchId,
144
+ // If the batch is empty, we need to return the sequence number aside
145
+ emptyBatchSequenceNumber:
146
+ groupedMessages.length === 0 ? message.sequenceNumber : undefined,
115
147
  };
116
148
  }
117
149
 
118
- const batchStartCsn = this.getAndUpdateBatchStartCsn(message);
119
-
120
150
  // Do a final unpack of runtime messages in case the message was not grouped, compressed, or chunked
121
- unpackRuntimeMessage(message);
122
- this.processorBatch.push(message as InboundSequencedContainerRuntimeMessage);
151
+ unpackRuntimeMessage(message, logLegacyCase);
123
152
 
124
- // this.batchStartCsn is undefined only if we have processed all messages in the batch.
125
- // If it's still defined, we're still in the middle of a batch, so we return nothing, letting
126
- // containerRuntime know that we're waiting for more messages to complete the batch.
127
- if (this.batchStartCsn !== undefined) {
153
+ const { batchEnded } = this.addMessageToBatch(
154
+ message as InboundSequencedContainerRuntimeMessage & { clientId: string },
155
+ );
156
+
157
+ if (!batchEnded) {
128
158
  // batch not yet complete
129
159
  return undefined;
130
160
  }
131
161
 
132
- const messages = [...this.processorBatch];
133
- this.processorBatch.length = 0;
134
- return {
135
- messages,
136
- batchStartCsn,
137
- };
162
+ const completedBatch = this.batchInProgress;
163
+ this.batchInProgress = undefined;
164
+ return completedBatch;
138
165
  }
139
166
 
140
167
  /**
141
- * Based on pre-existing batch tracking info and the current message's batch metadata,
142
- * this will return the starting CSN for this message's batch, and will also update
143
- * the batch tracking info (this.batchStartCsn) based on whether we're still mid-batch.
168
+ * Add the given message to the current batch, and indicate whether the batch is now complete.
169
+ *
170
+ * @returns batchEnded: true if the batch is now complete, batchEnded: false if more messages are expected
144
171
  */
145
- private getAndUpdateBatchStartCsn(message: ISequencedDocumentMessage): number {
172
+ private addMessageToBatch(
173
+ message: InboundSequencedContainerRuntimeMessage & { clientId: string },
174
+ ): { batchEnded: boolean } {
146
175
  const batchMetadataFlag = asBatchMetadata(message.metadata)?.batch;
147
- if (this.batchStartCsn === undefined) {
176
+ if (this.batchInProgress === undefined) {
148
177
  // We are waiting for a new batch
149
- assert(batchMetadataFlag !== false, "Unexpected batch end marker");
178
+ assert(batchMetadataFlag !== false, 0x9d5 /* Unexpected batch end marker */);
150
179
 
151
180
  // Start of a new multi-message batch
152
181
  if (batchMetadataFlag === true) {
153
- this.batchStartCsn = message.clientSequenceNumber;
154
- return this.batchStartCsn;
182
+ this.batchInProgress = {
183
+ messages: [message],
184
+ batchId: asBatchMetadata(message.metadata)?.batchId,
185
+ clientId: message.clientId,
186
+ batchStartCsn: message.clientSequenceNumber,
187
+ };
188
+
189
+ return { batchEnded: false };
155
190
  }
156
191
 
157
192
  // Single-message batch (Since metadata flag is undefined)
158
- // IMPORTANT: Leave this.batchStartCsn undefined, we're ready for the next batch now.
159
- return message.clientSequenceNumber;
193
+ this.batchInProgress = {
194
+ messages: [message],
195
+ batchStartCsn: message.clientSequenceNumber,
196
+ clientId: message.clientId,
197
+ batchId: asBatchMetadata(message.metadata)?.batchId,
198
+ };
199
+ return { batchEnded: true };
160
200
  }
201
+ assert(batchMetadataFlag !== true, 0x9d6 /* Unexpected batch start marker */);
161
202
 
162
- // We are in the middle or end of an existing multi-message batch. Return the current batchStartCsn
163
- const batchStartCsn = this.batchStartCsn;
164
-
165
- assert(batchMetadataFlag !== true, "Unexpected batch start marker");
166
- if (batchMetadataFlag === false) {
167
- // Batch end? Then get ready for the next batch to start
168
- this.batchStartCsn = undefined;
169
- }
203
+ this.batchInProgress.messages.push(message);
170
204
 
171
- return batchStartCsn;
205
+ return { batchEnded: batchMetadataFlag === false };
172
206
  }
173
207
  }
174
208
 
175
- /** Takes an incoming message and if the contents is a string, JSON.parse's it in place */
176
- function ensureContentsDeserialized(mutableMessage: ISequencedDocumentMessage): void {
177
- // back-compat: ADO #1385: eventually should become unconditional, but only for runtime messages!
178
- // System message may have no contents, or in some cases (mostly for back-compat) they may have actual objects.
179
- // Old ops may contain empty string (I assume noops).
209
+ /**
210
+ * Takes an incoming message and if the contents is a string, JSON.parse's it in place
211
+ * @param mutableMessage - op message received
212
+ * @param hasModernRuntimeMessageEnvelope - false if the message does not contain the modern op envelop where message.type is MessageType.Operation
213
+ * @param logLegacyCase - callback to log when legacy op is encountered
214
+ */
215
+ export function ensureContentsDeserialized(
216
+ mutableMessage: ISequencedDocumentMessage,
217
+ hasModernRuntimeMessageEnvelope: boolean,
218
+ logLegacyCase: (codePath: string) => void,
219
+ ): void {
220
+ // Currently the loader layer is parsing the contents of the message as JSON if it is a string,
221
+ // so we never expect to see this case.
222
+ // We intend to remove that logic from the Loader, at which point we will have it here.
223
+ // Only hasModernRuntimeMessageEnvelope true will be expected to have JSON contents.
224
+ let didParseJsonContents: boolean;
180
225
  if (typeof mutableMessage.contents === "string" && mutableMessage.contents !== "") {
181
226
  mutableMessage.contents = JSON.parse(mutableMessage.contents);
227
+ didParseJsonContents = true;
228
+ } else {
229
+ didParseJsonContents = false;
230
+ }
231
+
232
+ // The DeltaManager parses the contents of the message as JSON if it is a string,
233
+ // so we should never end up parsing it here.
234
+ // Let's observe if we are wrong about this to learn about these cases.
235
+ if (didParseJsonContents) {
236
+ logLegacyCase("ensureContentsDeserialized_foundJsonContents");
182
237
  }
183
238
  }
184
239
 
@@ -214,7 +269,10 @@ function unpack(message: ISequencedDocumentMessage): InboundSequencedContainerRu
214
269
  *
215
270
  * @internal
216
271
  */
217
- export function unpackRuntimeMessage(message: ISequencedDocumentMessage): boolean {
272
+ export function unpackRuntimeMessage(
273
+ message: ISequencedDocumentMessage,
274
+ logLegacyCase: (codePath: string) => void = () => {},
275
+ ): boolean {
218
276
  if (message.type !== MessageType.Operation) {
219
277
  // Legacy format, but it's already "unpacked",
220
278
  // i.e. message.type is actually ContainerMessageType.
@@ -230,6 +288,7 @@ export function unpackRuntimeMessage(message: ISequencedDocumentMessage): boolea
230
288
  (message.contents as { type?: unknown }).type === undefined
231
289
  ) {
232
290
  message.type = ContainerMessageType.FluidDataStoreOp;
291
+ logLegacyCase("unpackRuntimeMessage_contentsWithAddress");
233
292
  } else {
234
293
  // new format
235
294
  unpack(message);
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "2.1.0-281041";
9
+ export const pkgVersion = "2.2.0";