@fluidframework/container-runtime 2.53.0 → 2.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (461) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/api-report/{container-runtime.legacy.alpha.api.md → container-runtime.legacy.beta.api.md} +55 -55
  3. package/container-runtime.test-files.tar +0 -0
  4. package/dist/batchTracker.d.ts +1 -1
  5. package/dist/batchTracker.d.ts.map +1 -1
  6. package/dist/batchTracker.js.map +1 -1
  7. package/dist/blobManager/blobManager.d.ts +8 -2
  8. package/dist/blobManager/blobManager.d.ts.map +1 -1
  9. package/dist/blobManager/blobManager.js +45 -33
  10. package/dist/blobManager/blobManager.js.map +1 -1
  11. package/dist/blobManager/index.d.ts +2 -2
  12. package/dist/blobManager/index.d.ts.map +1 -1
  13. package/dist/blobManager/index.js.map +1 -1
  14. package/dist/channelCollection.d.ts +9 -11
  15. package/dist/channelCollection.d.ts.map +1 -1
  16. package/dist/channelCollection.js +2 -3
  17. package/dist/channelCollection.js.map +1 -1
  18. package/dist/compressionDefinitions.d.ts +3 -6
  19. package/dist/compressionDefinitions.d.ts.map +1 -1
  20. package/dist/compressionDefinitions.js +2 -4
  21. package/dist/compressionDefinitions.js.map +1 -1
  22. package/dist/connectionTelemetry.d.ts +3 -4
  23. package/dist/connectionTelemetry.d.ts.map +1 -1
  24. package/dist/connectionTelemetry.js.map +1 -1
  25. package/dist/containerHandleContext.d.ts +2 -2
  26. package/dist/containerHandleContext.d.ts.map +1 -1
  27. package/dist/containerHandleContext.js.map +1 -1
  28. package/dist/containerRuntime.d.ts +13 -20
  29. package/dist/containerRuntime.d.ts.map +1 -1
  30. package/dist/containerRuntime.js +3 -6
  31. package/dist/containerRuntime.js.map +1 -1
  32. package/dist/dataStore.d.ts +3 -3
  33. package/dist/dataStore.d.ts.map +1 -1
  34. package/dist/dataStore.js.map +1 -1
  35. package/dist/dataStoreContext.d.ts +8 -8
  36. package/dist/dataStoreContext.d.ts.map +1 -1
  37. package/dist/dataStoreContext.js.map +1 -1
  38. package/dist/dataStoreContexts.d.ts +2 -2
  39. package/dist/dataStoreContexts.d.ts.map +1 -1
  40. package/dist/dataStoreContexts.js.map +1 -1
  41. package/dist/dataStoreRegistry.d.ts +1 -1
  42. package/dist/dataStoreRegistry.d.ts.map +1 -1
  43. package/dist/dataStoreRegistry.js.map +1 -1
  44. package/dist/deltaManagerProxies.d.ts +2 -3
  45. package/dist/deltaManagerProxies.d.ts.map +1 -1
  46. package/dist/deltaManagerProxies.js.map +1 -1
  47. package/dist/deltaScheduler.d.ts +2 -2
  48. package/dist/deltaScheduler.d.ts.map +1 -1
  49. package/dist/deltaScheduler.js.map +1 -1
  50. package/dist/error.d.ts +1 -1
  51. package/dist/error.d.ts.map +1 -1
  52. package/dist/error.js.map +1 -1
  53. package/dist/gc/garbageCollection.d.ts +4 -4
  54. package/dist/gc/garbageCollection.d.ts.map +1 -1
  55. package/dist/gc/garbageCollection.js.map +1 -1
  56. package/dist/gc/gcConfigs.d.ts +3 -3
  57. package/dist/gc/gcConfigs.d.ts.map +1 -1
  58. package/dist/gc/gcConfigs.js.map +1 -1
  59. package/dist/gc/gcDefinitions.d.ts +10 -11
  60. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  61. package/dist/gc/gcDefinitions.js.map +1 -1
  62. package/dist/gc/gcHelpers.d.ts +4 -4
  63. package/dist/gc/gcHelpers.d.ts.map +1 -1
  64. package/dist/gc/gcHelpers.js.map +1 -1
  65. package/dist/gc/gcReferenceGraphAlgorithm.d.ts +1 -1
  66. package/dist/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -1
  67. package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
  68. package/dist/gc/gcSummaryDefinitions.d.ts +1 -1
  69. package/dist/gc/gcSummaryDefinitions.d.ts.map +1 -1
  70. package/dist/gc/gcSummaryDefinitions.js.map +1 -1
  71. package/dist/gc/gcSummaryStateTracker.d.ts +4 -4
  72. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
  73. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  74. package/dist/gc/gcTelemetry.d.ts +6 -6
  75. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  76. package/dist/gc/gcTelemetry.js.map +1 -1
  77. package/dist/gc/index.d.ts +3 -3
  78. package/dist/gc/index.d.ts.map +1 -1
  79. package/dist/gc/index.js.map +1 -1
  80. package/dist/inboundBatchAggregator.d.ts +2 -2
  81. package/dist/inboundBatchAggregator.d.ts.map +1 -1
  82. package/dist/inboundBatchAggregator.js.map +1 -1
  83. package/dist/index.d.ts +7 -7
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js.map +1 -1
  86. package/dist/messageTypes.d.ts +7 -8
  87. package/dist/messageTypes.d.ts.map +1 -1
  88. package/dist/messageTypes.js +1 -2
  89. package/dist/messageTypes.js.map +1 -1
  90. package/dist/opLifecycle/batchManager.d.ts +2 -2
  91. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  92. package/dist/opLifecycle/batchManager.js.map +1 -1
  93. package/dist/opLifecycle/definitions.d.ts +1 -1
  94. package/dist/opLifecycle/definitions.d.ts.map +1 -1
  95. package/dist/opLifecycle/definitions.js.map +1 -1
  96. package/dist/opLifecycle/duplicateBatchDetector.d.ts +1 -1
  97. package/dist/opLifecycle/duplicateBatchDetector.d.ts.map +1 -1
  98. package/dist/opLifecycle/duplicateBatchDetector.js.map +1 -1
  99. package/dist/opLifecycle/index.d.ts +5 -5
  100. package/dist/opLifecycle/index.d.ts.map +1 -1
  101. package/dist/opLifecycle/index.js.map +1 -1
  102. package/dist/opLifecycle/opCompressor.d.ts +2 -2
  103. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  104. package/dist/opLifecycle/opCompressor.js.map +1 -1
  105. package/dist/opLifecycle/opDecompressor.d.ts +2 -2
  106. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  107. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  108. package/dist/opLifecycle/opGroupingManager.d.ts +3 -3
  109. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  110. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  111. package/dist/opLifecycle/opSplitter.d.ts +4 -4
  112. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  113. package/dist/opLifecycle/opSplitter.js.map +1 -1
  114. package/dist/opLifecycle/outbox.d.ts +9 -9
  115. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  116. package/dist/opLifecycle/outbox.js.map +1 -1
  117. package/dist/opLifecycle/remoteMessageProcessor.d.ts +4 -4
  118. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  119. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  120. package/dist/opProperties.d.ts +1 -1
  121. package/dist/opProperties.d.ts.map +1 -1
  122. package/dist/opProperties.js.map +1 -1
  123. package/dist/packageVersion.d.ts +1 -1
  124. package/dist/packageVersion.js +1 -1
  125. package/dist/packageVersion.js.map +1 -1
  126. package/dist/pendingStateManager.d.ts +3 -3
  127. package/dist/pendingStateManager.d.ts.map +1 -1
  128. package/dist/pendingStateManager.js.map +1 -1
  129. package/dist/storageServiceWithAttachBlobs.d.ts +1 -1
  130. package/dist/storageServiceWithAttachBlobs.d.ts.map +1 -1
  131. package/dist/storageServiceWithAttachBlobs.js.map +1 -1
  132. package/dist/summary/documentSchema.d.ts +1 -2
  133. package/dist/summary/documentSchema.d.ts.map +1 -1
  134. package/dist/summary/documentSchema.js.map +1 -1
  135. package/dist/summary/index.d.ts +10 -10
  136. package/dist/summary/index.d.ts.map +1 -1
  137. package/dist/summary/index.js.map +1 -1
  138. package/dist/summary/orderedClientElection.d.ts +4 -4
  139. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  140. package/dist/summary/orderedClientElection.js.map +1 -1
  141. package/dist/summary/summarizerClientElection.d.ts +5 -5
  142. package/dist/summary/summarizerClientElection.d.ts.map +1 -1
  143. package/dist/summary/summarizerClientElection.js.map +1 -1
  144. package/dist/summary/summarizerNode/index.d.ts +3 -3
  145. package/dist/summary/summarizerNode/index.d.ts.map +1 -1
  146. package/dist/summary/summarizerNode/index.js.map +1 -1
  147. package/dist/summary/summarizerNode/summarizerNode.d.ts +5 -6
  148. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  149. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  150. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +3 -3
  151. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  152. package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  153. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -3
  154. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  155. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  156. package/dist/summary/summarizerTypes.d.ts +25 -44
  157. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  158. package/dist/summary/summarizerTypes.js.map +1 -1
  159. package/dist/summary/summarizerUtils.d.ts +3 -3
  160. package/dist/summary/summarizerUtils.d.ts.map +1 -1
  161. package/dist/summary/summarizerUtils.js.map +1 -1
  162. package/dist/summary/summaryCollection.d.ts +13 -23
  163. package/dist/summary/summaryCollection.d.ts.map +1 -1
  164. package/dist/summary/summaryCollection.js +1 -2
  165. package/dist/summary/summaryCollection.js.map +1 -1
  166. package/dist/summary/summaryDelayLoadedModule/index.d.ts +2 -2
  167. package/dist/summary/summaryDelayLoadedModule/index.d.ts.map +1 -1
  168. package/dist/summary/summaryDelayLoadedModule/index.js.map +1 -1
  169. package/dist/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.d.ts +1 -1
  170. package/dist/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.d.ts.map +1 -1
  171. package/dist/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.js.map +1 -1
  172. package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts +3 -3
  173. package/dist/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
  174. package/dist/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
  175. package/dist/summary/summaryDelayLoadedModule/summarizer.d.ts +5 -5
  176. package/dist/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -1
  177. package/dist/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
  178. package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts +3 -4
  179. package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts.map +1 -1
  180. package/dist/summary/summaryDelayLoadedModule/summarizerHeuristics.js.map +1 -1
  181. package/dist/summary/summaryDelayLoadedModule/summaryGenerator.d.ts +3 -3
  182. package/dist/summary/summaryDelayLoadedModule/summaryGenerator.d.ts.map +1 -1
  183. package/dist/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
  184. package/dist/summary/summaryDelayLoadedModule/summaryResultBuilder.d.ts +1 -1
  185. package/dist/summary/summaryDelayLoadedModule/summaryResultBuilder.d.ts.map +1 -1
  186. package/dist/summary/summaryDelayLoadedModule/summaryResultBuilder.js.map +1 -1
  187. package/dist/summary/summaryDelayLoadedModule/summaryResultTypes.d.ts +5 -10
  188. package/dist/summary/summaryDelayLoadedModule/summaryResultTypes.d.ts.map +1 -1
  189. package/dist/summary/summaryDelayLoadedModule/summaryResultTypes.js.map +1 -1
  190. package/dist/summary/summaryFormat.d.ts +9 -14
  191. package/dist/summary/summaryFormat.d.ts.map +1 -1
  192. package/dist/summary/summaryFormat.js.map +1 -1
  193. package/dist/summary/summaryHelpers.d.ts +1 -2
  194. package/dist/summary/summaryHelpers.d.ts.map +1 -1
  195. package/dist/summary/summaryHelpers.js +1 -2
  196. package/dist/summary/summaryHelpers.js.map +1 -1
  197. package/dist/summary/summaryManager.d.ts +3 -3
  198. package/dist/summary/summaryManager.d.ts.map +1 -1
  199. package/dist/summary/summaryManager.js.map +1 -1
  200. package/lib/batchTracker.d.ts +1 -1
  201. package/lib/batchTracker.d.ts.map +1 -1
  202. package/lib/batchTracker.js.map +1 -1
  203. package/lib/blobManager/blobManager.d.ts +8 -2
  204. package/lib/blobManager/blobManager.d.ts.map +1 -1
  205. package/lib/blobManager/blobManager.js +37 -25
  206. package/lib/blobManager/blobManager.js.map +1 -1
  207. package/lib/blobManager/index.d.ts +2 -2
  208. package/lib/blobManager/index.d.ts.map +1 -1
  209. package/lib/blobManager/index.js.map +1 -1
  210. package/lib/channelCollection.d.ts +9 -11
  211. package/lib/channelCollection.d.ts.map +1 -1
  212. package/lib/channelCollection.js +2 -3
  213. package/lib/channelCollection.js.map +1 -1
  214. package/lib/compressionDefinitions.d.ts +3 -6
  215. package/lib/compressionDefinitions.d.ts.map +1 -1
  216. package/lib/compressionDefinitions.js +2 -4
  217. package/lib/compressionDefinitions.js.map +1 -1
  218. package/lib/connectionTelemetry.d.ts +3 -4
  219. package/lib/connectionTelemetry.d.ts.map +1 -1
  220. package/lib/connectionTelemetry.js.map +1 -1
  221. package/lib/containerHandleContext.d.ts +2 -2
  222. package/lib/containerHandleContext.d.ts.map +1 -1
  223. package/lib/containerHandleContext.js.map +1 -1
  224. package/lib/containerRuntime.d.ts +13 -20
  225. package/lib/containerRuntime.d.ts.map +1 -1
  226. package/lib/containerRuntime.js +3 -6
  227. package/lib/containerRuntime.js.map +1 -1
  228. package/lib/dataStore.d.ts +3 -3
  229. package/lib/dataStore.d.ts.map +1 -1
  230. package/lib/dataStore.js.map +1 -1
  231. package/lib/dataStoreContext.d.ts +8 -8
  232. package/lib/dataStoreContext.d.ts.map +1 -1
  233. package/lib/dataStoreContext.js.map +1 -1
  234. package/lib/dataStoreContexts.d.ts +2 -2
  235. package/lib/dataStoreContexts.d.ts.map +1 -1
  236. package/lib/dataStoreContexts.js.map +1 -1
  237. package/lib/dataStoreRegistry.d.ts +1 -1
  238. package/lib/dataStoreRegistry.d.ts.map +1 -1
  239. package/lib/dataStoreRegistry.js.map +1 -1
  240. package/lib/deltaManagerProxies.d.ts +2 -3
  241. package/lib/deltaManagerProxies.d.ts.map +1 -1
  242. package/lib/deltaManagerProxies.js.map +1 -1
  243. package/lib/deltaScheduler.d.ts +2 -2
  244. package/lib/deltaScheduler.d.ts.map +1 -1
  245. package/lib/deltaScheduler.js +1 -1
  246. package/lib/deltaScheduler.js.map +1 -1
  247. package/lib/error.d.ts +1 -1
  248. package/lib/error.d.ts.map +1 -1
  249. package/lib/error.js.map +1 -1
  250. package/lib/gc/garbageCollection.d.ts +4 -4
  251. package/lib/gc/garbageCollection.d.ts.map +1 -1
  252. package/lib/gc/garbageCollection.js.map +1 -1
  253. package/lib/gc/gcConfigs.d.ts +3 -3
  254. package/lib/gc/gcConfigs.d.ts.map +1 -1
  255. package/lib/gc/gcConfigs.js.map +1 -1
  256. package/lib/gc/gcDefinitions.d.ts +10 -11
  257. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  258. package/lib/gc/gcDefinitions.js.map +1 -1
  259. package/lib/gc/gcHelpers.d.ts +4 -4
  260. package/lib/gc/gcHelpers.d.ts.map +1 -1
  261. package/lib/gc/gcHelpers.js.map +1 -1
  262. package/lib/gc/gcReferenceGraphAlgorithm.d.ts +1 -1
  263. package/lib/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -1
  264. package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -1
  265. package/lib/gc/gcSummaryDefinitions.d.ts +1 -1
  266. package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -1
  267. package/lib/gc/gcSummaryDefinitions.js.map +1 -1
  268. package/lib/gc/gcSummaryStateTracker.d.ts +4 -4
  269. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
  270. package/lib/gc/gcSummaryStateTracker.js.map +1 -1
  271. package/lib/gc/gcTelemetry.d.ts +6 -6
  272. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  273. package/lib/gc/gcTelemetry.js.map +1 -1
  274. package/lib/gc/index.d.ts +3 -3
  275. package/lib/gc/index.d.ts.map +1 -1
  276. package/lib/gc/index.js.map +1 -1
  277. package/lib/inboundBatchAggregator.d.ts +2 -2
  278. package/lib/inboundBatchAggregator.d.ts.map +1 -1
  279. package/lib/inboundBatchAggregator.js.map +1 -1
  280. package/lib/index.d.ts +7 -7
  281. package/lib/index.d.ts.map +1 -1
  282. package/lib/index.js.map +1 -1
  283. package/lib/messageTypes.d.ts +7 -8
  284. package/lib/messageTypes.d.ts.map +1 -1
  285. package/lib/messageTypes.js +1 -2
  286. package/lib/messageTypes.js.map +1 -1
  287. package/lib/opLifecycle/batchManager.d.ts +2 -2
  288. package/lib/opLifecycle/batchManager.d.ts.map +1 -1
  289. package/lib/opLifecycle/batchManager.js.map +1 -1
  290. package/lib/opLifecycle/definitions.d.ts +1 -1
  291. package/lib/opLifecycle/definitions.d.ts.map +1 -1
  292. package/lib/opLifecycle/definitions.js.map +1 -1
  293. package/lib/opLifecycle/duplicateBatchDetector.d.ts +1 -1
  294. package/lib/opLifecycle/duplicateBatchDetector.d.ts.map +1 -1
  295. package/lib/opLifecycle/duplicateBatchDetector.js.map +1 -1
  296. package/lib/opLifecycle/index.d.ts +5 -5
  297. package/lib/opLifecycle/index.d.ts.map +1 -1
  298. package/lib/opLifecycle/index.js.map +1 -1
  299. package/lib/opLifecycle/opCompressor.d.ts +2 -2
  300. package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
  301. package/lib/opLifecycle/opCompressor.js.map +1 -1
  302. package/lib/opLifecycle/opDecompressor.d.ts +2 -2
  303. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -1
  304. package/lib/opLifecycle/opDecompressor.js.map +1 -1
  305. package/lib/opLifecycle/opGroupingManager.d.ts +3 -3
  306. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
  307. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  308. package/lib/opLifecycle/opSplitter.d.ts +4 -4
  309. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  310. package/lib/opLifecycle/opSplitter.js +1 -1
  311. package/lib/opLifecycle/opSplitter.js.map +1 -1
  312. package/lib/opLifecycle/outbox.d.ts +9 -9
  313. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  314. package/lib/opLifecycle/outbox.js.map +1 -1
  315. package/lib/opLifecycle/remoteMessageProcessor.d.ts +4 -4
  316. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  317. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  318. package/lib/opProperties.d.ts +1 -1
  319. package/lib/opProperties.d.ts.map +1 -1
  320. package/lib/opProperties.js.map +1 -1
  321. package/lib/packageVersion.d.ts +1 -1
  322. package/lib/packageVersion.js +1 -1
  323. package/lib/packageVersion.js.map +1 -1
  324. package/lib/pendingStateManager.d.ts +3 -3
  325. package/lib/pendingStateManager.d.ts.map +1 -1
  326. package/lib/pendingStateManager.js.map +1 -1
  327. package/lib/storageServiceWithAttachBlobs.d.ts +1 -1
  328. package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -1
  329. package/lib/storageServiceWithAttachBlobs.js.map +1 -1
  330. package/lib/summary/documentSchema.d.ts +1 -2
  331. package/lib/summary/documentSchema.d.ts.map +1 -1
  332. package/lib/summary/documentSchema.js.map +1 -1
  333. package/lib/summary/index.d.ts +10 -10
  334. package/lib/summary/index.d.ts.map +1 -1
  335. package/lib/summary/index.js.map +1 -1
  336. package/lib/summary/orderedClientElection.d.ts +4 -4
  337. package/lib/summary/orderedClientElection.d.ts.map +1 -1
  338. package/lib/summary/orderedClientElection.js.map +1 -1
  339. package/lib/summary/summarizerClientElection.d.ts +5 -5
  340. package/lib/summary/summarizerClientElection.d.ts.map +1 -1
  341. package/lib/summary/summarizerClientElection.js.map +1 -1
  342. package/lib/summary/summarizerNode/index.d.ts +3 -3
  343. package/lib/summary/summarizerNode/index.d.ts.map +1 -1
  344. package/lib/summary/summarizerNode/index.js.map +1 -1
  345. package/lib/summary/summarizerNode/summarizerNode.d.ts +5 -6
  346. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  347. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  348. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts +3 -3
  349. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  350. package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  351. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -3
  352. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  353. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  354. package/lib/summary/summarizerTypes.d.ts +25 -44
  355. package/lib/summary/summarizerTypes.d.ts.map +1 -1
  356. package/lib/summary/summarizerTypes.js.map +1 -1
  357. package/lib/summary/summarizerUtils.d.ts +3 -3
  358. package/lib/summary/summarizerUtils.d.ts.map +1 -1
  359. package/lib/summary/summarizerUtils.js.map +1 -1
  360. package/lib/summary/summaryCollection.d.ts +13 -23
  361. package/lib/summary/summaryCollection.d.ts.map +1 -1
  362. package/lib/summary/summaryCollection.js +1 -2
  363. package/lib/summary/summaryCollection.js.map +1 -1
  364. package/lib/summary/summaryDelayLoadedModule/index.d.ts +2 -2
  365. package/lib/summary/summaryDelayLoadedModule/index.d.ts.map +1 -1
  366. package/lib/summary/summaryDelayLoadedModule/index.js.map +1 -1
  367. package/lib/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.d.ts +1 -1
  368. package/lib/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.d.ts.map +1 -1
  369. package/lib/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.js.map +1 -1
  370. package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts +3 -3
  371. package/lib/summary/summaryDelayLoadedModule/runningSummarizer.d.ts.map +1 -1
  372. package/lib/summary/summaryDelayLoadedModule/runningSummarizer.js.map +1 -1
  373. package/lib/summary/summaryDelayLoadedModule/summarizer.d.ts +5 -5
  374. package/lib/summary/summaryDelayLoadedModule/summarizer.d.ts.map +1 -1
  375. package/lib/summary/summaryDelayLoadedModule/summarizer.js.map +1 -1
  376. package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts +3 -4
  377. package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.d.ts.map +1 -1
  378. package/lib/summary/summaryDelayLoadedModule/summarizerHeuristics.js.map +1 -1
  379. package/lib/summary/summaryDelayLoadedModule/summaryGenerator.d.ts +3 -3
  380. package/lib/summary/summaryDelayLoadedModule/summaryGenerator.d.ts.map +1 -1
  381. package/lib/summary/summaryDelayLoadedModule/summaryGenerator.js.map +1 -1
  382. package/lib/summary/summaryDelayLoadedModule/summaryResultBuilder.d.ts +1 -1
  383. package/lib/summary/summaryDelayLoadedModule/summaryResultBuilder.d.ts.map +1 -1
  384. package/lib/summary/summaryDelayLoadedModule/summaryResultBuilder.js.map +1 -1
  385. package/lib/summary/summaryDelayLoadedModule/summaryResultTypes.d.ts +5 -10
  386. package/lib/summary/summaryDelayLoadedModule/summaryResultTypes.d.ts.map +1 -1
  387. package/lib/summary/summaryDelayLoadedModule/summaryResultTypes.js.map +1 -1
  388. package/lib/summary/summaryFormat.d.ts +9 -14
  389. package/lib/summary/summaryFormat.d.ts.map +1 -1
  390. package/lib/summary/summaryFormat.js.map +1 -1
  391. package/lib/summary/summaryHelpers.d.ts +1 -2
  392. package/lib/summary/summaryHelpers.d.ts.map +1 -1
  393. package/lib/summary/summaryHelpers.js +1 -2
  394. package/lib/summary/summaryHelpers.js.map +1 -1
  395. package/lib/summary/summaryManager.d.ts +3 -3
  396. package/lib/summary/summaryManager.d.ts.map +1 -1
  397. package/lib/summary/summaryManager.js.map +1 -1
  398. package/package.json +19 -19
  399. package/src/batchTracker.ts +3 -3
  400. package/src/blobManager/blobManager.ts +47 -53
  401. package/src/blobManager/index.ts +4 -4
  402. package/src/channelCollection.ts +28 -29
  403. package/src/compressionDefinitions.ts +3 -6
  404. package/src/connectionTelemetry.ts +8 -9
  405. package/src/containerHandleContext.ts +2 -2
  406. package/src/containerRuntime.ts +42 -49
  407. package/src/dataStore.ts +6 -6
  408. package/src/dataStoreContext.ts +33 -33
  409. package/src/dataStoreContexts.ts +3 -3
  410. package/src/dataStoreRegistry.ts +1 -1
  411. package/src/deltaManagerProxies.ts +3 -3
  412. package/src/deltaScheduler.ts +6 -3
  413. package/src/error.ts +1 -1
  414. package/src/gc/garbageCollection.ts +18 -18
  415. package/src/gc/gcConfigs.ts +7 -7
  416. package/src/gc/gcDefinitions.ts +11 -12
  417. package/src/gc/gcHelpers.ts +7 -7
  418. package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
  419. package/src/gc/gcSummaryDefinitions.ts +1 -1
  420. package/src/gc/gcSummaryStateTracker.ts +5 -5
  421. package/src/gc/gcTelemetry.ts +8 -8
  422. package/src/gc/index.ts +18 -18
  423. package/src/inboundBatchAggregator.ts +4 -4
  424. package/src/index.ts +79 -79
  425. package/src/messageTypes.ts +9 -10
  426. package/src/opLifecycle/batchManager.ts +2 -2
  427. package/src/opLifecycle/definitions.ts +1 -1
  428. package/src/opLifecycle/duplicateBatchDetector.ts +1 -1
  429. package/src/opLifecycle/index.ts +9 -9
  430. package/src/opLifecycle/opCompressor.ts +2 -2
  431. package/src/opLifecycle/opDecompressor.ts +3 -3
  432. package/src/opLifecycle/opGroupingManager.ts +6 -6
  433. package/src/opLifecycle/opSplitter.ts +10 -7
  434. package/src/opLifecycle/outbox.ts +17 -14
  435. package/src/opLifecycle/remoteMessageProcessor.ts +4 -4
  436. package/src/opProperties.ts +1 -1
  437. package/src/packageVersion.ts +1 -1
  438. package/src/pendingStateManager.ts +10 -10
  439. package/src/storageServiceWithAttachBlobs.ts +11 -11
  440. package/src/summary/documentSchema.ts +1 -2
  441. package/src/summary/index.ts +69 -69
  442. package/src/summary/orderedClientElection.ts +12 -4
  443. package/src/summary/summarizerClientElection.ts +5 -5
  444. package/src/summary/summarizerNode/index.ts +3 -3
  445. package/src/summary/summarizerNode/summarizerNode.ts +14 -12
  446. package/src/summary/summarizerNode/summarizerNodeUtils.ts +3 -3
  447. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +3 -3
  448. package/src/summary/summarizerTypes.ts +25 -44
  449. package/src/summary/summarizerUtils.ts +3 -3
  450. package/src/summary/summaryCollection.ts +19 -29
  451. package/src/summary/summaryDelayLoadedModule/index.ts +2 -2
  452. package/src/summary/summaryDelayLoadedModule/runWhileConnectedCoordinator.ts +1 -1
  453. package/src/summary/summaryDelayLoadedModule/runningSummarizer.ts +4 -4
  454. package/src/summary/summaryDelayLoadedModule/summarizer.ts +8 -8
  455. package/src/summary/summaryDelayLoadedModule/summarizerHeuristics.ts +4 -4
  456. package/src/summary/summaryDelayLoadedModule/summaryGenerator.ts +3 -3
  457. package/src/summary/summaryDelayLoadedModule/summaryResultBuilder.ts +3 -3
  458. package/src/summary/summaryDelayLoadedModule/summaryResultTypes.ts +5 -10
  459. package/src/summary/summaryFormat.ts +9 -14
  460. package/src/summary/summaryHelpers.ts +1 -2
  461. package/src/summary/summaryManager.ts +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"opCompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opCompressor.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 { IsoBuffer } from \"@fluid-internal/client-utils\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tDataProcessingError,\n\tcreateChildLogger,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { compress } from \"lz4js\";\n\nimport { CompressionAlgorithms } from \"../compressionDefinitions.js\";\n\nimport { type OutboundBatchMessage, type OutboundSingletonBatch } from \"./definitions.js\";\nimport { estimateSocketSize } from \"./outbox.js\";\n\n/**\n * Compresses batches of ops.\n *\n * @remarks Only single-message batches are supported\n * Use opGroupingManager to group a batch into a singleton batch suitable for compression.\n */\nexport class OpCompressor {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tconstructor(logger: ITelemetryBaseLogger) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpCompressor\" });\n\t}\n\n\t/**\n\t * Combines the contents of the singleton batch into a single JSON string and compresses it, putting\n\t * the resulting string as the message contents in place of the original uncompressed payload.\n\t * @param batch - The batch to compress. Must have only 1 message\n\t * @returns A singleton batch containing a single compressed message\n\t */\n\tpublic compressBatch(batch: OutboundSingletonBatch): OutboundSingletonBatch {\n\t\tassert(\n\t\t\tbatch.contentSizeInBytes > 0 && batch.messages.length === 1,\n\t\t\t0x5a4 /* Batch should not be empty and should contain a single message */,\n\t\t);\n\n\t\tconst compressionStart = Date.now();\n\t\tconst contentsAsBuffer = new TextEncoder().encode(this.serializeBatchContents(batch));\n\t\tconst compressedContents = compress(contentsAsBuffer);\n\t\tconst compressedContent = IsoBuffer.from(compressedContents).toString(\"base64\");\n\t\tconst duration = Date.now() - compressionStart;\n\n\t\tconst messages: [OutboundBatchMessage] = [\n\t\t\t{\n\t\t\t\t...batch.messages[0],\n\t\t\t\tcontents: JSON.stringify({ packedContents: compressedContent }),\n\t\t\t\tmetadata: batch.messages[0].metadata,\n\t\t\t\tcompression: CompressionAlgorithms.lz4,\n\t\t\t},\n\t\t];\n\n\t\tconst compressedBatch: OutboundSingletonBatch = {\n\t\t\tcontentSizeInBytes: compressedContent.length,\n\t\t\tmessages,\n\t\t\treferenceSequenceNumber: batch.referenceSequenceNumber,\n\t\t};\n\n\t\tif (batch.contentSizeInBytes > 200000) {\n\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\teventName: \"CompressedBatch\",\n\t\t\t\tduration,\n\t\t\t\tsizeBeforeCompression: batch.contentSizeInBytes,\n\t\t\t\tsizeAfterCompression: compressedBatch.contentSizeInBytes,\n\t\t\t\topCount: compressedBatch.messages.length,\n\t\t\t\tsocketSize: estimateSocketSize(compressedBatch),\n\t\t\t});\n\t\t}\n\n\t\treturn compressedBatch;\n\t}\n\n\t/**\n\t * Combine the batch's content strings into a single JSON string (a serialized array)\n\t */\n\tprivate serializeBatchContents(batch: OutboundSingletonBatch): string {\n\t\tconst [message, ...none] = batch.messages;\n\t\tassert(none.length === 0, 0xb78 /* Batch should only contain a single message */);\n\t\ttry {\n\t\t\t// This is expressed as a JSON array, for legacy reasons\n\t\t\treturn `[${message.contents}]`;\n\t\t} catch (error: unknown) {\n\t\t\tif ((error as Partial<Error>).message === \"Invalid string length\") {\n\t\t\t\t// This is how string interpolation signals that\n\t\t\t\t// the content size exceeds its capacity\n\t\t\t\tconst dpe = DataProcessingError.create(\"Payload too large\", \"OpCompressor\");\n\t\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"BatchTooLarge\",\n\t\t\t\t\t\tsize: batch.contentSizeInBytes,\n\t\t\t\t\t\tlength: batch.messages.length,\n\t\t\t\t\t},\n\t\t\t\t\tdpe,\n\t\t\t\t);\n\t\t\t\tthrow dpe;\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"opCompressor.js","sourceRoot":"","sources":["../../src/opLifecycle/opCompressor.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 { IsoBuffer } from \"@fluid-internal/client-utils\";\nimport type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport {\n\tDataProcessingError,\n\tcreateChildLogger,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { compress } from \"lz4js\";\n\nimport { CompressionAlgorithms } from \"../compressionDefinitions.js\";\n\nimport type { OutboundBatchMessage, OutboundSingletonBatch } from \"./definitions.js\";\nimport { estimateSocketSize } from \"./outbox.js\";\n\n/**\n * Compresses batches of ops.\n *\n * @remarks Only single-message batches are supported\n * Use opGroupingManager to group a batch into a singleton batch suitable for compression.\n */\nexport class OpCompressor {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tconstructor(logger: ITelemetryBaseLogger) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpCompressor\" });\n\t}\n\n\t/**\n\t * Combines the contents of the singleton batch into a single JSON string and compresses it, putting\n\t * the resulting string as the message contents in place of the original uncompressed payload.\n\t * @param batch - The batch to compress. Must have only 1 message\n\t * @returns A singleton batch containing a single compressed message\n\t */\n\tpublic compressBatch(batch: OutboundSingletonBatch): OutboundSingletonBatch {\n\t\tassert(\n\t\t\tbatch.contentSizeInBytes > 0 && batch.messages.length === 1,\n\t\t\t0x5a4 /* Batch should not be empty and should contain a single message */,\n\t\t);\n\n\t\tconst compressionStart = Date.now();\n\t\tconst contentsAsBuffer = new TextEncoder().encode(this.serializeBatchContents(batch));\n\t\tconst compressedContents = compress(contentsAsBuffer);\n\t\tconst compressedContent = IsoBuffer.from(compressedContents).toString(\"base64\");\n\t\tconst duration = Date.now() - compressionStart;\n\n\t\tconst messages: [OutboundBatchMessage] = [\n\t\t\t{\n\t\t\t\t...batch.messages[0],\n\t\t\t\tcontents: JSON.stringify({ packedContents: compressedContent }),\n\t\t\t\tmetadata: batch.messages[0].metadata,\n\t\t\t\tcompression: CompressionAlgorithms.lz4,\n\t\t\t},\n\t\t];\n\n\t\tconst compressedBatch: OutboundSingletonBatch = {\n\t\t\tcontentSizeInBytes: compressedContent.length,\n\t\t\tmessages,\n\t\t\treferenceSequenceNumber: batch.referenceSequenceNumber,\n\t\t};\n\n\t\tif (batch.contentSizeInBytes > 200000) {\n\t\t\tthis.logger.sendPerformanceEvent({\n\t\t\t\teventName: \"CompressedBatch\",\n\t\t\t\tduration,\n\t\t\t\tsizeBeforeCompression: batch.contentSizeInBytes,\n\t\t\t\tsizeAfterCompression: compressedBatch.contentSizeInBytes,\n\t\t\t\topCount: compressedBatch.messages.length,\n\t\t\t\tsocketSize: estimateSocketSize(compressedBatch),\n\t\t\t});\n\t\t}\n\n\t\treturn compressedBatch;\n\t}\n\n\t/**\n\t * Combine the batch's content strings into a single JSON string (a serialized array)\n\t */\n\tprivate serializeBatchContents(batch: OutboundSingletonBatch): string {\n\t\tconst [message, ...none] = batch.messages;\n\t\tassert(none.length === 0, 0xb78 /* Batch should only contain a single message */);\n\t\ttry {\n\t\t\t// This is expressed as a JSON array, for legacy reasons\n\t\t\treturn `[${message.contents}]`;\n\t\t} catch (error: unknown) {\n\t\t\tif ((error as Partial<Error>).message === \"Invalid string length\") {\n\t\t\t\t// This is how string interpolation signals that\n\t\t\t\t// the content size exceeds its capacity\n\t\t\t\tconst dpe = DataProcessingError.create(\"Payload too large\", \"OpCompressor\");\n\t\t\t\tthis.logger.sendErrorEvent(\n\t\t\t\t\t{\n\t\t\t\t\t\teventName: \"BatchTooLarge\",\n\t\t\t\t\t\tsize: batch.contentSizeInBytes,\n\t\t\t\t\t\tlength: batch.messages.length,\n\t\t\t\t\t},\n\t\t\t\t\tdpe,\n\t\t\t\t);\n\t\t\t\tthrow dpe;\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n"]}
@@ -2,8 +2,8 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
6
- import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
5
+ import type { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
6
+ import type { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
7
7
  /**
8
8
  * State machine that "unrolls" contents of compressed batches of ops after decompressing them.
9
9
  * This class relies on some implicit contracts defined below:
@@ -1 +1 @@
1
- {"version":3,"file":"opDecompressor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opDecompressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAiBxF;;;;;;;;;;GAUG;AACH,qBAAa,cAAc;IAC1B,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,mBAAmB,CAAkB;IAC7C,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;gBAEjC,MAAM,EAAE,oBAAoB;IAIjC,mBAAmB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO;IA2CvE,IAAW,kBAAkB,IAAI,OAAO,CAEvC;IAED;;OAEG;IACH,OAAO,CAAC,oBAAoB,CAAS;IAErC;;;OAGG;IACI,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,IAAI;IA8BnE;;;OAGG;IACI,MAAM,CAAC,OAAO,EAAE,yBAAyB,GAAG,yBAAyB;CAmC5E"}
1
+ {"version":3,"file":"opDecompressor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opDecompressor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAE5E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAiB7F;;;;;;;;;;GAUG;AACH,qBAAa,cAAc;IAC1B,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,mBAAmB,CAAkB;IAC7C,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;gBAEjC,MAAM,EAAE,oBAAoB;IAIjC,mBAAmB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO;IA2CvE,IAAW,kBAAkB,IAAI,OAAO,CAEvC;IAED;;OAEG;IACH,OAAO,CAAC,oBAAoB,CAAS;IAErC;;;OAGG;IACI,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,IAAI;IA8BnE;;;OAGG;IACI,MAAM,CAAC,OAAO,EAAE,yBAAyB,GAAG,yBAAyB;CAmC5E"}
@@ -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 { IsoBuffer, Uint8ArrayToString } from \"@fluid-internal/client-utils\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tcreateChildLogger,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { decompress } from \"lz4js\";\n\nimport { CompressionAlgorithms } from \"../compressionDefinitions.js\";\nimport { IBatchMetadata } from \"../metadata.js\";\n\n/**\n * Compression makes assumptions about the shape of message contents. This interface codifies those assumptions, but does not validate them.\n */\ninterface IPackedContentsContents {\n\tpackedContents: string;\n}\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 *\n * Compressed batches from current code are always a single message but this class needs to handle a legacy compressed batch with multiple messages\n * because we need that functionality for back compat.\n */\nexport class OpDecompressor {\n\tprivate activeBatch = false;\n\t// TODO: better typing\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tprivate rootMessageContents: any | undefined;\n\tprivate processedCount = 0;\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tconstructor(logger: ITelemetryBaseLogger) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpDecompressor\" });\n\t}\n\n\tpublic isCompressedMessage(message: ISequencedDocumentMessage): boolean {\n\t\tif (message.compression === CompressionAlgorithms.lz4) {\n\t\t\treturn true;\n\t\t}\n\n\t\t/**\n\t\t * Back-compat self healing mechanism for ADO:3538, as loaders from\n\t\t * version client_v2.0.0-internal.1.2.0 to client_v2.0.0-internal.2.2.0 do not\n\t\t * support adding the proper compression metadata to compressed messages submitted\n\t\t * by the runtime. Should be removed after the loader reaches sufficient saturation\n\t\t * for a version greater or equal than client_v2.0.0-internal.2.2.0.\n\t\t *\n\t\t * The condition holds true for compressed messages, regardless of metadata. We are ultimately\n\t\t * looking for a message with a single property `packedContents` inside `contents`, of type 'string'\n\t\t * with a base64 encoded value.\n\t\t */\n\t\ttry {\n\t\t\tif (\n\t\t\t\tmessage.contents !== null &&\n\t\t\t\ttypeof message.contents === \"object\" &&\n\t\t\t\tObject.keys(message.contents).length === 1 &&\n\t\t\t\ttypeof (message.contents as { packedContents?: unknown }).packedContents ===\n\t\t\t\t\t\"string\" &&\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents.length > 0 &&\n\t\t\t\tIsoBuffer.from(\n\t\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\t\"base64\",\n\t\t\t\t).toString(\"base64\") === (message.contents as IPackedContentsContents).packedContents\n\t\t\t) {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"LegacyCompression\",\n\t\t\t\t\ttype: message.type,\n\t\t\t\t\tbatch: (message.metadata as IBatchMetadata | undefined)?.batch,\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic get currentlyUnrolling(): boolean {\n\t\treturn this.activeBatch;\n\t}\n\n\t/**\n\t * Is the decompressed and stored batch only comprised of a single message\n\t */\n\tprivate isSingleMessageBatch = false;\n\n\t/**\n\t * Decompress the given compressed message and store it to be subsequently unrolled.\n\t * The stored message will be of type `any[]` where each element represents a message's `contents`\n\t */\n\tpublic decompressAndStore(message: ISequencedDocumentMessage): void {\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\t\tassert(\n\t\t\tthis.isCompressedMessage(message),\n\t\t\t0x940 /* provided message should be compressed */,\n\t\t);\n\n\t\tassert(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);\n\t\tthis.activeBatch = true;\n\n\t\tconst batchMetadata = (message.metadata as IBatchMetadata | undefined)?.batch;\n\t\tif (batchMetadata === undefined) {\n\t\t\tthis.isSingleMessageBatch = true;\n\t\t} else {\n\t\t\tassert(batchMetadata === true, 0x941 /* invalid batch metadata */);\n\t\t}\n\n\t\tconst contents = IsoBuffer.from(\n\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\"base64\",\n\t\t);\n\t\tconst decompressedMessage = decompress(contents);\n\t\tconst intoString = Uint8ArrayToString(decompressedMessage);\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\tthis.rootMessageContents = JSON.parse(intoString);\n\t}\n\n\t/**\n\t * Unroll the next message from the decompressed content provided to {@link decompressAndStore}\n\t * @returns the unrolled `ISequencedDocumentMessage`\n\t */\n\tpublic unroll(message: ISequencedDocumentMessage): ISequencedDocumentMessage {\n\t\tassert(this.currentlyUnrolling, 0x942 /* not currently unrolling */);\n\t\tassert(this.rootMessageContents !== undefined, 0x943 /* missing rootMessageContents */);\n\t\tassert(\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\tthis.rootMessageContents.length > this.processedCount,\n\t\t\t0x944 /* no more content to unroll */,\n\t\t);\n\n\t\tconst batchMetadata = (message.metadata as IBatchMetadata | undefined)?.batch;\n\n\t\tif (batchMetadata === false || this.isSingleMessageBatch) {\n\t\t\t// End of compressed batch\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\tconst returnMessage = newMessage(message, this.rootMessageContents[this.processedCount]);\n\n\t\t\tthis.activeBatch = false;\n\t\t\tthis.isSingleMessageBatch = false;\n\t\t\tthis.rootMessageContents = undefined;\n\t\t\tthis.processedCount = 0;\n\n\t\t\treturn returnMessage;\n\t\t} else if (batchMetadata === true) {\n\t\t\t// Start of compressed batch\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\treturn newMessage(message, this.rootMessageContents[this.processedCount++]);\n\t\t}\n\n\t\tassert(batchMetadata === undefined, 0x945 /* invalid batch metadata */);\n\t\tassert(message.contents === undefined, 0x512 /* Expecting empty message */);\n\n\t\t// Continuation of compressed batch\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\treturn newMessage(message, this.rootMessageContents[this.processedCount++]);\n\t}\n}\n\n// We should not be mutating the input message nor its metadata\nconst newMessage = (\n\toriginalMessage: ISequencedDocumentMessage,\n\tcontents: unknown,\n): ISequencedDocumentMessage => ({\n\t...originalMessage,\n\tcontents,\n\tcompression: undefined,\n\t// TODO: It should already be the case that we're not modifying any metadata, not clear if/why this shallow clone should be required.\n\n\tmetadata:\n\t\toriginalMessage.metadata === undefined ? undefined : { ...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 { IsoBuffer, Uint8ArrayToString } from \"@fluid-internal/client-utils\";\nimport type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tcreateChildLogger,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { decompress } from \"lz4js\";\n\nimport { CompressionAlgorithms } from \"../compressionDefinitions.js\";\nimport type { IBatchMetadata } from \"../metadata.js\";\n\n/**\n * Compression makes assumptions about the shape of message contents. This interface codifies those assumptions, but does not validate them.\n */\ninterface IPackedContentsContents {\n\tpackedContents: string;\n}\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 *\n * Compressed batches from current code are always a single message but this class needs to handle a legacy compressed batch with multiple messages\n * because we need that functionality for back compat.\n */\nexport class OpDecompressor {\n\tprivate activeBatch = false;\n\t// TODO: better typing\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tprivate rootMessageContents: any | undefined;\n\tprivate processedCount = 0;\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tconstructor(logger: ITelemetryBaseLogger) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpDecompressor\" });\n\t}\n\n\tpublic isCompressedMessage(message: ISequencedDocumentMessage): boolean {\n\t\tif (message.compression === CompressionAlgorithms.lz4) {\n\t\t\treturn true;\n\t\t}\n\n\t\t/**\n\t\t * Back-compat self healing mechanism for ADO:3538, as loaders from\n\t\t * version client_v2.0.0-internal.1.2.0 to client_v2.0.0-internal.2.2.0 do not\n\t\t * support adding the proper compression metadata to compressed messages submitted\n\t\t * by the runtime. Should be removed after the loader reaches sufficient saturation\n\t\t * for a version greater or equal than client_v2.0.0-internal.2.2.0.\n\t\t *\n\t\t * The condition holds true for compressed messages, regardless of metadata. We are ultimately\n\t\t * looking for a message with a single property `packedContents` inside `contents`, of type 'string'\n\t\t * with a base64 encoded value.\n\t\t */\n\t\ttry {\n\t\t\tif (\n\t\t\t\tmessage.contents !== null &&\n\t\t\t\ttypeof message.contents === \"object\" &&\n\t\t\t\tObject.keys(message.contents).length === 1 &&\n\t\t\t\ttypeof (message.contents as { packedContents?: unknown }).packedContents ===\n\t\t\t\t\t\"string\" &&\n\t\t\t\t(message.contents as IPackedContentsContents).packedContents.length > 0 &&\n\t\t\t\tIsoBuffer.from(\n\t\t\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\t\t\"base64\",\n\t\t\t\t).toString(\"base64\") === (message.contents as IPackedContentsContents).packedContents\n\t\t\t) {\n\t\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\t\teventName: \"LegacyCompression\",\n\t\t\t\t\ttype: message.type,\n\t\t\t\t\tbatch: (message.metadata as IBatchMetadata | undefined)?.batch,\n\t\t\t\t});\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic get currentlyUnrolling(): boolean {\n\t\treturn this.activeBatch;\n\t}\n\n\t/**\n\t * Is the decompressed and stored batch only comprised of a single message\n\t */\n\tprivate isSingleMessageBatch = false;\n\n\t/**\n\t * Decompress the given compressed message and store it to be subsequently unrolled.\n\t * The stored message will be of type `any[]` where each element represents a message's `contents`\n\t */\n\tpublic decompressAndStore(message: ISequencedDocumentMessage): void {\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\t\tassert(\n\t\t\tthis.isCompressedMessage(message),\n\t\t\t0x940 /* provided message should be compressed */,\n\t\t);\n\n\t\tassert(this.activeBatch === false, 0x4b8 /* shouldn't have multiple active batches */);\n\t\tthis.activeBatch = true;\n\n\t\tconst batchMetadata = (message.metadata as IBatchMetadata | undefined)?.batch;\n\t\tif (batchMetadata === undefined) {\n\t\t\tthis.isSingleMessageBatch = true;\n\t\t} else {\n\t\t\tassert(batchMetadata === true, 0x941 /* invalid batch metadata */);\n\t\t}\n\n\t\tconst contents = IsoBuffer.from(\n\t\t\t(message.contents as IPackedContentsContents).packedContents,\n\t\t\t\"base64\",\n\t\t);\n\t\tconst decompressedMessage = decompress(contents);\n\t\tconst intoString = Uint8ArrayToString(decompressedMessage);\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\tthis.rootMessageContents = JSON.parse(intoString);\n\t}\n\n\t/**\n\t * Unroll the next message from the decompressed content provided to {@link decompressAndStore}\n\t * @returns the unrolled `ISequencedDocumentMessage`\n\t */\n\tpublic unroll(message: ISequencedDocumentMessage): ISequencedDocumentMessage {\n\t\tassert(this.currentlyUnrolling, 0x942 /* not currently unrolling */);\n\t\tassert(this.rootMessageContents !== undefined, 0x943 /* missing rootMessageContents */);\n\t\tassert(\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\tthis.rootMessageContents.length > this.processedCount,\n\t\t\t0x944 /* no more content to unroll */,\n\t\t);\n\n\t\tconst batchMetadata = (message.metadata as IBatchMetadata | undefined)?.batch;\n\n\t\tif (batchMetadata === false || this.isSingleMessageBatch) {\n\t\t\t// End of compressed batch\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\tconst returnMessage = newMessage(message, this.rootMessageContents[this.processedCount]);\n\n\t\t\tthis.activeBatch = false;\n\t\t\tthis.isSingleMessageBatch = false;\n\t\t\tthis.rootMessageContents = undefined;\n\t\t\tthis.processedCount = 0;\n\n\t\t\treturn returnMessage;\n\t\t} else if (batchMetadata === true) {\n\t\t\t// Start of compressed batch\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\t\treturn newMessage(message, this.rootMessageContents[this.processedCount++]);\n\t\t}\n\n\t\tassert(batchMetadata === undefined, 0x945 /* invalid batch metadata */);\n\t\tassert(message.contents === undefined, 0x512 /* Expecting empty message */);\n\n\t\t// Continuation of compressed batch\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\treturn newMessage(message, this.rootMessageContents[this.processedCount++]);\n\t}\n}\n\n// We should not be mutating the input message nor its metadata\nconst newMessage = (\n\toriginalMessage: ISequencedDocumentMessage,\n\tcontents: unknown,\n): ISequencedDocumentMessage => ({\n\t...originalMessage,\n\tcontents,\n\tcompression: undefined,\n\t// TODO: It should already be the case that we're not modifying any metadata, not clear if/why this shallow clone should be required.\n\n\tmetadata:\n\t\toriginalMessage.metadata === undefined ? undefined : { ...originalMessage.metadata },\n});\n"]}
@@ -2,9 +2,9 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
6
- import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
7
- import { type LocalEmptyBatchPlaceholder, type OutboundBatch, type OutboundSingletonBatch } from "./definitions.js";
5
+ import type { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
6
+ import type { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
7
+ import type { LocalEmptyBatchPlaceholder, OutboundBatch, OutboundSingletonBatch } from "./definitions.js";
8
8
  export declare function isGroupedBatch(op: ISequencedDocumentMessage): boolean;
9
9
  export interface OpGroupingManagerConfig {
10
10
  readonly groupedBatchingEnabled: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"opGroupingManager.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opGroupingManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAMxF,OAAO,EACN,KAAK,0BAA0B,EAC/B,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAC3B,MAAM,kBAAkB,CAAC;AAuB1B,wBAAgB,cAAc,CAAC,EAAE,EAAE,yBAAyB,GAAG,OAAO,CAErE;AAED,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC;CACzC;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,OAAO,iBAAiB,CAAC,cAAc,CAAC;IAC9C,QAAQ,EAAE,SAAS,EAAE,CAAC;CACtB;AAED,qBAAa,iBAAiB;IAK5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJxB,MAAM,CAAC,QAAQ,CAAC,cAAc,kBAAkB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;gBAG3B,MAAM,EAAE,uBAAuB,EAChD,MAAM,EAAE,oBAAoB;IAK7B;;;;;;OAMG;IACI,uBAAuB,CAC7B,mBAAmB,EAAE,MAAM,EAC3B,uBAAuB,EAAE,MAAM,GAC7B;QACF,aAAa,EAAE,sBAAsB,CAAC;QACtC,kBAAkB,EAAE,0BAA0B,CAAC;KAC/C;IA0BD;;;;;;;;OAQG;IACI,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,sBAAsB;IAkDxD,SAAS,CAAC,EAAE,EAAE,yBAAyB,GAAG,yBAAyB,EAAE;IAcrE,sBAAsB,IAAI,OAAO;CAGxC"}
1
+ {"version":3,"file":"opGroupingManager.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opGroupingManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAE5E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAM7F,OAAO,KAAK,EACX,0BAA0B,EAC1B,aAAa,EACb,sBAAsB,EACtB,MAAM,kBAAkB,CAAC;AAuB1B,wBAAgB,cAAc,CAAC,EAAE,EAAE,yBAAyB,GAAG,OAAO,CAErE;AAED,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC;CACzC;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,OAAO,iBAAiB,CAAC,cAAc,CAAC;IAC9C,QAAQ,EAAE,SAAS,EAAE,CAAC;CACtB;AAED,qBAAa,iBAAiB;IAK5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJxB,MAAM,CAAC,QAAQ,CAAC,cAAc,kBAAkB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;gBAG3B,MAAM,EAAE,uBAAuB,EAChD,MAAM,EAAE,oBAAoB;IAK7B;;;;;;OAMG;IACI,uBAAuB,CAC7B,mBAAmB,EAAE,MAAM,EAC3B,uBAAuB,EAAE,MAAM,GAC7B;QACF,aAAa,EAAE,sBAAsB,CAAC;QACtC,kBAAkB,EAAE,0BAA0B,CAAC;KAC/C;IA0BD;;;;;;;;OAQG;IACI,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,sBAAsB;IAkDxD,SAAS,CAAC,EAAE,EAAE,yBAAyB,GAAG,yBAAyB,EAAE;IAcrE,sBAAsB,IAAI,OAAO;CAGxC"}
@@ -1 +1 @@
1
- {"version":3,"file":"opGroupingManager.js","sourceRoot":"","sources":["../../src/opLifecycle/opGroupingManager.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,kEAA6D;AAE7D,uEAGkD;AAsBlD,SAAS,eAAe,CAAC,UAAmB;IAC3C,OAAO,CACL,UAAoD,EAAE,IAAI;QAC3D,iBAAiB,CAAC,cAAc,CAChC,CAAC;AACH,CAAC;AAED,SAAgB,cAAc,CAAC,EAA6B;IAC3D,OAAO,eAAe,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;AACrC,CAAC;AAFD,wCAEC;AAgBD,MAAa,iBAAiB;IAI7B,YACkB,MAA+B,EAChD,MAA4B;QADX,WAAM,GAAN,MAAM,CAAyB;QAGhD,IAAI,CAAC,MAAM,GAAG,IAAA,4BAAiB,EAAC,EAAE,MAAM,EAAE,SAAS,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED;;;;;;OAMG;IACI,uBAAuB,CAC7B,mBAA2B,EAC3B,uBAA+B;QAK/B,IAAA,iBAAM,EACL,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAClC,KAAK,CAAC,yEAAyE,CAC/E,CAAC;QAEF,MAAM,iBAAiB,GAAsB;YAC5C,IAAI,EAAE,cAAc;YACpB,QAAQ,EAAE,EAAE;SACZ,CAAC;QACF,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAEvD,MAAM,kBAAkB,GAA+B;YACtD,QAAQ,EAAE,EAAE,OAAO,EAAE,mBAAmB,EAAE;YAC1C,eAAe,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;YACrC,uBAAuB;YACvB,SAAS,EAAE,iBAAiB;SAC5B,CAAC;QACF,MAAM,aAAa,GAA2B;YAC7C,kBAAkB,EAAE,CAAC;YACrB,QAAQ,EAAE,CAAC,EAAE,GAAG,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC;YACnF,uBAAuB;SACvB,CAAC;QACF,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,CAAC;IAC9C,CAAC;IAED;;;;;;;;OAQG;IACI,UAAU,CAAC,KAAoB;QACrC,IAAA,iBAAM,EAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACtE,IAAA,iBAAM,EAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAE1F,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,KAA+B,CAAC;QACxC,CAAC;QAED,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;gBAC9B,SAAS,EAAE,iBAAiB;gBAC5B,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;gBAC7B,SAAS,EAAE,KAAK,CAAC,eAAe;gBAChC,uBAAuB,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,uBAAuB;aAClE,CAAC,CAAC;QACJ,CAAC;QACD,kEAAkE;QAClE,IAAI,cAAc,CAAC;QACnB,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACtC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACtB,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;gBAC7D,IAAI,OAAO,EAAE,CAAC;oBACb,cAAc,GAAG,OAAO,CAAC;gBAC1B,CAAC;gBACD,IAAA,iBAAM,EAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACpF,CAAC;QACF,CAAC;QAED,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC;YACxC,IAAI,EAAE,iBAAiB,CAAC,cAAc;YACtC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAkB,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC3D,QAAQ,EAAE,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;gBACnF,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,WAAW,EAAE,OAAO,CAAC,WAAW;aAChC,CAAC,CAAC;SACH,CAAC,CAAC;QAEH,MAAM,YAAY,GAA2B;YAC5C,GAAG,KAAK;YACR,QAAQ,EAAE;gBACT;oBACC,QAAQ,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE;oBACrC,uBAAuB,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,uBAAuB;oBAClE,QAAQ,EAAE,iBAAiB;iBAC3B;aACD;SACD,CAAC;QACF,OAAO,YAAY,CAAC;IACrB,CAAC;IAEM,SAAS,CAAC,EAA6B;QAC7C,IAAA,iBAAM,EAAC,eAAe,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACnF,MAAM,QAAQ,GAAiC,EAAE,CAAC,QAAQ,CAAC;QAE3D,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YAC7C,GAAG,EAAE;YACL,oBAAoB,EAAE,OAAO,EAAE;YAC/B,QAAQ,EAAE,UAAU,CAAC,QAAQ;YAC7B,QAAQ,EAAE,UAAU,CAAC,QAAQ;YAC7B,WAAW,EAAE,UAAU,CAAC,WAAW;SACnC,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,sBAAsB;QAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC;IAC3C,CAAC;;AA7HF,8CA8HC;AA7HgB,gCAAc,GAAG,cAAc,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tcreateChildLogger,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport {\n\ttype LocalEmptyBatchPlaceholder,\n\ttype OutboundBatch,\n\ttype OutboundSingletonBatch,\n} from \"./definitions.js\";\n\n/**\n * Grouping makes assumptions about the shape of message contents. This interface codifies those assumptions, but does not validate them.\n */\ninterface IGroupedBatchMessageContents {\n\ttype: typeof OpGroupingManager.groupedBatchOp;\n\tcontents: IGroupedMessage[];\n}\n\ninterface IGroupedMessage {\n\tcontents?: unknown;\n\tmetadata?: Record<string, unknown>;\n\tcompression?: string;\n}\n\nfunction isGroupContents(opContents: unknown): opContents is IGroupedBatchMessageContents {\n\treturn (\n\t\t(opContents as Partial<IGroupedBatchMessageContents>)?.type ===\n\t\tOpGroupingManager.groupedBatchOp\n\t);\n}\n\nexport function isGroupedBatch(op: ISequencedDocumentMessage): boolean {\n\treturn isGroupContents(op.contents);\n}\n\nexport interface OpGroupingManagerConfig {\n\treadonly groupedBatchingEnabled: boolean;\n}\n\n/**\n * This is the type of an empty grouped batch we send over the wire\n * We also put this in the placeholder for an empty batch in the PendingStateManager.\n * But most places throughout the ContainerRuntime, this will not be used (just as Grouped Batches in general don't appear outside opLifecycle dir)\n */\nexport interface EmptyGroupedBatch {\n\ttype: typeof OpGroupingManager.groupedBatchOp;\n\tcontents: readonly [];\n}\n\nexport class OpGroupingManager {\n\tstatic readonly groupedBatchOp = \"groupedBatch\";\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tconstructor(\n\t\tprivate readonly config: OpGroupingManagerConfig,\n\t\tlogger: ITelemetryBaseLogger,\n\t) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpGroupingManager\" });\n\t}\n\n\t/**\n\t * Creates a new batch with a single message of type \"groupedBatch\" and empty contents.\n\t * This is needed as a placeholder if a batch becomes empty on resubmit, but we are tracking batch IDs.\n\t * @param resubmittingBatchId - batch ID of the resubmitting batch\n\t * @param referenceSequenceNumber - reference sequence number\n\t * @returns - The outbound batch as well as the interior placeholder message\n\t */\n\tpublic createEmptyGroupedBatch(\n\t\tresubmittingBatchId: string,\n\t\treferenceSequenceNumber: number,\n\t): {\n\t\toutboundBatch: OutboundSingletonBatch;\n\t\tplaceholderMessage: LocalEmptyBatchPlaceholder;\n\t} {\n\t\tassert(\n\t\t\tthis.config.groupedBatchingEnabled,\n\t\t\t0xa00 /* cannot create empty grouped batch when grouped batching is disabled */,\n\t\t);\n\n\t\tconst emptyGroupedBatch: EmptyGroupedBatch = {\n\t\t\ttype: \"groupedBatch\",\n\t\t\tcontents: [],\n\t\t};\n\t\tconst serializedOp = JSON.stringify(emptyGroupedBatch);\n\n\t\tconst placeholderMessage: LocalEmptyBatchPlaceholder = {\n\t\t\tmetadata: { batchId: resubmittingBatchId },\n\t\t\tlocalOpMetadata: { emptyBatch: true },\n\t\t\treferenceSequenceNumber,\n\t\t\truntimeOp: emptyGroupedBatch,\n\t\t};\n\t\tconst outboundBatch: OutboundSingletonBatch = {\n\t\t\tcontentSizeInBytes: 0,\n\t\t\tmessages: [{ ...placeholderMessage, runtimeOp: undefined, contents: serializedOp }],\n\t\t\treferenceSequenceNumber,\n\t\t};\n\t\treturn { outboundBatch, placeholderMessage };\n\t}\n\n\t/**\n\t * Converts the given batch into a \"grouped batch\" - a batch with a single message of type \"groupedBatch\",\n\t * with contents being an array of the original batch's messages.\n\t *\n\t * If the batch already has only 1 message, it is returned as-is.\n\t *\n\t * @remarks - Remember that a BatchMessage has its content JSON serialized, so the incoming batch message contents\n\t * must be parsed first, and then the type and contents mentioned above are hidden in that JSON serialization.\n\t */\n\tpublic groupBatch(batch: OutboundBatch): OutboundSingletonBatch {\n\t\tassert(this.groupedBatchingEnabled(), 0xb79 /* grouping disabled! */);\n\t\tassert(batch.messages.length > 0, 0xb7a /* Unexpected attempt to group an empty batch */);\n\n\t\tif (batch.messages.length === 1) {\n\t\t\treturn batch as OutboundSingletonBatch;\n\t\t}\n\n\t\tif (batch.messages.length >= 1000) {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"GroupLargeBatch\",\n\t\t\t\tlength: batch.messages.length,\n\t\t\t\treentrant: batch.hasReentrantOps,\n\t\t\t\treferenceSequenceNumber: batch.messages[0].referenceSequenceNumber,\n\t\t\t});\n\t\t}\n\t\t// We expect this will be on the first message, if present at all.\n\t\tlet groupedBatchId;\n\t\tfor (const message of batch.messages) {\n\t\t\tif (message.metadata) {\n\t\t\t\tconst { batch: _batch, batchId, ...rest } = message.metadata;\n\t\t\t\tif (batchId) {\n\t\t\t\t\tgroupedBatchId = batchId;\n\t\t\t\t}\n\t\t\t\tassert(Object.keys(rest).length === 0, 0x5dd /* cannot group ops with metadata */);\n\t\t\t}\n\t\t}\n\n\t\tconst serializedContent = JSON.stringify({\n\t\t\ttype: OpGroupingManager.groupedBatchOp,\n\t\t\tcontents: batch.messages.map<IGroupedMessage>((message) => ({\n\t\t\t\tcontents: message.contents === undefined ? undefined : JSON.parse(message.contents),\n\t\t\t\tmetadata: message.metadata,\n\t\t\t\tcompression: message.compression,\n\t\t\t})),\n\t\t});\n\n\t\tconst groupedBatch: OutboundSingletonBatch = {\n\t\t\t...batch,\n\t\t\tmessages: [\n\t\t\t\t{\n\t\t\t\t\tmetadata: { batchId: groupedBatchId },\n\t\t\t\t\treferenceSequenceNumber: batch.messages[0].referenceSequenceNumber,\n\t\t\t\t\tcontents: serializedContent,\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t\treturn groupedBatch;\n\t}\n\n\tpublic ungroupOp(op: ISequencedDocumentMessage): ISequencedDocumentMessage[] {\n\t\tassert(isGroupContents(op.contents), 0x947 /* can only ungroup a grouped batch */);\n\t\tconst contents: IGroupedBatchMessageContents = op.contents;\n\n\t\tlet fakeCsn = 1;\n\t\treturn contents.contents.map((subMessage) => ({\n\t\t\t...op,\n\t\t\tclientSequenceNumber: fakeCsn++,\n\t\t\tcontents: subMessage.contents,\n\t\t\tmetadata: subMessage.metadata,\n\t\t\tcompression: subMessage.compression,\n\t\t}));\n\t}\n\n\tpublic groupedBatchingEnabled(): boolean {\n\t\treturn this.config.groupedBatchingEnabled;\n\t}\n}\n"]}
1
+ {"version":3,"file":"opGroupingManager.js","sourceRoot":"","sources":["../../src/opLifecycle/opGroupingManager.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 type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tcreateChildLogger,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport type {\n\tLocalEmptyBatchPlaceholder,\n\tOutboundBatch,\n\tOutboundSingletonBatch,\n} from \"./definitions.js\";\n\n/**\n * Grouping makes assumptions about the shape of message contents. This interface codifies those assumptions, but does not validate them.\n */\ninterface IGroupedBatchMessageContents {\n\ttype: typeof OpGroupingManager.groupedBatchOp;\n\tcontents: IGroupedMessage[];\n}\n\ninterface IGroupedMessage {\n\tcontents?: unknown;\n\tmetadata?: Record<string, unknown>;\n\tcompression?: string;\n}\n\nfunction isGroupContents(opContents: unknown): opContents is IGroupedBatchMessageContents {\n\treturn (\n\t\t(opContents as Partial<IGroupedBatchMessageContents>)?.type ===\n\t\tOpGroupingManager.groupedBatchOp\n\t);\n}\n\nexport function isGroupedBatch(op: ISequencedDocumentMessage): boolean {\n\treturn isGroupContents(op.contents);\n}\n\nexport interface OpGroupingManagerConfig {\n\treadonly groupedBatchingEnabled: boolean;\n}\n\n/**\n * This is the type of an empty grouped batch we send over the wire\n * We also put this in the placeholder for an empty batch in the PendingStateManager.\n * But most places throughout the ContainerRuntime, this will not be used (just as Grouped Batches in general don't appear outside opLifecycle dir)\n */\nexport interface EmptyGroupedBatch {\n\ttype: typeof OpGroupingManager.groupedBatchOp;\n\tcontents: readonly [];\n}\n\nexport class OpGroupingManager {\n\tstatic readonly groupedBatchOp = \"groupedBatch\";\n\tprivate readonly logger: ITelemetryLoggerExt;\n\n\tconstructor(\n\t\tprivate readonly config: OpGroupingManagerConfig,\n\t\tlogger: ITelemetryBaseLogger,\n\t) {\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpGroupingManager\" });\n\t}\n\n\t/**\n\t * Creates a new batch with a single message of type \"groupedBatch\" and empty contents.\n\t * This is needed as a placeholder if a batch becomes empty on resubmit, but we are tracking batch IDs.\n\t * @param resubmittingBatchId - batch ID of the resubmitting batch\n\t * @param referenceSequenceNumber - reference sequence number\n\t * @returns - The outbound batch as well as the interior placeholder message\n\t */\n\tpublic createEmptyGroupedBatch(\n\t\tresubmittingBatchId: string,\n\t\treferenceSequenceNumber: number,\n\t): {\n\t\toutboundBatch: OutboundSingletonBatch;\n\t\tplaceholderMessage: LocalEmptyBatchPlaceholder;\n\t} {\n\t\tassert(\n\t\t\tthis.config.groupedBatchingEnabled,\n\t\t\t0xa00 /* cannot create empty grouped batch when grouped batching is disabled */,\n\t\t);\n\n\t\tconst emptyGroupedBatch: EmptyGroupedBatch = {\n\t\t\ttype: \"groupedBatch\",\n\t\t\tcontents: [],\n\t\t};\n\t\tconst serializedOp = JSON.stringify(emptyGroupedBatch);\n\n\t\tconst placeholderMessage: LocalEmptyBatchPlaceholder = {\n\t\t\tmetadata: { batchId: resubmittingBatchId },\n\t\t\tlocalOpMetadata: { emptyBatch: true },\n\t\t\treferenceSequenceNumber,\n\t\t\truntimeOp: emptyGroupedBatch,\n\t\t};\n\t\tconst outboundBatch: OutboundSingletonBatch = {\n\t\t\tcontentSizeInBytes: 0,\n\t\t\tmessages: [{ ...placeholderMessage, runtimeOp: undefined, contents: serializedOp }],\n\t\t\treferenceSequenceNumber,\n\t\t};\n\t\treturn { outboundBatch, placeholderMessage };\n\t}\n\n\t/**\n\t * Converts the given batch into a \"grouped batch\" - a batch with a single message of type \"groupedBatch\",\n\t * with contents being an array of the original batch's messages.\n\t *\n\t * If the batch already has only 1 message, it is returned as-is.\n\t *\n\t * @remarks - Remember that a BatchMessage has its content JSON serialized, so the incoming batch message contents\n\t * must be parsed first, and then the type and contents mentioned above are hidden in that JSON serialization.\n\t */\n\tpublic groupBatch(batch: OutboundBatch): OutboundSingletonBatch {\n\t\tassert(this.groupedBatchingEnabled(), 0xb79 /* grouping disabled! */);\n\t\tassert(batch.messages.length > 0, 0xb7a /* Unexpected attempt to group an empty batch */);\n\n\t\tif (batch.messages.length === 1) {\n\t\t\treturn batch as OutboundSingletonBatch;\n\t\t}\n\n\t\tif (batch.messages.length >= 1000) {\n\t\t\tthis.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"GroupLargeBatch\",\n\t\t\t\tlength: batch.messages.length,\n\t\t\t\treentrant: batch.hasReentrantOps,\n\t\t\t\treferenceSequenceNumber: batch.messages[0].referenceSequenceNumber,\n\t\t\t});\n\t\t}\n\t\t// We expect this will be on the first message, if present at all.\n\t\tlet groupedBatchId;\n\t\tfor (const message of batch.messages) {\n\t\t\tif (message.metadata) {\n\t\t\t\tconst { batch: _batch, batchId, ...rest } = message.metadata;\n\t\t\t\tif (batchId) {\n\t\t\t\t\tgroupedBatchId = batchId;\n\t\t\t\t}\n\t\t\t\tassert(Object.keys(rest).length === 0, 0x5dd /* cannot group ops with metadata */);\n\t\t\t}\n\t\t}\n\n\t\tconst serializedContent = JSON.stringify({\n\t\t\ttype: OpGroupingManager.groupedBatchOp,\n\t\t\tcontents: batch.messages.map<IGroupedMessage>((message) => ({\n\t\t\t\tcontents: message.contents === undefined ? undefined : JSON.parse(message.contents),\n\t\t\t\tmetadata: message.metadata,\n\t\t\t\tcompression: message.compression,\n\t\t\t})),\n\t\t});\n\n\t\tconst groupedBatch: OutboundSingletonBatch = {\n\t\t\t...batch,\n\t\t\tmessages: [\n\t\t\t\t{\n\t\t\t\t\tmetadata: { batchId: groupedBatchId },\n\t\t\t\t\treferenceSequenceNumber: batch.messages[0].referenceSequenceNumber,\n\t\t\t\t\tcontents: serializedContent,\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t\treturn groupedBatch;\n\t}\n\n\tpublic ungroupOp(op: ISequencedDocumentMessage): ISequencedDocumentMessage[] {\n\t\tassert(isGroupContents(op.contents), 0x947 /* can only ungroup a grouped batch */);\n\t\tconst contents: IGroupedBatchMessageContents = op.contents;\n\n\t\tlet fakeCsn = 1;\n\t\treturn contents.contents.map((subMessage) => ({\n\t\t\t...op,\n\t\t\tclientSequenceNumber: fakeCsn++,\n\t\t\tcontents: subMessage.contents,\n\t\t\tmetadata: subMessage.metadata,\n\t\t\tcompression: subMessage.compression,\n\t\t}));\n\t}\n\n\tpublic groupedBatchingEnabled(): boolean {\n\t\treturn this.config.groupedBatchingEnabled;\n\t}\n}\n"]}
@@ -2,10 +2,10 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { IBatchMessage } from "@fluidframework/container-definitions/internal";
6
- import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
7
- import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
8
- import { IChunkedOp, type OutboundBatchMessage, type OutboundSingletonBatch } from "./definitions.js";
5
+ import type { IBatchMessage } from "@fluidframework/container-definitions/internal";
6
+ import type { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
7
+ import type { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
8
+ import type { IChunkedOp, OutboundBatchMessage, OutboundSingletonBatch } from "./definitions.js";
9
9
  export declare function isChunkedMessage(message: ISequencedDocumentMessage): boolean;
10
10
  /**
11
11
  * Responsible for creating and reconstructing chunked messages.
@@ -1 +1 @@
1
- {"version":3,"file":"opSplitter.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAC;AAC/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAUxF,OAAO,EACN,UAAU,EACV,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,MAAM,kBAAkB,CAAC;AAG1B,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAE5E;AAWD;;GAEG;AACH,qBAAa,UAAU;IAOrB,OAAO,CAAC,QAAQ,CAAC,aAAa;aAGd,gBAAgB,EAAE,MAAM;IACxC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IATrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;gBAG5C,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,EACX,aAAa,EAC3B,CAAC,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,uBAAuB,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,GACtE,SAAS,EACI,gBAAgB,EAAE,MAAM,EACvB,mBAAmB,EAAE,MAAM,EAC5C,MAAM,EAAE,oBAAoB;IAM7B,IAAW,sBAAsB,IAAI,OAAO,CAI3C;IAED,IAAW,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAEjD;IAEM,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAMjD,OAAO,CAAC,QAAQ;IA0BhB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACI,0BAA0B,CAAC,KAAK,EAAE,sBAAsB,GAAG,sBAAsB;IAoEjF,YAAY,CAAC,OAAO,EAAE,yBAAyB,GAAG,kBAAkB;CAuC3E;AAED,KAAK,kBAAkB,GACpB;IACA,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC;CAC5B,GACD;IACA,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC;CAC3C,CAAC;AAkBL;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,OAAO,OACf,oBAAoB,oBACN,MAAM,YACf,OAAO,KACd,UAAU,EAkDZ,CAAC"}
1
+ {"version":3,"file":"opSplitter.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAC;AACpF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAE5E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AAa7F,OAAO,KAAK,EACX,UAAU,EACV,oBAAoB,EACpB,sBAAsB,EACtB,MAAM,kBAAkB,CAAC;AAG1B,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAE5E;AAWD;;GAEG;AACH,qBAAa,UAAU;IAOrB,OAAO,CAAC,QAAQ,CAAC,aAAa;aAGd,gBAAgB,EAAE,MAAM;IACxC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IATrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;gBAG5C,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,EACX,aAAa,EAC3B,CAAC,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,uBAAuB,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,GACtE,SAAS,EACI,gBAAgB,EAAE,MAAM,EACvB,mBAAmB,EAAE,MAAM,EAC5C,MAAM,EAAE,oBAAoB;IAM7B,IAAW,sBAAsB,IAAI,OAAO,CAI3C;IAED,IAAW,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAEjD;IAEM,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAMjD,OAAO,CAAC,QAAQ;IA0BhB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACI,0BAA0B,CAAC,KAAK,EAAE,sBAAsB,GAAG,sBAAsB;IAoEjF,YAAY,CAAC,OAAO,EAAE,yBAAyB,GAAG,kBAAkB;CAuC3E;AAED,KAAK,kBAAkB,GACpB;IACA,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC;CAC5B,GACD;IACA,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC;CAC3C,CAAC;AAkBL;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,OAAO,OACf,oBAAoB,oBACN,MAAM,YACf,OAAO,KACd,UAAU,EAkDZ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"opSplitter.js","sourceRoot":"","sources":["../../src/opLifecycle/opSplitter.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH,kEAA6D;AAE7D,uEAKkD;AAElD,wDAA4F;AAO5F,2CAAiD;AAEjD,SAAgB,gBAAgB,CAAC,OAAkC;IAClE,OAAO,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAFD,4CAEC;AAOD,SAAS,iBAAiB,CAAC,QAAiB;IAC3C,OAAQ,QAAsC,EAAE,IAAI,KAAK,sCAAoB,CAAC,SAAS,CAAC;AACzF,CAAC;AAED;;GAEG;AACH,MAAa,UAAU;IAKtB,YACC,MAA4B,EACX,aAEL,EACI,gBAAwB,EACvB,mBAA2B,EAC5C,MAA4B;QALX,kBAAa,GAAb,aAAa,CAElB;QACI,qBAAgB,GAAhB,gBAAgB,CAAQ;QACvB,wBAAmB,GAAnB,mBAAmB,CAAQ;QAG5C,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,CAAmB,MAAM,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,GAAG,IAAA,4BAAiB,EAAC,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,IAAW,sBAAsB;QAChC,OAAO,CACN,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,iBAAiB,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,CACpF,CAAC;IACH,CAAC;IAED,IAAW,MAAM;QAChB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAEM,kBAAkB,CAAC,QAAgB;QACzC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;IACF,CAAC;IAEO,QAAQ,CACf,QAAgB,EAChB,cAA0B,EAC1B,eAA0C;QAE1C,IAAI,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACvB,GAAG,GAAG,EAAE,CAAC;YACT,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAClC,CAAC;QAED,IAAI,cAAc,CAAC,OAAO,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/C,gGAAgG;YAChG,sGAAsG;YACtG,4DAA4D;YAC5D,MAAM,IAAI,8BAAmB,CAAC,mBAAmB,EAAE;gBAClD,GAAG,IAAA,2CAAgC,EAAC,eAAe,CAAC;gBACpD,cAAc,EAAE,GAAG,CAAC,MAAM;gBAC1B,OAAO,EAAE,cAAc,CAAC,OAAO;gBAC/B,WAAW,EAAE,cAAc,CAAC,WAAW;aACvC,CAAC,CAAC;QACJ,CAAC;QAED,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACI,0BAA0B,CAAC,KAA6B;QAC9D,IAAA,iBAAM,EAAC,IAAI,CAAC,sBAAsB,EAAE,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAC9E,IAAA,iBAAM,EACL,KAAK,CAAC,kBAAkB,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EACzD,KAAK,CAAC,iCAAiC,CACvC,CAAC;QACF,IAAA,iBAAM,EACL,KAAK,CAAC,uBAAuB,KAAK,SAAS,EAC3C,KAAK,CAAC,8DAA8D,CACpE,CAAC;QACF,IAAA,iBAAM,EAAC,IAAI,CAAC,gBAAgB,KAAK,CAAC,EAAE,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACjF,IAAA,iBAAM,EACL,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,EAChD,KAAK,CAAC,4DAA4D,CAClE,CAAC;QAEF,8FAA8F;QAC9F,sGAAsG;QACtG,MAAM,CAAC,YAAY,EAAE,GAAG,cAAc,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC;QACzD,IAAA,iBAAM,EACL,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAC7D,KAAK,CAAC,sDAAsD,CAC5D,CAAC;QAEF,MAAM,UAAU,GAAG,IAAA,8BAAkB,EAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,IAAA,eAAO,EACrB,YAAY,EACZ,IAAI,CAAC,gBAAgB;QACrB,wEAAwE;QACxE,gFAAgF;QAChF,yDAAyD;QACzD,UAAU,IAAI,IAAI,CAAC,mBAAmB,CACtC,CAAC;QAEF,IAAA,iBAAM,EAAC,IAAI,CAAC,aAAa,KAAK,SAAS,EAAE,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACnF,wCAAwC;QACxC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,IAAI,CAAC,aAAa,CACjB,CAAC,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,uBAAuB,CAAC,CAAC,EAC3D,KAAK,CAAC,uBAAuB,CAC7B,CAAC;QACH,CAAC;QAED,4DAA4D;QAC5D,oDAAoD;QACpD,MAAM,SAAS,GAAG,mBAAmB,CACpC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,EACzB,KAAK,CAAC,uBAAuB,EAC7B,EAAE,KAAK,EAAE,YAAY,CAAC,QAAQ,EAAE,KAAK,EAAE,CACvC,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC;YAChC,wCAAwC;YACxC,SAAS,EAAE,wBAAwB;YACnC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM;YAC7B,WAAW,EAAE,KAAK,CAAC,kBAAkB;YACrC,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,UAAU;SACV,CAAC,CAAC;QAEH,OAAO;YACN,QAAQ,EAAE,CAAC,SAAS,EAAE,GAAG,cAAc,CAAC;YACxC,kBAAkB,EAAE,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;YACnD,uBAAuB,EAAE,KAAK,CAAC,uBAAuB;SACtD,CAAC;IACH,CAAC;IAEM,YAAY,CAAC,OAAkC;QACrD,IAAA,iBAAM,EAAC,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvF,MAAM,QAAQ,GAAqB,OAAO,CAAC,QAAQ,CAAC;QAEpD,+FAA+F;QAE/F,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAkB,CAAC;QAC5C,MAAM,cAAc,GAAG,QAAQ,CAAC,QAAQ,CAAC;QACzC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAEjD,IAAI,cAAc,CAAC,OAAO,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC;YACzD,yDAAyD;YACzD,6DAA6D;YAC7D,OAAO;gBACN,YAAY,EAAE,KAAK;aACnB,CAAC;QACH,CAAC;QAED,oEAAoE;QACpE,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAElC,wEAAwE;QACxE,oDAAoD;QACpD,MAAM,eAAe,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;QACvC,eAAe,CAAC,QAAQ;YACvB,iBAAiB,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACtE,8BAA8B;QAC9B,kEAAkE;QAClE,+GAA+G;QAC/G,mJAAmJ;QACnJ,eAAe,CAAC,IAAI,GAAI,cAAsB,CAAC,YAAY,CAAC;QAC5D,eAAe,CAAC,QAAQ,GAAG,cAAc,CAAC,gBAAgB,CAAC;QAC3D,eAAe,CAAC,WAAW,GAAG,cAAc,CAAC,mBAAmB,CAAC;QACjE,OAAO;YACN,OAAO,EAAE,eAAe;YACxB,YAAY,EAAE,IAAI;SAClB,CAAC;IACH,CAAC;CACD;AAjMD,gCAiMC;AAWD,MAAM,mBAAmB,GAAG,CAC3B,KAAiB,EACjB,uBAA+B,EAC/B,WAAgD,SAAS,EAClC,EAAE;IACzB,MAAM,OAAO,GAAqC;QACjD,IAAI,EAAE,sCAAoB,CAAC,SAAS;QACpC,QAAQ,EAAE,KAAK;KACf,CAAC;IACF,OAAO;QACN,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;QACjC,QAAQ;QACR,uBAAuB;KACvB,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACI,MAAM,OAAO,GAAG,CACtB,EAAwB,EACxB,gBAAwB,EACxB,UAAmB,KAAK,EACT,EAAE;IACjB,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAA,iBAAM,EACL,EAAE,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,CAAC,QAAQ,KAAK,IAAI,EACjD,KAAK,CAAC,uCAAuC,CAC7C,CAAC;IAEF,MAAM,aAAa,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;IACzC,MAAM,UAAU,GACf,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5E,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,MAAM,KAAK,GAAe;YACzB,OAAO;YACP,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAAC;YAC9D,WAAW,EAAE,UAAU;SACvB,CAAC;QAEF,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;YAC5B,iDAAiD;YACjD,oDAAoD;YACpD,0DAA0D;YAC1D,KAAK,CAAC,gBAAgB,GAAG,EAAE,CAAC,QAAQ,CAAC;YACrC,KAAK,CAAC,mBAAmB,GAAG,EAAE,CAAC,WAAW,CAAC;YAE3C,8BAA8B;YAC9B,kDAAkD;YAClD,yGAAyG;YACzG,kHAAkH;YAClH,6FAA6F;YAC7F,sHAAsH;YACtH,qEAAqE;YACrE,0GAA0G;YACzG,KAAa,CAAC,YAAY,GAAG,WAAW,CAAC;QAC3C,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,MAAM,IAAI,gBAAgB,CAAC;QAC3B,IAAA,iBAAM,EACL,OAAO,IAAI,UAAU,GAAG,CAAC,IAAI,MAAM,IAAI,aAAa,EACpD,KAAK,CAAC,kCAAkC,CACxC,CAAC;IACH,CAAC;IAED,IAAA,iBAAM,EACL,MAAM,IAAI,aAAa,EACvB,KAAK,CAAC,wDAAwD,CAC9D,CAAC;IACF,IAAA,iBAAM,EAAC,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC5E,OAAO,MAAM,CAAC;AACf,CAAC,CAAC;AAtDW,QAAA,OAAO,WAsDlB","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IBatchMessage } from \"@fluidframework/container-definitions/internal\";\nimport { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tDataCorruptionError,\n\tcreateChildLogger,\n\textractSafePropertiesFromMessage,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { ContainerMessageType, ContainerRuntimeChunkedOpMessage } from \"../messageTypes.js\";\n\nimport {\n\tIChunkedOp,\n\ttype OutboundBatchMessage,\n\ttype OutboundSingletonBatch,\n} from \"./definitions.js\";\nimport { estimateSocketSize } from \"./outbox.js\";\n\nexport function isChunkedMessage(message: ISequencedDocumentMessage): boolean {\n\treturn isChunkedContents(message.contents);\n}\n\ninterface IChunkedContents {\n\treadonly type: typeof ContainerMessageType.ChunkedOp;\n\treadonly contents: IChunkedOp;\n}\n\nfunction isChunkedContents(contents: unknown): contents is IChunkedContents {\n\treturn (contents as Partial<IChunkedContents>)?.type === ContainerMessageType.ChunkedOp;\n}\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: ITelemetryLoggerExt;\n\n\tconstructor(\n\t\tchunks: [string, string[]][],\n\t\tprivate readonly submitBatchFn:\n\t\t\t| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)\n\t\t\t| undefined,\n\t\tpublic readonly chunkSizeInBytes: number,\n\t\tprivate readonly maxBatchSizeInBytes: number,\n\t\tlogger: ITelemetryBaseLogger,\n\t) {\n\t\tthis.chunkMap = new Map<string, string[]>(chunks);\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpSplitter\" });\n\t}\n\n\tpublic get isBatchChunkingEnabled(): boolean {\n\t\treturn (\n\t\t\tthis.chunkSizeInBytes < Number.POSITIVE_INFINITY && this.submitBatchFn !== undefined\n\t\t);\n\t}\n\n\tpublic get chunks(): ReadonlyMap<string, string[]> {\n\t\treturn this.chunkMap;\n\t}\n\n\tpublic clearPartialChunks(clientId: string): void {\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): void {\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 * Takes a singleton batch, and splits the interior message into chunks, sending the chunks separately and\n\t * returning a new singleton batch containing the last chunk.\n\t *\n\t * A compressed batch is formed by one large op at the first position.\n\t *\n\t * If the 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 * This will ensure that the batch semantics of the original (non-compressed) batch are preserved, as the original chunked op\n\t * will be unrolled by the runtime when the first message in the batch is processed (as it is the last chunk).\n\t *\n\t * To illustrate the current functionality, if the input is `[largeOp]`, `largeOp` will be split into `[chunk1, chunk2, chunk3, chunk4]`.\n\t * `chunk1`, `chunk2` and `chunk3` will be sent individually and `[chunk4]` will be returned.\n\t *\n\t * @remarks - A side effect here is that 1 or more chunks are queued immediately for sending in next JS turn.\n\t *\n\t * @privateRemarks\n\t * This maintains support for splitting a compressed batch with multiple messages (empty placeholders after the first),\n\t * but this is only used for Unit Tests so the typing has been updated to preclude that.\n\t * That code should be moved out of this function into a test helper.\n\t *\n\t * @param batch - the compressed batch which needs to be split into chunks before being sent over the wire\n\t * @returns A batch with the last chunk in place of the original complete compressed content\n\t */\n\tpublic splitSingletonBatchMessage(batch: OutboundSingletonBatch): OutboundSingletonBatch {\n\t\tassert(this.isBatchChunkingEnabled, 0x513 /* Chunking needs to be enabled */);\n\t\tassert(\n\t\t\tbatch.contentSizeInBytes > 0 && batch.messages.length > 0,\n\t\t\t0x514 /* Batch needs to be non-empty */,\n\t\t);\n\t\tassert(\n\t\t\tbatch.referenceSequenceNumber !== undefined,\n\t\t\t0x58a /* Batch must have a reference sequence number if 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\t// first message is the large compressed op to split, and we expect restOfMessages to be empty\n\t\t// (but we keep it here to support a legacy test case, wherein it contains empty placeholder messages)\n\t\tconst [firstMessage, ...restOfMessages] = batch.messages;\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 socketSize = estimateSocketSize(batch);\n\t\tconst chunks = splitOp(\n\t\t\tfirstMessage,\n\t\t\tthis.chunkSizeInBytes,\n\t\t\t// If we estimate that the socket batch size will exceed the batch limit\n\t\t\t// we will inject an empty op to minimize the risk of the payload failing due to\n\t\t\t// the overhead from the trailing empty ops in the batch.\n\t\t\tsocketSize >= this.maxBatchSizeInBytes,\n\t\t);\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(\n\t\t\t\t[chunkToBatchMessage(chunk, batch.referenceSequenceNumber)],\n\t\t\t\tbatch.referenceSequenceNumber,\n\t\t\t);\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\tbatch.referenceSequenceNumber,\n\t\t\t{ batch: firstMessage.metadata?.batch },\n\t\t);\n\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\t// Used to be \"Chunked compressed batch\"\n\t\t\teventName: \"CompressedChunkedBatch\",\n\t\t\tlength: batch.messages.length,\n\t\t\tsizeInBytes: batch.contentSizeInBytes,\n\t\t\tchunks: chunks.length,\n\t\t\tchunkSizeInBytes: this.chunkSizeInBytes,\n\t\t\tsocketSize,\n\t\t});\n\n\t\treturn {\n\t\t\tmessages: [lastChunk, ...restOfMessages],\n\t\t\tcontentSizeInBytes: lastChunk.contents?.length ?? 0,\n\t\t\treferenceSequenceNumber: batch.referenceSequenceNumber,\n\t\t};\n\t}\n\n\tpublic processChunk(message: ISequencedDocumentMessage): ProcessChunkResult {\n\t\tassert(isChunkedContents(message.contents), 0x948 /* message not of type ChunkedOp */);\n\t\tconst contents: IChunkedContents = message.contents;\n\n\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\n\t\tconst clientId = message.clientId as string;\n\t\tconst chunkedContent = contents.contents;\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\tisFinalChunk: false,\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\t// The final/complete message will contain the data from all the chunks.\n\t\t// It will have the sequenceNumber of the last chunk\n\t\tconst completeMessage = { ...message };\n\t\tcompleteMessage.contents =\n\t\t\tserializedContent === \"\" ? undefined : JSON.parse(serializedContent);\n\t\t// back-compat with 1.x builds\n\t\t// This is only required / present for non-compressed, chunked ops\n\t\t// For compressed ops, we have op grouping enabled, and type of each op is preserved within compressed content.\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\t\tcompleteMessage.type = (chunkedContent as any).originalType;\n\t\tcompleteMessage.metadata = chunkedContent.originalMetadata;\n\t\tcompleteMessage.compression = chunkedContent.originalCompression;\n\t\treturn {\n\t\t\tmessage: completeMessage,\n\t\t\tisFinalChunk: true,\n\t\t};\n\t}\n}\n\ntype ProcessChunkResult =\n\t| {\n\t\t\treadonly isFinalChunk: false;\n\t }\n\t| {\n\t\t\treadonly isFinalChunk: true;\n\t\t\treadonly message: ISequencedDocumentMessage;\n\t };\n\nconst chunkToBatchMessage = (\n\tchunk: IChunkedOp,\n\treferenceSequenceNumber: number,\n\tmetadata: Record<string, unknown> | undefined = undefined,\n): OutboundBatchMessage => {\n\tconst payload: ContainerRuntimeChunkedOpMessage = {\n\t\ttype: ContainerMessageType.ChunkedOp,\n\t\tcontents: chunk,\n\t};\n\treturn {\n\t\tcontents: JSON.stringify(payload),\n\t\tmetadata,\n\t\treferenceSequenceNumber,\n\t};\n};\n\n/**\n * Splits an op into smaller ops (chunks), based on the size of the op and the `chunkSizeInBytes` parameter.\n *\n * The last op of the result will be bundled with empty ops in the same batch. There is a risk of the batch payload\n * exceeding the 1MB limit due to the overhead from the empty ops. If the last op is large, the risk is even higher.\n * To minimize the odds, an extra empty op can be added to the result using the `extraOp` parameter.\n *\n * @param op - the op to be split\n * @param chunkSizeInBytes - how large should the chunks be\n * @param extraOp - should an extra empty op be added to the result\n * @returns an array of chunked ops\n */\nexport const splitOp = (\n\top: OutboundBatchMessage,\n\tchunkSizeInBytes: number,\n\textraOp: boolean = false,\n): 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 chunkCount =\n\t\tMath.floor((contentLength - 1) / chunkSizeInBytes) + 1 + (extraOp ? 1 : 0);\n\tlet offset = 0;\n\tfor (let chunkId = 1; chunkId <= chunkCount; chunkId++) {\n\t\tconst chunk: IChunkedOp = {\n\t\t\tchunkId,\n\t\t\tcontents: op.contents.slice(offset, offset + chunkSizeInBytes),\n\t\t\ttotalChunks: chunkCount,\n\t\t};\n\n\t\tif (chunkId === chunkCount) {\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\n\t\t\t// back-compat with 1.x builds\n\t\t\t// 2.x builds only do chunking for compressed ops.\n\t\t\t// originalType is no longer used in such cases, as each op preserves its type within compressed payload.\n\t\t\t// But, if 1.x builds see this op, and there is no type on the message, then it will ignore this message silently.\n\t\t\t// This is really bad, as we will crash on later ops and it's very hard to debug these cases.\n\t\t\t// If we put some known type here, then we will crash on it (as 1.x does not understand compression, and thus will not\n\t\t\t// find info on the op like address of the channel to deliver the op)\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n\t\t\t(chunk as any).originalType = \"component\";\n\t\t}\n\n\t\tchunks.push(chunk);\n\t\toffset += chunkSizeInBytes;\n\t\tassert(\n\t\t\tchunkId >= chunkCount - 1 || offset <= contentLength,\n\t\t\t0x58b /* Content offset within bounds */,\n\t\t);\n\t}\n\n\tassert(\n\t\toffset >= contentLength,\n\t\t0x58c /* Content offset equal or larger than content length */,\n\t);\n\tassert(chunks.length === chunkCount, 0x5a5 /* Expected number of chunks */);\n\treturn 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 type { IBatchMessage } from \"@fluidframework/container-definitions/internal\";\nimport type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { ISequencedDocumentMessage } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tDataCorruptionError,\n\tcreateChildLogger,\n\textractSafePropertiesFromMessage,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport {\n\tContainerMessageType,\n\ttype ContainerRuntimeChunkedOpMessage,\n} from \"../messageTypes.js\";\n\nimport type {\n\tIChunkedOp,\n\tOutboundBatchMessage,\n\tOutboundSingletonBatch,\n} from \"./definitions.js\";\nimport { estimateSocketSize } from \"./outbox.js\";\n\nexport function isChunkedMessage(message: ISequencedDocumentMessage): boolean {\n\treturn isChunkedContents(message.contents);\n}\n\ninterface IChunkedContents {\n\treadonly type: typeof ContainerMessageType.ChunkedOp;\n\treadonly contents: IChunkedOp;\n}\n\nfunction isChunkedContents(contents: unknown): contents is IChunkedContents {\n\treturn (contents as Partial<IChunkedContents>)?.type === ContainerMessageType.ChunkedOp;\n}\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: ITelemetryLoggerExt;\n\n\tconstructor(\n\t\tchunks: [string, string[]][],\n\t\tprivate readonly submitBatchFn:\n\t\t\t| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)\n\t\t\t| undefined,\n\t\tpublic readonly chunkSizeInBytes: number,\n\t\tprivate readonly maxBatchSizeInBytes: number,\n\t\tlogger: ITelemetryBaseLogger,\n\t) {\n\t\tthis.chunkMap = new Map<string, string[]>(chunks);\n\t\tthis.logger = createChildLogger({ logger, namespace: \"OpSplitter\" });\n\t}\n\n\tpublic get isBatchChunkingEnabled(): boolean {\n\t\treturn (\n\t\t\tthis.chunkSizeInBytes < Number.POSITIVE_INFINITY && this.submitBatchFn !== undefined\n\t\t);\n\t}\n\n\tpublic get chunks(): ReadonlyMap<string, string[]> {\n\t\treturn this.chunkMap;\n\t}\n\n\tpublic clearPartialChunks(clientId: string): void {\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): void {\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 * Takes a singleton batch, and splits the interior message into chunks, sending the chunks separately and\n\t * returning a new singleton batch containing the last chunk.\n\t *\n\t * A compressed batch is formed by one large op at the first position.\n\t *\n\t * If the 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 * This will ensure that the batch semantics of the original (non-compressed) batch are preserved, as the original chunked op\n\t * will be unrolled by the runtime when the first message in the batch is processed (as it is the last chunk).\n\t *\n\t * To illustrate the current functionality, if the input is `[largeOp]`, `largeOp` will be split into `[chunk1, chunk2, chunk3, chunk4]`.\n\t * `chunk1`, `chunk2` and `chunk3` will be sent individually and `[chunk4]` will be returned.\n\t *\n\t * @remarks - A side effect here is that 1 or more chunks are queued immediately for sending in next JS turn.\n\t *\n\t * @privateRemarks\n\t * This maintains support for splitting a compressed batch with multiple messages (empty placeholders after the first),\n\t * but this is only used for Unit Tests so the typing has been updated to preclude that.\n\t * That code should be moved out of this function into a test helper.\n\t *\n\t * @param batch - the compressed batch which needs to be split into chunks before being sent over the wire\n\t * @returns A batch with the last chunk in place of the original complete compressed content\n\t */\n\tpublic splitSingletonBatchMessage(batch: OutboundSingletonBatch): OutboundSingletonBatch {\n\t\tassert(this.isBatchChunkingEnabled, 0x513 /* Chunking needs to be enabled */);\n\t\tassert(\n\t\t\tbatch.contentSizeInBytes > 0 && batch.messages.length > 0,\n\t\t\t0x514 /* Batch needs to be non-empty */,\n\t\t);\n\t\tassert(\n\t\t\tbatch.referenceSequenceNumber !== undefined,\n\t\t\t0x58a /* Batch must have a reference sequence number if 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\t// first message is the large compressed op to split, and we expect restOfMessages to be empty\n\t\t// (but we keep it here to support a legacy test case, wherein it contains empty placeholder messages)\n\t\tconst [firstMessage, ...restOfMessages] = batch.messages;\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 socketSize = estimateSocketSize(batch);\n\t\tconst chunks = splitOp(\n\t\t\tfirstMessage,\n\t\t\tthis.chunkSizeInBytes,\n\t\t\t// If we estimate that the socket batch size will exceed the batch limit\n\t\t\t// we will inject an empty op to minimize the risk of the payload failing due to\n\t\t\t// the overhead from the trailing empty ops in the batch.\n\t\t\tsocketSize >= this.maxBatchSizeInBytes,\n\t\t);\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(\n\t\t\t\t[chunkToBatchMessage(chunk, batch.referenceSequenceNumber)],\n\t\t\t\tbatch.referenceSequenceNumber,\n\t\t\t);\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\tbatch.referenceSequenceNumber,\n\t\t\t{ batch: firstMessage.metadata?.batch },\n\t\t);\n\n\t\tthis.logger.sendPerformanceEvent({\n\t\t\t// Used to be \"Chunked compressed batch\"\n\t\t\teventName: \"CompressedChunkedBatch\",\n\t\t\tlength: batch.messages.length,\n\t\t\tsizeInBytes: batch.contentSizeInBytes,\n\t\t\tchunks: chunks.length,\n\t\t\tchunkSizeInBytes: this.chunkSizeInBytes,\n\t\t\tsocketSize,\n\t\t});\n\n\t\treturn {\n\t\t\tmessages: [lastChunk, ...restOfMessages],\n\t\t\tcontentSizeInBytes: lastChunk.contents?.length ?? 0,\n\t\t\treferenceSequenceNumber: batch.referenceSequenceNumber,\n\t\t};\n\t}\n\n\tpublic processChunk(message: ISequencedDocumentMessage): ProcessChunkResult {\n\t\tassert(isChunkedContents(message.contents), 0x948 /* message not of type ChunkedOp */);\n\t\tconst contents: IChunkedContents = message.contents;\n\n\t\t// TODO: Verify whether this should be able to handle server-generated ops (with null clientId)\n\n\t\tconst clientId = message.clientId as string;\n\t\tconst chunkedContent = contents.contents;\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\tisFinalChunk: false,\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\t// The final/complete message will contain the data from all the chunks.\n\t\t// It will have the sequenceNumber of the last chunk\n\t\tconst completeMessage = { ...message };\n\t\tcompleteMessage.contents =\n\t\t\tserializedContent === \"\" ? undefined : JSON.parse(serializedContent);\n\t\t// back-compat with 1.x builds\n\t\t// This is only required / present for non-compressed, chunked ops\n\t\t// For compressed ops, we have op grouping enabled, and type of each op is preserved within compressed content.\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\t\tcompleteMessage.type = (chunkedContent as any).originalType;\n\t\tcompleteMessage.metadata = chunkedContent.originalMetadata;\n\t\tcompleteMessage.compression = chunkedContent.originalCompression;\n\t\treturn {\n\t\t\tmessage: completeMessage,\n\t\t\tisFinalChunk: true,\n\t\t};\n\t}\n}\n\ntype ProcessChunkResult =\n\t| {\n\t\t\treadonly isFinalChunk: false;\n\t }\n\t| {\n\t\t\treadonly isFinalChunk: true;\n\t\t\treadonly message: ISequencedDocumentMessage;\n\t };\n\nconst chunkToBatchMessage = (\n\tchunk: IChunkedOp,\n\treferenceSequenceNumber: number,\n\tmetadata: Record<string, unknown> | undefined = undefined,\n): OutboundBatchMessage => {\n\tconst payload: ContainerRuntimeChunkedOpMessage = {\n\t\ttype: ContainerMessageType.ChunkedOp,\n\t\tcontents: chunk,\n\t};\n\treturn {\n\t\tcontents: JSON.stringify(payload),\n\t\tmetadata,\n\t\treferenceSequenceNumber,\n\t};\n};\n\n/**\n * Splits an op into smaller ops (chunks), based on the size of the op and the `chunkSizeInBytes` parameter.\n *\n * The last op of the result will be bundled with empty ops in the same batch. There is a risk of the batch payload\n * exceeding the 1MB limit due to the overhead from the empty ops. If the last op is large, the risk is even higher.\n * To minimize the odds, an extra empty op can be added to the result using the `extraOp` parameter.\n *\n * @param op - the op to be split\n * @param chunkSizeInBytes - how large should the chunks be\n * @param extraOp - should an extra empty op be added to the result\n * @returns an array of chunked ops\n */\nexport const splitOp = (\n\top: OutboundBatchMessage,\n\tchunkSizeInBytes: number,\n\textraOp: boolean = false,\n): 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 chunkCount =\n\t\tMath.floor((contentLength - 1) / chunkSizeInBytes) + 1 + (extraOp ? 1 : 0);\n\tlet offset = 0;\n\tfor (let chunkId = 1; chunkId <= chunkCount; chunkId++) {\n\t\tconst chunk: IChunkedOp = {\n\t\t\tchunkId,\n\t\t\tcontents: op.contents.slice(offset, offset + chunkSizeInBytes),\n\t\t\ttotalChunks: chunkCount,\n\t\t};\n\n\t\tif (chunkId === chunkCount) {\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\n\t\t\t// back-compat with 1.x builds\n\t\t\t// 2.x builds only do chunking for compressed ops.\n\t\t\t// originalType is no longer used in such cases, as each op preserves its type within compressed payload.\n\t\t\t// But, if 1.x builds see this op, and there is no type on the message, then it will ignore this message silently.\n\t\t\t// This is really bad, as we will crash on later ops and it's very hard to debug these cases.\n\t\t\t// If we put some known type here, then we will crash on it (as 1.x does not understand compression, and thus will not\n\t\t\t// find info on the op like address of the channel to deliver the op)\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n\t\t\t(chunk as any).originalType = \"component\";\n\t\t}\n\n\t\tchunks.push(chunk);\n\t\toffset += chunkSizeInBytes;\n\t\tassert(\n\t\t\tchunkId >= chunkCount - 1 || offset <= contentLength,\n\t\t\t0x58b /* Content offset within bounds */,\n\t\t);\n\t}\n\n\tassert(\n\t\toffset >= contentLength,\n\t\t0x58c /* Content offset equal or larger than content length */,\n\t);\n\tassert(chunks.length === chunkCount, 0x5a5 /* Expected number of chunks */);\n\treturn chunks;\n};\n"]}
@@ -2,15 +2,15 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { IBatchMessage } from "@fluidframework/container-definitions/internal";
6
- import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
7
- import { ICompressionRuntimeOptions } from "../compressionDefinitions.js";
8
- import { PendingMessageResubmitData, PendingStateManager } from "../pendingStateManager.js";
9
- import { BatchSequenceNumbers } from "./batchManager.js";
10
- import { LocalBatchMessage, IBatchCheckpoint, type LocalBatch, type OutboundBatch } from "./definitions.js";
11
- import { OpCompressor } from "./opCompressor.js";
12
- import { OpGroupingManager } from "./opGroupingManager.js";
13
- import { OpSplitter } from "./opSplitter.js";
5
+ import type { IBatchMessage } from "@fluidframework/container-definitions/internal";
6
+ import type { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
7
+ import type { ICompressionRuntimeOptions } from "../compressionDefinitions.js";
8
+ import type { PendingMessageResubmitData, PendingStateManager } from "../pendingStateManager.js";
9
+ import { type BatchSequenceNumbers } from "./batchManager.js";
10
+ import type { LocalBatchMessage, IBatchCheckpoint, LocalBatch, OutboundBatch } from "./definitions.js";
11
+ import type { OpCompressor } from "./opCompressor.js";
12
+ import type { OpGroupingManager } from "./opGroupingManager.js";
13
+ import type { OpSplitter } from "./opSplitter.js";
14
14
  export interface IOutboxConfig {
15
15
  readonly compressionOptions: ICompressionRuntimeOptions;
16
16
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/outbox.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
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 { IBatchMessage } from \"@fluidframework/container-definitions/internal\";\nimport {\n\tITelemetryBaseLogger,\n\ttype ITelemetryBaseProperties,\n} from \"@fluidframework/core-interfaces\";\nimport { assert, Lazy } from \"@fluidframework/core-utils/internal\";\nimport {\n\tDataProcessingError,\n\tUsageError,\n\tcreateChildLogger,\n\ttype IFluidErrorBase,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { ICompressionRuntimeOptions } from \"../compressionDefinitions.js\";\nimport { PendingMessageResubmitData, PendingStateManager } from \"../pendingStateManager.js\";\n\nimport {\n\tBatchManager,\n\tBatchSequenceNumbers,\n\tsequenceNumbersMatch,\n\ttype BatchId,\n} from \"./batchManager.js\";\nimport {\n\tLocalBatchMessage,\n\tIBatchCheckpoint,\n\ttype OutboundBatchMessage,\n\ttype OutboundSingletonBatch,\n\ttype LocalBatch,\n\ttype OutboundBatch,\n} from \"./definitions.js\";\nimport { OpCompressor } from \"./opCompressor.js\";\nimport { OpGroupingManager } from \"./opGroupingManager.js\";\nimport { serializeOp } from \"./opSerialization.js\";\nimport { OpSplitter } from \"./opSplitter.js\";\n\nexport interface IOutboxConfig {\n\treadonly compressionOptions: ICompressionRuntimeOptions;\n\t/**\n\t * The maximum size of a batch that we can send over the wire.\n\t */\n\treadonly maxBatchSizeInBytes: number;\n\t/**\n\t * If true, maybeFlushPartialBatch will flush the batch if the reference sequence number changed\n\t * since the batch started. Otherwise, it will throw in this case (apart from reentrancy which is handled elsewhere).\n\t * Once the new throw-based flow is proved in a production environment, this option will be removed.\n\t */\n\treadonly flushPartialBatches: boolean;\n}\n\nexport interface IOutboxParameters {\n\treadonly shouldSend: () => boolean;\n\treadonly pendingStateManager: PendingStateManager;\n\treadonly submitBatchFn:\n\t\t| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)\n\t\t| undefined;\n\treadonly legacySendBatchFn: (batch: OutboundBatch) => number;\n\treadonly config: IOutboxConfig;\n\treadonly compressor: OpCompressor;\n\treadonly splitter: OpSplitter;\n\treadonly logger: ITelemetryBaseLogger;\n\treadonly groupingManager: OpGroupingManager;\n\treadonly getCurrentSequenceNumbers: () => BatchSequenceNumbers;\n\treadonly reSubmit: (message: PendingMessageResubmitData, squash: boolean) => void;\n\treadonly opReentrancy: () => boolean;\n}\n\n/**\n * Info needed to correctly resubmit a batch\n */\nexport interface BatchResubmitInfo {\n\t/**\n\t * If defined, indicates the Batch ID of the batch being resubmitted.\n\t * This must be preserved on the new batch about to be submitted so they can be correlated/deduped in case both are sent.\n\t */\n\tbatchId?: string;\n\t/**\n\t * Indicates whether or not this batch is \"staged\", meaning it should not be sent to the ordering service yet\n\t * This is important on resubmit because we may be in Staging Mode for new changes,\n\t * but resubmitting a non-staged change from before entering Staging Mode\n\t */\n\tstaged: boolean;\n}\n\n/**\n * Temporarily increase the stack limit while executing the provided action.\n * If a negative value is provided for `length`, no stack frames will be collected.\n * If Infinity is provided, all frames will be collected.\n *\n * ADO:4663 - add this to the common packages.\n *\n * @param action - action which returns an error\n * @param length - number of stack frames to collect, 50 if unspecified.\n * @returns the result of the action provided\n */\nexport function getLongStack<T>(action: () => T, length: number = 50): T {\n\t// TODO: better typing here\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment\n\tconst errorObj = Error as any;\n\tif (\n\t\t/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */\n\t\t// ?? is not logically equivalent when the first clause returns false.\n\t\t(\n\t\t\tObject.getOwnPropertyDescriptor(errorObj, \"stackTraceLimit\") ||\n\t\t\tObject.getOwnPropertyDescriptor(Object.getPrototypeOf(errorObj), \"stackTraceLimit\")\n\t\t)?.writable !== true\n\t\t/* eslint-enable @typescript-eslint/prefer-nullish-coalescing */\n\t) {\n\t\treturn action();\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\tconst originalStackTraceLimit = errorObj.stackTraceLimit;\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\terrorObj.stackTraceLimit = length;\n\t\treturn action();\n\t} finally {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\t\terrorObj.stackTraceLimit = originalStackTraceLimit;\n\t}\n}\n\n/**\n * Convert from local batch to outbound batch, including computing contentSizeInBytes.\n */\nexport function localBatchToOutboundBatch({\n\tstaged: _staged, // Peel this off the incoming batch, it's irrelevant (see Note below)\n\t...localBatch\n}: LocalBatch): OutboundBatch {\n\t// Note: the staged property might be misleading here, in case a pre-staging batch is resubmitted during staging mode.\n\t// It will be set to true, but the batch was not actually staged.\n\n\t// Shallow copy each message as we switch types\n\tconst outboundMessages = localBatch.messages.map<OutboundBatchMessage>(\n\t\t({ runtimeOp, ...message }) => ({\n\t\t\tcontents: serializeOp(runtimeOp),\n\t\t\t...message,\n\t\t}),\n\t);\n\tconst contentSizeInBytes = outboundMessages.reduce(\n\t\t(acc, message) => acc + (message.contents?.length ?? 0),\n\t\t0,\n\t);\n\n\t// Shallow copy the local batch, updating the messages to be outbound messages and adding contentSizeInBytes\n\tconst outboundBatch: OutboundBatch = {\n\t\t...localBatch,\n\t\tmessages: outboundMessages,\n\t\tcontentSizeInBytes,\n\t};\n\n\treturn outboundBatch;\n}\n\n/**\n * Estimated size of the stringification overhead for an op accumulated\n * from runtime to loader to the service.\n */\nconst opOverhead = 200;\n\n/**\n * Estimates the real size in bytes on the socket for a given batch. It assumes that\n * the envelope size (and the size of an empty op) is 200 bytes, taking into account\n * extra overhead from stringification.\n *\n * @remarks\n * Also content will be stringified, and that adds a lot of overhead due to a lot of escape characters.\n * Not taking it into account, as compression work should help there - compressed payload will be\n * initially stored as base64, and that requires only 2 extra escape characters.\n *\n * @param batch - the batch to inspect\n * @returns An estimate of the payload size in bytes which will be produced when the batch is sent over the wire\n */\nexport const estimateSocketSize = (batch: OutboundBatch): number => {\n\treturn batch.contentSizeInBytes + opOverhead * batch.messages.length;\n};\n\n/**\n * The Outbox collects messages submitted by the ContainerRuntime into a batch,\n * and then flushes the batch when requested.\n *\n * @remarks There are actually multiple independent batches (some are for a specific message type),\n * to support slight variation in semantics for each batch (e.g. support for rebasing or grouping).\n */\nexport class Outbox {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate readonly mainBatch: BatchManager;\n\tprivate readonly blobAttachBatch: BatchManager;\n\tprivate readonly idAllocationBatch: BatchManager;\n\tprivate batchRebasesToReport = 5;\n\tprivate rebasing = false;\n\n\t/**\n\t * Track the number of ops which were detected to have a mismatched\n\t * reference sequence number, in order to self-throttle the telemetry events.\n\t *\n\t * This should be removed as part of ADO:2322\n\t */\n\tprivate readonly maxMismatchedOpsToReport = 3;\n\tprivate mismatchedOpsReported = 0;\n\n\tconstructor(private readonly params: IOutboxParameters) {\n\t\tthis.logger = createChildLogger({ logger: params.logger, namespace: \"Outbox\" });\n\n\t\tthis.mainBatch = new BatchManager({ canRebase: true });\n\t\tthis.blobAttachBatch = new BatchManager({ canRebase: true });\n\t\tthis.idAllocationBatch = new BatchManager({\n\t\t\tcanRebase: false,\n\t\t\tignoreBatchId: true,\n\t\t});\n\t}\n\n\tpublic get messageCount(): number {\n\t\treturn this.mainBatch.length + this.blobAttachBatch.length + this.idAllocationBatch.length;\n\t}\n\n\tpublic get mainBatchMessageCount(): number {\n\t\treturn this.mainBatch.length;\n\t}\n\n\tpublic get blobAttachBatchMessageCount(): number {\n\t\treturn this.blobAttachBatch.length;\n\t}\n\n\tpublic get idAllocationBatchMessageCount(): number {\n\t\treturn this.idAllocationBatch.length;\n\t}\n\n\tpublic get isEmpty(): boolean {\n\t\treturn this.messageCount === 0;\n\t}\n\n\tpublic containsUserChanges(): boolean {\n\t\treturn (\n\t\t\tthis.mainBatch.containsUserChanges() || this.blobAttachBatch.containsUserChanges()\n\t\t\t// ID Allocation ops are not user changes\n\t\t);\n\t}\n\n\t/**\n\t * Detect whether batching has been interrupted by an incoming message being processed. In this case,\n\t * we will flush the accumulated messages to account for that (if allowed) and create a new batch with the new\n\t * message as the first message. If flushing partial batch is not enabled, we will throw (except for reentrant ops).\n\t * This would indicate we expected this case to be precluded by logic elsewhere.\n\t *\n\t * @remarks - To detect batch interruption, we compare both the reference sequence number\n\t * (i.e. last message processed by DeltaManager) and the client sequence number of the\n\t * last message processed by the ContainerRuntime. In the absence of op reentrancy, this\n\t * pair will remain stable during a single JS turn during which the batch is being built up.\n\t */\n\tprivate maybeFlushPartialBatch(): void {\n\t\tconst mainBatchSeqNums = this.mainBatch.sequenceNumbers;\n\t\tconst blobAttachSeqNums = this.blobAttachBatch.sequenceNumbers;\n\t\tconst idAllocSeqNums = this.idAllocationBatch.sequenceNumbers;\n\t\tassert(\n\t\t\tsequenceNumbersMatch(mainBatchSeqNums, blobAttachSeqNums) &&\n\t\t\t\tsequenceNumbersMatch(mainBatchSeqNums, idAllocSeqNums),\n\t\t\t0x58d /* Reference sequence numbers from both batches must be in sync */,\n\t\t);\n\n\t\tconst currentSequenceNumbers = this.params.getCurrentSequenceNumbers();\n\n\t\tif (\n\t\t\tsequenceNumbersMatch(mainBatchSeqNums, currentSequenceNumbers) &&\n\t\t\tsequenceNumbersMatch(blobAttachSeqNums, currentSequenceNumbers) &&\n\t\t\tsequenceNumbersMatch(idAllocSeqNums, currentSequenceNumbers)\n\t\t) {\n\t\t\t// The reference sequence numbers are stable, there is nothing to do\n\t\t\treturn;\n\t\t}\n\n\t\t// Reference and/or Client sequence number will be advancing while processing this batch,\n\t\t// so we can't use this check to detect wrongdoing. But we will still log via telemetry.\n\t\t// This is rare, and the reentrancy will be handled during Flush.\n\t\tconst expectedDueToReentrancy = this.isContextReentrant();\n\n\t\tconst errorWrapper = new Lazy(() =>\n\t\t\tgetLongStack(() =>\n\t\t\t\tDataProcessingError.create(\n\t\t\t\t\t\"Sequence numbers advanced as if ops were processed while a batch is accumulating\",\n\t\t\t\t\t\"outboxSequenceNumberCoherencyCheck\",\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t\tif (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\t// Only log error if this is truly unexpected\n\t\t\t\t\tcategory:\n\t\t\t\t\t\texpectedDueToReentrancy || this.params.config.flushPartialBatches\n\t\t\t\t\t\t\t? \"generic\"\n\t\t\t\t\t\t\t: \"error\",\n\t\t\t\t\teventName: \"ReferenceSequenceNumberMismatch\",\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\texpectedDueToReentrancy,\n\t\t\t\t\t\tmainReferenceSequenceNumber: mainBatchSeqNums.referenceSequenceNumber,\n\t\t\t\t\t\tmainClientSequenceNumber: mainBatchSeqNums.clientSequenceNumber,\n\t\t\t\t\t\tblobAttachReferenceSequenceNumber: blobAttachSeqNums.referenceSequenceNumber,\n\t\t\t\t\t\tblobAttachClientSequenceNumber: blobAttachSeqNums.clientSequenceNumber,\n\t\t\t\t\t\tcurrentReferenceSequenceNumber: currentSequenceNumbers.referenceSequenceNumber,\n\t\t\t\t\t\tcurrentClientSequenceNumber: currentSequenceNumbers.clientSequenceNumber,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\terrorWrapper.value,\n\t\t\t);\n\t\t}\n\n\t\t// If we're configured to flush partial batches, do that now and return (don't throw)\n\t\tif (this.params.config.flushPartialBatches) {\n\t\t\tthis.flushAll();\n\t\t\treturn;\n\t\t}\n\n\t\t// If we are in a reentrant context, we know this can happen without causing any harm.\n\t\tif (expectedDueToReentrancy) {\n\t\t\treturn;\n\t\t}\n\n\t\tthrow errorWrapper.value;\n\t}\n\n\tpublic submit(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.mainBatch, message);\n\t}\n\n\tpublic submitBlobAttach(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.blobAttachBatch, message);\n\t}\n\n\tpublic submitIdAllocation(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.idAllocationBatch, message);\n\t}\n\n\tprivate addMessageToBatchManager(\n\t\tbatchManager: BatchManager,\n\t\tmessage: LocalBatchMessage,\n\t): void {\n\t\tbatchManager.push(\n\t\t\tmessage,\n\t\t\tthis.isContextReentrant(),\n\t\t\tthis.params.getCurrentSequenceNumbers().clientSequenceNumber,\n\t\t);\n\t}\n\n\t/**\n\t * Flush all the batches to the ordering service.\n\t * This method is expected to be called at the end of a batch.\n\t *\n\t * @throws If called from a reentrant context, or if the batch being flushed is too large.\n\t * @param resubmitInfo - Key information when flushing a resubmitted batch. Undefined means this is not resubmit.\n\t */\n\tpublic flush(resubmitInfo?: BatchResubmitInfo): void {\n\t\tassert(\n\t\t\t!this.isContextReentrant(),\n\t\t\t0xb7b /* Flushing must not happen while incoming changes are being processed */,\n\t\t);\n\t\tthis.flushAll(resubmitInfo);\n\t}\n\n\tprivate flushAll(resubmitInfo?: BatchResubmitInfo): void {\n\t\tconst allBatchesEmpty =\n\t\t\tthis.idAllocationBatch.empty && this.blobAttachBatch.empty && this.mainBatch.empty;\n\t\tif (allBatchesEmpty) {\n\t\t\t// If we're resubmitting with a batchId and all batches are empty, we need to flush an empty batch.\n\t\t\t// Note that we currently resubmit one batch at a time, so on resubmit, 1 of the 2 batches will *always* be empty.\n\t\t\t// It's theoretically possible that we don't *need* to resubmit this empty batch, and in those cases, it'll safely be ignored\n\t\t\t// by the rest of the system, including remote clients.\n\t\t\t// In some cases we *must* resubmit the empty batch (to match up with a non-empty version tracked locally by a container fork), so we do it always.\n\t\t\tif (resubmitInfo?.batchId !== undefined) {\n\t\t\t\tthis.flushEmptyBatch(resubmitInfo.batchId, resubmitInfo.staged);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Don't use resubmittingBatchId for idAllocationBatch.\n\t\t// ID Allocation messages are not directly resubmitted so don't pass the resubmitInfo\n\t\tthis.flushInternal({\n\t\t\tbatchManager: this.idAllocationBatch,\n\t\t\t// Note: For now, we will never stage ID Allocation messages.\n\t\t\t// They won't contain personal info and no harm in extra allocations in case of discarding the staged changes\n\t\t});\n\t\tthis.flushInternal({\n\t\t\tbatchManager: this.blobAttachBatch,\n\t\t\tdisableGroupedBatching: true,\n\t\t\tresubmitInfo,\n\t\t});\n\t\tthis.flushInternal({\n\t\t\tbatchManager: this.mainBatch,\n\t\t\tresubmitInfo,\n\t\t});\n\t}\n\n\tprivate flushEmptyBatch(\n\t\tresubmittingBatchId: BatchId,\n\t\tresubmittingStagedBatch: boolean,\n\t): void {\n\t\tconst referenceSequenceNumber =\n\t\t\tthis.params.getCurrentSequenceNumbers().referenceSequenceNumber;\n\t\tassert(\n\t\t\treferenceSequenceNumber !== undefined,\n\t\t\t0xa01 /* reference sequence number should be defined */,\n\t\t);\n\t\tconst { outboundBatch, placeholderMessage } =\n\t\t\tthis.params.groupingManager.createEmptyGroupedBatch(\n\t\t\t\tresubmittingBatchId,\n\t\t\t\treferenceSequenceNumber,\n\t\t\t);\n\t\tlet clientSequenceNumber: number | undefined;\n\t\tif (this.params.shouldSend() && !resubmittingStagedBatch) {\n\t\t\tclientSequenceNumber = this.sendBatch(outboundBatch);\n\t\t}\n\n\t\t// Push the empty batch placeholder to the PendingStateManager\n\t\tthis.params.pendingStateManager.onFlushEmptyBatch(\n\t\t\tplaceholderMessage,\n\t\t\tclientSequenceNumber,\n\t\t\tresubmittingStagedBatch,\n\t\t);\n\t\treturn;\n\t}\n\n\tprivate flushInternal(params: {\n\t\tbatchManager: BatchManager;\n\t\tdisableGroupedBatching?: boolean;\n\t\tresubmitInfo?: BatchResubmitInfo; // undefined if not resubmitting\n\t}): void {\n\t\tconst { batchManager, disableGroupedBatching = false, resubmitInfo } = params;\n\t\tif (batchManager.empty) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rawBatch = batchManager.popBatch(resubmitInfo?.batchId);\n\n\t\t// On resubmit we use the original batch's staged state, so these should match as well.\n\t\tconst staged = rawBatch.staged === true;\n\t\tassert(\n\t\t\tresubmitInfo === undefined || resubmitInfo.staged === staged,\n\t\t\t0xba3 /* Mismatch in staged state tracking */,\n\t\t);\n\n\t\tconst groupingEnabled =\n\t\t\t!disableGroupedBatching && this.params.groupingManager.groupedBatchingEnabled();\n\t\tif (\n\t\t\tbatchManager.options.canRebase &&\n\t\t\trawBatch.hasReentrantOps === true &&\n\t\t\tgroupingEnabled\n\t\t) {\n\t\t\tassert(!this.rebasing, 0x6fa /* A rebased batch should never have reentrant ops */);\n\t\t\t// If a batch contains reentrant ops (ops created as a result from processing another op)\n\t\t\t// it needs to be rebased so that we can ensure consistent reference sequence numbers\n\t\t\t// and eventual consistency at the DDS level.\n\t\t\t// Note: Since this is happening in the same turn the ops were originally created with,\n\t\t\t// and they haven't gone to PendingStateManager yet, we can just let them respect\n\t\t\t// ContainerRuntime.inStagingMode. So we do not plumb local 'staged' variable through here.\n\t\t\tthis.rebase(rawBatch, batchManager);\n\t\t\treturn;\n\t\t}\n\n\t\tlet clientSequenceNumber: number | undefined;\n\t\t// Did we disconnect? (i.e. is shouldSend false?)\n\t\t// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.\n\t\t// Because flush() is a task that executes async (on clean stack), we can get here in disconnected state.\n\t\tif (this.params.shouldSend() && !staged) {\n\t\t\tconst virtualizedBatch = this.virtualizeBatch(rawBatch, groupingEnabled);\n\n\t\t\tclientSequenceNumber = this.sendBatch(virtualizedBatch);\n\t\t\tassert(\n\t\t\t\tclientSequenceNumber === undefined || clientSequenceNumber >= 0,\n\t\t\t\t0x9d2 /* unexpected negative clientSequenceNumber (empty batch should yield undefined) */,\n\t\t\t);\n\t\t}\n\n\t\tthis.params.pendingStateManager.onFlushBatch(\n\t\t\trawBatch.messages,\n\t\t\tclientSequenceNumber,\n\t\t\tstaged,\n\t\t\tbatchManager.options.ignoreBatchId,\n\t\t);\n\t}\n\n\t/**\n\t * Rebases a batch. All the ops in the batch are resubmitted to the runtime and\n\t * they will end up back in the same batch manager they were flushed from and subsequently flushed.\n\t *\n\t * @param rawBatch - the batch to be rebased\n\t */\n\tprivate rebase(rawBatch: LocalBatch, batchManager: BatchManager): void {\n\t\tassert(!this.rebasing, 0x6fb /* Reentrancy */);\n\t\tassert(batchManager.options.canRebase, 0x9a7 /* BatchManager does not support rebase */);\n\n\t\tthis.rebasing = true;\n\t\tconst squash = false;\n\t\tfor (const message of rawBatch.messages) {\n\t\t\tthis.params.reSubmit(\n\t\t\t\t{\n\t\t\t\t\truntimeOp: message.runtimeOp,\n\t\t\t\t\tlocalOpMetadata: message.localOpMetadata,\n\t\t\t\t\topMetadata: message.metadata,\n\t\t\t\t},\n\t\t\t\tsquash,\n\t\t\t);\n\t\t}\n\n\t\tif (this.batchRebasesToReport > 0) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: \"BatchRebase\",\n\t\t\t\t\tlength: rawBatch.messages.length,\n\t\t\t\t\treferenceSequenceNumber: rawBatch.referenceSequenceNumber,\n\t\t\t\t},\n\t\t\t\tnew UsageError(\"BatchRebase\"),\n\t\t\t);\n\t\t\tthis.batchRebasesToReport--;\n\t\t}\n\n\t\tthis.flushInternal({ batchManager });\n\t\tthis.rebasing = false;\n\t}\n\n\tprivate isContextReentrant(): boolean {\n\t\treturn this.params.opReentrancy() && !this.rebasing;\n\t}\n\n\t/**\n\t * As necessary and enabled, groups / compresses / chunks the given batch.\n\t *\n\t * @remarks - If chunking happens, a side effect here is that 1 or more chunks are queued immediately for sending in next JS turn.\n\t *\n\t * @param localBatch - Local Batch to be virtualized - i.e. transformed into an Outbound Batch\n\t * @param groupingEnabled - If true, Grouped batching is enabled.\n\t * @returns One of the following:\n\t * - (A) The original batch (Based on what's enabled)\n\t * - (B) A grouped batch (it's a singleton batch)\n\t * - (C) A compressed singleton batch\n\t * - (D) A singleton batch containing the last chunk.\n\t */\n\tprivate virtualizeBatch(localBatch: LocalBatch, groupingEnabled: boolean): OutboundBatch {\n\t\t// Shallow copy the local batch, updating the messages to be outbound messages\n\t\tconst originalBatch = localBatchToOutboundBatch(localBatch);\n\n\t\tconst originalOrGroupedBatch = groupingEnabled\n\t\t\t? this.params.groupingManager.groupBatch(originalBatch)\n\t\t\t: originalBatch;\n\n\t\tif (originalOrGroupedBatch.messages.length !== 1) {\n\t\t\t// Compression requires a single message, so return early otherwise.\n\t\t\treturn originalOrGroupedBatch;\n\t\t}\n\n\t\t// Regardless of whether we grouped or not, we now have a batch with a single message.\n\t\t// Now proceed to compress/chunk it if necessary.\n\t\tconst singletonBatch = originalOrGroupedBatch as OutboundSingletonBatch;\n\n\t\tif (\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes >\n\t\t\t\tsingletonBatch.contentSizeInBytes ||\n\t\t\tthis.params.submitBatchFn === undefined\n\t\t) {\n\t\t\t// Nothing to do if compression is disabled, unnecessary or unsupported.\n\t\t\treturn singletonBatch;\n\t\t}\n\n\t\tconst compressedBatch = this.params.compressor.compressBatch(singletonBatch);\n\n\t\tif (this.params.splitter.isBatchChunkingEnabled) {\n\t\t\treturn compressedBatch.contentSizeInBytes <= this.params.splitter.chunkSizeInBytes\n\t\t\t\t? compressedBatch\n\t\t\t\t: this.params.splitter.splitSingletonBatchMessage(compressedBatch);\n\t\t}\n\n\t\t// We want to distinguish this \"BatchTooLarge\" case from the generic \"BatchTooLarge\" case in sendBatch\n\t\tif (compressedBatch.contentSizeInBytes >= this.params.config.maxBatchSizeInBytes) {\n\t\t\tthrow this.makeBatchTooLargeError(compressedBatch, \"CompressionInsufficient\", {\n\t\t\t\tuncompressedSizeInBytes: singletonBatch.contentSizeInBytes,\n\t\t\t});\n\t\t}\n\n\t\treturn compressedBatch;\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 clientSequenceNumber of the start of the batch, or undefined if nothing was sent\n\t */\n\tprivate sendBatch(batch: OutboundBatch): number | undefined {\n\t\tconst length = batch.messages.length;\n\t\tif (length === 0) {\n\t\t\treturn undefined; // Nothing submitted\n\t\t}\n\n\t\tconst socketSize = estimateSocketSize(batch);\n\t\tif (socketSize >= this.params.config.maxBatchSizeInBytes) {\n\t\t\tthrow this.makeBatchTooLargeError(batch, \"CannotSend\");\n\t\t}\n\n\t\tlet clientSequenceNumber: number;\n\t\tif (this.params.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\tassert(\n\t\t\t\tbatch.messages[0].compression === undefined,\n\t\t\t\t0x5a6 /* Compression should not have happened if the loader does not support it */,\n\t\t\t);\n\n\t\t\tclientSequenceNumber = this.params.legacySendBatchFn(batch);\n\t\t} else {\n\t\t\tassert(batch.referenceSequenceNumber !== undefined, 0x58e /* Batch must not be empty */);\n\t\t\tclientSequenceNumber = this.params.submitBatchFn(\n\t\t\t\tbatch.messages.map<IBatchMessage>((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\treferenceSequenceNumber: message.referenceSequenceNumber,\n\t\t\t\t})),\n\t\t\t\tbatch.referenceSequenceNumber,\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 makeBatchTooLargeError(\n\t\tbatch: OutboundBatch,\n\t\tcodepath: string,\n\t\tmoreDetails?: ITelemetryBaseProperties,\n\t): IFluidErrorBase {\n\t\treturn DataProcessingError.create(\n\t\t\t\"BatchTooLarge\",\n\t\t\tcodepath,\n\t\t\t/* sequencedMessage */ undefined,\n\t\t\t{\n\t\t\t\terrorDetails: {\n\t\t\t\t\topCount: batch.messages.length,\n\t\t\t\t\tcontentSizeInBytes: batch.contentSizeInBytes,\n\t\t\t\t\tsocketSize: estimateSocketSize(batch),\n\t\t\t\t\tmaxBatchSizeInBytes: this.params.config.maxBatchSizeInBytes,\n\t\t\t\t\tgroupedBatchingEnabled: this.params.groupingManager.groupedBatchingEnabled(),\n\t\t\t\t\tcompressionOptions: JSON.stringify(this.params.config.compressionOptions),\n\t\t\t\t\tchunkingEnabled: this.params.splitter.isBatchChunkingEnabled,\n\t\t\t\t\tchunkSizeInBytes: this.params.splitter.chunkSizeInBytes,\n\t\t\t\t\t...moreDetails,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Gets a checkpoint object per batch that facilitates iterating over the batch messages when rolling back.\n\t */\n\tpublic getBatchCheckpoints(): {\n\t\tmainBatch: IBatchCheckpoint;\n\t\tidAllocationBatch: IBatchCheckpoint;\n\t\tblobAttachBatch: IBatchCheckpoint;\n\t} {\n\t\t// This variable is declared with a specific type so that we have a standard import of the IBatchCheckpoint type.\n\t\t// When the type is inferred, the generated .d.ts uses a dynamic import which doesn't resolve.\n\t\tconst mainBatch: IBatchCheckpoint = this.mainBatch.checkpoint();\n\t\treturn {\n\t\t\tmainBatch,\n\t\t\tidAllocationBatch: this.idAllocationBatch.checkpoint(),\n\t\t\tblobAttachBatch: this.blobAttachBatch.checkpoint(),\n\t\t};\n\t}\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 type { IBatchMessage } from \"@fluidframework/container-definitions/internal\";\nimport type {\n\tITelemetryBaseLogger,\n\tITelemetryBaseProperties,\n} from \"@fluidframework/core-interfaces\";\nimport { assert, Lazy } from \"@fluidframework/core-utils/internal\";\nimport {\n\tDataProcessingError,\n\tUsageError,\n\tcreateChildLogger,\n\ttype IFluidErrorBase,\n\ttype ITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { ICompressionRuntimeOptions } from \"../compressionDefinitions.js\";\nimport type {\n\tPendingMessageResubmitData,\n\tPendingStateManager,\n} from \"../pendingStateManager.js\";\n\nimport {\n\tBatchManager,\n\ttype BatchSequenceNumbers,\n\tsequenceNumbersMatch,\n\ttype BatchId,\n} from \"./batchManager.js\";\nimport type {\n\tLocalBatchMessage,\n\tIBatchCheckpoint,\n\tOutboundBatchMessage,\n\tOutboundSingletonBatch,\n\tLocalBatch,\n\tOutboundBatch,\n} from \"./definitions.js\";\nimport type { OpCompressor } from \"./opCompressor.js\";\nimport type { OpGroupingManager } from \"./opGroupingManager.js\";\nimport { serializeOp } from \"./opSerialization.js\";\nimport type { OpSplitter } from \"./opSplitter.js\";\n\nexport interface IOutboxConfig {\n\treadonly compressionOptions: ICompressionRuntimeOptions;\n\t/**\n\t * The maximum size of a batch that we can send over the wire.\n\t */\n\treadonly maxBatchSizeInBytes: number;\n\t/**\n\t * If true, maybeFlushPartialBatch will flush the batch if the reference sequence number changed\n\t * since the batch started. Otherwise, it will throw in this case (apart from reentrancy which is handled elsewhere).\n\t * Once the new throw-based flow is proved in a production environment, this option will be removed.\n\t */\n\treadonly flushPartialBatches: boolean;\n}\n\nexport interface IOutboxParameters {\n\treadonly shouldSend: () => boolean;\n\treadonly pendingStateManager: PendingStateManager;\n\treadonly submitBatchFn:\n\t\t| ((batch: IBatchMessage[], referenceSequenceNumber?: number) => number)\n\t\t| undefined;\n\treadonly legacySendBatchFn: (batch: OutboundBatch) => number;\n\treadonly config: IOutboxConfig;\n\treadonly compressor: OpCompressor;\n\treadonly splitter: OpSplitter;\n\treadonly logger: ITelemetryBaseLogger;\n\treadonly groupingManager: OpGroupingManager;\n\treadonly getCurrentSequenceNumbers: () => BatchSequenceNumbers;\n\treadonly reSubmit: (message: PendingMessageResubmitData, squash: boolean) => void;\n\treadonly opReentrancy: () => boolean;\n}\n\n/**\n * Info needed to correctly resubmit a batch\n */\nexport interface BatchResubmitInfo {\n\t/**\n\t * If defined, indicates the Batch ID of the batch being resubmitted.\n\t * This must be preserved on the new batch about to be submitted so they can be correlated/deduped in case both are sent.\n\t */\n\tbatchId?: string;\n\t/**\n\t * Indicates whether or not this batch is \"staged\", meaning it should not be sent to the ordering service yet\n\t * This is important on resubmit because we may be in Staging Mode for new changes,\n\t * but resubmitting a non-staged change from before entering Staging Mode\n\t */\n\tstaged: boolean;\n}\n\n/**\n * Temporarily increase the stack limit while executing the provided action.\n * If a negative value is provided for `length`, no stack frames will be collected.\n * If Infinity is provided, all frames will be collected.\n *\n * ADO:4663 - add this to the common packages.\n *\n * @param action - action which returns an error\n * @param length - number of stack frames to collect, 50 if unspecified.\n * @returns the result of the action provided\n */\nexport function getLongStack<T>(action: () => T, length: number = 50): T {\n\t// TODO: better typing here\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment\n\tconst errorObj = Error as any;\n\tif (\n\t\t/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */\n\t\t// ?? is not logically equivalent when the first clause returns false.\n\t\t(\n\t\t\tObject.getOwnPropertyDescriptor(errorObj, \"stackTraceLimit\") ||\n\t\t\tObject.getOwnPropertyDescriptor(Object.getPrototypeOf(errorObj), \"stackTraceLimit\")\n\t\t)?.writable !== true\n\t\t/* eslint-enable @typescript-eslint/prefer-nullish-coalescing */\n\t) {\n\t\treturn action();\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\tconst originalStackTraceLimit = errorObj.stackTraceLimit;\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\terrorObj.stackTraceLimit = length;\n\t\treturn action();\n\t} finally {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment\n\t\terrorObj.stackTraceLimit = originalStackTraceLimit;\n\t}\n}\n\n/**\n * Convert from local batch to outbound batch, including computing contentSizeInBytes.\n */\nexport function localBatchToOutboundBatch({\n\tstaged: _staged, // Peel this off the incoming batch, it's irrelevant (see Note below)\n\t...localBatch\n}: LocalBatch): OutboundBatch {\n\t// Note: the staged property might be misleading here, in case a pre-staging batch is resubmitted during staging mode.\n\t// It will be set to true, but the batch was not actually staged.\n\n\t// Shallow copy each message as we switch types\n\tconst outboundMessages = localBatch.messages.map<OutboundBatchMessage>(\n\t\t({ runtimeOp, ...message }) => ({\n\t\t\tcontents: serializeOp(runtimeOp),\n\t\t\t...message,\n\t\t}),\n\t);\n\tconst contentSizeInBytes = outboundMessages.reduce(\n\t\t(acc, message) => acc + (message.contents?.length ?? 0),\n\t\t0,\n\t);\n\n\t// Shallow copy the local batch, updating the messages to be outbound messages and adding contentSizeInBytes\n\tconst outboundBatch: OutboundBatch = {\n\t\t...localBatch,\n\t\tmessages: outboundMessages,\n\t\tcontentSizeInBytes,\n\t};\n\n\treturn outboundBatch;\n}\n\n/**\n * Estimated size of the stringification overhead for an op accumulated\n * from runtime to loader to the service.\n */\nconst opOverhead = 200;\n\n/**\n * Estimates the real size in bytes on the socket for a given batch. It assumes that\n * the envelope size (and the size of an empty op) is 200 bytes, taking into account\n * extra overhead from stringification.\n *\n * @remarks\n * Also content will be stringified, and that adds a lot of overhead due to a lot of escape characters.\n * Not taking it into account, as compression work should help there - compressed payload will be\n * initially stored as base64, and that requires only 2 extra escape characters.\n *\n * @param batch - the batch to inspect\n * @returns An estimate of the payload size in bytes which will be produced when the batch is sent over the wire\n */\nexport const estimateSocketSize = (batch: OutboundBatch): number => {\n\treturn batch.contentSizeInBytes + opOverhead * batch.messages.length;\n};\n\n/**\n * The Outbox collects messages submitted by the ContainerRuntime into a batch,\n * and then flushes the batch when requested.\n *\n * @remarks There are actually multiple independent batches (some are for a specific message type),\n * to support slight variation in semantics for each batch (e.g. support for rebasing or grouping).\n */\nexport class Outbox {\n\tprivate readonly logger: ITelemetryLoggerExt;\n\tprivate readonly mainBatch: BatchManager;\n\tprivate readonly blobAttachBatch: BatchManager;\n\tprivate readonly idAllocationBatch: BatchManager;\n\tprivate batchRebasesToReport = 5;\n\tprivate rebasing = false;\n\n\t/**\n\t * Track the number of ops which were detected to have a mismatched\n\t * reference sequence number, in order to self-throttle the telemetry events.\n\t *\n\t * This should be removed as part of ADO:2322\n\t */\n\tprivate readonly maxMismatchedOpsToReport = 3;\n\tprivate mismatchedOpsReported = 0;\n\n\tconstructor(private readonly params: IOutboxParameters) {\n\t\tthis.logger = createChildLogger({ logger: params.logger, namespace: \"Outbox\" });\n\n\t\tthis.mainBatch = new BatchManager({ canRebase: true });\n\t\tthis.blobAttachBatch = new BatchManager({ canRebase: true });\n\t\tthis.idAllocationBatch = new BatchManager({\n\t\t\tcanRebase: false,\n\t\t\tignoreBatchId: true,\n\t\t});\n\t}\n\n\tpublic get messageCount(): number {\n\t\treturn this.mainBatch.length + this.blobAttachBatch.length + this.idAllocationBatch.length;\n\t}\n\n\tpublic get mainBatchMessageCount(): number {\n\t\treturn this.mainBatch.length;\n\t}\n\n\tpublic get blobAttachBatchMessageCount(): number {\n\t\treturn this.blobAttachBatch.length;\n\t}\n\n\tpublic get idAllocationBatchMessageCount(): number {\n\t\treturn this.idAllocationBatch.length;\n\t}\n\n\tpublic get isEmpty(): boolean {\n\t\treturn this.messageCount === 0;\n\t}\n\n\tpublic containsUserChanges(): boolean {\n\t\treturn (\n\t\t\tthis.mainBatch.containsUserChanges() || this.blobAttachBatch.containsUserChanges()\n\t\t\t// ID Allocation ops are not user changes\n\t\t);\n\t}\n\n\t/**\n\t * Detect whether batching has been interrupted by an incoming message being processed. In this case,\n\t * we will flush the accumulated messages to account for that (if allowed) and create a new batch with the new\n\t * message as the first message. If flushing partial batch is not enabled, we will throw (except for reentrant ops).\n\t * This would indicate we expected this case to be precluded by logic elsewhere.\n\t *\n\t * @remarks - To detect batch interruption, we compare both the reference sequence number\n\t * (i.e. last message processed by DeltaManager) and the client sequence number of the\n\t * last message processed by the ContainerRuntime. In the absence of op reentrancy, this\n\t * pair will remain stable during a single JS turn during which the batch is being built up.\n\t */\n\tprivate maybeFlushPartialBatch(): void {\n\t\tconst mainBatchSeqNums = this.mainBatch.sequenceNumbers;\n\t\tconst blobAttachSeqNums = this.blobAttachBatch.sequenceNumbers;\n\t\tconst idAllocSeqNums = this.idAllocationBatch.sequenceNumbers;\n\t\tassert(\n\t\t\tsequenceNumbersMatch(mainBatchSeqNums, blobAttachSeqNums) &&\n\t\t\t\tsequenceNumbersMatch(mainBatchSeqNums, idAllocSeqNums),\n\t\t\t0x58d /* Reference sequence numbers from both batches must be in sync */,\n\t\t);\n\n\t\tconst currentSequenceNumbers = this.params.getCurrentSequenceNumbers();\n\n\t\tif (\n\t\t\tsequenceNumbersMatch(mainBatchSeqNums, currentSequenceNumbers) &&\n\t\t\tsequenceNumbersMatch(blobAttachSeqNums, currentSequenceNumbers) &&\n\t\t\tsequenceNumbersMatch(idAllocSeqNums, currentSequenceNumbers)\n\t\t) {\n\t\t\t// The reference sequence numbers are stable, there is nothing to do\n\t\t\treturn;\n\t\t}\n\n\t\t// Reference and/or Client sequence number will be advancing while processing this batch,\n\t\t// so we can't use this check to detect wrongdoing. But we will still log via telemetry.\n\t\t// This is rare, and the reentrancy will be handled during Flush.\n\t\tconst expectedDueToReentrancy = this.isContextReentrant();\n\n\t\tconst errorWrapper = new Lazy(() =>\n\t\t\tgetLongStack(() =>\n\t\t\t\tDataProcessingError.create(\n\t\t\t\t\t\"Sequence numbers advanced as if ops were processed while a batch is accumulating\",\n\t\t\t\t\t\"outboxSequenceNumberCoherencyCheck\",\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t\tif (++this.mismatchedOpsReported <= this.maxMismatchedOpsToReport) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\t// Only log error if this is truly unexpected\n\t\t\t\t\tcategory:\n\t\t\t\t\t\texpectedDueToReentrancy || this.params.config.flushPartialBatches\n\t\t\t\t\t\t\t? \"generic\"\n\t\t\t\t\t\t\t: \"error\",\n\t\t\t\t\teventName: \"ReferenceSequenceNumberMismatch\",\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\texpectedDueToReentrancy,\n\t\t\t\t\t\tmainReferenceSequenceNumber: mainBatchSeqNums.referenceSequenceNumber,\n\t\t\t\t\t\tmainClientSequenceNumber: mainBatchSeqNums.clientSequenceNumber,\n\t\t\t\t\t\tblobAttachReferenceSequenceNumber: blobAttachSeqNums.referenceSequenceNumber,\n\t\t\t\t\t\tblobAttachClientSequenceNumber: blobAttachSeqNums.clientSequenceNumber,\n\t\t\t\t\t\tcurrentReferenceSequenceNumber: currentSequenceNumbers.referenceSequenceNumber,\n\t\t\t\t\t\tcurrentClientSequenceNumber: currentSequenceNumbers.clientSequenceNumber,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\terrorWrapper.value,\n\t\t\t);\n\t\t}\n\n\t\t// If we're configured to flush partial batches, do that now and return (don't throw)\n\t\tif (this.params.config.flushPartialBatches) {\n\t\t\tthis.flushAll();\n\t\t\treturn;\n\t\t}\n\n\t\t// If we are in a reentrant context, we know this can happen without causing any harm.\n\t\tif (expectedDueToReentrancy) {\n\t\t\treturn;\n\t\t}\n\n\t\tthrow errorWrapper.value;\n\t}\n\n\tpublic submit(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.mainBatch, message);\n\t}\n\n\tpublic submitBlobAttach(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.blobAttachBatch, message);\n\t}\n\n\tpublic submitIdAllocation(message: LocalBatchMessage): void {\n\t\tthis.maybeFlushPartialBatch();\n\n\t\tthis.addMessageToBatchManager(this.idAllocationBatch, message);\n\t}\n\n\tprivate addMessageToBatchManager(\n\t\tbatchManager: BatchManager,\n\t\tmessage: LocalBatchMessage,\n\t): void {\n\t\tbatchManager.push(\n\t\t\tmessage,\n\t\t\tthis.isContextReentrant(),\n\t\t\tthis.params.getCurrentSequenceNumbers().clientSequenceNumber,\n\t\t);\n\t}\n\n\t/**\n\t * Flush all the batches to the ordering service.\n\t * This method is expected to be called at the end of a batch.\n\t *\n\t * @throws If called from a reentrant context, or if the batch being flushed is too large.\n\t * @param resubmitInfo - Key information when flushing a resubmitted batch. Undefined means this is not resubmit.\n\t */\n\tpublic flush(resubmitInfo?: BatchResubmitInfo): void {\n\t\tassert(\n\t\t\t!this.isContextReentrant(),\n\t\t\t0xb7b /* Flushing must not happen while incoming changes are being processed */,\n\t\t);\n\t\tthis.flushAll(resubmitInfo);\n\t}\n\n\tprivate flushAll(resubmitInfo?: BatchResubmitInfo): void {\n\t\tconst allBatchesEmpty =\n\t\t\tthis.idAllocationBatch.empty && this.blobAttachBatch.empty && this.mainBatch.empty;\n\t\tif (allBatchesEmpty) {\n\t\t\t// If we're resubmitting with a batchId and all batches are empty, we need to flush an empty batch.\n\t\t\t// Note that we currently resubmit one batch at a time, so on resubmit, 1 of the 2 batches will *always* be empty.\n\t\t\t// It's theoretically possible that we don't *need* to resubmit this empty batch, and in those cases, it'll safely be ignored\n\t\t\t// by the rest of the system, including remote clients.\n\t\t\t// In some cases we *must* resubmit the empty batch (to match up with a non-empty version tracked locally by a container fork), so we do it always.\n\t\t\tif (resubmitInfo?.batchId !== undefined) {\n\t\t\t\tthis.flushEmptyBatch(resubmitInfo.batchId, resubmitInfo.staged);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Don't use resubmittingBatchId for idAllocationBatch.\n\t\t// ID Allocation messages are not directly resubmitted so don't pass the resubmitInfo\n\t\tthis.flushInternal({\n\t\t\tbatchManager: this.idAllocationBatch,\n\t\t\t// Note: For now, we will never stage ID Allocation messages.\n\t\t\t// They won't contain personal info and no harm in extra allocations in case of discarding the staged changes\n\t\t});\n\t\tthis.flushInternal({\n\t\t\tbatchManager: this.blobAttachBatch,\n\t\t\tdisableGroupedBatching: true,\n\t\t\tresubmitInfo,\n\t\t});\n\t\tthis.flushInternal({\n\t\t\tbatchManager: this.mainBatch,\n\t\t\tresubmitInfo,\n\t\t});\n\t}\n\n\tprivate flushEmptyBatch(\n\t\tresubmittingBatchId: BatchId,\n\t\tresubmittingStagedBatch: boolean,\n\t): void {\n\t\tconst referenceSequenceNumber =\n\t\t\tthis.params.getCurrentSequenceNumbers().referenceSequenceNumber;\n\t\tassert(\n\t\t\treferenceSequenceNumber !== undefined,\n\t\t\t0xa01 /* reference sequence number should be defined */,\n\t\t);\n\t\tconst { outboundBatch, placeholderMessage } =\n\t\t\tthis.params.groupingManager.createEmptyGroupedBatch(\n\t\t\t\tresubmittingBatchId,\n\t\t\t\treferenceSequenceNumber,\n\t\t\t);\n\t\tlet clientSequenceNumber: number | undefined;\n\t\tif (this.params.shouldSend() && !resubmittingStagedBatch) {\n\t\t\tclientSequenceNumber = this.sendBatch(outboundBatch);\n\t\t}\n\n\t\t// Push the empty batch placeholder to the PendingStateManager\n\t\tthis.params.pendingStateManager.onFlushEmptyBatch(\n\t\t\tplaceholderMessage,\n\t\t\tclientSequenceNumber,\n\t\t\tresubmittingStagedBatch,\n\t\t);\n\t\treturn;\n\t}\n\n\tprivate flushInternal(params: {\n\t\tbatchManager: BatchManager;\n\t\tdisableGroupedBatching?: boolean;\n\t\tresubmitInfo?: BatchResubmitInfo; // undefined if not resubmitting\n\t}): void {\n\t\tconst { batchManager, disableGroupedBatching = false, resubmitInfo } = params;\n\t\tif (batchManager.empty) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rawBatch = batchManager.popBatch(resubmitInfo?.batchId);\n\n\t\t// On resubmit we use the original batch's staged state, so these should match as well.\n\t\tconst staged = rawBatch.staged === true;\n\t\tassert(\n\t\t\tresubmitInfo === undefined || resubmitInfo.staged === staged,\n\t\t\t0xba3 /* Mismatch in staged state tracking */,\n\t\t);\n\n\t\tconst groupingEnabled =\n\t\t\t!disableGroupedBatching && this.params.groupingManager.groupedBatchingEnabled();\n\t\tif (\n\t\t\tbatchManager.options.canRebase &&\n\t\t\trawBatch.hasReentrantOps === true &&\n\t\t\tgroupingEnabled\n\t\t) {\n\t\t\tassert(!this.rebasing, 0x6fa /* A rebased batch should never have reentrant ops */);\n\t\t\t// If a batch contains reentrant ops (ops created as a result from processing another op)\n\t\t\t// it needs to be rebased so that we can ensure consistent reference sequence numbers\n\t\t\t// and eventual consistency at the DDS level.\n\t\t\t// Note: Since this is happening in the same turn the ops were originally created with,\n\t\t\t// and they haven't gone to PendingStateManager yet, we can just let them respect\n\t\t\t// ContainerRuntime.inStagingMode. So we do not plumb local 'staged' variable through here.\n\t\t\tthis.rebase(rawBatch, batchManager);\n\t\t\treturn;\n\t\t}\n\n\t\tlet clientSequenceNumber: number | undefined;\n\t\t// Did we disconnect? (i.e. is shouldSend false?)\n\t\t// If so, do nothing, as pending state manager will resubmit it correctly on reconnect.\n\t\t// Because flush() is a task that executes async (on clean stack), we can get here in disconnected state.\n\t\tif (this.params.shouldSend() && !staged) {\n\t\t\tconst virtualizedBatch = this.virtualizeBatch(rawBatch, groupingEnabled);\n\n\t\t\tclientSequenceNumber = this.sendBatch(virtualizedBatch);\n\t\t\tassert(\n\t\t\t\tclientSequenceNumber === undefined || clientSequenceNumber >= 0,\n\t\t\t\t0x9d2 /* unexpected negative clientSequenceNumber (empty batch should yield undefined) */,\n\t\t\t);\n\t\t}\n\n\t\tthis.params.pendingStateManager.onFlushBatch(\n\t\t\trawBatch.messages,\n\t\t\tclientSequenceNumber,\n\t\t\tstaged,\n\t\t\tbatchManager.options.ignoreBatchId,\n\t\t);\n\t}\n\n\t/**\n\t * Rebases a batch. All the ops in the batch are resubmitted to the runtime and\n\t * they will end up back in the same batch manager they were flushed from and subsequently flushed.\n\t *\n\t * @param rawBatch - the batch to be rebased\n\t */\n\tprivate rebase(rawBatch: LocalBatch, batchManager: BatchManager): void {\n\t\tassert(!this.rebasing, 0x6fb /* Reentrancy */);\n\t\tassert(batchManager.options.canRebase, 0x9a7 /* BatchManager does not support rebase */);\n\n\t\tthis.rebasing = true;\n\t\tconst squash = false;\n\t\tfor (const message of rawBatch.messages) {\n\t\t\tthis.params.reSubmit(\n\t\t\t\t{\n\t\t\t\t\truntimeOp: message.runtimeOp,\n\t\t\t\t\tlocalOpMetadata: message.localOpMetadata,\n\t\t\t\t\topMetadata: message.metadata,\n\t\t\t\t},\n\t\t\t\tsquash,\n\t\t\t);\n\t\t}\n\n\t\tif (this.batchRebasesToReport > 0) {\n\t\t\tthis.logger.sendTelemetryEvent(\n\t\t\t\t{\n\t\t\t\t\teventName: \"BatchRebase\",\n\t\t\t\t\tlength: rawBatch.messages.length,\n\t\t\t\t\treferenceSequenceNumber: rawBatch.referenceSequenceNumber,\n\t\t\t\t},\n\t\t\t\tnew UsageError(\"BatchRebase\"),\n\t\t\t);\n\t\t\tthis.batchRebasesToReport--;\n\t\t}\n\n\t\tthis.flushInternal({ batchManager });\n\t\tthis.rebasing = false;\n\t}\n\n\tprivate isContextReentrant(): boolean {\n\t\treturn this.params.opReentrancy() && !this.rebasing;\n\t}\n\n\t/**\n\t * As necessary and enabled, groups / compresses / chunks the given batch.\n\t *\n\t * @remarks - If chunking happens, a side effect here is that 1 or more chunks are queued immediately for sending in next JS turn.\n\t *\n\t * @param localBatch - Local Batch to be virtualized - i.e. transformed into an Outbound Batch\n\t * @param groupingEnabled - If true, Grouped batching is enabled.\n\t * @returns One of the following:\n\t * - (A) The original batch (Based on what's enabled)\n\t * - (B) A grouped batch (it's a singleton batch)\n\t * - (C) A compressed singleton batch\n\t * - (D) A singleton batch containing the last chunk.\n\t */\n\tprivate virtualizeBatch(localBatch: LocalBatch, groupingEnabled: boolean): OutboundBatch {\n\t\t// Shallow copy the local batch, updating the messages to be outbound messages\n\t\tconst originalBatch = localBatchToOutboundBatch(localBatch);\n\n\t\tconst originalOrGroupedBatch = groupingEnabled\n\t\t\t? this.params.groupingManager.groupBatch(originalBatch)\n\t\t\t: originalBatch;\n\n\t\tif (originalOrGroupedBatch.messages.length !== 1) {\n\t\t\t// Compression requires a single message, so return early otherwise.\n\t\t\treturn originalOrGroupedBatch;\n\t\t}\n\n\t\t// Regardless of whether we grouped or not, we now have a batch with a single message.\n\t\t// Now proceed to compress/chunk it if necessary.\n\t\tconst singletonBatch = originalOrGroupedBatch as OutboundSingletonBatch;\n\n\t\tif (\n\t\t\tthis.params.config.compressionOptions.minimumBatchSizeInBytes >\n\t\t\t\tsingletonBatch.contentSizeInBytes ||\n\t\t\tthis.params.submitBatchFn === undefined\n\t\t) {\n\t\t\t// Nothing to do if compression is disabled, unnecessary or unsupported.\n\t\t\treturn singletonBatch;\n\t\t}\n\n\t\tconst compressedBatch = this.params.compressor.compressBatch(singletonBatch);\n\n\t\tif (this.params.splitter.isBatchChunkingEnabled) {\n\t\t\treturn compressedBatch.contentSizeInBytes <= this.params.splitter.chunkSizeInBytes\n\t\t\t\t? compressedBatch\n\t\t\t\t: this.params.splitter.splitSingletonBatchMessage(compressedBatch);\n\t\t}\n\n\t\t// We want to distinguish this \"BatchTooLarge\" case from the generic \"BatchTooLarge\" case in sendBatch\n\t\tif (compressedBatch.contentSizeInBytes >= this.params.config.maxBatchSizeInBytes) {\n\t\t\tthrow this.makeBatchTooLargeError(compressedBatch, \"CompressionInsufficient\", {\n\t\t\t\tuncompressedSizeInBytes: singletonBatch.contentSizeInBytes,\n\t\t\t});\n\t\t}\n\n\t\treturn compressedBatch;\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 clientSequenceNumber of the start of the batch, or undefined if nothing was sent\n\t */\n\tprivate sendBatch(batch: OutboundBatch): number | undefined {\n\t\tconst length = batch.messages.length;\n\t\tif (length === 0) {\n\t\t\treturn undefined; // Nothing submitted\n\t\t}\n\n\t\tconst socketSize = estimateSocketSize(batch);\n\t\tif (socketSize >= this.params.config.maxBatchSizeInBytes) {\n\t\t\tthrow this.makeBatchTooLargeError(batch, \"CannotSend\");\n\t\t}\n\n\t\tlet clientSequenceNumber: number;\n\t\tif (this.params.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\tassert(\n\t\t\t\tbatch.messages[0].compression === undefined,\n\t\t\t\t0x5a6 /* Compression should not have happened if the loader does not support it */,\n\t\t\t);\n\n\t\t\tclientSequenceNumber = this.params.legacySendBatchFn(batch);\n\t\t} else {\n\t\t\tassert(batch.referenceSequenceNumber !== undefined, 0x58e /* Batch must not be empty */);\n\t\t\tclientSequenceNumber = this.params.submitBatchFn(\n\t\t\t\tbatch.messages.map<IBatchMessage>((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\treferenceSequenceNumber: message.referenceSequenceNumber,\n\t\t\t\t})),\n\t\t\t\tbatch.referenceSequenceNumber,\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 makeBatchTooLargeError(\n\t\tbatch: OutboundBatch,\n\t\tcodepath: string,\n\t\tmoreDetails?: ITelemetryBaseProperties,\n\t): IFluidErrorBase {\n\t\treturn DataProcessingError.create(\n\t\t\t\"BatchTooLarge\",\n\t\t\tcodepath,\n\t\t\t/* sequencedMessage */ undefined,\n\t\t\t{\n\t\t\t\terrorDetails: {\n\t\t\t\t\topCount: batch.messages.length,\n\t\t\t\t\tcontentSizeInBytes: batch.contentSizeInBytes,\n\t\t\t\t\tsocketSize: estimateSocketSize(batch),\n\t\t\t\t\tmaxBatchSizeInBytes: this.params.config.maxBatchSizeInBytes,\n\t\t\t\t\tgroupedBatchingEnabled: this.params.groupingManager.groupedBatchingEnabled(),\n\t\t\t\t\tcompressionOptions: JSON.stringify(this.params.config.compressionOptions),\n\t\t\t\t\tchunkingEnabled: this.params.splitter.isBatchChunkingEnabled,\n\t\t\t\t\tchunkSizeInBytes: this.params.splitter.chunkSizeInBytes,\n\t\t\t\t\t...moreDetails,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t}\n\n\t/**\n\t * Gets a checkpoint object per batch that facilitates iterating over the batch messages when rolling back.\n\t */\n\tpublic getBatchCheckpoints(): {\n\t\tmainBatch: IBatchCheckpoint;\n\t\tidAllocationBatch: IBatchCheckpoint;\n\t\tblobAttachBatch: IBatchCheckpoint;\n\t} {\n\t\t// This variable is declared with a specific type so that we have a standard import of the IBatchCheckpoint type.\n\t\t// When the type is inferred, the generated .d.ts uses a dynamic import which doesn't resolve.\n\t\tconst mainBatch: IBatchCheckpoint = this.mainBatch.checkpoint();\n\t\treturn {\n\t\t\tmainBatch,\n\t\t\tidAllocationBatch: this.idAllocationBatch.checkpoint(),\n\t\t\tblobAttachBatch: this.blobAttachBatch.checkpoint(),\n\t\t};\n\t}\n}\n"]}
@@ -2,11 +2,11 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
5
+ import { type ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
6
6
  import { type InboundSequencedContainerRuntimeMessage } from "../messageTypes.js";
7
- import { OpDecompressor } from "./opDecompressor.js";
8
- import { OpGroupingManager } from "./opGroupingManager.js";
9
- import { OpSplitter } from "./opSplitter.js";
7
+ import type { OpDecompressor } from "./opDecompressor.js";
8
+ import { type OpGroupingManager } from "./opGroupingManager.js";
9
+ import { type OpSplitter } from "./opSplitter.js";
10
10
  /**
11
11
  * Info about the batch we learn when we process the first message
12
12
  */
@@ -1 +1 @@
1
- {"version":3,"file":"remoteMessageProcessor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAEN,yBAAyB,EACzB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EAGN,KAAK,uCAAuC,EAC5C,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAkB,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAoB,MAAM,iBAAiB,CAAC;AAC/D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,yBAAyB,CAAC;CAC/C;AAED;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAC7B;IACA,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,uCAAuC,EAAE,CAAC;IACpD,UAAU,EAAE,cAAc,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;CACrB,GACD;IACA,IAAI,EAAE,sBAAsB,CAAC;IAC7B,UAAU,EAAE,cAAc,CAAC;IAC3B,WAAW,EAAE,uCAAuC,CAAC;IACrD,MAAM,CAAC,EAAE,KAAK,CAAC;CACd,GACD;IACA,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,uCAAuC,CAAC;IACrD,MAAM,CAAC,EAAE,KAAK,CAAC;CACd,CAAC;AAWL;;;;;GAKG;AACH,qBAAa,sBAAsB;IAIjC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IALnC,OAAO,CAAC,eAAe,CAAkB;gBAGvB,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,cAAc,EAC9B,iBAAiB,EAAE,iBAAiB;IAGtD,IAAW,eAAe,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAE1D;IAEM,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAItD;;;;;;;;;;;;;;;;;;OAkBG;IACI,OAAO,CACb,iBAAiB,EAAE,yBAAyB,EAC5C,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GACvC,oBAAoB,GAAG,SAAS;IA0DnC;;;OAGG;IACH,OAAO,CAAC,6BAA6B;CAkDrC;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,yBAAyB,EAClC,aAAa,GAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAe,GAClD,OAAO,CAuBT"}
1
+ {"version":3,"file":"remoteMessageProcessor.d.ts","sourceRoot":"","sources":["../../src/opLifecycle/remoteMessageProcessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAEN,KAAK,yBAAyB,EAC9B,MAAM,6CAA6C,CAAC;AAErD,OAAO,EAGN,KAAK,uCAAuC,EAC5C,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,KAAK,iBAAiB,EAAkB,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,KAAK,UAAU,EAAoB,MAAM,iBAAiB,CAAC;AACpE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,yBAAyB,CAAC;CAC/C;AAED;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAC7B;IACA,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,uCAAuC,EAAE,CAAC;IACpD,UAAU,EAAE,cAAc,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;CACrB,GACD;IACA,IAAI,EAAE,sBAAsB,CAAC;IAC7B,UAAU,EAAE,cAAc,CAAC;IAC3B,WAAW,EAAE,uCAAuC,CAAC;IACrD,MAAM,CAAC,EAAE,KAAK,CAAC;CACd,GACD;IACA,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,uCAAuC,CAAC;IACrD,MAAM,CAAC,EAAE,KAAK,CAAC;CACd,CAAC;AAWL;;;;;GAKG;AACH,qBAAa,sBAAsB;IAIjC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IALnC,OAAO,CAAC,eAAe,CAAkB;gBAGvB,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,cAAc,EAC9B,iBAAiB,EAAE,iBAAiB;IAGtD,IAAW,eAAe,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAE1D;IAEM,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAItD;;;;;;;;;;;;;;;;;;OAkBG;IACI,OAAO,CACb,iBAAiB,EAAE,yBAAyB,EAC5C,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GACvC,oBAAoB,GAAG,SAAS;IA0DnC;;;OAGG;IACH,OAAO,CAAC,6BAA6B;CAkDrC;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,yBAAyB,EAClC,aAAa,GAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAe,GAClD,OAAO,CAuBT"}