@fluidframework/container-runtime 2.0.0-internal.3.0.5 → 2.0.0-internal.3.1.1

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 (329) hide show
  1. package/.eslintrc.js +19 -19
  2. package/.mocharc.js +2 -2
  3. package/api-extractor.json +2 -2
  4. package/dist/batchTracker.d.ts.map +1 -1
  5. package/dist/batchTracker.js +2 -1
  6. package/dist/batchTracker.js.map +1 -1
  7. package/dist/blobManager.d.ts +9 -2
  8. package/dist/blobManager.d.ts.map +1 -1
  9. package/dist/blobManager.js +80 -33
  10. package/dist/blobManager.js.map +1 -1
  11. package/dist/connectionTelemetry.d.ts.map +1 -1
  12. package/dist/connectionTelemetry.js +11 -9
  13. package/dist/connectionTelemetry.js.map +1 -1
  14. package/dist/containerHandleContext.d.ts.map +1 -1
  15. package/dist/containerHandleContext.js +3 -1
  16. package/dist/containerHandleContext.js.map +1 -1
  17. package/dist/containerRuntime.d.ts +11 -1
  18. package/dist/containerRuntime.d.ts.map +1 -1
  19. package/dist/containerRuntime.js +116 -72
  20. package/dist/containerRuntime.js.map +1 -1
  21. package/dist/dataStore.d.ts.map +1 -1
  22. package/dist/dataStore.js +11 -9
  23. package/dist/dataStore.js.map +1 -1
  24. package/dist/dataStoreContext.d.ts +18 -13
  25. package/dist/dataStoreContext.d.ts.map +1 -1
  26. package/dist/dataStoreContext.js +68 -55
  27. package/dist/dataStoreContext.js.map +1 -1
  28. package/dist/dataStoreContexts.d.ts.map +1 -1
  29. package/dist/dataStoreContexts.js +7 -3
  30. package/dist/dataStoreContexts.js.map +1 -1
  31. package/dist/dataStoreRegistry.d.ts.map +1 -1
  32. package/dist/dataStoreRegistry.js +3 -1
  33. package/dist/dataStoreRegistry.js.map +1 -1
  34. package/dist/dataStores.d.ts +26 -1
  35. package/dist/dataStores.d.ts.map +1 -1
  36. package/dist/dataStores.js +103 -18
  37. package/dist/dataStores.js.map +1 -1
  38. package/dist/deltaScheduler.d.ts.map +1 -1
  39. package/dist/deltaScheduler.js +8 -3
  40. package/dist/deltaScheduler.js.map +1 -1
  41. package/dist/garbageCollection.d.ts +33 -14
  42. package/dist/garbageCollection.d.ts.map +1 -1
  43. package/dist/garbageCollection.js +178 -92
  44. package/dist/garbageCollection.js.map +1 -1
  45. package/dist/garbageCollectionConstants.d.ts +1 -0
  46. package/dist/garbageCollectionConstants.d.ts.map +1 -1
  47. package/dist/garbageCollectionConstants.js +4 -1
  48. package/dist/garbageCollectionConstants.js.map +1 -1
  49. package/dist/garbageCollectionHelpers.d.ts +26 -0
  50. package/dist/garbageCollectionHelpers.d.ts.map +1 -0
  51. package/dist/garbageCollectionHelpers.js +45 -0
  52. package/dist/garbageCollectionHelpers.js.map +1 -0
  53. package/dist/gcSweepReadyUsageDetection.d.ts +5 -5
  54. package/dist/gcSweepReadyUsageDetection.d.ts.map +1 -1
  55. package/dist/gcSweepReadyUsageDetection.js +14 -10
  56. package/dist/gcSweepReadyUsageDetection.js.map +1 -1
  57. package/dist/index.d.ts +2 -2
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js.map +1 -1
  60. package/dist/opLifecycle/batchManager.d.ts +5 -5
  61. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  62. package/dist/opLifecycle/batchManager.js +19 -12
  63. package/dist/opLifecycle/batchManager.js.map +1 -1
  64. package/dist/opLifecycle/definitions.d.ts.map +1 -1
  65. package/dist/opLifecycle/definitions.js.map +1 -1
  66. package/dist/opLifecycle/index.d.ts.map +1 -1
  67. package/dist/opLifecycle/index.js.map +1 -1
  68. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  69. package/dist/opLifecycle/opCompressor.js.map +1 -1
  70. package/dist/opLifecycle/opDecompressor.d.ts +0 -4
  71. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  72. package/dist/opLifecycle/opDecompressor.js +7 -43
  73. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  74. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  75. package/dist/opLifecycle/opSplitter.js +4 -1
  76. package/dist/opLifecycle/opSplitter.js.map +1 -1
  77. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  78. package/dist/opLifecycle/outbox.js +20 -19
  79. package/dist/opLifecycle/outbox.js.map +1 -1
  80. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  81. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  82. package/dist/opProperties.d.ts.map +1 -1
  83. package/dist/opProperties.js +1 -3
  84. package/dist/opProperties.js.map +1 -1
  85. package/dist/orderedClientElection.d.ts.map +1 -1
  86. package/dist/orderedClientElection.js +10 -4
  87. package/dist/orderedClientElection.js.map +1 -1
  88. package/dist/packageVersion.d.ts +1 -1
  89. package/dist/packageVersion.js +1 -1
  90. package/dist/packageVersion.js.map +1 -1
  91. package/dist/pendingStateManager.d.ts +7 -0
  92. package/dist/pendingStateManager.d.ts.map +1 -1
  93. package/dist/pendingStateManager.js +7 -4
  94. package/dist/pendingStateManager.js.map +1 -1
  95. package/dist/runWhileConnectedCoordinator.d.ts.map +1 -1
  96. package/dist/runWhileConnectedCoordinator.js.map +1 -1
  97. package/dist/runningSummarizer.d.ts.map +1 -1
  98. package/dist/runningSummarizer.js +34 -21
  99. package/dist/runningSummarizer.js.map +1 -1
  100. package/dist/scheduleManager.d.ts.map +1 -1
  101. package/dist/scheduleManager.js +3 -2
  102. package/dist/scheduleManager.js.map +1 -1
  103. package/dist/serializedSnapshotStorage.d.ts +2 -2
  104. package/dist/serializedSnapshotStorage.d.ts.map +1 -1
  105. package/dist/serializedSnapshotStorage.js +5 -3
  106. package/dist/serializedSnapshotStorage.js.map +1 -1
  107. package/dist/summarizer.d.ts +2 -2
  108. package/dist/summarizer.d.ts.map +1 -1
  109. package/dist/summarizer.js +37 -17
  110. package/dist/summarizer.js.map +1 -1
  111. package/dist/summarizerClientElection.d.ts.map +1 -1
  112. package/dist/summarizerClientElection.js.map +1 -1
  113. package/dist/summarizerHandle.d.ts.map +1 -1
  114. package/dist/summarizerHandle.js.map +1 -1
  115. package/dist/summarizerHeuristics.d.ts.map +1 -1
  116. package/dist/summarizerHeuristics.js +6 -9
  117. package/dist/summarizerHeuristics.js.map +1 -1
  118. package/dist/summarizerTypes.d.ts +21 -21
  119. package/dist/summarizerTypes.d.ts.map +1 -1
  120. package/dist/summarizerTypes.js.map +1 -1
  121. package/dist/summaryCollection.d.ts.map +1 -1
  122. package/dist/summaryCollection.js +18 -8
  123. package/dist/summaryCollection.js.map +1 -1
  124. package/dist/summaryFormat.d.ts +5 -2
  125. package/dist/summaryFormat.d.ts.map +1 -1
  126. package/dist/summaryFormat.js +18 -10
  127. package/dist/summaryFormat.js.map +1 -1
  128. package/dist/summaryGenerator.d.ts.map +1 -1
  129. package/dist/summaryGenerator.js +35 -16
  130. package/dist/summaryGenerator.js.map +1 -1
  131. package/dist/summaryManager.d.ts.map +1 -1
  132. package/dist/summaryManager.js +21 -9
  133. package/dist/summaryManager.js.map +1 -1
  134. package/dist/throttler.d.ts +2 -2
  135. package/dist/throttler.d.ts.map +1 -1
  136. package/dist/throttler.js +4 -4
  137. package/dist/throttler.js.map +1 -1
  138. package/garbageCollection.md +15 -2
  139. package/lib/batchTracker.d.ts.map +1 -1
  140. package/lib/batchTracker.js +2 -1
  141. package/lib/batchTracker.js.map +1 -1
  142. package/lib/blobManager.d.ts +9 -2
  143. package/lib/blobManager.d.ts.map +1 -1
  144. package/lib/blobManager.js +82 -35
  145. package/lib/blobManager.js.map +1 -1
  146. package/lib/connectionTelemetry.d.ts.map +1 -1
  147. package/lib/connectionTelemetry.js +11 -9
  148. package/lib/connectionTelemetry.js.map +1 -1
  149. package/lib/containerHandleContext.d.ts.map +1 -1
  150. package/lib/containerHandleContext.js +3 -1
  151. package/lib/containerHandleContext.js.map +1 -1
  152. package/lib/containerRuntime.d.ts +11 -1
  153. package/lib/containerRuntime.d.ts.map +1 -1
  154. package/lib/containerRuntime.js +122 -78
  155. package/lib/containerRuntime.js.map +1 -1
  156. package/lib/dataStore.d.ts.map +1 -1
  157. package/lib/dataStore.js +11 -9
  158. package/lib/dataStore.js.map +1 -1
  159. package/lib/dataStoreContext.d.ts +18 -13
  160. package/lib/dataStoreContext.d.ts.map +1 -1
  161. package/lib/dataStoreContext.js +71 -58
  162. package/lib/dataStoreContext.js.map +1 -1
  163. package/lib/dataStoreContexts.d.ts.map +1 -1
  164. package/lib/dataStoreContexts.js +7 -3
  165. package/lib/dataStoreContexts.js.map +1 -1
  166. package/lib/dataStoreRegistry.d.ts.map +1 -1
  167. package/lib/dataStoreRegistry.js +3 -1
  168. package/lib/dataStoreRegistry.js.map +1 -1
  169. package/lib/dataStores.d.ts +26 -1
  170. package/lib/dataStores.d.ts.map +1 -1
  171. package/lib/dataStores.js +109 -24
  172. package/lib/dataStores.js.map +1 -1
  173. package/lib/deltaScheduler.d.ts.map +1 -1
  174. package/lib/deltaScheduler.js +9 -4
  175. package/lib/deltaScheduler.js.map +1 -1
  176. package/lib/garbageCollection.d.ts +33 -14
  177. package/lib/garbageCollection.d.ts.map +1 -1
  178. package/lib/garbageCollection.js +180 -94
  179. package/lib/garbageCollection.js.map +1 -1
  180. package/lib/garbageCollectionConstants.d.ts +1 -0
  181. package/lib/garbageCollectionConstants.d.ts.map +1 -1
  182. package/lib/garbageCollectionConstants.js +3 -0
  183. package/lib/garbageCollectionConstants.js.map +1 -1
  184. package/lib/garbageCollectionHelpers.d.ts +26 -0
  185. package/lib/garbageCollectionHelpers.d.ts.map +1 -0
  186. package/lib/garbageCollectionHelpers.js +40 -0
  187. package/lib/garbageCollectionHelpers.js.map +1 -0
  188. package/lib/gcSweepReadyUsageDetection.d.ts +5 -5
  189. package/lib/gcSweepReadyUsageDetection.d.ts.map +1 -1
  190. package/lib/gcSweepReadyUsageDetection.js +14 -10
  191. package/lib/gcSweepReadyUsageDetection.js.map +1 -1
  192. package/lib/index.d.ts +2 -2
  193. package/lib/index.d.ts.map +1 -1
  194. package/lib/index.js +1 -1
  195. package/lib/index.js.map +1 -1
  196. package/lib/opLifecycle/batchManager.d.ts +5 -5
  197. package/lib/opLifecycle/batchManager.d.ts.map +1 -1
  198. package/lib/opLifecycle/batchManager.js +19 -12
  199. package/lib/opLifecycle/batchManager.js.map +1 -1
  200. package/lib/opLifecycle/definitions.d.ts.map +1 -1
  201. package/lib/opLifecycle/definitions.js.map +1 -1
  202. package/lib/opLifecycle/index.d.ts.map +1 -1
  203. package/lib/opLifecycle/index.js.map +1 -1
  204. package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
  205. package/lib/opLifecycle/opCompressor.js.map +1 -1
  206. package/lib/opLifecycle/opDecompressor.d.ts +0 -4
  207. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  208. package/lib/opLifecycle/opDecompressor.js +7 -43
  209. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  210. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  211. package/lib/opLifecycle/opSplitter.js +5 -2
  212. package/lib/opLifecycle/opSplitter.js.map +1 -1
  213. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  214. package/lib/opLifecycle/outbox.js +20 -19
  215. package/lib/opLifecycle/outbox.js.map +1 -1
  216. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  217. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  218. package/lib/opProperties.d.ts.map +1 -1
  219. package/lib/opProperties.js +1 -3
  220. package/lib/opProperties.js.map +1 -1
  221. package/lib/orderedClientElection.d.ts.map +1 -1
  222. package/lib/orderedClientElection.js +10 -4
  223. package/lib/orderedClientElection.js.map +1 -1
  224. package/lib/packageVersion.d.ts +1 -1
  225. package/lib/packageVersion.js +1 -1
  226. package/lib/packageVersion.js.map +1 -1
  227. package/lib/pendingStateManager.d.ts +7 -0
  228. package/lib/pendingStateManager.d.ts.map +1 -1
  229. package/lib/pendingStateManager.js +7 -4
  230. package/lib/pendingStateManager.js.map +1 -1
  231. package/lib/runWhileConnectedCoordinator.d.ts.map +1 -1
  232. package/lib/runWhileConnectedCoordinator.js.map +1 -1
  233. package/lib/runningSummarizer.d.ts.map +1 -1
  234. package/lib/runningSummarizer.js +35 -22
  235. package/lib/runningSummarizer.js.map +1 -1
  236. package/lib/scheduleManager.d.ts.map +1 -1
  237. package/lib/scheduleManager.js +3 -2
  238. package/lib/scheduleManager.js.map +1 -1
  239. package/lib/serializedSnapshotStorage.d.ts +2 -2
  240. package/lib/serializedSnapshotStorage.d.ts.map +1 -1
  241. package/lib/serializedSnapshotStorage.js +5 -3
  242. package/lib/serializedSnapshotStorage.js.map +1 -1
  243. package/lib/summarizer.d.ts +2 -2
  244. package/lib/summarizer.d.ts.map +1 -1
  245. package/lib/summarizer.js +37 -17
  246. package/lib/summarizer.js.map +1 -1
  247. package/lib/summarizerClientElection.d.ts.map +1 -1
  248. package/lib/summarizerClientElection.js.map +1 -1
  249. package/lib/summarizerHandle.d.ts.map +1 -1
  250. package/lib/summarizerHandle.js.map +1 -1
  251. package/lib/summarizerHeuristics.d.ts.map +1 -1
  252. package/lib/summarizerHeuristics.js +6 -9
  253. package/lib/summarizerHeuristics.js.map +1 -1
  254. package/lib/summarizerTypes.d.ts +21 -21
  255. package/lib/summarizerTypes.d.ts.map +1 -1
  256. package/lib/summarizerTypes.js.map +1 -1
  257. package/lib/summaryCollection.d.ts.map +1 -1
  258. package/lib/summaryCollection.js +18 -8
  259. package/lib/summaryCollection.js.map +1 -1
  260. package/lib/summaryFormat.d.ts +5 -2
  261. package/lib/summaryFormat.d.ts.map +1 -1
  262. package/lib/summaryFormat.js +20 -12
  263. package/lib/summaryFormat.js.map +1 -1
  264. package/lib/summaryGenerator.d.ts.map +1 -1
  265. package/lib/summaryGenerator.js +35 -16
  266. package/lib/summaryGenerator.js.map +1 -1
  267. package/lib/summaryManager.d.ts.map +1 -1
  268. package/lib/summaryManager.js +21 -9
  269. package/lib/summaryManager.js.map +1 -1
  270. package/lib/throttler.d.ts +2 -2
  271. package/lib/throttler.d.ts.map +1 -1
  272. package/lib/throttler.js +4 -4
  273. package/lib/throttler.js.map +1 -1
  274. package/package.json +121 -115
  275. package/prettier.config.cjs +1 -1
  276. package/src/batchTracker.ts +54 -49
  277. package/src/blobManager.ts +793 -672
  278. package/src/connectionTelemetry.ts +280 -249
  279. package/src/containerHandleContext.ts +27 -29
  280. package/src/containerRuntime.ts +3168 -2988
  281. package/src/dataStore.ts +172 -159
  282. package/src/dataStoreContext.ts +1098 -1055
  283. package/src/dataStoreContexts.ts +178 -161
  284. package/src/dataStoreRegistry.ts +25 -20
  285. package/src/dataStores.ts +884 -728
  286. package/src/deltaScheduler.ts +158 -150
  287. package/src/garbageCollection.ts +1860 -1688
  288. package/src/garbageCollectionConstants.ts +3 -0
  289. package/src/garbageCollectionHelpers.ts +61 -0
  290. package/src/gcSweepReadyUsageDetection.ts +89 -83
  291. package/src/index.ts +67 -66
  292. package/src/opLifecycle/README.md +152 -0
  293. package/src/opLifecycle/batchManager.ts +145 -141
  294. package/src/opLifecycle/definitions.ts +29 -29
  295. package/src/opLifecycle/index.ts +5 -5
  296. package/src/opLifecycle/opCompressor.ts +54 -53
  297. package/src/opLifecycle/opDecompressor.ts +100 -128
  298. package/src/opLifecycle/opSplitter.ts +214 -188
  299. package/src/opLifecycle/outbox.ts +204 -195
  300. package/src/opLifecycle/remoteMessageProcessor.ts +62 -62
  301. package/src/opProperties.ts +11 -9
  302. package/src/orderedClientElection.ts +489 -457
  303. package/src/packageVersion.ts +1 -1
  304. package/src/pendingStateManager.ts +384 -338
  305. package/src/runWhileConnectedCoordinator.ts +78 -71
  306. package/src/runningSummarizer.ts +619 -581
  307. package/src/scheduleManager.ts +299 -269
  308. package/src/serializedSnapshotStorage.ts +126 -112
  309. package/src/summarizer.ts +417 -381
  310. package/src/summarizerClientElection.ts +107 -100
  311. package/src/summarizerHandle.ts +11 -9
  312. package/src/summarizerHeuristics.ts +183 -186
  313. package/src/summarizerTypes.ts +344 -330
  314. package/src/summaryCollection.ts +378 -349
  315. package/src/summaryFormat.ts +165 -143
  316. package/src/summaryGenerator.ts +465 -410
  317. package/src/summaryManager.ts +377 -348
  318. package/src/throttler.ts +131 -122
  319. package/tsconfig.esnext.json +6 -6
  320. package/tsconfig.json +9 -13
  321. package/dist/garbageCollectionTombstoneUtils.d.ts +0 -14
  322. package/dist/garbageCollectionTombstoneUtils.d.ts.map +0 -1
  323. package/dist/garbageCollectionTombstoneUtils.js +0 -23
  324. package/dist/garbageCollectionTombstoneUtils.js.map +0 -1
  325. package/lib/garbageCollectionTombstoneUtils.d.ts +0 -14
  326. package/lib/garbageCollectionTombstoneUtils.d.ts.map +0 -1
  327. package/lib/garbageCollectionTombstoneUtils.js +0 -19
  328. package/lib/garbageCollectionTombstoneUtils.js.map +0 -1
  329. package/src/garbageCollectionTombstoneUtils.ts +0 -28
@@ -7,7 +7,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.OpDecompressor = void 0;
8
8
  const lz4js_1 = require("lz4js");
9
9
  const common_utils_1 = require("@fluidframework/common-utils");
10
- const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
11
10
  const containerRuntime_1 = require("../containerRuntime");
12
11
  /**
13
12
  * State machine that "unrolls" contents of compressed batches of ops after decompressing them.
@@ -18,15 +17,14 @@ const containerRuntime_1 = require("../containerRuntime");
18
17
  * 4. An individually compressed op will have undefined batch metadata and compression set to true
19
18
  */
20
19
  class OpDecompressor {
21
- constructor(logger) {
20
+ constructor() {
22
21
  this.activeBatch = false;
23
22
  this.processedCount = 0;
24
- this.logger = telemetry_utils_1.ChildLogger.create(logger, "OpDecompressor");
25
23
  }
26
24
  processMessage(message) {
27
25
  var _a, _b, _c, _d;
28
26
  (0, common_utils_1.assert)(message.compression === undefined || message.compression === containerRuntime_1.CompressionAlgorithms.lz4, 0x511 /* Only lz4 compression is supported */);
29
- if (((_a = message.metadata) === null || _a === void 0 ? void 0 : _a.batch) === true && this.isCompressed(message)) {
27
+ if (((_a = message.metadata) === null || _a === void 0 ? void 0 : _a.batch) === true && message.compression === containerRuntime_1.CompressionAlgorithms.lz4) {
30
28
  // Beginning of a compressed batch
31
29
  (0, common_utils_1.assert)(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);
32
30
  if (message.compression) {
@@ -44,7 +42,9 @@ class OpDecompressor {
44
42
  state: "Accepted",
45
43
  };
46
44
  }
47
- if (this.rootMessageContents !== undefined && ((_b = message.metadata) === null || _b === void 0 ? void 0 : _b.batch) === undefined && this.activeBatch) {
45
+ if (this.rootMessageContents !== undefined &&
46
+ ((_b = message.metadata) === null || _b === void 0 ? void 0 : _b.batch) === undefined &&
47
+ this.activeBatch) {
48
48
  (0, common_utils_1.assert)(message.contents === undefined, 0x512 /* Expecting empty message */);
49
49
  // Continuation of compressed batch
50
50
  return {
@@ -63,7 +63,8 @@ class OpDecompressor {
63
63
  state: "Processed",
64
64
  };
65
65
  }
66
- if (((_d = message.metadata) === null || _d === void 0 ? void 0 : _d.batch) === undefined && this.isCompressed(message)) {
66
+ if (((_d = message.metadata) === null || _d === void 0 ? void 0 : _d.batch) === undefined &&
67
+ message.compression === containerRuntime_1.CompressionAlgorithms.lz4) {
67
68
  // Single compressed message
68
69
  (0, common_utils_1.assert)(this.activeBatch === false, 0x4ba /* shouldn't receive compressed message in middle of a batch */);
69
70
  const contents = common_utils_1.IsoBuffer.from(message.contents.packedContents, "base64");
@@ -80,43 +81,6 @@ class OpDecompressor {
80
81
  state: "Skipped",
81
82
  };
82
83
  }
83
- isCompressed(message) {
84
- var _a, _b, _c;
85
- if (message.compression === containerRuntime_1.CompressionAlgorithms.lz4) {
86
- return true;
87
- }
88
- /**
89
- * Back-compat self healing mechanism for ADO:3538, as loaders from
90
- * version client_v2.0.0-internal.1.2.0 to client_v2.0.0-internal.2.2.0 do not
91
- * support adding the proper compression metadata to compressed messages submitted
92
- * by the runtime. Should be removed after the loader reaches sufficient saturation
93
- * for a version greater or equal than client_v2.0.0-internal.2.2.0.
94
- *
95
- * The condition holds true for compressed messages, regardless of metadata. We are ultimately
96
- * looking for a message with a single property `packedContents` inside `contents`, of type 'string'
97
- * with a base64 encoded value.
98
- */
99
- try {
100
- if (typeof message.contents === "object" &&
101
- Object.keys(message.contents).length === 1 &&
102
- ((_a = message.contents) === null || _a === void 0 ? void 0 : _a.packedContents) !== undefined &&
103
- typeof ((_b = message.contents) === null || _b === void 0 ? void 0 : _b.packedContents) === "string" &&
104
- message.contents.packedContents.length > 0 &&
105
- common_utils_1.IsoBuffer.from(message.contents.packedContents, "base64").toString("base64") ===
106
- message.contents.packedContents) {
107
- this.logger.sendTelemetryEvent({
108
- eventName: "LegacyCompression",
109
- type: message.type,
110
- batch: (_c = message.metadata) === null || _c === void 0 ? void 0 : _c.batch,
111
- });
112
- return true;
113
- }
114
- }
115
- catch (err) {
116
- return false;
117
- }
118
- return false;
119
- }
120
84
  }
121
85
  exports.OpDecompressor = OpDecompressor;
122
86
  // We should not be mutating the input message nor its metadata
@@ -1 +1 @@
1
- {"version":3,"file":"opDecompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opDecompressor.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { decompress } from \"lz4js\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { assert, IsoBuffer, Uint8ArrayToString } from \"@fluidframework/common-utils\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { CompressionAlgorithms } from \"../containerRuntime\";\nimport { IMessageProcessingResult } from \"./definitions\";\n\n/**\n * State machine that \"unrolls\" contents of compressed batches of ops after decompressing them.\n * This class relies on some implicit contracts defined below:\n * 1. A compressed batch will have its first message with batch metadata set to true and compressed set to true\n * 2. Messages in the middle of a compressed batch will have neither batch metadata nor the compression property set\n * 3. The final message of a batch will have batch metadata set to false\n * 4. An individually compressed op will have undefined batch metadata and compression set to true\n */\nexport class OpDecompressor {\n private activeBatch = false;\n private rootMessageContents: any | undefined;\n private processedCount = 0;\n private readonly logger;\n\n constructor(logger: ITelemetryLogger) {\n this.logger = ChildLogger.create(logger, \"OpDecompressor\");\n }\n\n public processMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {\n assert(\n message.compression === undefined || message.compression === CompressionAlgorithms.lz4,\n 0x511 /* Only lz4 compression is supported */);\n\n if (message.metadata?.batch === true && this.isCompressed(message)) {\n // Beginning of a compressed batch\n assert(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);\n if (message.compression) {\n // lz4 is the only supported compression algorithm for now\n assert(message.compression === CompressionAlgorithms.lz4,\n 0x4b9 /* lz4 is currently the only supported compression algorithm */);\n }\n\n this.activeBatch = true;\n\n const contents = IsoBuffer.from(message.contents.packedContents, \"base64\");\n const decompressedMessage = decompress(contents);\n const intoString = Uint8ArrayToString(decompressedMessage);\n const asObj = JSON.parse(intoString);\n this.rootMessageContents = asObj;\n\n return {\n message: newMessage(message, this.rootMessageContents[this.processedCount++]),\n state: \"Accepted\",\n };\n }\n\n if (this.rootMessageContents !== undefined && message.metadata?.batch === undefined && this.activeBatch) {\n assert(message.contents === undefined, 0x512 /* Expecting empty message */);\n\n // Continuation of compressed batch\n return {\n message: newMessage(message, this.rootMessageContents[this.processedCount++]),\n state: \"Accepted\",\n };\n }\n\n if (this.rootMessageContents !== undefined && message.metadata?.batch === false) {\n // End of compressed batch\n const returnMessage = newMessage(message, this.rootMessageContents[this.processedCount++]);\n\n this.activeBatch = false;\n this.rootMessageContents = undefined;\n this.processedCount = 0;\n\n return {\n message: returnMessage,\n state: \"Processed\",\n };\n }\n\n if (message.metadata?.batch === undefined && this.isCompressed(message)) {\n // Single compressed message\n assert(this.activeBatch === false, 0x4ba /* shouldn't receive compressed message in middle of a batch */);\n\n const contents = IsoBuffer.from(message.contents.packedContents, \"base64\");\n const decompressedMessage = decompress(contents);\n const intoString = new TextDecoder().decode(decompressedMessage);\n const asObj = JSON.parse(intoString);\n\n return {\n message: newMessage(message, asObj[0]),\n state: \"Processed\",\n };\n }\n\n return {\n message,\n state: \"Skipped\",\n };\n }\n\n private isCompressed(message: ISequencedDocumentMessage) {\n if (message.compression === CompressionAlgorithms.lz4) {\n return true;\n }\n\n /**\n * Back-compat self healing mechanism for ADO:3538, as loaders from\n * version client_v2.0.0-internal.1.2.0 to client_v2.0.0-internal.2.2.0 do not\n * support adding the proper compression metadata to compressed messages submitted\n * by the runtime. Should be removed after the loader reaches sufficient saturation\n * for a version greater or equal than client_v2.0.0-internal.2.2.0.\n *\n * The condition holds true for compressed messages, regardless of metadata. We are ultimately\n * looking for a message with a single property `packedContents` inside `contents`, of type 'string'\n * with a base64 encoded value.\n */\n try {\n if (\n typeof message.contents === \"object\" &&\n Object.keys(message.contents).length === 1 &&\n message.contents?.packedContents !== undefined &&\n typeof message.contents?.packedContents === \"string\" &&\n message.contents.packedContents.length > 0 &&\n IsoBuffer.from(message.contents.packedContents, \"base64\").toString(\"base64\") ===\n message.contents.packedContents\n ) {\n this.logger.sendTelemetryEvent({\n eventName: \"LegacyCompression\",\n type: message.type,\n batch: message.metadata?.batch,\n });\n return true;\n }\n } catch (err) {\n return false;\n }\n\n return false;\n }\n}\n\n// We should not be mutating the input message nor its metadata\nconst newMessage = (originalMessage: ISequencedDocumentMessage, contents: any): ISequencedDocumentMessage => ({\n ...originalMessage,\n contents,\n compression: undefined,\n metadata: { ...originalMessage.metadata },\n});\n"]}
1
+ {"version":3,"file":"opDecompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opDecompressor.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { decompress } from \"lz4js\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { assert, IsoBuffer, Uint8ArrayToString } from \"@fluidframework/common-utils\";\nimport { CompressionAlgorithms } from \"../containerRuntime\";\nimport { IMessageProcessingResult } from \"./definitions\";\n\n/**\n * State machine that \"unrolls\" contents of compressed batches of ops after decompressing them.\n * This class relies on some implicit contracts defined below:\n * 1. A compressed batch will have its first message with batch metadata set to true and compressed set to true\n * 2. Messages in the middle of a compressed batch will have neither batch metadata nor the compression property set\n * 3. The final message of a batch will have batch metadata set to false\n * 4. An individually compressed op will have undefined batch metadata and compression set to true\n */\nexport class OpDecompressor {\n\tprivate activeBatch = false;\n\tprivate rootMessageContents: any | undefined;\n\tprivate processedCount = 0;\n\n\tpublic processMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {\n\t\tassert(\n\t\t\tmessage.compression === undefined || message.compression === CompressionAlgorithms.lz4,\n\t\t\t0x511 /* Only lz4 compression is supported */,\n\t\t);\n\n\t\tif (message.metadata?.batch === true && message.compression === CompressionAlgorithms.lz4) {\n\t\t\t// Beginning of a compressed batch\n\t\t\tassert(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);\n\t\t\tif (message.compression) {\n\t\t\t\t// lz4 is the only supported compression algorithm for now\n\t\t\t\tassert(\n\t\t\t\t\tmessage.compression === CompressionAlgorithms.lz4,\n\t\t\t\t\t0x4b9 /* lz4 is currently the only supported compression algorithm */,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.activeBatch = true;\n\n\t\t\tconst contents = IsoBuffer.from(message.contents.packedContents, \"base64\");\n\t\t\tconst decompressedMessage = decompress(contents);\n\t\t\tconst intoString = Uint8ArrayToString(decompressedMessage);\n\t\t\tconst asObj = JSON.parse(intoString);\n\t\t\tthis.rootMessageContents = asObj;\n\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, this.rootMessageContents[this.processedCount++]),\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\tthis.rootMessageContents !== undefined &&\n\t\t\tmessage.metadata?.batch === undefined &&\n\t\t\tthis.activeBatch\n\t\t) {\n\t\t\tassert(message.contents === undefined, 0x512 /* Expecting empty message */);\n\n\t\t\t// Continuation of compressed batch\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, this.rootMessageContents[this.processedCount++]),\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\tif (this.rootMessageContents !== undefined && message.metadata?.batch === false) {\n\t\t\t// End of compressed batch\n\t\t\tconst returnMessage = newMessage(\n\t\t\t\tmessage,\n\t\t\t\tthis.rootMessageContents[this.processedCount++],\n\t\t\t);\n\n\t\t\tthis.activeBatch = false;\n\t\t\tthis.rootMessageContents = undefined;\n\t\t\tthis.processedCount = 0;\n\n\t\t\treturn {\n\t\t\t\tmessage: returnMessage,\n\t\t\t\tstate: \"Processed\",\n\t\t\t};\n\t\t}\n\n\t\tif (\n\t\t\tmessage.metadata?.batch === undefined &&\n\t\t\tmessage.compression === CompressionAlgorithms.lz4\n\t\t) {\n\t\t\t// Single compressed message\n\t\t\tassert(\n\t\t\t\tthis.activeBatch === false,\n\t\t\t\t0x4ba /* shouldn't receive compressed message in middle of a batch */,\n\t\t\t);\n\n\t\t\tconst contents = IsoBuffer.from(message.contents.packedContents, \"base64\");\n\t\t\tconst decompressedMessage = decompress(contents);\n\t\t\tconst intoString = new TextDecoder().decode(decompressedMessage);\n\t\t\tconst asObj = JSON.parse(intoString);\n\n\t\t\treturn {\n\t\t\t\tmessage: newMessage(message, asObj[0]),\n\t\t\t\tstate: \"Processed\",\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tmessage,\n\t\t\tstate: \"Skipped\",\n\t\t};\n\t}\n}\n\n// We should not be mutating the input message nor its metadata\nconst newMessage = (\n\toriginalMessage: ISequencedDocumentMessage,\n\tcontents: any,\n): ISequencedDocumentMessage => ({\n\t...originalMessage,\n\tcontents,\n\tcompression: undefined,\n\tmetadata: { ...originalMessage.metadata },\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"opSplitter.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAEtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAGjF,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAE3F;;GAEG;AACH,qBAAa,UAAU;IAOf,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IAPxC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAGpB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,EACX,aAAa,EAAE,CAAC,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,MAAM,CAAC,GAAG,SAAS,EAC/D,gBAAgB,EAAE,MAAM,EACxB,mBAAmB,EAAE,MAAM,EAC5C,MAAM,EAAE,gBAAgB;IAM5B,IAAW,sBAAsB,IAAI,OAAO,CAE3C;IAED,IAAW,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAEjD;IAEM,oBAAoB,CAAC,OAAO,EAAE,yBAAyB,GAAG,wBAAwB;IAoClF,kBAAkB,CAAC,QAAQ,EAAE,MAAM;IAM1C,OAAO,CAAC,QAAQ;IAsBhB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACI,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAuCrD;AAiBD,eAAO,MAAM,OAAO,OAAQ,YAAY,oBAAoB,MAAM,KAAG,UAAU,EA4B9E,CAAC"}
1
+ {"version":3,"file":"opSplitter.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAKtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAGjF,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAE3F;;GAEG;AACH,qBAAa,UAAU;IAOrB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IAPrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAGvB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,EACX,aAAa,EAAE,CAAC,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,MAAM,CAAC,GAAG,SAAS,EAC/D,gBAAgB,EAAE,MAAM,EACxB,mBAAmB,EAAE,MAAM,EAC5C,MAAM,EAAE,gBAAgB;IAMzB,IAAW,sBAAsB,IAAI,OAAO,CAE3C;IAED,IAAW,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAEjD;IAEM,oBAAoB,CAAC,OAAO,EAAE,yBAAyB,GAAG,wBAAwB;IAoClF,kBAAkB,CAAC,QAAQ,EAAE,MAAM;IAM1C,OAAO,CAAC,QAAQ;IA0BhB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACI,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAoDlD;AAoBD,eAAO,MAAM,OAAO,OAAQ,YAAY,oBAAoB,MAAM,KAAG,UAAU,EA+B9E,CAAC"}
@@ -132,7 +132,10 @@ class OpSplitter {
132
132
  }
133
133
  exports.OpSplitter = OpSplitter;
134
134
  const chunkToBatchMessage = (chunk, referenceSequenceNumber, metadata = undefined) => {
135
- const payload = { type: containerRuntime_1.ContainerMessageType.ChunkedOp, contents: chunk };
135
+ const payload = {
136
+ type: containerRuntime_1.ContainerMessageType.ChunkedOp,
137
+ contents: chunk,
138
+ };
136
139
  return {
137
140
  contents: JSON.stringify(payload),
138
141
  deserializedContent: payload,
@@ -1 +1 @@
1
- {"version":3,"file":"opSplitter.js","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IBatchMessage } from \"@fluidframework/container-definitions\";\nimport { DataCorruptionError, extractSafePropertiesFromMessage } from \"@fluidframework/container-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ContainerMessageType, ContainerRuntimeMessage } from \"../containerRuntime\";\nimport { BatchMessage, IBatch, IChunkedOp, IMessageProcessingResult } from \"./definitions\";\n\n/**\n * Responsible for creating and reconstructing chunked messages.\n */\nexport class OpSplitter {\n // Local copy of incomplete received chunks.\n private readonly chunkMap: Map<string, string[]>;\n private readonly logger;\n\n constructor(\n chunks: [string, string[]][],\n private readonly submitBatchFn: ((batch: IBatchMessage[]) => number) | undefined,\n private readonly chunkSizeInBytes: number,\n private readonly maxBatchSizeInBytes: number,\n logger: ITelemetryLogger,\n ) {\n this.chunkMap = new Map<string, string[]>(chunks);\n this.logger = ChildLogger.create(logger, \"OpSplitter\");\n }\n\n public get isBatchChunkingEnabled(): boolean {\n return this.chunkSizeInBytes < Number.POSITIVE_INFINITY && this.submitBatchFn !== undefined;\n }\n\n public get chunks(): ReadonlyMap<string, string[]> {\n return this.chunkMap;\n }\n\n public processRemoteMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {\n if (message.type !== ContainerMessageType.ChunkedOp) {\n return {\n message,\n state: \"Skipped\",\n };\n }\n\n const clientId = message.clientId;\n const chunkedContent = message.contents as IChunkedOp;\n this.addChunk(clientId, chunkedContent, message);\n\n if (chunkedContent.chunkId < chunkedContent.totalChunks) {\n // We are processing the op in chunks but haven't reached\n // the last chunk yet in order to reconstruct the original op\n return {\n message,\n state: \"Accepted\",\n };\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const serializedContent = this.chunkMap.get(clientId)!.join(\"\");\n this.clearPartialChunks(clientId);\n\n const newMessage = { ...message };\n newMessage.contents = serializedContent === \"\" ? undefined : JSON.parse(serializedContent);\n newMessage.type = chunkedContent.originalType;\n newMessage.metadata = chunkedContent.originalMetadata;\n newMessage.compression = chunkedContent.originalCompression;\n return {\n message: newMessage,\n state: \"Processed\",\n };\n }\n\n public clearPartialChunks(clientId: string) {\n if (this.chunkMap.has(clientId)) {\n this.chunkMap.delete(clientId);\n }\n }\n\n private addChunk(clientId: string, chunkedContent: IChunkedOp, originalMessage: ISequencedDocumentMessage) {\n let map = this.chunkMap.get(clientId);\n if (map === undefined) {\n map = [];\n this.chunkMap.set(clientId, map);\n }\n\n if (chunkedContent.chunkId !== map.length + 1) {\n // We are expecting the chunks to be processed sequentially, in the same order as they are sent.\n // Therefore, the chunkId of the incoming op needs to match the length of the array (1-based indexing)\n // holding the existing chunks for that particular clientId.\n throw new DataCorruptionError(\"Chunk Id mismatch\", {\n ...extractSafePropertiesFromMessage(originalMessage),\n chunkMapLength: map.length,\n chunkId: chunkedContent.chunkId,\n totalChunks: chunkedContent.totalChunks,\n });\n }\n\n map.push(chunkedContent.contents);\n }\n\n /**\n * Splits the first op of a compressed batch in chunks, sends the chunks separately and\n * returns a new batch composed of the last chunk and the rest of the ops in the original batch.\n *\n * A compressed batch is formed by one large op at the first position, followed by a series of placeholder ops\n * which are used in order to reserve the sequence numbers for when the first op gets unrolled into the original\n * uncompressed ops at ingestion in the runtime.\n *\n * If the first op is too large, it can be chunked (split into smaller op) which can be sent individually over the wire\n * and accumulate at ingestion, until the last op in the chunk is processed, when the original op is unrolled.\n *\n * This method will send the first N - 1 chunks separately and use the last chunk as the first message in the result batch\n * and then appends the original placeholder ops. This will ensure that the batch semantics of the original (non-compressed) batch\n * are preserved, as the original chunked op will be unrolled by the runtime when the first message in the batch is processed\n * (as it is the last chunk).\n *\n * To illustrate, if the input is `[largeOp, emptyOp, emptyOp]`, `largeOp` will be split into `[chunk1, chunk2, chunk3, chunk4]`.\n * `chunk1`, `chunk2` and `chunk3` will be sent individually and `[chunk4, emptyOp, emptyOp]` will be returned.\n *\n * @param batch - the compressed batch which needs to be processed\n * @returns A new adjusted batch which can be sent over the wire\n */\n public splitCompressedBatch(batch: IBatch): IBatch {\n assert(this.isBatchChunkingEnabled, 0x513 /* Chunking needs to be enabled */);\n assert(batch.contentSizeInBytes > 0 && batch.content.length > 0, 0x514 /* Batch needs to be non-empty */);\n assert(this.chunkSizeInBytes !== 0, 0x515 /* Chunk size needs to be non-zero */);\n assert(this.chunkSizeInBytes < this.maxBatchSizeInBytes, 0x516 /* Chunk size needs to be smaller than the max batch size */);\n\n const firstMessage = batch.content[0]; // we expect this to be the large compressed op, which needs to be split\n assert(firstMessage.metadata?.compressed === true || firstMessage.compression !== undefined, 0x517 /* Batch needs to be compressed */);\n assert((firstMessage.contents?.length ?? 0) >= this.chunkSizeInBytes, 0x518 /* First message in the batch needs to be chunkable */);\n\n const restOfMessages = batch.content.slice(1); // we expect these to be empty ops, created to reserve sequence numbers\n const chunks = splitOp(firstMessage, this.chunkSizeInBytes);\n\n assert(this.submitBatchFn !== undefined, 0x519 /* We don't support old loaders */);\n // Send the first N-1 chunks immediately\n for (const chunk of chunks.slice(0, -1)) {\n this.submitBatchFn([chunkToBatchMessage(chunk, firstMessage.referenceSequenceNumber)]);\n }\n\n // The last chunk will be part of the new batch and needs to\n // preserve the batch metadata of the original batch\n const lastChunk = chunkToBatchMessage(\n chunks[chunks.length - 1],\n firstMessage.referenceSequenceNumber,\n { batch: firstMessage.metadata?.batch });\n\n this.logger.sendPerformanceEvent({\n eventName: \"Chunked compressed batch\",\n length: batch.content.length,\n sizeInBytes: batch.contentSizeInBytes,\n chunks: chunks.length,\n chunkSizeInBytes: this.chunkSizeInBytes,\n });\n\n return {\n content: [lastChunk, ...restOfMessages],\n contentSizeInBytes: lastChunk.contents?.length ?? 0,\n };\n }\n}\n\nconst chunkToBatchMessage = (\n chunk: IChunkedOp,\n referenceSequenceNumber: number,\n metadata: Record<string, unknown> | undefined = undefined,\n): BatchMessage => {\n const payload: ContainerRuntimeMessage = { type: ContainerMessageType.ChunkedOp, contents: chunk };\n return {\n contents: JSON.stringify(payload),\n deserializedContent: payload,\n metadata,\n localOpMetadata: undefined,\n referenceSequenceNumber,\n };\n}\n\nexport const splitOp = (op: BatchMessage, chunkSizeInBytes: number): IChunkedOp[] => {\n const chunks: IChunkedOp[] = [];\n assert(op.contents !== undefined && op.contents !== null, 0x51a /* We should have something to chunk */);\n\n const contentLength = op.contents.length;\n const chunkN = Math.floor((contentLength - 1) / chunkSizeInBytes) + 1;\n let offset = 0;\n for (let i = 1; i <= chunkN; i++) {\n const chunk: IChunkedOp = {\n chunkId: i,\n contents: op.contents.substr(offset, chunkSizeInBytes),\n originalType: op.deserializedContent.type,\n totalChunks: chunkN,\n }\n\n if (i === chunkN) {\n // We don't need to port these to all the chunks,\n // as we rebuild the original op when we process the\n // last chunk, therefore it is the only one that needs it.\n chunk.originalMetadata = op.metadata;\n chunk.originalCompression = op.compression;\n }\n\n chunks.push(chunk);\n offset += chunkSizeInBytes;\n }\n\n return chunks;\n};\n"]}
1
+ {"version":3,"file":"opSplitter.js","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IBatchMessage } from \"@fluidframework/container-definitions\";\nimport {\n\tDataCorruptionError,\n\textractSafePropertiesFromMessage,\n} from \"@fluidframework/container-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ContainerMessageType, ContainerRuntimeMessage } from \"../containerRuntime\";\nimport { BatchMessage, IBatch, IChunkedOp, IMessageProcessingResult } from \"./definitions\";\n\n/**\n * Responsible for creating and reconstructing chunked messages.\n */\nexport class OpSplitter {\n\t// Local copy of incomplete received chunks.\n\tprivate readonly chunkMap: Map<string, string[]>;\n\tprivate readonly logger;\n\n\tconstructor(\n\t\tchunks: [string, string[]][],\n\t\tprivate readonly submitBatchFn: ((batch: IBatchMessage[]) => number) | undefined,\n\t\tprivate readonly chunkSizeInBytes: number,\n\t\tprivate readonly maxBatchSizeInBytes: number,\n\t\tlogger: ITelemetryLogger,\n\t) {\n\t\tthis.chunkMap = new Map<string, string[]>(chunks);\n\t\tthis.logger = ChildLogger.create(logger, \"OpSplitter\");\n\t}\n\n\tpublic get isBatchChunkingEnabled(): boolean {\n\t\treturn this.chunkSizeInBytes < Number.POSITIVE_INFINITY && this.submitBatchFn !== undefined;\n\t}\n\n\tpublic get chunks(): ReadonlyMap<string, string[]> {\n\t\treturn this.chunkMap;\n\t}\n\n\tpublic processRemoteMessage(message: ISequencedDocumentMessage): IMessageProcessingResult {\n\t\tif (message.type !== ContainerMessageType.ChunkedOp) {\n\t\t\treturn {\n\t\t\t\tmessage,\n\t\t\t\tstate: \"Skipped\",\n\t\t\t};\n\t\t}\n\n\t\tconst clientId = message.clientId;\n\t\tconst chunkedContent = message.contents as IChunkedOp;\n\t\tthis.addChunk(clientId, chunkedContent, message);\n\n\t\tif (chunkedContent.chunkId < chunkedContent.totalChunks) {\n\t\t\t// We are processing the op in chunks but haven't reached\n\t\t\t// the last chunk yet in order to reconstruct the original op\n\t\t\treturn {\n\t\t\t\tmessage,\n\t\t\t\tstate: \"Accepted\",\n\t\t\t};\n\t\t}\n\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst serializedContent = this.chunkMap.get(clientId)!.join(\"\");\n\t\tthis.clearPartialChunks(clientId);\n\n\t\tconst newMessage = { ...message };\n\t\tnewMessage.contents = serializedContent === \"\" ? undefined : JSON.parse(serializedContent);\n\t\tnewMessage.type = chunkedContent.originalType;\n\t\tnewMessage.metadata = chunkedContent.originalMetadata;\n\t\tnewMessage.compression = chunkedContent.originalCompression;\n\t\treturn {\n\t\t\tmessage: newMessage,\n\t\t\tstate: \"Processed\",\n\t\t};\n\t}\n\n\tpublic clearPartialChunks(clientId: string) {\n\t\tif (this.chunkMap.has(clientId)) {\n\t\t\tthis.chunkMap.delete(clientId);\n\t\t}\n\t}\n\n\tprivate addChunk(\n\t\tclientId: string,\n\t\tchunkedContent: IChunkedOp,\n\t\toriginalMessage: ISequencedDocumentMessage,\n\t) {\n\t\tlet map = this.chunkMap.get(clientId);\n\t\tif (map === undefined) {\n\t\t\tmap = [];\n\t\t\tthis.chunkMap.set(clientId, map);\n\t\t}\n\n\t\tif (chunkedContent.chunkId !== map.length + 1) {\n\t\t\t// We are expecting the chunks to be processed sequentially, in the same order as they are sent.\n\t\t\t// Therefore, the chunkId of the incoming op needs to match the length of the array (1-based indexing)\n\t\t\t// holding the existing chunks for that particular clientId.\n\t\t\tthrow new DataCorruptionError(\"Chunk Id mismatch\", {\n\t\t\t\t...extractSafePropertiesFromMessage(originalMessage),\n\t\t\t\tchunkMapLength: map.length,\n\t\t\t\tchunkId: chunkedContent.chunkId,\n\t\t\t\ttotalChunks: chunkedContent.totalChunks,\n\t\t\t});\n\t\t}\n\n\t\tmap.push(chunkedContent.contents);\n\t}\n\n\t/**\n\t * Splits the first op of a compressed batch in chunks, sends the chunks separately and\n\t * returns a new batch composed of the last chunk and the rest of the ops in the original batch.\n\t *\n\t * A compressed batch is formed by one large op at the first position, followed by a series of placeholder ops\n\t * which are used in order to reserve the sequence numbers for when the first op gets unrolled into the original\n\t * uncompressed ops at ingestion in the runtime.\n\t *\n\t * If the first op is too large, it can be chunked (split into smaller op) which can be sent individually over the wire\n\t * and accumulate at ingestion, until the last op in the chunk is processed, when the original op is unrolled.\n\t *\n\t * This method will send the first N - 1 chunks separately and use the last chunk as the first message in the result batch\n\t * and then appends the original placeholder ops. This will ensure that the batch semantics of the original (non-compressed) batch\n\t * are preserved, as the original chunked op will be unrolled by the runtime when the first message in the batch is processed\n\t * (as it is the last chunk).\n\t *\n\t * To illustrate, if the input is `[largeOp, emptyOp, emptyOp]`, `largeOp` will be split into `[chunk1, chunk2, chunk3, chunk4]`.\n\t * `chunk1`, `chunk2` and `chunk3` will be sent individually and `[chunk4, emptyOp, emptyOp]` will be returned.\n\t *\n\t * @param batch - the compressed batch which needs to be processed\n\t * @returns A new adjusted batch which can be sent over the wire\n\t */\n\tpublic splitCompressedBatch(batch: IBatch): IBatch {\n\t\tassert(this.isBatchChunkingEnabled, 0x513 /* Chunking needs to be enabled */);\n\t\tassert(\n\t\t\tbatch.contentSizeInBytes > 0 && batch.content.length > 0,\n\t\t\t0x514 /* Batch needs to be non-empty */,\n\t\t);\n\t\tassert(this.chunkSizeInBytes !== 0, 0x515 /* Chunk size needs to be non-zero */);\n\t\tassert(\n\t\t\tthis.chunkSizeInBytes < this.maxBatchSizeInBytes,\n\t\t\t0x516 /* Chunk size needs to be smaller than the max batch size */,\n\t\t);\n\n\t\tconst firstMessage = batch.content[0]; // we expect this to be the large compressed op, which needs to be split\n\t\tassert(\n\t\t\tfirstMessage.metadata?.compressed === true || firstMessage.compression !== undefined,\n\t\t\t0x517 /* Batch needs to be compressed */,\n\t\t);\n\t\tassert(\n\t\t\t(firstMessage.contents?.length ?? 0) >= this.chunkSizeInBytes,\n\t\t\t0x518 /* First message in the batch needs to be chunkable */,\n\t\t);\n\n\t\tconst restOfMessages = batch.content.slice(1); // we expect these to be empty ops, created to reserve sequence numbers\n\t\tconst chunks = splitOp(firstMessage, this.chunkSizeInBytes);\n\n\t\tassert(this.submitBatchFn !== undefined, 0x519 /* We don't support old loaders */);\n\t\t// Send the first N-1 chunks immediately\n\t\tfor (const chunk of chunks.slice(0, -1)) {\n\t\t\tthis.submitBatchFn([chunkToBatchMessage(chunk, firstMessage.referenceSequenceNumber)]);\n\t\t}\n\n\t\t// The last chunk will be part of the new batch and needs to\n\t\t// preserve the batch metadata of the original batch\n\t\tconst lastChunk = chunkToBatchMessage(\n\t\t\tchunks[chunks.length - 1],\n\t\t\tfirstMessage.referenceSequenceNumber,\n\t\t\t{ batch: firstMessage.metadata?.batch },\n\t\t);\n\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\teventName: \"Chunked compressed batch\",\n\t\t\tlength: batch.content.length,\n\t\t\tsizeInBytes: batch.contentSizeInBytes,\n\t\t\tchunks: chunks.length,\n\t\t\tchunkSizeInBytes: this.chunkSizeInBytes,\n\t\t});\n\n\t\treturn {\n\t\t\tcontent: [lastChunk, ...restOfMessages],\n\t\t\tcontentSizeInBytes: lastChunk.contents?.length ?? 0,\n\t\t};\n\t}\n}\n\nconst chunkToBatchMessage = (\n\tchunk: IChunkedOp,\n\treferenceSequenceNumber: number,\n\tmetadata: Record<string, unknown> | undefined = undefined,\n): BatchMessage => {\n\tconst payload: ContainerRuntimeMessage = {\n\t\ttype: ContainerMessageType.ChunkedOp,\n\t\tcontents: chunk,\n\t};\n\treturn {\n\t\tcontents: JSON.stringify(payload),\n\t\tdeserializedContent: payload,\n\t\tmetadata,\n\t\tlocalOpMetadata: undefined,\n\t\treferenceSequenceNumber,\n\t};\n};\n\nexport const splitOp = (op: BatchMessage, chunkSizeInBytes: number): IChunkedOp[] => {\n\tconst chunks: IChunkedOp[] = [];\n\tassert(\n\t\top.contents !== undefined && op.contents !== null,\n\t\t0x51a /* We should have something to chunk */,\n\t);\n\n\tconst contentLength = op.contents.length;\n\tconst chunkN = Math.floor((contentLength - 1) / chunkSizeInBytes) + 1;\n\tlet offset = 0;\n\tfor (let i = 1; i <= chunkN; i++) {\n\t\tconst chunk: IChunkedOp = {\n\t\t\tchunkId: i,\n\t\t\tcontents: op.contents.substr(offset, chunkSizeInBytes),\n\t\t\toriginalType: op.deserializedContent.type,\n\t\t\ttotalChunks: chunkN,\n\t\t};\n\n\t\tif (i === chunkN) {\n\t\t\t// We don't need to port these to all the chunks,\n\t\t\t// as we rebuild the original op when we process the\n\t\t\t// last chunk, therefore it is the only one that needs it.\n\t\t\tchunk.originalMetadata = op.metadata;\n\t\t\tchunk.originalCompression = op.compression;\n\t\t}\n\n\t\tchunks.push(chunk);\n\t\toffset += chunkSizeInBytes;\n\t}\n\n\treturn chunks;\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAG1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAU,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;IAExD,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC3C;AAED,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;IACnC,QAAQ,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;IAClD,QAAQ,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;IAC7C,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;CACrC;AAED,qBAAa,MAAM;IAKH,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAe;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,iCAAiC,CAAa;gBAElC,MAAM,EAAE,iBAAiB;IAiBtD,IAAW,OAAO,IAAI,OAAO,CAE5B;IAEM,MAAM,CAAC,OAAO,EAAE,YAAY;IAa5B,YAAY,CAAC,OAAO,EAAE,YAAY;IA4BlC,KAAK;IAKZ,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,aAAa;IA+BrB;;;;;;OAMG;IACH,OAAO,CAAC,SAAS;IA2CjB,OAAO,CAAC,YAAY;IAkBb,UAAU;;;;CAMpB"}
1
+ {"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAG1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAU,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,kBAAkB,EAAE,0BAA0B,CAAC;IAExD,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC;IACnC,QAAQ,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;IAClD,QAAQ,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;IAC7C,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;CAClC;AAED,qBAAa,MAAM;IAKN,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAe;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,iCAAiC,CAAa;gBAElC,MAAM,EAAE,iBAAiB;IAyBtD,IAAW,OAAO,IAAI,OAAO,CAE5B;IAEM,MAAM,CAAC,OAAO,EAAE,YAAY;IAW5B,YAAY,CAAC,OAAO,EAAE,YAAY;IA6BlC,KAAK;IAKZ,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,aAAa;IA+BrB;;;;;;OAMG;IACH,OAAO,CAAC,SAAS;IA6CjB,OAAO,CAAC,YAAY;IAkBb,UAAU;;;;CAMjB"}
@@ -9,12 +9,12 @@ const common_utils_1 = require("@fluidframework/common-utils");
9
9
  const container_utils_1 = require("@fluidframework/container-utils");
10
10
  const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
11
11
  const batchManager_1 = require("./batchManager");
12
- ;
13
12
  class Outbox {
14
13
  constructor(params) {
15
14
  this.params = params;
16
15
  this.defaultAttachFlowSoftLimitInBytes = 64 * 1024;
17
- const isCompressionEnabled = this.params.config.compressionOptions.minimumBatchSizeInBytes !== Number.POSITIVE_INFINITY;
16
+ const isCompressionEnabled = this.params.config.compressionOptions.minimumBatchSizeInBytes !==
17
+ Number.POSITIVE_INFINITY;
18
18
  // We need to allow infinite size batches if we enable compression
19
19
  const hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;
20
20
  const softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;
@@ -34,9 +34,9 @@ class Outbox {
34
34
  submit(message) {
35
35
  var _a, _b;
36
36
  if (!this.mainBatch.push(message)) {
37
- throw new container_utils_1.GenericError("BatchTooLarge",
38
- /* error */ undefined, {
39
- opSize: (_b = ((_a = message.contents) === null || _a === void 0 ? void 0 : _a.length)) !== null && _b !== void 0 ? _b : 0,
37
+ throw new container_utils_1.GenericError("BatchTooLarge", /* error */ undefined, {
38
+ opSize: (_b = (_a = message.contents) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0,
39
+ batchSize: this.mainBatch.contentSizeInBytes,
40
40
  count: this.mainBatch.length,
41
41
  limit: this.mainBatch.options.hardLimit,
42
42
  });
@@ -50,9 +50,9 @@ class Outbox {
50
50
  // Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit
51
51
  this.flushInternal(this.attachFlowBatch.popBatch());
52
52
  if (!this.attachFlowBatch.push(message)) {
53
- throw new container_utils_1.GenericError("BatchTooLarge",
54
- /* error */ undefined, {
55
- opSize: (_b = ((_a = message.contents) === null || _a === void 0 ? void 0 : _a.length)) !== null && _b !== void 0 ? _b : 0,
53
+ throw new container_utils_1.GenericError("BatchTooLarge", /* error */ undefined, {
54
+ opSize: (_b = (_a = message.contents) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0,
55
+ batchSize: this.attachFlowBatch.contentSizeInBytes,
56
56
  count: this.attachFlowBatch.length,
57
57
  limit: this.attachFlowBatch.options.hardLimit,
58
58
  });
@@ -63,7 +63,8 @@ class Outbox {
63
63
  // of the overall size of the accumulated ops in the batch.
64
64
  // However, it is more efficient to flush these ops faster, preferably
65
65
  // after they reach a size which would benefit from compression.
66
- if (this.attachFlowBatch.contentSizeInBytes >= this.params.config.compressionOptions.minimumBatchSizeInBytes) {
66
+ if (this.attachFlowBatch.contentSizeInBytes >=
67
+ this.params.config.compressionOptions.minimumBatchSizeInBytes) {
67
68
  this.flushInternal(this.attachFlowBatch.popBatch());
68
69
  }
69
70
  }
@@ -77,11 +78,10 @@ class Outbox {
77
78
  this.persistBatch(clientSequenceNumber, rawBatch.content);
78
79
  }
79
80
  compressBatch(batch) {
80
- if (batch.content.length === 0
81
- || this.params.config.compressionOptions === undefined
82
- || this.params.config.compressionOptions.minimumBatchSizeInBytes > batch.contentSizeInBytes
83
- || this.params.containerContext.submitBatchFn === undefined) {
84
- // Nothing to do if the batch is empty or if compression is disabled or not supported, or if we don't need to compress
81
+ if (batch.content.length === 0 ||
82
+ this.params.config.compressionOptions === undefined ||
83
+ this.params.config.compressionOptions.minimumBatchSizeInBytes > batch.contentSizeInBytes) {
84
+ // Nothing to do if the batch is empty or if compression is disabled or if we don't need to compress
85
85
  return batch;
86
86
  }
87
87
  const compressedBatch = this.params.compressor.compressBatch(batch);
@@ -93,12 +93,13 @@ class Outbox {
93
93
  return this.params.splitter.splitCompressedBatch(compressedBatch);
94
94
  }
95
95
  // If we've reached this point, the runtime would attempt to send a batch larger than the allowed size
96
- throw new container_utils_1.GenericError("BatchTooLarge",
97
- /* error */ undefined, {
98
- opSize: batch.contentSizeInBytes,
99
- count: batch.content.length,
96
+ throw new container_utils_1.GenericError("BatchTooLarge", /* error */ undefined, {
97
+ batchSize: batch.contentSizeInBytes,
98
+ compressedBatchSize: compressedBatch.contentSizeInBytes,
99
+ count: compressedBatch.content.length,
100
100
  limit: this.params.config.maxBatchSizeInBytes,
101
- compressed: true,
101
+ chunkingEnabled: this.params.splitter.isBatchChunkingEnabled,
102
+ compressionOptions: JSON.stringify(this.params.config.compressionOptions),
102
103
  });
103
104
  }
104
105
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,+DAAsD;AAEtD,qEAA+D;AAC/D,+EAAmE;AAGnE,iDAA8C;AAU7C,CAAC;AAYF,MAAa,MAAM;IAKf,YAA6B,MAAyB;QAAzB,WAAM,GAAN,MAAM,CAAmB;QAFrC,sCAAiC,GAAG,EAAE,GAAG,IAAI,CAAC;QAG3D,MAAM,oBAAoB,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,uBAAuB,KAAK,MAAM,CAAC,iBAAiB,CAAC;QACxH,kEAAkE;QAClE,MAAM,SAAS,GAAG,oBAAoB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC;QAC3F,MAAM,SAAS,GAAG,oBAAoB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,iCAAiC,CAAC;QAE3F,IAAI,CAAC,eAAe,GAAG,IAAI,2BAAY,CAAC;YACpC,SAAS;YACT,SAAS;YACT,oBAAoB,EAAE,MAAM,CAAC,MAAM,CAAC,oBAAoB;SAC3D,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,IAAI,2BAAY,CAAC;YAC9B,SAAS;YACT,oBAAoB,EAAE,MAAM,CAAC,MAAM,CAAC,oBAAoB;SAC3D,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACtB,CAAC;IAED,IAAW,OAAO;QACd,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC;IAC5E,CAAC;IAEM,MAAM,CAAC,OAAqB;;QAC/B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;YAC/B,MAAM,IAAI,8BAAY,CAClB,eAAe;YACf,WAAW,CAAC,SAAS,EACrB;gBACI,MAAM,EAAE,MAAA,CAAC,MAAA,OAAO,CAAC,QAAQ,0CAAE,MAAM,CAAC,mCAAI,CAAC;gBACvC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM;gBAC5B,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS;aAC1C,CAAC,CAAC;SACV;IACL,CAAC;IAEM,YAAY,CAAC,OAAqB;;QACrC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;YACrC,oFAAoF;YACpF,2BAA2B;YAC3B,8FAA8F;YAC9F,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC;YACpD,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;gBACrC,MAAM,IAAI,8BAAY,CAClB,eAAe;gBACf,WAAW,CAAC,SAAS,EACrB;oBACI,MAAM,EAAE,MAAA,CAAC,MAAA,OAAO,CAAC,QAAQ,0CAAE,MAAM,CAAC,mCAAI,CAAC;oBACvC,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,MAAM;oBAClC,KAAK,EAAE,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,SAAS;iBAChD,CAAC,CAAC;aACV;SACJ;QAED,iEAAiE;QACjE,yEAAyE;QACzE,2DAA2D;QAC3D,sEAAsE;QACtE,gEAAgE;QAChE,IAAI,IAAI,CAAC,eAAe,CAAC,kBAAkB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,uBAAuB,EAAE;YAC1G,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC;SACvD;IACL,CAAC;IAEM,KAAK;QACR,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;IAClD,CAAC;IAEO,aAAa,CAAC,QAAgB;QAClC,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,oBAAoB,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QAE5D,IAAI,CAAC,YAAY,CAAC,oBAAoB,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9D,CAAC;IAEO,aAAa,CAAC,KAAa;QAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;eACvB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,KAAK,SAAS;eACnD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,uBAAuB,GAAG,KAAK,CAAC,kBAAkB;eACxF,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,KAAK,SAAS,EAAE;YAC7D,sHAAsH;YACtH,OAAO,KAAK,CAAC;SAChB;QAED,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpE,IAAI,eAAe,CAAC,kBAAkB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE;YAC9E,uFAAuF;YACvF,OAAO,eAAe,CAAC;SAC1B;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,EAAE;YAC7C,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC;SACrE;QAED,sGAAsG;QACtG,MAAM,IAAI,8BAAY,CAClB,eAAe;QACf,WAAW,CAAC,SAAS,EACrB;YACI,MAAM,EAAE,KAAK,CAAC,kBAAkB;YAChC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM;YAC3B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB;YAC7C,UAAU,EAAE,IAAI;SACnB,CAAC,CAAC;IACX,CAAC;IAED;;;;;;OAMG;IACK,SAAS,CAAC,KAAa;;QAC3B,IAAI,oBAAoB,GAAW,CAAC,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAEpC,uDAAuD;QACvD,uFAAuF;QACvF,IAAI,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE;YAC3C,OAAO,oBAAoB,CAAC;SAC/B;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,KAAK,SAAS,EAAE;YAC1D,yFAAyF;YACzF,uDAAuD;YACvD,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE;gBACjC,+FAA+F;gBAC/F,IAAI,MAAA,OAAO,CAAC,QAAQ,0CAAE,UAAU,EAAE;oBAC9B,OAAO,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;iBACtC;gBAED,oBAAoB,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CACxD,kCAAW,CAAC,SAAS,EACrB,OAAO,CAAC,mBAAmB,EAC3B,IAAI,EAAE,QAAQ;gBACd,OAAO,CAAC,QAAQ,CAAC,CAAC;aACzB;YAED,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;SACrD;aAAM;YACH,0DAA0D;YAC1D,oBAAoB,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAC7D,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,WAAW,EAAE,OAAO,CAAC,WAAW;aACnC,CAAC,CAAC,CAAC,CAAC;SACZ;QAED,2GAA2G;QAC3G,oBAAoB,IAAI,MAAM,GAAG,CAAC,CAAC;QACnC,IAAA,qBAAM,EAAC,oBAAoB,IAAI,CAAC,EAAE,KAAK,CAAC,4CAA4C,CAAC,CAAC;QACtF,OAAO,oBAAoB,CAAC;IAChC,CAAC;IAEO,YAAY,CAAC,2BAAmC,EAAE,KAAqB;QAC3E,IAAI,oBAAoB,GAAG,2BAA2B,CAAC;QACvD,iEAAiE;QACjE,4DAA4D;QAC5D,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE;YACzB,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,eAAe,CAC3C,OAAO,CAAC,mBAAmB,CAAC,IAAI,EAChC,oBAAoB,EACpB,OAAO,CAAC,uBAAuB,EAC/B,OAAO,CAAC,mBAAmB,CAAC,QAAQ,EACpC,OAAO,CAAC,eAAe,EACvB,OAAO,CAAC,QAAQ,CACnB,CAAC;YAEF,oBAAoB,EAAE,CAAC;SAC1B;IACL,CAAC;IAEM,UAAU;QACb,OAAO;YACH,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE;YACtC,eAAe,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE;SACrD,CAAC;IACN,CAAC;CACJ;AAxLD,wBAwLC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IContainerContext } from \"@fluidframework/container-definitions\";\nimport { GenericError } from \"@fluidframework/container-utils\";\nimport { MessageType } from \"@fluidframework/protocol-definitions\";\nimport { ICompressionRuntimeOptions } from \"../containerRuntime\";\nimport { PendingStateManager } from \"../pendingStateManager\";\nimport { BatchManager } from \"./batchManager\";\nimport { BatchMessage, IBatch } from \"./definitions\";\nimport { OpCompressor } from \"./opCompressor\";\nimport { OpSplitter } from \"./opSplitter\";\n\nexport interface IOutboxConfig {\n readonly compressionOptions: ICompressionRuntimeOptions;\n // The maximum size of a batch that we can send over the wire.\n readonly maxBatchSizeInBytes: number;\n readonly enableOpReentryCheck?: boolean;\n};\n\nexport interface IOutboxParameters {\n readonly shouldSend: () => boolean,\n readonly pendingStateManager: PendingStateManager,\n readonly containerContext: IContainerContext,\n readonly config: IOutboxConfig,\n readonly compressor: OpCompressor;\n readonly splitter: OpSplitter;\n readonly logger: ITelemetryLogger;\n}\n\nexport class Outbox {\n private readonly attachFlowBatch: BatchManager;\n private readonly mainBatch: BatchManager;\n private readonly defaultAttachFlowSoftLimitInBytes = 64 * 1024;\n\n constructor(private readonly params: IOutboxParameters) {\n const isCompressionEnabled = this.params.config.compressionOptions.minimumBatchSizeInBytes !== Number.POSITIVE_INFINITY;\n // We need to allow infinite size batches if we enable compression\n const hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;\n const softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;\n\n this.attachFlowBatch = new BatchManager({\n hardLimit,\n softLimit,\n enableOpReentryCheck: params.config.enableOpReentryCheck,\n }, params.logger);\n this.mainBatch = new BatchManager({\n hardLimit,\n enableOpReentryCheck: params.config.enableOpReentryCheck,\n }, params.logger);\n }\n\n public get isEmpty(): boolean {\n return this.attachFlowBatch.length === 0 && this.mainBatch.length === 0;\n }\n\n public submit(message: BatchMessage) {\n if (!this.mainBatch.push(message)) {\n throw new GenericError(\n \"BatchTooLarge\",\n /* error */ undefined,\n {\n opSize: (message.contents?.length) ?? 0,\n count: this.mainBatch.length,\n limit: this.mainBatch.options.hardLimit,\n });\n }\n }\n\n public submitAttach(message: BatchMessage) {\n if (!this.attachFlowBatch.push(message)) {\n // BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged\n // when queue is not empty.\n // Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit\n this.flushInternal(this.attachFlowBatch.popBatch());\n if (!this.attachFlowBatch.push(message)) {\n throw new GenericError(\n \"BatchTooLarge\",\n /* error */ undefined,\n {\n opSize: (message.contents?.length) ?? 0,\n count: this.attachFlowBatch.length,\n limit: this.attachFlowBatch.options.hardLimit,\n });\n }\n }\n\n // If compression is enabled, we will always successfully receive\n // attach ops and compress then send them at the next JS turn, regardless\n // of the overall size of the accumulated ops in the batch.\n // However, it is more efficient to flush these ops faster, preferably\n // after they reach a size which would benefit from compression.\n if (this.attachFlowBatch.contentSizeInBytes >= this.params.config.compressionOptions.minimumBatchSizeInBytes) {\n this.flushInternal(this.attachFlowBatch.popBatch());\n }\n }\n\n public flush() {\n this.flushInternal(this.attachFlowBatch.popBatch());\n this.flushInternal(this.mainBatch.popBatch());\n }\n\n private flushInternal(rawBatch: IBatch) {\n const processedBatch = this.compressBatch(rawBatch);\n const clientSequenceNumber = this.sendBatch(processedBatch);\n\n this.persistBatch(clientSequenceNumber, rawBatch.content);\n }\n\n private compressBatch(batch: IBatch): IBatch {\n if (batch.content.length === 0\n || this.params.config.compressionOptions === undefined\n || this.params.config.compressionOptions.minimumBatchSizeInBytes > batch.contentSizeInBytes\n || this.params.containerContext.submitBatchFn === undefined) {\n // Nothing to do if the batch is empty or if compression is disabled or not supported, or if we don't need to compress\n return batch;\n }\n\n const compressedBatch = this.params.compressor.compressBatch(batch);\n if (compressedBatch.contentSizeInBytes <= this.params.config.maxBatchSizeInBytes) {\n // If we don't reach the maximum supported size of a batch, it can safely be sent as is\n return compressedBatch;\n }\n\n if (this.params.splitter.isBatchChunkingEnabled) {\n return this.params.splitter.splitCompressedBatch(compressedBatch);\n }\n\n // If we've reached this point, the runtime would attempt to send a batch larger than the allowed size\n throw new GenericError(\n \"BatchTooLarge\",\n /* error */ undefined,\n {\n opSize: batch.contentSizeInBytes,\n count: batch.content.length,\n limit: this.params.config.maxBatchSizeInBytes,\n compressed: true,\n });\n }\n\n /**\n * Sends the batch object to the container context to be sent over the wire.\n *\n * @param batch - batch to be sent\n * @returns the client sequence number of the last batched op which was sent and\n * -1 if there are no ops or the container cannot send ops.\n */\n private sendBatch(batch: IBatch): number {\n let clientSequenceNumber: number = -1;\n const length = batch.content.length;\n\n // Did we disconnect in the middle of turn-based batch?\n // If so, do nothing, as pending state manager will resubmit it correctly on reconnect.\n if (length === 0 || !this.params.shouldSend()) {\n return clientSequenceNumber;\n }\n\n if (this.params.containerContext.submitBatchFn === undefined) {\n // Legacy path - supporting old loader versions. Can be removed only when LTS moves above\n // version that has support for batches (submitBatchFn)\n for (const message of batch.content) {\n // Legacy path doesn't support compressed payloads and will submit uncompressed payload anyways\n if (message.metadata?.compressed) {\n delete message.metadata.compressed;\n }\n\n clientSequenceNumber = this.params.containerContext.submitFn(\n MessageType.Operation,\n message.deserializedContent,\n true, // batch\n message.metadata);\n }\n\n this.params.containerContext.deltaManager.flush();\n } else {\n // returns clientSequenceNumber of last message in a batch\n clientSequenceNumber = this.params.containerContext.submitBatchFn(\n batch.content.map((message) => ({\n contents: message.contents,\n metadata: message.metadata,\n compression: message.compression,\n })));\n }\n\n // Convert from clientSequenceNumber of last message in the batch to clientSequenceNumber of first message.\n clientSequenceNumber -= length - 1;\n assert(clientSequenceNumber >= 0, 0x3d0 /* clientSequenceNumber can't be negative */);\n return clientSequenceNumber;\n }\n\n private persistBatch(initialClientSequenceNumber: number, batch: BatchMessage[]) {\n let clientSequenceNumber = initialClientSequenceNumber;\n // Let the PendingStateManager know that a message was submitted.\n // In future, need to shift toward keeping batch as a whole!\n for (const message of batch) {\n this.params.pendingStateManager.onSubmitMessage(\n message.deserializedContent.type,\n clientSequenceNumber,\n message.referenceSequenceNumber,\n message.deserializedContent.contents,\n message.localOpMetadata,\n message.metadata,\n );\n\n clientSequenceNumber++;\n }\n }\n\n public checkpoint() {\n return {\n mainBatch: this.mainBatch.checkpoint(),\n attachFlowBatch: this.attachFlowBatch.checkpoint(),\n };\n }\n}\n"]}
1
+ {"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IContainerContext } from \"@fluidframework/container-definitions\";\nimport { GenericError } from \"@fluidframework/container-utils\";\nimport { MessageType } from \"@fluidframework/protocol-definitions\";\nimport { ICompressionRuntimeOptions } from \"../containerRuntime\";\nimport { PendingStateManager } from \"../pendingStateManager\";\nimport { BatchManager } from \"./batchManager\";\nimport { BatchMessage, IBatch } from \"./definitions\";\nimport { OpCompressor } from \"./opCompressor\";\nimport { OpSplitter } from \"./opSplitter\";\n\nexport interface IOutboxConfig {\n\treadonly compressionOptions: ICompressionRuntimeOptions;\n\t// The maximum size of a batch that we can send over the wire.\n\treadonly maxBatchSizeInBytes: number;\n\treadonly enableOpReentryCheck?: boolean;\n}\n\nexport interface IOutboxParameters {\n\treadonly shouldSend: () => boolean;\n\treadonly pendingStateManager: PendingStateManager;\n\treadonly containerContext: IContainerContext;\n\treadonly config: IOutboxConfig;\n\treadonly compressor: OpCompressor;\n\treadonly splitter: OpSplitter;\n\treadonly logger: ITelemetryLogger;\n}\n\nexport class Outbox {\n\tprivate readonly attachFlowBatch: BatchManager;\n\tprivate readonly mainBatch: BatchManager;\n\tprivate readonly defaultAttachFlowSoftLimitInBytes = 64 * 1024;\n\n\tconstructor(private readonly params: IOutboxParameters) {\n\t\tconst isCompressionEnabled =\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes !==\n\t\t\tNumber.POSITIVE_INFINITY;\n\t\t// We need to allow infinite size batches if we enable compression\n\t\tconst hardLimit = isCompressionEnabled ? Infinity : this.params.config.maxBatchSizeInBytes;\n\t\tconst softLimit = isCompressionEnabled ? Infinity : this.defaultAttachFlowSoftLimitInBytes;\n\n\t\tthis.attachFlowBatch = new BatchManager(\n\t\t\t{\n\t\t\t\thardLimit,\n\t\t\t\tsoftLimit,\n\t\t\t\tenableOpReentryCheck: params.config.enableOpReentryCheck,\n\t\t\t},\n\t\t\tparams.logger,\n\t\t);\n\t\tthis.mainBatch = new BatchManager(\n\t\t\t{\n\t\t\t\thardLimit,\n\t\t\t\tenableOpReentryCheck: params.config.enableOpReentryCheck,\n\t\t\t},\n\t\t\tparams.logger,\n\t\t);\n\t}\n\n\tpublic get isEmpty(): boolean {\n\t\treturn this.attachFlowBatch.length === 0 && this.mainBatch.length === 0;\n\t}\n\n\tpublic submit(message: BatchMessage) {\n\t\tif (!this.mainBatch.push(message)) {\n\t\t\tthrow new GenericError(\"BatchTooLarge\", /* error */ undefined, {\n\t\t\t\topSize: message.contents?.length ?? 0,\n\t\t\t\tbatchSize: this.mainBatch.contentSizeInBytes,\n\t\t\t\tcount: this.mainBatch.length,\n\t\t\t\tlimit: this.mainBatch.options.hardLimit,\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic submitAttach(message: BatchMessage) {\n\t\tif (!this.attachFlowBatch.push(message)) {\n\t\t\t// BatchManager has two limits - soft limit & hard limit. Soft limit is only engaged\n\t\t\t// when queue is not empty.\n\t\t\t// Flush queue & retry. Failure on retry would mean - single message is bigger than hard limit\n\t\t\tthis.flushInternal(this.attachFlowBatch.popBatch());\n\t\t\tif (!this.attachFlowBatch.push(message)) {\n\t\t\t\tthrow new GenericError(\"BatchTooLarge\", /* error */ undefined, {\n\t\t\t\t\topSize: message.contents?.length ?? 0,\n\t\t\t\t\tbatchSize: this.attachFlowBatch.contentSizeInBytes,\n\t\t\t\t\tcount: this.attachFlowBatch.length,\n\t\t\t\t\tlimit: this.attachFlowBatch.options.hardLimit,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// If compression is enabled, we will always successfully receive\n\t\t// attach ops and compress then send them at the next JS turn, regardless\n\t\t// of the overall size of the accumulated ops in the batch.\n\t\t// However, it is more efficient to flush these ops faster, preferably\n\t\t// after they reach a size which would benefit from compression.\n\t\tif (\n\t\t\tthis.attachFlowBatch.contentSizeInBytes >=\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes\n\t\t) {\n\t\t\tthis.flushInternal(this.attachFlowBatch.popBatch());\n\t\t}\n\t}\n\n\tpublic flush() {\n\t\tthis.flushInternal(this.attachFlowBatch.popBatch());\n\t\tthis.flushInternal(this.mainBatch.popBatch());\n\t}\n\n\tprivate flushInternal(rawBatch: IBatch) {\n\t\tconst processedBatch = this.compressBatch(rawBatch);\n\t\tconst clientSequenceNumber = this.sendBatch(processedBatch);\n\n\t\tthis.persistBatch(clientSequenceNumber, rawBatch.content);\n\t}\n\n\tprivate compressBatch(batch: IBatch): IBatch {\n\t\tif (\n\t\t\tbatch.content.length === 0 ||\n\t\t\tthis.params.config.compressionOptions === undefined ||\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes > batch.contentSizeInBytes\n\t\t) {\n\t\t\t// Nothing to do if the batch is empty or if compression is disabled or if we don't need to compress\n\t\t\treturn batch;\n\t\t}\n\n\t\tconst compressedBatch = this.params.compressor.compressBatch(batch);\n\t\tif (compressedBatch.contentSizeInBytes <= this.params.config.maxBatchSizeInBytes) {\n\t\t\t// If we don't reach the maximum supported size of a batch, it can safely be sent as is\n\t\t\treturn compressedBatch;\n\t\t}\n\n\t\tif (this.params.splitter.isBatchChunkingEnabled) {\n\t\t\treturn this.params.splitter.splitCompressedBatch(compressedBatch);\n\t\t}\n\n\t\t// If we've reached this point, the runtime would attempt to send a batch larger than the allowed size\n\t\tthrow new GenericError(\"BatchTooLarge\", /* error */ undefined, {\n\t\t\tbatchSize: batch.contentSizeInBytes,\n\t\t\tcompressedBatchSize: compressedBatch.contentSizeInBytes,\n\t\t\tcount: compressedBatch.content.length,\n\t\t\tlimit: this.params.config.maxBatchSizeInBytes,\n\t\t\tchunkingEnabled: this.params.splitter.isBatchChunkingEnabled,\n\t\t\tcompressionOptions: JSON.stringify(this.params.config.compressionOptions),\n\t\t});\n\t}\n\n\t/**\n\t * Sends the batch object to the container context to be sent over the wire.\n\t *\n\t * @param batch - batch to be sent\n\t * @returns the client sequence number of the last batched op which was sent and\n\t * -1 if there are no ops or the container cannot send ops.\n\t */\n\tprivate sendBatch(batch: IBatch): number {\n\t\tlet clientSequenceNumber: number = -1;\n\t\tconst length = batch.content.length;\n\n\t\t// Did we disconnect in the middle of turn-based batch?\n\t\t// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.\n\t\tif (length === 0 || !this.params.shouldSend()) {\n\t\t\treturn clientSequenceNumber;\n\t\t}\n\n\t\tif (this.params.containerContext.submitBatchFn === undefined) {\n\t\t\t// Legacy path - supporting old loader versions. Can be removed only when LTS moves above\n\t\t\t// version that has support for batches (submitBatchFn)\n\t\t\tfor (const message of batch.content) {\n\t\t\t\t// Legacy path doesn't support compressed payloads and will submit uncompressed payload anyways\n\t\t\t\tif (message.metadata?.compressed) {\n\t\t\t\t\tdelete message.metadata.compressed;\n\t\t\t\t}\n\n\t\t\t\tclientSequenceNumber = this.params.containerContext.submitFn(\n\t\t\t\t\tMessageType.Operation,\n\t\t\t\t\tmessage.deserializedContent,\n\t\t\t\t\ttrue, // batch\n\t\t\t\t\tmessage.metadata,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthis.params.containerContext.deltaManager.flush();\n\t\t} else {\n\t\t\t// returns clientSequenceNumber of last message in a batch\n\t\t\tclientSequenceNumber = this.params.containerContext.submitBatchFn(\n\t\t\t\tbatch.content.map((message) => ({\n\t\t\t\t\tcontents: message.contents,\n\t\t\t\t\tmetadata: message.metadata,\n\t\t\t\t\tcompression: message.compression,\n\t\t\t\t})),\n\t\t\t);\n\t\t}\n\n\t\t// Convert from clientSequenceNumber of last message in the batch to clientSequenceNumber of first message.\n\t\tclientSequenceNumber -= length - 1;\n\t\tassert(clientSequenceNumber >= 0, 0x3d0 /* clientSequenceNumber can't be negative */);\n\t\treturn clientSequenceNumber;\n\t}\n\n\tprivate persistBatch(initialClientSequenceNumber: number, batch: BatchMessage[]) {\n\t\tlet clientSequenceNumber = initialClientSequenceNumber;\n\t\t// Let the PendingStateManager know that a message was submitted.\n\t\t// In future, need to shift toward keeping batch as a whole!\n\t\tfor (const message of batch) {\n\t\t\tthis.params.pendingStateManager.onSubmitMessage(\n\t\t\t\tmessage.deserializedContent.type,\n\t\t\t\tclientSequenceNumber,\n\t\t\t\tmessage.referenceSequenceNumber,\n\t\t\t\tmessage.deserializedContent.contents,\n\t\t\t\tmessage.localOpMetadata,\n\t\t\t\tmessage.metadata,\n\t\t\t);\n\n\t\t\tclientSequenceNumber++;\n\t\t}\n\t}\n\n\tpublic checkpoint() {\n\t\treturn {\n\t\t\tmainBatch: this.mainBatch.checkpoint(),\n\t\t\tattachFlowBatch: this.attachFlowBatch.checkpoint(),\n\t\t};\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"remoteMessageProcessor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAe,MAAM,sCAAsC,CAAC;AAE9F,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,qBAAa,sBAAsB;IAE3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;gBADd,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,cAAc;IAGnD,IAAW,eAAe,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAE1D;IAEM,uBAAuB,CAAC,QAAQ,EAAE,MAAM;IAIxC,OAAO,CAAC,aAAa,EAAE,yBAAyB,GAAG,yBAAyB;CAyBtF;AA6BD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAkBhF"}
1
+ {"version":3,"file":"remoteMessageProcessor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAe,MAAM,sCAAsC,CAAC;AAE9F,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,qBAAa,sBAAsB;IAEjC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;gBADd,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,cAAc;IAGhD,IAAW,eAAe,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAE1D;IAEM,uBAAuB,CAAC,QAAQ,EAAE,MAAM;IAIxC,OAAO,CAAC,aAAa,EAAE,yBAAyB,GAAG,yBAAyB;CAyBnF;AA6BD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAkBhF"}
@@ -1 +1 @@
1
- {"version":3,"file":"remoteMessageProcessor.js","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+EAA8F;AAC9F,0DAAoF;AAIpF,MAAa,sBAAsB;IAC/B,YACqB,UAAsB,EACtB,cAA8B;QAD9B,eAAU,GAAV,UAAU,CAAY;QACtB,mBAAc,GAAd,cAAc,CAAgB;IAC/C,CAAC;IAEL,IAAW,eAAe;QACtB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;IAClC,CAAC;IAEM,uBAAuB,CAAC,QAAgB;QAC3C,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC;IAEM,OAAO,CAAC,aAAwC;QACnD,IAAI,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;QAClC,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;QAC9D,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAE9B,MAAM,qBAAqB,GAAG,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC5E,OAAO,GAAG,qBAAqB,CAAC,OAAO,CAAC;QACxC,IAAI,qBAAqB,CAAC,KAAK,KAAK,WAAW,EAAE;YAC7C,6FAA6F;YAC7F,0CAA0C;YAC1C,OAAO,OAAO,CAAC;SAClB;QAED,MAAM,0BAA0B,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC/E,OAAO,GAAG,0BAA0B,CAAC,OAAO,CAAC;QAC7C,IAAI,0BAA0B,CAAC,KAAK,KAAK,SAAS,EAAE;YAChD,8DAA8D;YAC9D,0CAA0C;YAC1C,OAAO,OAAO,CAAC;SAClB;QAED,kEAAkE;QAClE,MAAM,CAAC,OAAO,CAAC,CAAC;QAChB,OAAO,OAAO,CAAC;IACnB,CAAC;CACJ;AAvCD,wDAuCC;AAED,MAAM,IAAI,GAAG,CAAC,aAAwC,EAA6B,EAAE;IACjF,qEAAqE;IACrE,qEAAqE;IACrE,4FAA4F;IAC5F,wCAAwC;IACxC,MAAM,OAAO,qBAAQ,aAAa,CAAE,CAAC;IAErC,iGAAiG;IACjG,+GAA+G;IAC/G,qDAAqD;IACrD,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,KAAK,EAAE,EAAE;QACjE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;KACnD;IAED,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,GAAG,CAAC,OAAkC,EAAE,EAAE;IAClD,MAAM,aAAa,GAAG,OAAO,CAAC,QAAmC,CAAC;IAClE,OAAO,CAAC,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC;IAClC,OAAO,CAAC,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;AAC9C,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,SAAgB,oBAAoB,CAAC,OAAkC;IACnE,IAAI,OAAO,CAAC,IAAI,KAAK,kCAAW,CAAC,SAAS,EAAE;QACxC,8CAA8C;QAC9C,sDAAsD;QACtD,+BAA+B;QAC/B,8BAA8B;QAC9B,OAAO,KAAK,CAAC;KAChB;IAED,oBAAoB;IACpB,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE;QAC/E,OAAO,CAAC,IAAI,GAAG,uCAAoB,CAAC,gBAAgB,CAAC;KACxD;SAAM;QACH,aAAa;QACb,MAAM,CAAC,OAAO,CAAC,CAAC;KACnB;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAlBD,oDAkBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { ContainerMessageType, ContainerRuntimeMessage } from \"../containerRuntime\";\nimport { OpDecompressor } from \"./opDecompressor\";\nimport { OpSplitter } from \"./opSplitter\";\n\nexport class RemoteMessageProcessor {\n constructor(\n private readonly opSplitter: OpSplitter,\n private readonly opDecompressor: OpDecompressor,\n ) { }\n\n public get partialMessages(): ReadonlyMap<string, string[]> {\n return this.opSplitter.chunks;\n }\n\n public clearPartialMessagesFor(clientId: string) {\n this.opSplitter.clearPartialChunks(clientId);\n }\n\n public process(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage {\n let message = copy(remoteMessage);\n message = this.opDecompressor.processMessage(message).message;\n unpackRuntimeMessage(message);\n\n const chunkProcessingResult = this.opSplitter.processRemoteMessage(message);\n message = chunkProcessingResult.message;\n if (chunkProcessingResult.state !== \"Processed\") {\n // If the message is not chunked or if the splitter is still rebuilding the original message,\n // there is no need to continue processing\n return message;\n }\n\n const decompressionAfterChunking = this.opDecompressor.processMessage(message);\n message = decompressionAfterChunking.message;\n if (decompressionAfterChunking.state === \"Skipped\") {\n // After chunking, if the original message was not compressed,\n // there is no need to continue processing\n return message;\n }\n\n // The message needs to be unpacked after chunking + decompression\n unpack(message);\n return message;\n }\n}\n\nconst copy = (remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage => {\n // Do shallow copy of message, as the processing flow will modify it.\n // There might be multiple container instances receiving same message\n // We do not need to make deep copy, as each layer will just replace message.content itself,\n // but would not modify contents details\n const message = { ...remoteMessage };\n\n // back-compat: ADO #1385: eventually should become unconditional, but only for runtime messages!\n // System message may have no contents, or in some cases (mostly for back-compat) they may have actual objects.\n // Old ops may contain empty string (I assume noops).\n if (typeof message.contents === \"string\" && message.contents !== \"\") {\n message.contents = JSON.parse(message.contents);\n }\n\n return message;\n};\n\n/**\n * For a given message, it moves the nested contents and type on level up.\n *\n */\nconst unpack = (message: ISequencedDocumentMessage) => {\n const innerContents = message.contents as ContainerRuntimeMessage;\n message.type = innerContents.type;\n message.contents = innerContents.contents;\n};\n\n/**\n * Unpacks runtime messages.\n *\n * @remarks This API makes no promises regarding backward-compatibility. This is internal API.\n * @param message - message (as it observed in storage / service)\n * @returns unpacked runtime message\n *\n * @internal\n */\nexport function unpackRuntimeMessage(message: ISequencedDocumentMessage): boolean {\n if (message.type !== MessageType.Operation) {\n // Legacy format, but it's already \"unpacked\",\n // i.e. message.type is actually ContainerMessageType.\n // Or it's non-runtime message.\n // Nothing to do in such case.\n return false;\n }\n\n // legacy op format?\n if (message.contents.address !== undefined && message.contents.type === undefined) {\n message.type = ContainerMessageType.FluidDataStoreOp;\n } else {\n // new format\n unpack(message);\n }\n\n return true;\n}\n"]}
1
+ {"version":3,"file":"remoteMessageProcessor.js","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+EAA8F;AAC9F,0DAAoF;AAIpF,MAAa,sBAAsB;IAClC,YACkB,UAAsB,EACtB,cAA8B;QAD9B,eAAU,GAAV,UAAU,CAAY;QACtB,mBAAc,GAAd,cAAc,CAAgB;IAC7C,CAAC;IAEJ,IAAW,eAAe;QACzB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;IAC/B,CAAC;IAEM,uBAAuB,CAAC,QAAgB;QAC9C,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAEM,OAAO,CAAC,aAAwC;QACtD,IAAI,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;QAClC,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;QAC9D,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAE9B,MAAM,qBAAqB,GAAG,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC5E,OAAO,GAAG,qBAAqB,CAAC,OAAO,CAAC;QACxC,IAAI,qBAAqB,CAAC,KAAK,KAAK,WAAW,EAAE;YAChD,6FAA6F;YAC7F,0CAA0C;YAC1C,OAAO,OAAO,CAAC;SACf;QAED,MAAM,0BAA0B,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC/E,OAAO,GAAG,0BAA0B,CAAC,OAAO,CAAC;QAC7C,IAAI,0BAA0B,CAAC,KAAK,KAAK,SAAS,EAAE;YACnD,8DAA8D;YAC9D,0CAA0C;YAC1C,OAAO,OAAO,CAAC;SACf;QAED,kEAAkE;QAClE,MAAM,CAAC,OAAO,CAAC,CAAC;QAChB,OAAO,OAAO,CAAC;IAChB,CAAC;CACD;AAvCD,wDAuCC;AAED,MAAM,IAAI,GAAG,CAAC,aAAwC,EAA6B,EAAE;IACpF,qEAAqE;IACrE,qEAAqE;IACrE,4FAA4F;IAC5F,wCAAwC;IACxC,MAAM,OAAO,qBAAQ,aAAa,CAAE,CAAC;IAErC,iGAAiG;IACjG,+GAA+G;IAC/G,qDAAqD;IACrD,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,KAAK,EAAE,EAAE;QACpE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;KAChD;IAED,OAAO,OAAO,CAAC;AAChB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,GAAG,CAAC,OAAkC,EAAE,EAAE;IACrD,MAAM,aAAa,GAAG,OAAO,CAAC,QAAmC,CAAC;IAClE,OAAO,CAAC,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC;IAClC,OAAO,CAAC,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;AAC3C,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,SAAgB,oBAAoB,CAAC,OAAkC;IACtE,IAAI,OAAO,CAAC,IAAI,KAAK,kCAAW,CAAC,SAAS,EAAE;QAC3C,8CAA8C;QAC9C,sDAAsD;QACtD,+BAA+B;QAC/B,8BAA8B;QAC9B,OAAO,KAAK,CAAC;KACb;IAED,oBAAoB;IACpB,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE;QAClF,OAAO,CAAC,IAAI,GAAG,uCAAoB,CAAC,gBAAgB,CAAC;KACrD;SAAM;QACN,aAAa;QACb,MAAM,CAAC,OAAO,CAAC,CAAC;KAChB;IAED,OAAO,IAAI,CAAC;AACb,CAAC;AAlBD,oDAkBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { ContainerMessageType, ContainerRuntimeMessage } from \"../containerRuntime\";\nimport { OpDecompressor } from \"./opDecompressor\";\nimport { OpSplitter } from \"./opSplitter\";\n\nexport class RemoteMessageProcessor {\n\tconstructor(\n\t\tprivate readonly opSplitter: OpSplitter,\n\t\tprivate readonly opDecompressor: OpDecompressor,\n\t) {}\n\n\tpublic get partialMessages(): ReadonlyMap<string, string[]> {\n\t\treturn this.opSplitter.chunks;\n\t}\n\n\tpublic clearPartialMessagesFor(clientId: string) {\n\t\tthis.opSplitter.clearPartialChunks(clientId);\n\t}\n\n\tpublic process(remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage {\n\t\tlet message = copy(remoteMessage);\n\t\tmessage = this.opDecompressor.processMessage(message).message;\n\t\tunpackRuntimeMessage(message);\n\n\t\tconst chunkProcessingResult = this.opSplitter.processRemoteMessage(message);\n\t\tmessage = chunkProcessingResult.message;\n\t\tif (chunkProcessingResult.state !== \"Processed\") {\n\t\t\t// If the message is not chunked or if the splitter is still rebuilding the original message,\n\t\t\t// there is no need to continue processing\n\t\t\treturn message;\n\t\t}\n\n\t\tconst decompressionAfterChunking = this.opDecompressor.processMessage(message);\n\t\tmessage = decompressionAfterChunking.message;\n\t\tif (decompressionAfterChunking.state === \"Skipped\") {\n\t\t\t// After chunking, if the original message was not compressed,\n\t\t\t// there is no need to continue processing\n\t\t\treturn message;\n\t\t}\n\n\t\t// The message needs to be unpacked after chunking + decompression\n\t\tunpack(message);\n\t\treturn message;\n\t}\n}\n\nconst copy = (remoteMessage: ISequencedDocumentMessage): ISequencedDocumentMessage => {\n\t// Do shallow copy of message, as the processing flow will modify it.\n\t// There might be multiple container instances receiving same message\n\t// We do not need to make deep copy, as each layer will just replace message.content itself,\n\t// but would not modify contents details\n\tconst message = { ...remoteMessage };\n\n\t// back-compat: ADO #1385: eventually should become unconditional, but only for runtime messages!\n\t// System message may have no contents, or in some cases (mostly for back-compat) they may have actual objects.\n\t// Old ops may contain empty string (I assume noops).\n\tif (typeof message.contents === \"string\" && message.contents !== \"\") {\n\t\tmessage.contents = JSON.parse(message.contents);\n\t}\n\n\treturn message;\n};\n\n/**\n * For a given message, it moves the nested contents and type on level up.\n *\n */\nconst unpack = (message: ISequencedDocumentMessage) => {\n\tconst innerContents = message.contents as ContainerRuntimeMessage;\n\tmessage.type = innerContents.type;\n\tmessage.contents = innerContents.contents;\n};\n\n/**\n * Unpacks runtime messages.\n *\n * @remarks This API makes no promises regarding backward-compatibility. This is internal API.\n * @param message - message (as it observed in storage / service)\n * @returns unpacked runtime message\n *\n * @internal\n */\nexport function unpackRuntimeMessage(message: ISequencedDocumentMessage): boolean {\n\tif (message.type !== MessageType.Operation) {\n\t\t// Legacy format, but it's already \"unpacked\",\n\t\t// i.e. message.type is actually ContainerMessageType.\n\t\t// Or it's non-runtime message.\n\t\t// Nothing to do in such case.\n\t\treturn false;\n\t}\n\n\t// legacy op format?\n\tif (message.contents.address !== undefined && message.contents.type === undefined) {\n\t\tmessage.type = ContainerMessageType.FluidDataStoreOp;\n\t} else {\n\t\t// new format\n\t\tunpack(message);\n\t}\n\n\treturn true;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"opProperties.d.ts","sourceRoot":"","sources":["../src/opProperties.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAmC,MAAM,sCAAsC,CAAC;AAElH,eAAO,MAAM,MAAM,OAAQ,yBAAyB,KAAG,MAQtD,CAAC"}
1
+ {"version":3,"file":"opProperties.d.ts","sourceRoot":"","sources":["../src/opProperties.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,yBAAyB,EAEzB,MAAM,sCAAsC,CAAC;AAE9C,eAAO,MAAM,MAAM,OAAQ,yBAAyB,KAAG,MAOtD,CAAC"}
@@ -9,9 +9,7 @@ const opSize = (op) => {
9
9
  var _a;
10
10
  // Some messages may already have string contents,
11
11
  // so stringifying them again will add inaccurate overhead.
12
- const content = typeof op.contents === "string" ?
13
- op.contents :
14
- (_a = JSON.stringify(op.contents)) !== null && _a !== void 0 ? _a : "";
12
+ const content = typeof op.contents === "string" ? op.contents : (_a = JSON.stringify(op.contents)) !== null && _a !== void 0 ? _a : "";
15
13
  const data = opHasData(op) ? op.data : "";
16
14
  return content.length + data.length;
17
15
  };
@@ -1 +1 @@
1
- {"version":3,"file":"opProperties.js","sourceRoot":"","sources":["../src/opProperties.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAII,MAAM,MAAM,GAAG,CAAC,EAA6B,EAAU,EAAE;;IAC5D,kDAAkD;IAClD,2DAA2D;IAC3D,MAAM,OAAO,GAAG,OAAO,EAAE,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QAC7C,EAAE,CAAC,QAAQ,CAAC,CAAC;QACb,MAAA,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,mCAAI,EAAE,CAAC;IACtC,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1C,OAAO,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;AACxC,CAAC,CAAC;AARW,QAAA,MAAM,UAQjB;AAEF,MAAM,SAAS,GAAG,CAAC,EAA6B,EAAyC,EAAE,CACtF,EAAsC,CAAC,IAAI,KAAK,SAAS,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISequencedDocumentMessage, ISequencedDocumentSystemMessage } from \"@fluidframework/protocol-definitions\";\n\nexport const opSize = (op: ISequencedDocumentMessage): number => {\n // Some messages may already have string contents,\n // so stringifying them again will add inaccurate overhead.\n const content = typeof op.contents === \"string\" ?\n op.contents :\n JSON.stringify(op.contents) ?? \"\";\n const data = opHasData(op) ? op.data : \"\";\n return content.length + data.length;\n};\n\nconst opHasData = (op: ISequencedDocumentMessage): op is ISequencedDocumentSystemMessage =>\n (op as ISequencedDocumentSystemMessage).data !== undefined;\n"]}
1
+ {"version":3,"file":"opProperties.js","sourceRoot":"","sources":["../src/opProperties.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAOI,MAAM,MAAM,GAAG,CAAC,EAA6B,EAAU,EAAE;;IAC/D,kDAAkD;IAClD,2DAA2D;IAC3D,MAAM,OAAO,GACZ,OAAO,EAAE,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAA,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,mCAAI,EAAE,CAAC;IACnF,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1C,OAAO,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;AACrC,CAAC,CAAC;AAPW,QAAA,MAAM,UAOjB;AAEF,MAAM,SAAS,GAAG,CAAC,EAA6B,EAAyC,EAAE,CACzF,EAAsC,CAAC,IAAI,KAAK,SAAS,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tISequencedDocumentMessage,\n\tISequencedDocumentSystemMessage,\n} from \"@fluidframework/protocol-definitions\";\n\nexport const opSize = (op: ISequencedDocumentMessage): number => {\n\t// Some messages may already have string contents,\n\t// so stringifying them again will add inaccurate overhead.\n\tconst content =\n\t\ttypeof op.contents === \"string\" ? op.contents : JSON.stringify(op.contents) ?? \"\";\n\tconst data = opHasData(op) ? op.data : \"\";\n\treturn content.length + data.length;\n};\n\nconst opHasData = (op: ISequencedDocumentMessage): op is ISequencedDocumentSystemMessage =>\n\t(op as ISequencedDocumentSystemMessage).data !== undefined;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"orderedClientElection.d.ts","sourceRoot":"","sources":["../src/orderedClientElection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orderedClientElection.d.ts","sourceRoot":"","sources":["../src/orderedClientElection.ts"],"names":[],"mappings":"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"}
@@ -38,7 +38,11 @@ class OrderedClientCollection extends common_utils_1.TypedEventEmitter {
38
38
  const sequenceNumber = deltaManager.lastSequenceNumber;
39
39
  const removeClient = this.removeClient(clientId);
40
40
  if (removeClient === undefined) {
41
- this.logger.sendErrorEvent({ eventName: "ClientNotFound", clientId, sequenceNumber });
41
+ this.logger.sendErrorEvent({
42
+ eventName: "ClientNotFound",
43
+ clientId,
44
+ sequenceNumber,
45
+ });
42
46
  }
43
47
  else {
44
48
  this.emit("removeClient", removeClient, sequenceNumber);
@@ -263,7 +267,8 @@ class OrderedClientElection extends common_utils_1.TypedEventEmitter {
263
267
  findFirstEligibleParent(client) {
264
268
  let candidateClient = client;
265
269
  while (candidateClient !== undefined &&
266
- (!this.isEligibleFn(candidateClient) || candidateClient.client.details.type === summarizerClientElection_1.summarizerClientType)) {
270
+ (!this.isEligibleFn(candidateClient) ||
271
+ candidateClient.client.details.type === summarizerClientElection_1.summarizerClientType)) {
267
272
  candidateClient = candidateClient.youngerClient;
268
273
  }
269
274
  return candidateClient;
@@ -281,7 +286,8 @@ class OrderedClientElection extends common_utils_1.TypedEventEmitter {
281
286
  const newClientIsSummarizer = client.client.details.type === summarizerClientElection_1.summarizerClientType;
282
287
  const electedClientIsSummarizer = ((_a = this._electedClient) === null || _a === void 0 ? void 0 : _a.client.details.type) === summarizerClientElection_1.summarizerClientType;
283
288
  // Note that we allow a summarizer client to supercede an interactive client as elected client.
284
- if (this._electedClient === undefined || (!electedClientIsSummarizer && newClientIsSummarizer)) {
289
+ if (this._electedClient === undefined ||
290
+ (!electedClientIsSummarizer && newClientIsSummarizer)) {
285
291
  this.tryElectingClient(client, sequenceNumber);
286
292
  }
287
293
  else if (this._electedParent === undefined && !newClientIsSummarizer) {
@@ -365,7 +371,7 @@ class OrderedClientElection extends common_utils_1.TypedEventEmitter {
365
371
  }
366
372
  peekNextElectedClient() {
367
373
  var _a, _b;
368
- return (_b = this.findFirstEligibleParent((_a = this._electedParent) === null || _a === void 0 ? void 0 : _a.youngerClient)) !== null && _b !== void 0 ? _b : this.findFirstEligibleParent(this.orderedClientCollection.oldestClient);
374
+ return ((_b = this.findFirstEligibleParent((_a = this._electedParent) === null || _a === void 0 ? void 0 : _a.youngerClient)) !== null && _b !== void 0 ? _b : this.findFirstEligibleParent(this.orderedClientCollection.oldestClient));
369
375
  }
370
376
  serialize() {
371
377
  var _a, _b;