@fluidframework/container-runtime 2.0.0-rc.1.0.6 → 2.0.0-rc.2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (687) hide show
  1. package/{.eslintrc.js → .eslintrc.cjs} +5 -5
  2. package/{.mocharc.js → .mocharc.cjs} +1 -1
  3. package/CHANGELOG.md +54 -0
  4. package/README.md +45 -0
  5. package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
  6. package/api-extractor-lint.json +1 -1
  7. package/api-extractor.json +1 -1
  8. package/api-report/container-runtime.api.md +63 -29
  9. package/dist/batchTracker.d.ts +1 -2
  10. package/dist/batchTracker.d.ts.map +1 -1
  11. package/dist/batchTracker.js.map +1 -1
  12. package/dist/blobManager.js.map +1 -1
  13. package/{lib/dataStores.d.mts → dist/channelCollection.d.ts} +94 -27
  14. package/dist/channelCollection.d.ts.map +1 -0
  15. package/dist/{dataStores.js → channelCollection.js} +359 -84
  16. package/dist/channelCollection.js.map +1 -0
  17. package/dist/connectionTelemetry.d.ts +11 -1
  18. package/dist/connectionTelemetry.d.ts.map +1 -1
  19. package/dist/connectionTelemetry.js +42 -4
  20. package/dist/connectionTelemetry.js.map +1 -1
  21. package/dist/container-runtime-alpha.d.ts +93 -39
  22. package/dist/container-runtime-beta.d.ts +27 -9
  23. package/dist/container-runtime-public.d.ts +27 -9
  24. package/dist/container-runtime-untrimmed.d.ts +118 -39
  25. package/dist/containerHandleContext.d.ts +1 -1
  26. package/dist/containerHandleContext.d.ts.map +1 -1
  27. package/dist/containerHandleContext.js.map +1 -1
  28. package/dist/containerRuntime.d.ts +74 -54
  29. package/dist/containerRuntime.d.ts.map +1 -1
  30. package/dist/containerRuntime.js +534 -410
  31. package/dist/containerRuntime.js.map +1 -1
  32. package/dist/dataStore.d.ts +2 -3
  33. package/dist/dataStore.d.ts.map +1 -1
  34. package/dist/dataStore.js +12 -11
  35. package/dist/dataStore.js.map +1 -1
  36. package/dist/dataStoreContext.d.ts +34 -29
  37. package/dist/dataStoreContext.d.ts.map +1 -1
  38. package/dist/dataStoreContext.js +157 -133
  39. package/dist/dataStoreContext.js.map +1 -1
  40. package/dist/dataStoreContexts.d.ts +1 -1
  41. package/dist/dataStoreContexts.d.ts.map +1 -1
  42. package/dist/dataStoreContexts.js.map +1 -1
  43. package/dist/deltaManagerSummarizerProxy.d.ts +29 -4
  44. package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
  45. package/dist/deltaManagerSummarizerProxy.js +91 -5
  46. package/dist/deltaManagerSummarizerProxy.js.map +1 -1
  47. package/dist/gc/garbageCollection.d.ts +5 -4
  48. package/dist/gc/garbageCollection.d.ts.map +1 -1
  49. package/dist/gc/garbageCollection.js +64 -53
  50. package/dist/gc/garbageCollection.js.map +1 -1
  51. package/dist/gc/gcConfigs.d.ts +2 -2
  52. package/dist/gc/gcConfigs.d.ts.map +1 -1
  53. package/dist/gc/gcConfigs.js +21 -21
  54. package/dist/gc/gcConfigs.js.map +1 -1
  55. package/dist/gc/gcDefinitions.d.ts +10 -3
  56. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  57. package/dist/gc/gcDefinitions.js.map +1 -1
  58. package/dist/gc/gcHelpers.d.ts +2 -2
  59. package/dist/gc/gcHelpers.d.ts.map +1 -1
  60. package/dist/gc/gcHelpers.js.map +1 -1
  61. package/dist/gc/gcReferenceGraphAlgorithm.d.ts +1 -1
  62. package/dist/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -1
  63. package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
  64. package/dist/gc/gcSummaryStateTracker.d.ts +4 -4
  65. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
  66. package/dist/gc/gcSummaryStateTracker.js +5 -5
  67. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  68. package/dist/gc/gcTelemetry.d.ts +6 -7
  69. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  70. package/dist/gc/gcTelemetry.js +17 -17
  71. package/dist/gc/gcTelemetry.js.map +1 -1
  72. package/dist/gc/gcUnreferencedStateTracker.d.ts +1 -1
  73. package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
  74. package/dist/gc/gcUnreferencedStateTracker.js +10 -10
  75. package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
  76. package/dist/gc/index.d.ts +8 -8
  77. package/dist/gc/index.d.ts.map +1 -1
  78. package/dist/gc/index.js +39 -39
  79. package/dist/gc/index.js.map +1 -1
  80. package/dist/index.d.ts +8 -20
  81. package/dist/index.d.ts.map +1 -1
  82. package/dist/index.js +28 -40
  83. package/dist/index.js.map +1 -1
  84. package/dist/messageTypes.d.ts +4 -4
  85. package/dist/messageTypes.d.ts.map +1 -1
  86. package/dist/messageTypes.js.map +1 -1
  87. package/dist/opLifecycle/batchManager.d.ts +2 -2
  88. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  89. package/dist/opLifecycle/batchManager.js.map +1 -1
  90. package/dist/opLifecycle/definitions.d.ts +2 -2
  91. package/dist/opLifecycle/definitions.d.ts.map +1 -1
  92. package/dist/opLifecycle/definitions.js.map +1 -1
  93. package/dist/opLifecycle/index.d.ts +8 -8
  94. package/dist/opLifecycle/index.d.ts.map +1 -1
  95. package/dist/opLifecycle/index.js +18 -18
  96. package/dist/opLifecycle/index.js.map +1 -1
  97. package/dist/opLifecycle/opCompressor.d.ts +1 -1
  98. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  99. package/dist/opLifecycle/opCompressor.js +4 -4
  100. package/dist/opLifecycle/opCompressor.js.map +1 -1
  101. package/dist/opLifecycle/opDecompressor.d.ts +1 -1
  102. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  103. package/dist/opLifecycle/opDecompressor.js +3 -3
  104. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  105. package/dist/opLifecycle/opGroupingManager.d.ts +1 -1
  106. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  107. package/dist/opLifecycle/opGroupingManager.js +1 -10
  108. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  109. package/dist/opLifecycle/opSplitter.d.ts +1 -1
  110. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  111. package/dist/opLifecycle/opSplitter.js +5 -5
  112. package/dist/opLifecycle/opSplitter.js.map +1 -1
  113. package/dist/opLifecycle/outbox.d.ts +7 -7
  114. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  115. package/dist/opLifecycle/outbox.js +20 -12
  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 +2 -2
  120. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  121. package/dist/package.json +3 -0
  122. package/dist/packageVersion.d.ts +1 -1
  123. package/dist/packageVersion.js +1 -1
  124. package/dist/packageVersion.js.map +1 -1
  125. package/dist/pendingStateManager.d.ts +2 -1
  126. package/dist/pendingStateManager.d.ts.map +1 -1
  127. package/dist/pendingStateManager.js +18 -10
  128. package/dist/pendingStateManager.js.map +1 -1
  129. package/dist/scheduleManager.d.ts +1 -2
  130. package/dist/scheduleManager.d.ts.map +1 -1
  131. package/dist/scheduleManager.js +5 -5
  132. package/dist/scheduleManager.js.map +1 -1
  133. package/dist/summary/index.d.ts +12 -12
  134. package/dist/summary/index.d.ts.map +1 -1
  135. package/dist/summary/index.js +43 -43
  136. package/dist/summary/index.js.map +1 -1
  137. package/dist/summary/orderedClientElection.js +8 -8
  138. package/dist/summary/orderedClientElection.js.map +1 -1
  139. package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -1
  140. package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
  141. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
  142. package/dist/summary/runningSummarizer.d.ts +11 -10
  143. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  144. package/dist/summary/runningSummarizer.js +114 -81
  145. package/dist/summary/runningSummarizer.js.map +1 -1
  146. package/dist/summary/summarizer.d.ts +4 -4
  147. package/dist/summary/summarizer.d.ts.map +1 -1
  148. package/dist/summary/summarizer.js +6 -6
  149. package/dist/summary/summarizer.js.map +1 -1
  150. package/dist/summary/summarizerClientElection.d.ts +2 -2
  151. package/dist/summary/summarizerClientElection.d.ts.map +1 -1
  152. package/dist/summary/summarizerClientElection.js.map +1 -1
  153. package/dist/summary/summarizerHeuristics.d.ts +3 -3
  154. package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
  155. package/dist/summary/summarizerHeuristics.js.map +1 -1
  156. package/dist/summary/summarizerNode/index.d.ts +3 -3
  157. package/dist/summary/summarizerNode/index.d.ts.map +1 -1
  158. package/dist/summary/summarizerNode/index.js +4 -4
  159. package/dist/summary/summarizerNode/index.js.map +1 -1
  160. package/dist/summary/summarizerNode/summarizerNode.d.ts +17 -7
  161. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  162. package/dist/summary/summarizerNode/summarizerNode.js +45 -57
  163. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  164. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +10 -19
  165. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  166. package/dist/summary/summarizerNode/summarizerNodeUtils.js +1 -21
  167. package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  168. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +5 -6
  169. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  170. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +16 -16
  171. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  172. package/dist/summary/summarizerTypes.d.ts +10 -21
  173. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  174. package/dist/summary/summarizerTypes.js.map +1 -1
  175. package/dist/summary/summaryFormat.d.ts +15 -2
  176. package/dist/summary/summaryFormat.d.ts.map +1 -1
  177. package/dist/summary/summaryFormat.js.map +1 -1
  178. package/dist/summary/summaryGenerator.d.ts +6 -5
  179. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  180. package/dist/summary/summaryGenerator.js +10 -1
  181. package/dist/summary/summaryGenerator.js.map +1 -1
  182. package/dist/summary/summaryManager.d.ts +5 -6
  183. package/dist/summary/summaryManager.d.ts.map +1 -1
  184. package/dist/summary/summaryManager.js +4 -5
  185. package/dist/summary/summaryManager.js.map +1 -1
  186. package/dist/tsdoc-metadata.json +1 -1
  187. package/lib/{batchTracker.d.mts → batchTracker.d.ts} +2 -3
  188. package/lib/batchTracker.d.ts.map +1 -0
  189. package/lib/{batchTracker.mjs → batchTracker.js} +1 -1
  190. package/lib/batchTracker.js.map +1 -0
  191. package/lib/{blobManager.d.mts → blobManager.d.ts} +1 -1
  192. package/lib/blobManager.d.ts.map +1 -0
  193. package/lib/{blobManager.mjs → blobManager.js} +1 -1
  194. package/lib/blobManager.js.map +1 -0
  195. package/{dist/dataStores.d.ts → lib/channelCollection.d.ts} +94 -27
  196. package/lib/channelCollection.d.ts.map +1 -0
  197. package/lib/{dataStores.mjs → channelCollection.js} +345 -73
  198. package/lib/channelCollection.js.map +1 -0
  199. package/lib/{connectionTelemetry.d.mts → connectionTelemetry.d.ts} +12 -2
  200. package/lib/connectionTelemetry.d.ts.map +1 -0
  201. package/lib/{connectionTelemetry.mjs → connectionTelemetry.js} +43 -5
  202. package/lib/connectionTelemetry.js.map +1 -0
  203. package/lib/{container-runtime-alpha.d.mts → container-runtime-alpha.d.ts} +93 -39
  204. package/lib/{container-runtime-public.d.mts → container-runtime-beta.d.ts} +27 -9
  205. package/lib/{container-runtime-beta.d.mts → container-runtime-public.d.ts} +27 -9
  206. package/lib/{container-runtime-untrimmed.d.mts → container-runtime-untrimmed.d.ts} +118 -39
  207. package/lib/{containerHandleContext.d.mts → containerHandleContext.d.ts} +2 -2
  208. package/lib/containerHandleContext.d.ts.map +1 -0
  209. package/lib/{containerHandleContext.mjs → containerHandleContext.js} +1 -1
  210. package/lib/containerHandleContext.js.map +1 -0
  211. package/lib/{containerRuntime.d.mts → containerRuntime.d.ts} +79 -55
  212. package/lib/containerRuntime.d.ts.map +1 -0
  213. package/lib/{containerRuntime.mjs → containerRuntime.js} +453 -331
  214. package/lib/containerRuntime.js.map +1 -0
  215. package/lib/{dataStore.d.mts → dataStore.d.ts} +3 -4
  216. package/lib/dataStore.d.ts.map +1 -0
  217. package/lib/{dataStore.mjs → dataStore.js} +13 -12
  218. package/lib/dataStore.js.map +1 -0
  219. package/lib/{dataStoreContext.d.mts → dataStoreContext.d.ts} +35 -30
  220. package/lib/dataStoreContext.d.ts.map +1 -0
  221. package/lib/{dataStoreContext.mjs → dataStoreContext.js} +146 -122
  222. package/lib/dataStoreContext.js.map +1 -0
  223. package/lib/{dataStoreContexts.d.mts → dataStoreContexts.d.ts} +2 -2
  224. package/lib/dataStoreContexts.d.ts.map +1 -0
  225. package/lib/{dataStoreContexts.mjs → dataStoreContexts.js} +1 -1
  226. package/lib/dataStoreContexts.js.map +1 -0
  227. package/lib/{dataStoreRegistry.d.mts → dataStoreRegistry.d.ts} +1 -1
  228. package/lib/dataStoreRegistry.d.ts.map +1 -0
  229. package/lib/{dataStoreRegistry.mjs → dataStoreRegistry.js} +5 -1
  230. package/lib/dataStoreRegistry.js.map +1 -0
  231. package/{dist/deltaManagerProxyBase.d.ts → lib/deltaManagerSummarizerProxy.d.ts} +16 -7
  232. package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -0
  233. package/lib/deltaManagerSummarizerProxy.js +124 -0
  234. package/lib/deltaManagerSummarizerProxy.js.map +1 -0
  235. package/lib/{deltaScheduler.d.mts → deltaScheduler.d.ts} +1 -1
  236. package/lib/deltaScheduler.d.ts.map +1 -0
  237. package/lib/{deltaScheduler.mjs → deltaScheduler.js} +1 -1
  238. package/lib/deltaScheduler.js.map +1 -0
  239. package/lib/{error.d.mts → error.d.ts} +1 -1
  240. package/lib/error.d.ts.map +1 -0
  241. package/lib/{error.mjs → error.js} +1 -1
  242. package/lib/error.js.map +1 -0
  243. package/lib/gc/{garbageCollection.d.mts → garbageCollection.d.ts} +6 -5
  244. package/lib/gc/garbageCollection.d.ts.map +1 -0
  245. package/lib/gc/{garbageCollection.mjs → garbageCollection.js} +25 -14
  246. package/lib/gc/garbageCollection.js.map +1 -0
  247. package/lib/gc/{gcConfigs.d.mts → gcConfigs.d.ts} +3 -3
  248. package/lib/gc/gcConfigs.d.ts.map +1 -0
  249. package/lib/gc/{gcConfigs.mjs → gcConfigs.js} +3 -3
  250. package/lib/gc/gcConfigs.js.map +1 -0
  251. package/lib/gc/{gcDefinitions.d.mts → gcDefinitions.d.ts} +11 -4
  252. package/lib/gc/gcDefinitions.d.ts.map +1 -0
  253. package/lib/gc/{gcDefinitions.mjs → gcDefinitions.js} +1 -1
  254. package/lib/gc/gcDefinitions.js.map +1 -0
  255. package/lib/gc/{gcHelpers.d.mts → gcHelpers.d.ts} +3 -3
  256. package/lib/gc/{gcHelpers.d.mts.map → gcHelpers.d.ts.map} +1 -1
  257. package/lib/gc/{gcHelpers.mjs → gcHelpers.js} +1 -1
  258. package/lib/gc/gcHelpers.js.map +1 -0
  259. package/lib/gc/{gcReferenceGraphAlgorithm.d.mts → gcReferenceGraphAlgorithm.d.ts} +2 -2
  260. package/lib/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -0
  261. package/lib/gc/{gcReferenceGraphAlgorithm.mjs → gcReferenceGraphAlgorithm.js} +1 -1
  262. package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -0
  263. package/lib/gc/{gcSummaryDefinitions.d.mts → gcSummaryDefinitions.d.ts} +1 -1
  264. package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -0
  265. package/lib/gc/{gcSummaryDefinitions.mjs → gcSummaryDefinitions.js} +1 -1
  266. package/lib/gc/gcSummaryDefinitions.js.map +1 -0
  267. package/lib/gc/{gcSummaryStateTracker.d.mts → gcSummaryStateTracker.d.ts} +5 -5
  268. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -0
  269. package/lib/gc/{gcSummaryStateTracker.mjs → gcSummaryStateTracker.js} +4 -4
  270. package/lib/gc/gcSummaryStateTracker.js.map +1 -0
  271. package/lib/gc/{gcTelemetry.d.mts → gcTelemetry.d.ts} +7 -8
  272. package/lib/gc/gcTelemetry.d.ts.map +1 -0
  273. package/lib/gc/{gcTelemetry.mjs → gcTelemetry.js} +2 -2
  274. package/lib/gc/gcTelemetry.js.map +1 -0
  275. package/lib/gc/{gcUnreferencedStateTracker.d.mts → gcUnreferencedStateTracker.d.ts} +2 -2
  276. package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
  277. package/lib/gc/{gcUnreferencedStateTracker.mjs → gcUnreferencedStateTracker.js} +2 -2
  278. package/lib/gc/gcUnreferencedStateTracker.js.map +1 -0
  279. package/lib/gc/{index.d.mts → index.d.ts} +9 -9
  280. package/lib/gc/index.d.ts.map +1 -0
  281. package/lib/gc/{index.mjs → index.js} +8 -8
  282. package/lib/gc/index.js.map +1 -0
  283. package/lib/{index.d.mts → index.d.ts} +9 -21
  284. package/lib/index.d.ts.map +1 -0
  285. package/lib/index.js +12 -0
  286. package/lib/index.js.map +1 -0
  287. package/lib/{messageTypes.d.mts → messageTypes.d.ts} +5 -5
  288. package/lib/messageTypes.d.ts.map +1 -0
  289. package/lib/{messageTypes.mjs → messageTypes.js} +1 -1
  290. package/lib/messageTypes.js.map +1 -0
  291. package/lib/{metadata.d.mts → metadata.d.ts} +1 -1
  292. package/lib/metadata.d.ts.map +1 -0
  293. package/lib/{metadata.mjs → metadata.js} +1 -1
  294. package/lib/metadata.js.map +1 -0
  295. package/lib/opLifecycle/{batchManager.d.mts → batchManager.d.ts} +3 -3
  296. package/lib/opLifecycle/batchManager.d.ts.map +1 -0
  297. package/lib/opLifecycle/{batchManager.mjs → batchManager.js} +1 -1
  298. package/lib/opLifecycle/batchManager.js.map +1 -0
  299. package/lib/opLifecycle/{definitions.d.mts → definitions.d.ts} +3 -3
  300. package/lib/opLifecycle/definitions.d.ts.map +1 -0
  301. package/lib/opLifecycle/{definitions.mjs → definitions.js} +1 -1
  302. package/lib/opLifecycle/definitions.js.map +1 -0
  303. package/lib/opLifecycle/index.d.ts +13 -0
  304. package/lib/opLifecycle/index.d.ts.map +1 -0
  305. package/lib/opLifecycle/index.js +12 -0
  306. package/lib/opLifecycle/index.js.map +1 -0
  307. package/lib/opLifecycle/{opCompressor.d.mts → opCompressor.d.ts} +2 -2
  308. package/lib/opLifecycle/opCompressor.d.ts.map +1 -0
  309. package/lib/opLifecycle/{opCompressor.mjs → opCompressor.js} +3 -3
  310. package/lib/opLifecycle/opCompressor.js.map +1 -0
  311. package/lib/opLifecycle/{opDecompressor.d.mts → opDecompressor.d.ts} +2 -2
  312. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -0
  313. package/lib/opLifecycle/{opDecompressor.mjs → opDecompressor.js} +2 -2
  314. package/lib/opLifecycle/opDecompressor.js.map +1 -0
  315. package/lib/opLifecycle/{opGroupingManager.d.mts → opGroupingManager.d.ts} +2 -2
  316. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -0
  317. package/lib/opLifecycle/{opGroupingManager.mjs → opGroupingManager.js} +2 -11
  318. package/lib/opLifecycle/opGroupingManager.js.map +1 -0
  319. package/lib/opLifecycle/{opSplitter.d.mts → opSplitter.d.ts} +2 -2
  320. package/lib/opLifecycle/opSplitter.d.ts.map +1 -0
  321. package/lib/opLifecycle/{opSplitter.mjs → opSplitter.js} +3 -3
  322. package/lib/opLifecycle/opSplitter.js.map +1 -0
  323. package/lib/opLifecycle/{outbox.d.mts → outbox.d.ts} +8 -8
  324. package/lib/opLifecycle/outbox.d.ts.map +1 -0
  325. package/lib/opLifecycle/{outbox.mjs → outbox.js} +12 -4
  326. package/lib/opLifecycle/outbox.js.map +1 -0
  327. package/lib/opLifecycle/{remoteMessageProcessor.d.mts → remoteMessageProcessor.d.ts} +5 -5
  328. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -0
  329. package/lib/opLifecycle/{remoteMessageProcessor.mjs → remoteMessageProcessor.js} +2 -2
  330. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -0
  331. package/lib/{opProperties.d.mts → opProperties.d.ts} +1 -1
  332. package/lib/opProperties.d.ts.map +1 -0
  333. package/lib/{opProperties.mjs → opProperties.js} +1 -1
  334. package/lib/opProperties.js.map +1 -0
  335. package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
  336. package/lib/packageVersion.d.ts.map +1 -0
  337. package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
  338. package/lib/packageVersion.js.map +1 -0
  339. package/lib/{pendingStateManager.d.mts → pendingStateManager.d.ts} +3 -2
  340. package/lib/pendingStateManager.d.ts.map +1 -0
  341. package/lib/{pendingStateManager.mjs → pendingStateManager.js} +18 -10
  342. package/lib/pendingStateManager.js.map +1 -0
  343. package/lib/{scheduleManager.d.mts → scheduleManager.d.ts} +6 -3
  344. package/lib/scheduleManager.d.ts.map +1 -0
  345. package/lib/{scheduleManager.mjs → scheduleManager.js} +3 -3
  346. package/lib/scheduleManager.js.map +1 -0
  347. package/lib/{storageServiceWithAttachBlobs.d.mts → storageServiceWithAttachBlobs.d.ts} +1 -1
  348. package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -0
  349. package/lib/{storageServiceWithAttachBlobs.mjs → storageServiceWithAttachBlobs.js} +1 -1
  350. package/lib/storageServiceWithAttachBlobs.js.map +1 -0
  351. package/lib/summary/{index.d.mts → index.d.ts} +13 -13
  352. package/lib/summary/index.d.ts.map +1 -0
  353. package/lib/summary/{index.mjs → index.js} +12 -12
  354. package/lib/summary/index.js.map +1 -0
  355. package/lib/summary/{orderedClientElection.d.mts → orderedClientElection.d.ts} +5 -1
  356. package/lib/summary/orderedClientElection.d.ts.map +1 -0
  357. package/lib/summary/{orderedClientElection.mjs → orderedClientElection.js} +2 -2
  358. package/lib/summary/orderedClientElection.js.map +1 -0
  359. package/lib/summary/{runWhileConnectedCoordinator.d.mts → runWhileConnectedCoordinator.d.ts} +2 -2
  360. package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
  361. package/lib/summary/{runWhileConnectedCoordinator.mjs → runWhileConnectedCoordinator.js} +1 -1
  362. package/lib/summary/runWhileConnectedCoordinator.js.map +1 -0
  363. package/lib/summary/{runningSummarizer.d.mts → runningSummarizer.d.ts} +12 -11
  364. package/lib/summary/runningSummarizer.d.ts.map +1 -0
  365. package/lib/summary/{runningSummarizer.mjs → runningSummarizer.js} +108 -75
  366. package/lib/summary/runningSummarizer.js.map +1 -0
  367. package/lib/summary/{summarizer.d.mts → summarizer.d.ts} +5 -5
  368. package/lib/summary/summarizer.d.ts.map +1 -0
  369. package/lib/summary/{summarizer.mjs → summarizer.js} +4 -4
  370. package/lib/summary/summarizer.js.map +1 -0
  371. package/lib/summary/{summarizerClientElection.d.mts → summarizerClientElection.d.ts} +3 -3
  372. package/lib/summary/summarizerClientElection.d.ts.map +1 -0
  373. package/lib/summary/{summarizerClientElection.mjs → summarizerClientElection.js} +1 -1
  374. package/lib/summary/summarizerClientElection.js.map +1 -0
  375. package/lib/summary/{summarizerHeuristics.d.mts → summarizerHeuristics.d.ts} +4 -4
  376. package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
  377. package/lib/summary/{summarizerHeuristics.mjs → summarizerHeuristics.js} +1 -1
  378. package/lib/summary/summarizerHeuristics.js.map +1 -0
  379. package/lib/summary/summarizerNode/{index.d.mts → index.d.ts} +4 -4
  380. package/lib/summary/summarizerNode/index.d.ts.map +1 -0
  381. package/lib/summary/summarizerNode/index.js +7 -0
  382. package/lib/summary/summarizerNode/index.js.map +1 -0
  383. package/lib/summary/summarizerNode/{summarizerNode.d.mts → summarizerNode.d.ts} +18 -8
  384. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -0
  385. package/lib/summary/summarizerNode/{summarizerNode.mjs → summarizerNode.js} +41 -53
  386. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -0
  387. package/lib/summary/summarizerNode/{summarizerNodeUtils.d.mts → summarizerNodeUtils.d.ts} +11 -20
  388. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -0
  389. package/lib/summary/summarizerNode/{summarizerNodeUtils.mjs → summarizerNodeUtils.js} +1 -20
  390. package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -0
  391. package/lib/summary/summarizerNode/{summarizerNodeWithGc.d.mts → summarizerNodeWithGc.d.ts} +6 -7
  392. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -0
  393. package/lib/summary/summarizerNode/{summarizerNodeWithGc.mjs → summarizerNodeWithGc.js} +12 -12
  394. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -0
  395. package/lib/summary/{summarizerTypes.d.mts → summarizerTypes.d.ts} +11 -22
  396. package/lib/summary/summarizerTypes.d.ts.map +1 -0
  397. package/lib/summary/{summarizerTypes.mjs → summarizerTypes.js} +1 -1
  398. package/lib/summary/summarizerTypes.js.map +1 -0
  399. package/lib/summary/{summaryCollection.d.mts → summaryCollection.d.ts} +1 -1
  400. package/lib/summary/summaryCollection.d.ts.map +1 -0
  401. package/lib/summary/{summaryCollection.mjs → summaryCollection.js} +1 -1
  402. package/lib/summary/summaryCollection.js.map +1 -0
  403. package/lib/summary/{summaryFormat.d.mts → summaryFormat.d.ts} +16 -3
  404. package/lib/summary/summaryFormat.d.ts.map +1 -0
  405. package/lib/summary/{summaryFormat.mjs → summaryFormat.js} +1 -1
  406. package/lib/summary/summaryFormat.js.map +1 -0
  407. package/lib/summary/{summaryGenerator.d.mts → summaryGenerator.d.ts} +7 -6
  408. package/lib/summary/summaryGenerator.d.ts.map +1 -0
  409. package/lib/summary/{summaryGenerator.mjs → summaryGenerator.js} +11 -2
  410. package/lib/summary/summaryGenerator.js.map +1 -0
  411. package/lib/summary/{summaryManager.d.mts → summaryManager.d.ts} +6 -7
  412. package/lib/summary/summaryManager.d.ts.map +1 -0
  413. package/lib/summary/{summaryManager.mjs → summaryManager.js} +4 -5
  414. package/lib/summary/summaryManager.js.map +1 -0
  415. package/lib/test/batchTracker.spec.js +88 -0
  416. package/lib/test/batchTracker.spec.js.map +1 -0
  417. package/lib/test/blobManager.spec.js +835 -0
  418. package/lib/test/blobManager.spec.js.map +1 -0
  419. package/lib/test/channelCollection.spec.js +141 -0
  420. package/lib/test/channelCollection.spec.js.map +1 -0
  421. package/lib/test/containerRuntime.spec.js +1748 -0
  422. package/lib/test/containerRuntime.spec.js.map +1 -0
  423. package/lib/test/dataStoreContext.spec.js +801 -0
  424. package/lib/test/dataStoreContext.spec.js.map +1 -0
  425. package/lib/test/dataStoreCreation.spec.js +312 -0
  426. package/lib/test/dataStoreCreation.spec.js.map +1 -0
  427. package/lib/test/dataStoreRegistry.spec.js +26 -0
  428. package/lib/test/dataStoreRegistry.spec.js.map +1 -0
  429. package/lib/test/fuzz/fuzzUtils.js +66 -0
  430. package/lib/test/fuzz/fuzzUtils.js.map +1 -0
  431. package/lib/test/fuzz/summarizer.fuzz.spec.js +31 -0
  432. package/lib/test/fuzz/summarizer.fuzz.spec.js.map +1 -0
  433. package/lib/test/fuzz/summarizerFuzzMocks.js +162 -0
  434. package/lib/test/fuzz/summarizerFuzzMocks.js.map +1 -0
  435. package/lib/test/fuzz/summarizerFuzzSuite.js +106 -0
  436. package/lib/test/fuzz/summarizerFuzzSuite.js.map +1 -0
  437. package/lib/test/gc/garbageCollection.spec.js +1465 -0
  438. package/lib/test/gc/garbageCollection.spec.js.map +1 -0
  439. package/lib/test/gc/gcConfigs.spec.js +690 -0
  440. package/lib/test/gc/gcConfigs.spec.js.map +1 -0
  441. package/lib/test/gc/gcHelpers.spec.js +110 -0
  442. package/lib/test/gc/gcHelpers.spec.js.map +1 -0
  443. package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js +68 -0
  444. package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js.map +1 -0
  445. package/lib/test/gc/gcStats.spec.js +391 -0
  446. package/lib/test/gc/gcStats.spec.js.map +1 -0
  447. package/lib/test/gc/gcSummaryStateTracker.spec.js +228 -0
  448. package/lib/test/gc/gcSummaryStateTracker.spec.js.map +1 -0
  449. package/lib/test/gc/gcTelemetry.spec.js +530 -0
  450. package/lib/test/gc/gcTelemetry.spec.js.map +1 -0
  451. package/lib/test/gc/gcUnitTestHelpers.js +29 -0
  452. package/lib/test/gc/gcUnitTestHelpers.js.map +1 -0
  453. package/lib/test/gc/gcUnreferencedStateTracker.spec.js +192 -0
  454. package/lib/test/gc/gcUnreferencedStateTracker.spec.js.map +1 -0
  455. package/lib/test/getPendingBlobs.spec.js +193 -0
  456. package/lib/test/getPendingBlobs.spec.js.map +1 -0
  457. package/lib/test/hardwareStats.spec.js +93 -0
  458. package/lib/test/hardwareStats.spec.js.map +1 -0
  459. package/lib/test/index.js +6 -0
  460. package/lib/test/index.js.map +1 -0
  461. package/lib/test/opLifecycle/OpGroupingManager.spec.js +225 -0
  462. package/lib/test/opLifecycle/OpGroupingManager.spec.js.map +1 -0
  463. package/lib/test/opLifecycle/batchManager.spec.js +189 -0
  464. package/lib/test/opLifecycle/batchManager.spec.js.map +1 -0
  465. package/lib/test/opLifecycle/opCompressor.spec.js +74 -0
  466. package/lib/test/opLifecycle/opCompressor.spec.js.map +1 -0
  467. package/lib/test/opLifecycle/opDecompressor.spec.js +218 -0
  468. package/lib/test/opLifecycle/opDecompressor.spec.js.map +1 -0
  469. package/lib/test/opLifecycle/opSplitter.spec.js +272 -0
  470. package/lib/test/opLifecycle/opSplitter.spec.js.map +1 -0
  471. package/lib/test/opLifecycle/outbox.spec.js +675 -0
  472. package/lib/test/opLifecycle/outbox.spec.js.map +1 -0
  473. package/lib/test/opLifecycle/remoteMessageProcessor.spec.js +196 -0
  474. package/lib/test/opLifecycle/remoteMessageProcessor.spec.js.map +1 -0
  475. package/lib/test/pendingStateManager.spec.js +329 -0
  476. package/lib/test/pendingStateManager.spec.js.map +1 -0
  477. package/lib/test/scheduleManager.spec.js +270 -0
  478. package/lib/test/scheduleManager.spec.js.map +1 -0
  479. package/lib/test/summarizerNode.spec.js +326 -0
  480. package/lib/test/summarizerNode.spec.js.map +1 -0
  481. package/lib/test/summarizerNodeWithGc.spec.js +318 -0
  482. package/lib/test/summarizerNodeWithGc.spec.js.map +1 -0
  483. package/lib/test/summary/orderedClientElection.spec.js +535 -0
  484. package/lib/test/summary/orderedClientElection.spec.js.map +1 -0
  485. package/lib/test/summary/runningSummarizer.spec.js +1349 -0
  486. package/lib/test/summary/runningSummarizer.spec.js.map +1 -0
  487. package/lib/test/summary/summarizer.spec.js +29 -0
  488. package/lib/test/summary/summarizer.spec.js.map +1 -0
  489. package/lib/test/summary/summarizerClientElection.spec.js +436 -0
  490. package/lib/test/summary/summarizerClientElection.spec.js.map +1 -0
  491. package/lib/test/summary/summarizerHeuristics.spec.js +289 -0
  492. package/lib/test/summary/summarizerHeuristics.spec.js.map +1 -0
  493. package/lib/test/summary/summaryCollection.spec.js +200 -0
  494. package/lib/test/summary/summaryCollection.spec.js.map +1 -0
  495. package/lib/test/summary/summaryManager.spec.js +430 -0
  496. package/lib/test/summary/summaryManager.spec.js.map +1 -0
  497. package/lib/test/summary/testQuorumClients.js +34 -0
  498. package/lib/test/summary/testQuorumClients.js.map +1 -0
  499. package/lib/test/throttler.spec.js +175 -0
  500. package/lib/test/throttler.spec.js.map +1 -0
  501. package/lib/test/types/validateContainerRuntimePrevious.generated.js +180 -0
  502. package/lib/test/types/validateContainerRuntimePrevious.generated.js.map +1 -0
  503. package/lib/{throttler.d.mts → throttler.d.ts} +1 -1
  504. package/lib/throttler.d.ts.map +1 -0
  505. package/lib/{throttler.mjs → throttler.js} +1 -1
  506. package/lib/throttler.js.map +1 -0
  507. package/package.json +99 -88
  508. package/src/batchTracker.ts +1 -1
  509. package/src/blobManager.ts +1 -1
  510. package/src/{dataStores.ts → channelCollection.ts} +467 -88
  511. package/src/connectionTelemetry.ts +42 -3
  512. package/src/containerHandleContext.ts +1 -1
  513. package/src/containerRuntime.ts +649 -462
  514. package/src/dataStore.ts +13 -15
  515. package/src/dataStoreContext.ts +203 -173
  516. package/src/dataStoreContexts.ts +1 -1
  517. package/src/deltaManagerSummarizerProxy.ts +132 -7
  518. package/src/gc/garbageCollection.ts +29 -16
  519. package/src/gc/gcConfigs.ts +3 -3
  520. package/src/gc/gcDefinitions.ts +10 -3
  521. package/src/gc/gcHelpers.ts +2 -2
  522. package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
  523. package/src/gc/gcSummaryStateTracker.ts +5 -6
  524. package/src/gc/gcTelemetry.ts +6 -6
  525. package/src/gc/gcUnreferencedStateTracker.ts +1 -1
  526. package/src/gc/index.ts +8 -8
  527. package/src/index.ts +16 -27
  528. package/src/messageTypes.ts +4 -4
  529. package/src/opLifecycle/README.md +2 -4
  530. package/src/opLifecycle/batchManager.ts +2 -2
  531. package/src/opLifecycle/definitions.ts +2 -2
  532. package/src/opLifecycle/index.ts +8 -8
  533. package/src/opLifecycle/opCompressor.ts +3 -3
  534. package/src/opLifecycle/opDecompressor.ts +3 -3
  535. package/src/opLifecycle/opGroupingManager.ts +3 -12
  536. package/src/opLifecycle/opSplitter.ts +3 -3
  537. package/src/opLifecycle/outbox.ts +29 -9
  538. package/src/opLifecycle/remoteMessageProcessor.ts +4 -4
  539. package/src/packageVersion.ts +1 -1
  540. package/src/pendingStateManager.ts +19 -13
  541. package/src/scheduleManager.ts +4 -4
  542. package/src/summary/index.ts +13 -12
  543. package/src/summary/orderedClientElection.ts +1 -1
  544. package/src/summary/runWhileConnectedCoordinator.ts +1 -1
  545. package/src/summary/runningSummarizer.ts +141 -93
  546. package/src/summary/summarizer.ts +7 -7
  547. package/src/summary/summarizerClientElection.ts +2 -2
  548. package/src/summary/summarizerHeuristics.ts +3 -3
  549. package/src/summary/summarizerNode/index.ts +6 -3
  550. package/src/summary/summarizerNode/summarizerNode.ts +54 -69
  551. package/src/summary/summarizerNode/summarizerNodeUtils.ts +16 -34
  552. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +11 -17
  553. package/src/summary/summarizerTypes.ts +12 -24
  554. package/src/summary/summaryFormat.ts +16 -2
  555. package/src/summary/summaryGenerator.ts +16 -4
  556. package/src/summary/summaryManager.ts +6 -7
  557. package/tsconfig.cjs.json +7 -0
  558. package/tsconfig.json +2 -5
  559. package/dist/dataStores.d.ts.map +0 -1
  560. package/dist/dataStores.js.map +0 -1
  561. package/dist/deltaManagerProxyBase.d.ts.map +0 -1
  562. package/dist/deltaManagerProxyBase.js +0 -77
  563. package/dist/deltaManagerProxyBase.js.map +0 -1
  564. package/lib/batchTracker.d.mts.map +0 -1
  565. package/lib/batchTracker.mjs.map +0 -1
  566. package/lib/blobManager.d.mts.map +0 -1
  567. package/lib/blobManager.mjs.map +0 -1
  568. package/lib/connectionTelemetry.d.mts.map +0 -1
  569. package/lib/connectionTelemetry.mjs.map +0 -1
  570. package/lib/containerHandleContext.d.mts.map +0 -1
  571. package/lib/containerHandleContext.mjs.map +0 -1
  572. package/lib/containerRuntime.d.mts.map +0 -1
  573. package/lib/containerRuntime.mjs.map +0 -1
  574. package/lib/dataStore.d.mts.map +0 -1
  575. package/lib/dataStore.mjs.map +0 -1
  576. package/lib/dataStoreContext.d.mts.map +0 -1
  577. package/lib/dataStoreContext.mjs.map +0 -1
  578. package/lib/dataStoreContexts.d.mts.map +0 -1
  579. package/lib/dataStoreContexts.mjs.map +0 -1
  580. package/lib/dataStoreRegistry.d.mts.map +0 -1
  581. package/lib/dataStoreRegistry.mjs.map +0 -1
  582. package/lib/dataStores.d.mts.map +0 -1
  583. package/lib/dataStores.mjs.map +0 -1
  584. package/lib/deltaManagerProxyBase.d.mts +0 -35
  585. package/lib/deltaManagerProxyBase.d.mts.map +0 -1
  586. package/lib/deltaManagerProxyBase.mjs +0 -73
  587. package/lib/deltaManagerProxyBase.mjs.map +0 -1
  588. package/lib/deltaManagerSummarizerProxy.d.mts +0 -19
  589. package/lib/deltaManagerSummarizerProxy.d.mts.map +0 -1
  590. package/lib/deltaManagerSummarizerProxy.mjs +0 -38
  591. package/lib/deltaManagerSummarizerProxy.mjs.map +0 -1
  592. package/lib/deltaScheduler.d.mts.map +0 -1
  593. package/lib/deltaScheduler.mjs.map +0 -1
  594. package/lib/error.d.mts.map +0 -1
  595. package/lib/error.mjs.map +0 -1
  596. package/lib/gc/garbageCollection.d.mts.map +0 -1
  597. package/lib/gc/garbageCollection.mjs.map +0 -1
  598. package/lib/gc/gcConfigs.d.mts.map +0 -1
  599. package/lib/gc/gcConfigs.mjs.map +0 -1
  600. package/lib/gc/gcDefinitions.d.mts.map +0 -1
  601. package/lib/gc/gcDefinitions.mjs.map +0 -1
  602. package/lib/gc/gcHelpers.mjs.map +0 -1
  603. package/lib/gc/gcReferenceGraphAlgorithm.d.mts.map +0 -1
  604. package/lib/gc/gcReferenceGraphAlgorithm.mjs.map +0 -1
  605. package/lib/gc/gcSummaryDefinitions.d.mts.map +0 -1
  606. package/lib/gc/gcSummaryDefinitions.mjs.map +0 -1
  607. package/lib/gc/gcSummaryStateTracker.d.mts.map +0 -1
  608. package/lib/gc/gcSummaryStateTracker.mjs.map +0 -1
  609. package/lib/gc/gcTelemetry.d.mts.map +0 -1
  610. package/lib/gc/gcTelemetry.mjs.map +0 -1
  611. package/lib/gc/gcUnreferencedStateTracker.d.mts.map +0 -1
  612. package/lib/gc/gcUnreferencedStateTracker.mjs.map +0 -1
  613. package/lib/gc/index.d.mts.map +0 -1
  614. package/lib/gc/index.mjs.map +0 -1
  615. package/lib/index.d.mts.map +0 -1
  616. package/lib/index.mjs +0 -24
  617. package/lib/index.mjs.map +0 -1
  618. package/lib/messageTypes.d.mts.map +0 -1
  619. package/lib/messageTypes.mjs.map +0 -1
  620. package/lib/metadata.d.mts.map +0 -1
  621. package/lib/metadata.mjs.map +0 -1
  622. package/lib/opLifecycle/batchManager.d.mts.map +0 -1
  623. package/lib/opLifecycle/batchManager.mjs.map +0 -1
  624. package/lib/opLifecycle/definitions.d.mts.map +0 -1
  625. package/lib/opLifecycle/definitions.mjs.map +0 -1
  626. package/lib/opLifecycle/index.d.mts +0 -13
  627. package/lib/opLifecycle/index.d.mts.map +0 -1
  628. package/lib/opLifecycle/index.mjs +0 -12
  629. package/lib/opLifecycle/index.mjs.map +0 -1
  630. package/lib/opLifecycle/opCompressor.d.mts.map +0 -1
  631. package/lib/opLifecycle/opCompressor.mjs.map +0 -1
  632. package/lib/opLifecycle/opDecompressor.d.mts.map +0 -1
  633. package/lib/opLifecycle/opDecompressor.mjs.map +0 -1
  634. package/lib/opLifecycle/opGroupingManager.d.mts.map +0 -1
  635. package/lib/opLifecycle/opGroupingManager.mjs.map +0 -1
  636. package/lib/opLifecycle/opSplitter.d.mts.map +0 -1
  637. package/lib/opLifecycle/opSplitter.mjs.map +0 -1
  638. package/lib/opLifecycle/outbox.d.mts.map +0 -1
  639. package/lib/opLifecycle/outbox.mjs.map +0 -1
  640. package/lib/opLifecycle/remoteMessageProcessor.d.mts.map +0 -1
  641. package/lib/opLifecycle/remoteMessageProcessor.mjs.map +0 -1
  642. package/lib/opProperties.d.mts.map +0 -1
  643. package/lib/opProperties.mjs.map +0 -1
  644. package/lib/packageVersion.d.mts.map +0 -1
  645. package/lib/packageVersion.mjs.map +0 -1
  646. package/lib/pendingStateManager.d.mts.map +0 -1
  647. package/lib/pendingStateManager.mjs.map +0 -1
  648. package/lib/scheduleManager.d.mts.map +0 -1
  649. package/lib/scheduleManager.mjs.map +0 -1
  650. package/lib/storageServiceWithAttachBlobs.d.mts.map +0 -1
  651. package/lib/storageServiceWithAttachBlobs.mjs.map +0 -1
  652. package/lib/summary/index.d.mts.map +0 -1
  653. package/lib/summary/index.mjs.map +0 -1
  654. package/lib/summary/orderedClientElection.d.mts.map +0 -1
  655. package/lib/summary/orderedClientElection.mjs.map +0 -1
  656. package/lib/summary/runWhileConnectedCoordinator.d.mts.map +0 -1
  657. package/lib/summary/runWhileConnectedCoordinator.mjs.map +0 -1
  658. package/lib/summary/runningSummarizer.d.mts.map +0 -1
  659. package/lib/summary/runningSummarizer.mjs.map +0 -1
  660. package/lib/summary/summarizer.d.mts.map +0 -1
  661. package/lib/summary/summarizer.mjs.map +0 -1
  662. package/lib/summary/summarizerClientElection.d.mts.map +0 -1
  663. package/lib/summary/summarizerClientElection.mjs.map +0 -1
  664. package/lib/summary/summarizerHeuristics.d.mts.map +0 -1
  665. package/lib/summary/summarizerHeuristics.mjs.map +0 -1
  666. package/lib/summary/summarizerNode/index.d.mts.map +0 -1
  667. package/lib/summary/summarizerNode/index.mjs +0 -7
  668. package/lib/summary/summarizerNode/index.mjs.map +0 -1
  669. package/lib/summary/summarizerNode/summarizerNode.d.mts.map +0 -1
  670. package/lib/summary/summarizerNode/summarizerNode.mjs.map +0 -1
  671. package/lib/summary/summarizerNode/summarizerNodeUtils.d.mts.map +0 -1
  672. package/lib/summary/summarizerNode/summarizerNodeUtils.mjs.map +0 -1
  673. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.mts.map +0 -1
  674. package/lib/summary/summarizerNode/summarizerNodeWithGc.mjs.map +0 -1
  675. package/lib/summary/summarizerTypes.d.mts.map +0 -1
  676. package/lib/summary/summarizerTypes.mjs.map +0 -1
  677. package/lib/summary/summaryCollection.d.mts.map +0 -1
  678. package/lib/summary/summaryCollection.mjs.map +0 -1
  679. package/lib/summary/summaryFormat.d.mts.map +0 -1
  680. package/lib/summary/summaryFormat.mjs.map +0 -1
  681. package/lib/summary/summaryGenerator.d.mts.map +0 -1
  682. package/lib/summary/summaryGenerator.mjs.map +0 -1
  683. package/lib/summary/summaryManager.d.mts.map +0 -1
  684. package/lib/summary/summaryManager.mjs.map +0 -1
  685. package/lib/throttler.d.mts.map +0 -1
  686. package/lib/throttler.mjs.map +0 -1
  687. package/src/deltaManagerProxyBase.ts +0 -111
@@ -1,31 +1,29 @@
1
1
  import { AttachState, LoaderHeader, } from "@fluidframework/container-definitions";
2
- import { assert, delay, LazyPromise } from "@fluidframework/core-utils";
2
+ import { assert, Deferred, delay, LazyPromise, PromiseCache } from "@fluidframework/core-utils";
3
3
  import { Trace, TypedEventEmitter } from "@fluid-internal/client-utils";
4
- import { createChildLogger, createChildMonitoringContext, DataCorruptionError, DataProcessingError, GenericError, raiseConnectedEvent, PerformanceEvent,
5
- // eslint-disable-next-line import/no-deprecated
6
- TaggedLoggerAdapter, wrapError, UsageError, LoggingError, } from "@fluidframework/telemetry-utils";
4
+ import { createChildLogger, createChildMonitoringContext, DataCorruptionError, DataProcessingError, GenericError, raiseConnectedEvent, PerformanceEvent, TaggedLoggerAdapter, wrapError, UsageError, LoggingError, createSampledLogger, loggerToMonitoringContext, } from "@fluidframework/telemetry-utils";
7
5
  import { DriverHeader, FetchSource, } from "@fluidframework/driver-definitions";
8
6
  import { readAndParse } from "@fluidframework/driver-utils";
9
7
  import { MessageType, SummaryType, } from "@fluidframework/protocol-definitions";
10
8
  import { FlushMode, FlushModeExperimental, gcTreeKey, channelsTreeName, } from "@fluidframework/runtime-definitions";
11
- import { addBlobToSummary, addSummarizeResultToSummary, addTreeToSummary, RequestParser, create404Response, exceptionToResponse, GCDataBuilder, seqFromTree, calculateStats, TelemetryContext, responseToException, } from "@fluidframework/runtime-utils";
9
+ import { addBlobToSummary, addSummarizeResultToSummary, RequestParser, create404Response, exceptionToResponse, GCDataBuilder, seqFromTree, calculateStats, TelemetryContext, responseToException, } from "@fluidframework/runtime-utils";
12
10
  import { v4 as uuid } from "uuid";
13
- import { ContainerFluidHandleContext } from "./containerHandleContext.mjs";
14
- import { FluidDataStoreRegistry } from "./dataStoreRegistry.mjs";
15
- import { ReportOpPerfTelemetry } from "./connectionTelemetry.mjs";
16
- import { PendingStateManager, } from "./pendingStateManager.mjs";
17
- import { pkgVersion } from "./packageVersion.mjs";
18
- import { BlobManager } from "./blobManager.mjs";
19
- import { DataStores, getSummaryForDatastores } from "./dataStores.mjs";
20
- import { aliasBlobName, blobsTreeName, chunksBlobName, createRootSummarizerNodeWithGC, electedSummarizerBlobName, extractSummaryMetadataMessage, idCompressorBlobName, metadataBlobName, Summarizer, SummaryManager, wrapSummaryInChannelsTree, SummaryCollection, OrderedClientCollection, OrderedClientElection, SummarizerClientElection, summarizerClientType, RunWhileConnectedCoordinator, RetriableSummaryError, } from "./summary/index.mjs";
21
- import { formExponentialFn, Throttler } from "./throttler.mjs";
22
- import { GarbageCollector, GCNodeType, gcGenerationOptionName, trimLeadingAndTrailingSlashes, } from "./gc/index.mjs";
23
- import { channelToDataStore, isDataStoreAliasMessage } from "./dataStore.mjs";
24
- import { BindBatchTracker } from "./batchTracker.mjs";
25
- import { ScheduleManager } from "./scheduleManager.mjs";
26
- import { OpCompressor, OpDecompressor, Outbox, OpSplitter, RemoteMessageProcessor, OpGroupingManager, getLongStack, } from "./opLifecycle/index.mjs";
27
- import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy.mjs";
28
- import { ContainerMessageType, } from "./messageTypes.mjs";
11
+ import { ContainerFluidHandleContext } from "./containerHandleContext.js";
12
+ import { FluidDataStoreRegistry } from "./dataStoreRegistry.js";
13
+ import { ReportOpPerfTelemetry } from "./connectionTelemetry.js";
14
+ import { PendingStateManager, } from "./pendingStateManager.js";
15
+ import { pkgVersion } from "./packageVersion.js";
16
+ import { BlobManager } from "./blobManager.js";
17
+ import { ChannelCollection, getSummaryForDatastores, wrapContext } from "./channelCollection.js";
18
+ import { aliasBlobName, blobsTreeName, chunksBlobName, createRootSummarizerNodeWithGC, electedSummarizerBlobName, extractSummaryMetadataMessage, idCompressorBlobName, metadataBlobName, Summarizer, SummaryManager, wrapSummaryInChannelsTree, SummaryCollection, OrderedClientCollection, OrderedClientElection, SummarizerClientElection, summarizerClientType, RunWhileConnectedCoordinator, RetriableSummaryError, rootHasIsolatedChannels, } from "./summary/index.js";
19
+ import { formExponentialFn, Throttler } from "./throttler.js";
20
+ import { GarbageCollector, GCNodeType, gcGenerationOptionName, } from "./gc/index.js";
21
+ import { channelToDataStore } from "./dataStore.js";
22
+ import { BindBatchTracker } from "./batchTracker.js";
23
+ import { ScheduleManager } from "./scheduleManager.js";
24
+ import { OpCompressor, OpDecompressor, Outbox, OpSplitter, RemoteMessageProcessor, OpGroupingManager, getLongStack, } from "./opLifecycle/index.js";
25
+ import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy.js";
26
+ import { ContainerMessageType, } from "./messageTypes.js";
29
27
  /**
30
28
  * Utility to implement compat behaviors given an unknown message type
31
29
  * The parameters are typed to support compile-time enforcement of handling all known types/behaviors
@@ -55,26 +53,6 @@ export const DefaultSummaryConfiguration = {
55
53
  runtimeOpWeight: 1.0,
56
54
  nonRuntimeHeuristicThreshold: 20,
57
55
  };
58
- /**
59
- * Accepted header keys for requests coming to the runtime.
60
- * @internal
61
- */
62
- export var RuntimeHeaders;
63
- (function (RuntimeHeaders) {
64
- /** True to wait for a data store to be created and loaded before returning it. */
65
- RuntimeHeaders["wait"] = "wait";
66
- /** True if the request is coming from an IFluidHandle. */
67
- RuntimeHeaders["viaHandle"] = "viaHandle";
68
- })(RuntimeHeaders || (RuntimeHeaders = {}));
69
- /** True if a tombstoned object should be returned without erroring
70
- * @alpha
71
- */
72
- export const AllowTombstoneRequestHeaderKey = "allowTombstone"; // Belongs in the enum above, but avoiding the breaking change
73
- /**
74
- * [IRRELEVANT IF throwOnInactiveLoad OPTION NOT SET] True if an inactive object should be returned without erroring
75
- * @internal
76
- */
77
- export const AllowInactiveRequestHeaderKey = "allowInactive"; // Belongs in the enum above, but avoiding the breaking change
78
56
  /**
79
57
  * Tombstone error responses will have this header set to true
80
58
  * @alpha
@@ -243,7 +221,6 @@ export class ContainerRuntime extends TypedEventEmitter {
243
221
  // back-compat: Remove the TaggedLoggerAdapter fallback once all the host are using loader > 0.45
244
222
  const backCompatContext = context;
245
223
  const passLogger = backCompatContext.taggedLogger ??
246
- // eslint-disable-next-line import/no-deprecated
247
224
  new TaggedLoggerAdapter(backCompatContext.logger);
248
225
  const logger = createChildLogger({
249
226
  logger: passLogger,
@@ -253,7 +230,8 @@ export class ContainerRuntime extends TypedEventEmitter {
253
230
  },
254
231
  },
255
232
  });
256
- const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor = false, chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, enableGroupedBatching = false, } = runtimeOptions;
233
+ const mc = loggerToMonitoringContext(logger);
234
+ const { summaryOptions = {}, gcOptions = {}, loadSequenceNumberVerification = "close", flushMode = defaultFlushMode, compressionOptions = defaultCompressionConfig, maxBatchSizeInBytes = defaultMaxBatchSizeInBytes, enableRuntimeIdCompressor = "off", chunkSizeInBytes = defaultChunkSizeInBytes, enableOpReentryCheck = false, enableGroupedBatching = false, } = runtimeOptions;
257
235
  const registry = new FluidDataStoreRegistry(registryEntries);
258
236
  const tryFetchBlob = async (blobName) => {
259
237
  const blobId = context.baseSnapshot?.blobs[blobName];
@@ -298,21 +276,62 @@ export class ContainerRuntime extends TypedEventEmitter {
298
276
  }
299
277
  }
300
278
  }
301
- const idCompressorEnabled = metadata?.idCompressorEnabled ?? runtimeOptions.enableRuntimeIdCompressor ?? false;
302
- let idCompressor;
303
- if (idCompressorEnabled) {
279
+ // Enabling the IdCompressor is a one-way operation and we only want to
280
+ // allow new containers to turn it on
281
+ let idCompressorMode;
282
+ if (existing) {
283
+ // This setting has to be sticky for correctness:
284
+ // 1) if compressior is OFF, it can't be enabled, as already running clients (in given document session) do not know
285
+ // how to process compressor ops
286
+ // 2) if it's ON, then all sessions should load compressor right away
287
+ // 3) Same logic applies for "delayed" mode
288
+ // Maybe in the future we will need to enabled (and figure how to do it safely) "delayed" -> "on" change.
289
+ // We could do "off" -> "on" transtition too, if all clients start loading compressor (but not using it initially) and do so for a while -
290
+ // this will allow clients to eventually to disregard "off" setting (when it's safe so) and start using compressor in future sessions.
291
+ // Everyting is possible, but it needs to be designed and executed carefully, when such need arises.
292
+ idCompressorMode = metadata?.idCompressorMode ?? "off";
293
+ }
294
+ else {
295
+ // FG overwrite
296
+ const enabled = mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled");
297
+ switch (enabled) {
298
+ case true:
299
+ idCompressorMode = "on";
300
+ break;
301
+ case false:
302
+ idCompressorMode = "off";
303
+ break;
304
+ default:
305
+ idCompressorMode = enableRuntimeIdCompressor;
306
+ break;
307
+ }
308
+ }
309
+ const createIdCompressorFn = async () => {
304
310
  const { createIdCompressor, deserializeIdCompressor, createSessionId } = await import("@fluidframework/id-compressor");
311
+ /**
312
+ * Because the IdCompressor emits so much telemetry, this function is used to sample
313
+ * approximately 5% of all clients. Only the given percentage of sessions will emit telemetry.
314
+ */
315
+ const idCompressorEventSampler = (() => {
316
+ const isIdCompressorTelemetryEnabled = Math.random() < 0.05;
317
+ return {
318
+ sample: () => {
319
+ return isIdCompressorTelemetryEnabled;
320
+ },
321
+ };
322
+ })();
323
+ const compressorLogger = createSampledLogger(logger, idCompressorEventSampler);
305
324
  const pendingLocalState = context.pendingLocalState;
306
325
  if (pendingLocalState?.pendingIdCompressorState !== undefined) {
307
- idCompressor = deserializeIdCompressor(pendingLocalState.pendingIdCompressorState);
326
+ return deserializeIdCompressor(pendingLocalState.pendingIdCompressorState, compressorLogger);
308
327
  }
309
328
  else if (serializedIdCompressor !== undefined) {
310
- idCompressor = deserializeIdCompressor(serializedIdCompressor, createSessionId());
329
+ return deserializeIdCompressor(serializedIdCompressor, createSessionId(), compressorLogger);
311
330
  }
312
331
  else {
313
- idCompressor = createIdCompressor(logger);
332
+ return createIdCompressor(compressorLogger);
314
333
  }
315
- }
334
+ };
316
335
  const runtime = new containerRuntimeCtor(context, registry, metadata, electedSummarizerData, chunks ?? [], aliases ?? [], {
317
336
  summaryOptions,
318
337
  gcOptions,
@@ -324,7 +343,7 @@ export class ContainerRuntime extends TypedEventEmitter {
324
343
  enableRuntimeIdCompressor,
325
344
  enableOpReentryCheck,
326
345
  enableGroupedBatching,
327
- }, containerScope, logger, existing, blobManagerSnapshot, context.storage, idCompressor, provideEntryPoint, requestHandler, undefined);
346
+ }, containerScope, logger, existing, blobManagerSnapshot, context.storage, createIdCompressorFn, idCompressorMode, provideEntryPoint, requestHandler, undefined);
328
347
  // Apply stashed ops with a reference sequence number equal to the sequence number of the snapshot,
329
348
  // or zero. This must be done before Container replays saved ops.
330
349
  await runtime.pendingStateManager.applyStashedOpsAt(runtimeSequenceNumber ?? 0);
@@ -338,6 +357,9 @@ export class ContainerRuntime extends TypedEventEmitter {
338
357
  get storage() {
339
358
  return this._storage;
340
359
  }
360
+ get containerRuntime() {
361
+ return this;
362
+ }
341
363
  get flushMode() {
342
364
  return this._flushMode;
343
365
  }
@@ -350,6 +372,25 @@ export class ContainerRuntime extends TypedEventEmitter {
350
372
  get attachState() {
351
373
  return this._getAttachState();
352
374
  }
375
+ /**
376
+ * See IContainerRuntimeBase.idCompressor() for details.
377
+ */
378
+ get idCompressor() {
379
+ // Expose ID Compressor only if it's On from the start.
380
+ // If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
381
+ // That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
382
+ // to reason over such things as session ID space.
383
+ if (this.idCompressorMode === "on") {
384
+ assert(this._idCompressor !== undefined, 0x8ea /* compressor should have been loaded */);
385
+ return this._idCompressor;
386
+ }
387
+ }
388
+ /**
389
+ * See IContainerRuntimeBase.generateDocumentUniqueId() for details.
390
+ */
391
+ generateDocumentUniqueId() {
392
+ return this._idCompressor?.generateDocumentUniqueId() ?? uuid();
393
+ }
353
394
  get IFluidHandleContext() {
354
395
  return this.handleContext;
355
396
  }
@@ -387,9 +428,6 @@ export class ContainerRuntime extends TypedEventEmitter {
387
428
  isSummariesDisabled() {
388
429
  return this.summaryConfiguration.state === "disabled";
389
430
  }
390
- isHeuristicsDisabled() {
391
- return this.summaryConfiguration.state === "disableHeuristics";
392
- }
393
431
  getMaxOpsSinceLastSummary() {
394
432
  return this.summaryConfiguration.state !== "disabled"
395
433
  ? this.summaryConfiguration.maxOpsSinceLastSummary
@@ -414,7 +452,7 @@ export class ContainerRuntime extends TypedEventEmitter {
414
452
  return this.garbageCollector.throwOnTombstoneUsage;
415
453
  }
416
454
  /***/
417
- constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, idCompressor, provideEntryPoint, requestHandler, summaryConfiguration = {
455
+ constructor(context, registry, metadata, electedSummarizerData, chunks, dataStoreAliasMap, runtimeOptions, containerScope, logger, existing, blobManagerSnapshot, _storage, createIdCompressor, idCompressorMode, provideEntryPoint, requestHandler, summaryConfiguration = {
418
456
  // the defaults
419
457
  ...DefaultSummaryConfiguration,
420
458
  // the runtime configuration overrides
@@ -422,13 +460,24 @@ export class ContainerRuntime extends TypedEventEmitter {
422
460
  }) {
423
461
  super();
424
462
  this.registry = registry;
463
+ this.metadata = metadata;
425
464
  this.runtimeOptions = runtimeOptions;
426
465
  this.containerScope = containerScope;
427
466
  this.logger = logger;
428
467
  this._storage = _storage;
468
+ this.createIdCompressor = createIdCompressor;
469
+ this.idCompressorMode = idCompressorMode;
429
470
  this.requestHandler = requestHandler;
430
471
  this.summaryConfiguration = summaryConfiguration;
431
472
  this.imminentClosure = false;
473
+ // We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
474
+ // Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
475
+ this.pendingIdCompressorOps = [];
476
+ /**
477
+ * True if we have ID compressor loading in-flight (async operation). Useful only for
478
+ * this.idCompressorMode === "delayed" mode
479
+ */
480
+ this.compressorLoadInitiated = false;
432
481
  this.defaultMaxConsecutiveReconnects = 7;
433
482
  this._orderSequentiallyCalls = 0;
434
483
  this.flushTaskExists = false;
@@ -450,6 +499,13 @@ export class ContainerRuntime extends TypedEventEmitter {
450
499
  signalTimestamp: 0,
451
500
  trackingSignalSequenceNumber: undefined,
452
501
  };
502
+ /**
503
+ * It a cache for holding mapping for loading groupIds with its snapshot from the service. Add expiry policy of 1 minute.
504
+ * Starting with 1 min and based on recorded usage we can tweak it later on.
505
+ */
506
+ this.snapshotCacheForLoadingGroupIds = new PromiseCache({
507
+ expiry: { policy: "absolute", durationMs: 60000 },
508
+ });
453
509
  const { options, clientDetails, connected, baseSnapshot, submitFn, submitBatchFn, submitSummaryFn, submitSignalFn, disposeFn, closeFn, deltaManager, quorum, audience, loader, pendingLocalState, supportedFeatures, } = context;
454
510
  this.innerDeltaManager = deltaManager;
455
511
  this.deltaManager = new DeltaManagerSummarizerProxy(this.innerDeltaManager);
@@ -459,7 +515,9 @@ export class ContainerRuntime extends TypedEventEmitter {
459
515
  this.submitBatchFn = submitBatchFn;
460
516
  this.submitSummaryFn = submitSummaryFn;
461
517
  this.submitSignalFn = submitSignalFn;
462
- this.options = options;
518
+ // TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
519
+ // Values are generally expected to be set from the runtime side.
520
+ this.options = options ?? {};
463
521
  this.clientDetails = clientDetails;
464
522
  this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
465
523
  this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
@@ -497,9 +555,6 @@ export class ContainerRuntime extends TypedEventEmitter {
497
555
  // summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
498
556
  // the count is reset to 0.
499
557
  loadSummaryNumber = metadata?.summaryNumber ?? 0;
500
- // Enabling the IdCompressor is a one-way operation and we only want to
501
- // allow new containers to turn it on
502
- this.idCompressorEnabled = metadata?.idCompressorEnabled ?? false;
503
558
  }
504
559
  else {
505
560
  this.createContainerMetadata = {
@@ -507,9 +562,6 @@ export class ContainerRuntime extends TypedEventEmitter {
507
562
  createContainerTimestamp: Date.now(),
508
563
  };
509
564
  loadSummaryNumber = 0;
510
- this.idCompressorEnabled =
511
- this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled") ??
512
- idCompressor !== undefined;
513
565
  }
514
566
  this.nextSummaryNumber = loadSummaryNumber + 1;
515
567
  this.messageAtLastSummary = metadata?.message;
@@ -544,12 +596,8 @@ export class ContainerRuntime extends TypedEventEmitter {
544
596
  // Allow for a break-glass config to override the options
545
597
  disableOpReentryCheck !== true;
546
598
  this.summariesDisabled = this.isSummariesDisabled();
547
- this.heuristicsDisabled = this.isHeuristicsDisabled();
548
599
  this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
549
600
  this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
550
- if (this.idCompressorEnabled) {
551
- this.idCompressor = idCompressor;
552
- }
553
601
  this.maxConsecutiveReconnects =
554
602
  this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
555
603
  this.defaultMaxConsecutiveReconnects;
@@ -563,13 +611,15 @@ export class ContainerRuntime extends TypedEventEmitter {
563
611
  this._flushMode = runtimeOptions.flushMode;
564
612
  }
565
613
  const pendingRuntimeState = pendingLocalState;
566
- const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
567
- if (maxSnapshotCacheDurationMs !== undefined &&
568
- maxSnapshotCacheDurationMs > 5 * 24 * 60 * 60 * 1000) {
569
- // This is a runtime enforcement of what's already explicit in the policy's type itself,
570
- // which dictates the value is either undefined or exactly 5 days in ms.
571
- // As long as the actual value is less than 5 days, the assumptions GC makes here are valid.
572
- throw new UsageError("Driver's maximumCacheDurationMs policy cannot exceed 5 days");
614
+ if (context.attachState === AttachState.Attached) {
615
+ const maxSnapshotCacheDurationMs = this._storage?.policies?.maximumCacheDurationMs;
616
+ if (maxSnapshotCacheDurationMs !== undefined &&
617
+ maxSnapshotCacheDurationMs > 5 * 24 * 60 * 60 * 1000) {
618
+ // This is a runtime enforcement of what's already explicit in the policy's type itself,
619
+ // which dictates the value is either undefined or exactly 5 days in ms.
620
+ // As long as the actual value is less than 5 days, the assumptions GC makes here are valid.
621
+ throw new UsageError("Driver's maximumCacheDurationMs policy cannot exceed 5 days");
622
+ }
573
623
  }
574
624
  this.garbageCollector = GarbageCollector.create({
575
625
  runtime: this,
@@ -584,6 +634,7 @@ export class ContainerRuntime extends TypedEventEmitter {
584
634
  getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
585
635
  readAndParseBlob: async (id) => readAndParse(this.storage, id),
586
636
  submitMessage: (message) => this.submit(message),
637
+ sessionExpiryTimerStarted: pendingRuntimeState?.sessionExpiryTimerStarted,
587
638
  });
588
639
  const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
589
640
  this.summarizerNode = createRootSummarizerNodeWithGC(createChildLogger({ logger: this.logger, namespace: "SummarizerNode" }),
@@ -596,9 +647,6 @@ export class ContainerRuntime extends TypedEventEmitter {
596
647
  // Must set to false to prevent sending summary handle which would be pointing to
597
648
  // a summary with an older protocol state.
598
649
  canReuseHandle: false,
599
- // Must set to true to throw on any data stores failure that was too severe to be handled.
600
- // We also are not decoding the base summaries at the root.
601
- throwOnFailure: true,
602
650
  // If GC should not run, let the summarizer node know so that it does not track GC state.
603
651
  gcDisabled: !this.garbageCollector.shouldRunGC,
604
652
  },
@@ -609,7 +657,16 @@ export class ContainerRuntime extends TypedEventEmitter {
609
657
  if (baseSnapshot) {
610
658
  this.summarizerNode.updateBaseSummaryState(baseSnapshot);
611
659
  }
612
- this.dataStores = new DataStores(getSummaryForDatastores(baseSnapshot, metadata), this, (attachMsg) => this.submit({ type: ContainerMessageType.Attach, contents: attachMsg }), (id, createParam) => (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn), (id) => this.summarizerNode.deleteChild(id), this.mc.logger, (path, timestampMs, packagePath) => this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath), (path) => this.garbageCollector.isNodeDeleted(path), new Map(dataStoreAliasMap));
660
+ const parentContext = wrapContext(this);
661
+ // Due to a mismatch between different layers in terms of
662
+ // what is the interface of passing signals, we need the
663
+ // downstream stores to wrap the signal.
664
+ parentContext.submitSignal = (type, content, targetClientId) => {
665
+ const envelope1 = content;
666
+ const envelope2 = this.createNewSignalEnvelope(envelope1.address, type, envelope1.contents);
667
+ return this.submitSignalFn(envelope2, targetClientId);
668
+ };
669
+ this.channelCollection = new ChannelCollection(getSummaryForDatastores(baseSnapshot, metadata), parentContext, this.mc.logger, (path, reason, timestampMs, packagePath, request, headerData) => this.garbageCollector.nodeUpdated(path, reason, timestampMs, packagePath, request, headerData), (path) => this.garbageCollector.isNodeDeleted(path), new Map(dataStoreAliasMap), async (runtime) => provideEntryPoint);
613
670
  this.blobManager = new BlobManager(this.handleContext, blobManagerSnapshot, () => this.storage, (localId, blobId) => {
614
671
  if (!this.disposed) {
615
672
  this.submit({ type: ContainerMessageType.BlobAttach, contents: undefined }, undefined, {
@@ -627,6 +684,7 @@ export class ContainerRuntime extends TypedEventEmitter {
627
684
  reSubmit: this.reSubmit.bind(this),
628
685
  reSubmitBatch: this.reSubmitBatch.bind(this),
629
686
  isActiveConnection: () => this.innerDeltaManager.active,
687
+ isAttached: () => this.attachState !== AttachState.Detached,
630
688
  }, pendingRuntimeState?.pending, this.logger);
631
689
  const disableCompression = this.mc.config.getBoolean("Fluid.ContainerRuntime.CompressionDisabled");
632
690
  const compressionOptions = disableCompression === true
@@ -718,7 +776,7 @@ export class ContainerRuntime extends TypedEventEmitter {
718
776
  // throttling function increases exponentially (0ms, 40ms, 80ms, 160ms, etc)
719
777
  formExponentialFn({ coefficient: 20, initialDelay: 0 })), {
720
778
  initialDelayMs: this.initialSummarizerDelayMs,
721
- }, this.heuristicsDisabled);
779
+ });
722
780
  this.summaryManager.on("summarize", (eventProps) => {
723
781
  this.emit("summarize", eventProps);
724
782
  });
@@ -733,25 +791,26 @@ export class ContainerRuntime extends TypedEventEmitter {
733
791
  this.mc.logger.sendTelemetryEvent({
734
792
  eventName: "ContainerLoadStats",
735
793
  ...this.createContainerMetadata,
736
- ...this.dataStores.containerLoadStats,
794
+ ...this.channelCollection.containerLoadStats,
737
795
  summaryNumber: loadSummaryNumber,
738
796
  summaryFormatVersion: metadata?.summaryFormatVersion,
739
797
  disableIsolatedChannels: metadata?.disableIsolatedChannels,
740
798
  gcVersion: metadata?.gcFeature,
741
799
  options: JSON.stringify(runtimeOptions),
800
+ idCompressorModeMetadata: metadata?.idCompressorMode,
801
+ idCompressorMode: this.idCompressorMode,
742
802
  featureGates: JSON.stringify({
743
803
  disableCompression,
744
804
  disableOpReentryCheck,
745
805
  disableChunking,
746
806
  disableAttachReorder: this.disableAttachReorder,
747
807
  disablePartialFlush,
748
- idCompressorEnabled: this.idCompressorEnabled,
749
808
  closeSummarizerDelayOverride,
750
809
  }),
751
810
  telemetryDocumentId: this.telemetryDocumentId,
752
811
  groupedBatchingEnabled: this.groupedBatchingEnabled,
753
812
  });
754
- ReportOpPerfTelemetry(this.clientId, this.deltaManager, this.logger);
813
+ ReportOpPerfTelemetry(this.clientId, this.deltaManager, this, this.logger);
755
814
  BindBatchTracker(this, this.logger);
756
815
  this.entryPoint = new LazyPromise(async () => {
757
816
  if (this.isSummarizerClient) {
@@ -760,11 +819,29 @@ export class ContainerRuntime extends TypedEventEmitter {
760
819
  }
761
820
  return provideEntryPoint(this);
762
821
  });
822
+ // If we loaded from pending state, then we need to skip any ops that are already accounted in such
823
+ // saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
824
+ this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
825
+ }
826
+ getCreateChildSummarizerNodeFn(id, createParam) {
827
+ return (summarizeInternal, getGCDataFn) => this.summarizerNode.createChild(summarizeInternal, id, createParam, undefined, getGCDataFn);
828
+ }
829
+ deleteChildSummarizerNode(id) {
830
+ return this.summarizerNode.deleteChild(id);
831
+ }
832
+ makeLocallyVisible() {
833
+ assert(false, 0x8eb /* should not be called */);
763
834
  }
764
835
  /**
765
836
  * Initializes the state from the base snapshot this container runtime loaded from.
766
837
  */
767
838
  async initializeBaseState() {
839
+ if (this.idCompressorMode === "on" ||
840
+ (this.idCompressorMode === "delayed" && this.connected)) {
841
+ // This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
842
+ assert(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
843
+ this._idCompressor = await this.createIdCompressor();
844
+ }
768
845
  await this.garbageCollector.initializeBaseState();
769
846
  }
770
847
  dispose(error) {
@@ -783,11 +860,110 @@ export class ContainerRuntime extends TypedEventEmitter {
783
860
  }
784
861
  this.garbageCollector.dispose();
785
862
  this._summarizer?.dispose();
786
- this.dataStores.dispose();
863
+ this.channelCollection.dispose();
787
864
  this.pendingStateManager.dispose();
788
865
  this.emit("dispose");
789
866
  this.removeAllListeners();
790
867
  }
868
+ /**
869
+ * Api to fetch the snapshot from the service for a loadingGroupIds.
870
+ * @param loadingGroupIds - LoadingGroupId for which the snapshot is asked for.
871
+ * @param pathParts - Parts of the path, which we want to extract from the snapshot tree.
872
+ * @returns - snapshotTree and the sequence number of the snapshot.
873
+ */
874
+ async getSnapshotForLoadingGroupId(loadingGroupIds, pathParts) {
875
+ const sortedLoadingGroupIds = loadingGroupIds.sort();
876
+ assert(this.storage.getSnapshot !== undefined, 0x8ed /* getSnapshot api should be defined if used */);
877
+ let loadedFromCache = true;
878
+ // Lookup up in the cache, if not present then make the network call as multiple datastores could
879
+ // be in same loading group. So, once we have fetched the snapshot for that loading group on
880
+ // any request, then cache that as same group could be requested in future too.
881
+ const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(sortedLoadingGroupIds.join(), async () => {
882
+ assert(this.storage.getSnapshot !== undefined, 0x8ee /* getSnapshot api should be defined if used */);
883
+ loadedFromCache = false;
884
+ return this.storage.getSnapshot({
885
+ cacheSnapshot: false,
886
+ scenarioName: "snapshotForLoadingGroupId",
887
+ loadingGroupIds: sortedLoadingGroupIds,
888
+ });
889
+ });
890
+ this.logger.sendTelemetryEvent({
891
+ eventName: "GroupIdSnapshotFetched",
892
+ details: JSON.stringify({
893
+ fromCache: loadedFromCache,
894
+ loadingGroupIds: loadingGroupIds.join(","),
895
+ }),
896
+ });
897
+ // Find the snapshotTree inside the returned snapshot based on the path as given in the request.
898
+ const hasIsolatedChannels = rootHasIsolatedChannels(this.metadata);
899
+ const snapshotTreeForPath = this.getSnapshotTreeForPath(snapshot.snapshotTree, pathParts, hasIsolatedChannels);
900
+ assert(snapshotTreeForPath !== undefined, 0x8ef /* no snapshotTree for the path */);
901
+ const snapshotSeqNumber = snapshot.sequenceNumber;
902
+ assert(snapshotSeqNumber !== undefined, 0x8f0 /* snapshotSeqNumber should be present */);
903
+ // This assert fires if we get a snapshot older than the snapshot we loaded from. This is a service issue.
904
+ // Snapshots should only move forward. If we observe an older snapshot than the one we loaded from, then likely
905
+ // the file has been overwritten or service lost data.
906
+ if (snapshotSeqNumber < this.deltaManager.initialSequenceNumber) {
907
+ throw DataProcessingError.create("Downloaded snapshot older than snapshot we loaded from", "getSnapshotForLoadingGroupId", undefined, {
908
+ loadingGroupIds: sortedLoadingGroupIds.join(","),
909
+ snapshotSeqNumber,
910
+ initialSequenceNumber: this.deltaManager.initialSequenceNumber,
911
+ });
912
+ }
913
+ // If the snapshot is ahead of the last seq number of the delta manager, then catch up before
914
+ // returning the snapshot.
915
+ if (snapshotSeqNumber > this.deltaManager.lastSequenceNumber) {
916
+ // If this is a summarizer client, which is trying to load a group and it finds that there is
917
+ // another snapshot from which the summarizer loaded and it is behind, then just give up as
918
+ // the summarizer state is not up to date.
919
+ // This should be a recoverable scenario and shouldn't happen as we should process the ack first.
920
+ if (this.isSummarizerClient) {
921
+ throw new Error("Summarizer client behind, loaded newer snapshot with loadingGroupId");
922
+ }
923
+ // We want to catchup from sequenceNumber to targetSequenceNumber
924
+ const props = {
925
+ eventName: "GroupIdSnapshotCatchup",
926
+ loadingGroupIds: sortedLoadingGroupIds.join(","),
927
+ targetSequenceNumber: snapshotSeqNumber,
928
+ sequenceNumber: this.deltaManager.lastSequenceNumber, // This is so we reuse some columns in telemetry
929
+ };
930
+ const event = PerformanceEvent.start(this.mc.logger, {
931
+ ...props,
932
+ });
933
+ // If the inbound deltas queue is paused or disconnected, we expect a reconnect and unpause
934
+ // as long as it's not a summarizer client.
935
+ if (this.deltaManager.inbound.paused) {
936
+ props.inboundPaused = this.deltaManager.inbound.paused; // reusing telemetry
937
+ }
938
+ const defP = new Deferred();
939
+ this.deltaManager.on("op", (message) => {
940
+ if (message.sequenceNumber >= snapshotSeqNumber) {
941
+ defP.resolve(true);
942
+ }
943
+ });
944
+ await defP.promise;
945
+ event.end(props);
946
+ }
947
+ return { snapshotTree: snapshotTreeForPath, sequenceNumber: snapshotSeqNumber };
948
+ }
949
+ /**
950
+ * Api to find a snapshot tree inside a bigger snapshot tree based on the path in the pathParts array.
951
+ * @param snapshotTree - snapshot tree to look into.
952
+ * @param pathParts - Part of the path, which we want to extract from the snapshot tree.
953
+ * @param hasIsolatedChannels - whether the channels are present inside ".channels" subtree. Older
954
+ * snapshots will not have trees inside ".channels", so check that.
955
+ * @returns - requested snapshot tree based on the path parts.
956
+ */
957
+ getSnapshotTreeForPath(snapshotTree, pathParts, hasIsolatedChannels) {
958
+ let childTree = snapshotTree;
959
+ for (const part of pathParts) {
960
+ if (hasIsolatedChannels) {
961
+ childTree = childTree?.trees[channelsTreeName];
962
+ }
963
+ childTree = childTree?.trees[part];
964
+ }
965
+ return childTree;
966
+ }
791
967
  /**
792
968
  * Notifies this object about the request made to the container.
793
969
  * @param request - Request made to the handler.
@@ -841,15 +1017,7 @@ export class ContainerRuntime extends TypedEventEmitter {
841
1017
  : create404Response(request);
842
1018
  }
843
1019
  else if (requestParser.pathParts.length > 0) {
844
- // Differentiate between requesting the dataStore directly, or one of its children
845
- const requestForChild = !requestParser.isLeaf(1);
846
- const dataStore = await this.getDataStoreFromRequest(id, request, requestForChild);
847
- const subRequest = requestParser.createSubRequest(1);
848
- // We always expect createSubRequest to include a leading slash, but asserting here to protect against
849
- // unintentionally modifying the url if that changes.
850
- assert(subRequest.url.startsWith("/"), 0x126 /* "Expected createSubRequest url to include a leading slash" */);
851
- // eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
852
- return dataStore.request(subRequest);
1020
+ return await this.channelCollection.request(request);
853
1021
  }
854
1022
  return create404Response(request);
855
1023
  }
@@ -864,38 +1032,7 @@ export class ContainerRuntime extends TypedEventEmitter {
864
1032
  return this.entryPoint;
865
1033
  }
866
1034
  internalId(maybeAlias) {
867
- return this.dataStores.aliases.get(maybeAlias) ?? maybeAlias;
868
- }
869
- async getDataStoreFromRequest(id, request, requestForChild) {
870
- const headerData = {};
871
- if (typeof request.headers?.[RuntimeHeaders.wait] === "boolean") {
872
- headerData.wait = request.headers[RuntimeHeaders.wait];
873
- }
874
- if (typeof request.headers?.[RuntimeHeaders.viaHandle] === "boolean") {
875
- headerData.viaHandle = request.headers[RuntimeHeaders.viaHandle];
876
- }
877
- if (typeof request.headers?.[AllowTombstoneRequestHeaderKey] === "boolean") {
878
- headerData.allowTombstone = request.headers[AllowTombstoneRequestHeaderKey];
879
- }
880
- if (typeof request.headers?.[AllowInactiveRequestHeaderKey] === "boolean") {
881
- headerData.allowInactive = request.headers[AllowInactiveRequestHeaderKey];
882
- }
883
- // We allow Tombstone requests for sub-DataStore objects
884
- if (requestForChild) {
885
- headerData.allowTombstone = true;
886
- }
887
- await this.dataStores.waitIfPendingAlias(id);
888
- const internalId = this.internalId(id);
889
- const dataStoreContext = await this.dataStores.getDataStore(internalId, headerData);
890
- // Remove query params, leading and trailing slashes from the url. This is done to make sure the format is
891
- // the same as GC nodes id.
892
- const urlWithoutQuery = trimLeadingAndTrailingSlashes(request.url.split("?")[0]);
893
- // Get the initial snapshot details which contain the data store package path.
894
- const details = await dataStoreContext.getInitialSnapshotDetails();
895
- // Note that this will throw if the data store is inactive or tombstoned and throwing on incorrect usage
896
- // is configured.
897
- this.garbageCollector.nodeUpdated(`/${urlWithoutQuery}`, "Loaded", undefined /* timestampMs */, details.pkg, request, headerData);
898
- return dataStoreContext.realize();
1035
+ return this.channelCollection.internalId(maybeAlias);
899
1036
  }
900
1037
  /** Adds the container's metadata to the given summary tree. */
901
1038
  addMetadataToSummary(summaryTree) {
@@ -910,22 +1047,21 @@ export class ContainerRuntime extends TypedEventEmitter {
910
1047
  message: extractSummaryMetadataMessage(this.deltaManager.lastMessage) ??
911
1048
  this.messageAtLastSummary,
912
1049
  telemetryDocumentId: this.telemetryDocumentId,
913
- idCompressorEnabled: this.idCompressorEnabled ? true : undefined,
1050
+ idCompressorMode: this.idCompressorMode,
914
1051
  };
915
1052
  addBlobToSummary(summaryTree, metadataBlobName, JSON.stringify(metadata));
916
1053
  }
917
1054
  addContainerStateToSummary(summaryTree, fullTree, trackState, telemetryContext) {
918
1055
  this.addMetadataToSummary(summaryTree);
919
- if (this.idCompressorEnabled) {
920
- assert(this.idCompressor !== undefined, 0x67a /* IdCompressor should be defined if enabled */);
921
- const idCompressorState = JSON.stringify(this.idCompressor.serialize(false));
1056
+ if (this._idCompressor) {
1057
+ const idCompressorState = JSON.stringify(this._idCompressor.serialize(false));
922
1058
  addBlobToSummary(summaryTree, idCompressorBlobName, idCompressorState);
923
1059
  }
924
1060
  if (this.remoteMessageProcessor.partialMessages.size > 0) {
925
1061
  const content = JSON.stringify([...this.remoteMessageProcessor.partialMessages]);
926
1062
  addBlobToSummary(summaryTree, chunksBlobName, content);
927
1063
  }
928
- const dataStoreAliases = this.dataStores.aliases;
1064
+ const dataStoreAliases = this.channelCollection.aliases;
929
1065
  if (dataStoreAliases.size > 0) {
930
1066
  addBlobToSummary(summaryTree, aliasBlobName, JSON.stringify([...dataStoreAliases]));
931
1067
  }
@@ -937,7 +1073,7 @@ export class ContainerRuntime extends TypedEventEmitter {
937
1073
  // Some storage (like git) doesn't allow empty tree, so we can omit it.
938
1074
  // and the blob manager can handle the tree not existing when loading
939
1075
  if (Object.keys(blobManagerSummary.summary.tree).length > 0) {
940
- addTreeToSummary(summaryTree, blobsTreeName, blobManagerSummary);
1076
+ addSummarizeResultToSummary(summaryTree, blobsTreeName, blobManagerSummary);
941
1077
  }
942
1078
  const gcSummary = this.garbageCollector.summarize(fullTree, trackState, telemetryContext);
943
1079
  if (gcSummary !== undefined) {
@@ -1024,13 +1160,12 @@ export class ContainerRuntime extends TypedEventEmitter {
1024
1160
  const opContents = this.parseLocalOpContent(serializedOpContent);
1025
1161
  switch (opContents.type) {
1026
1162
  case ContainerMessageType.FluidDataStoreOp:
1027
- return this.dataStores.applyStashedOp(opContents.contents);
1028
1163
  case ContainerMessageType.Attach:
1029
- return this.dataStores.applyStashedAttachOp(opContents.contents);
1164
+ case ContainerMessageType.Alias:
1165
+ return this.channelCollection.applyStashedOp(opContents);
1030
1166
  case ContainerMessageType.IdAllocation:
1031
- assert(this.idCompressor !== undefined, 0x67b /* IdCompressor should be defined if enabled */);
1167
+ assert(this.idCompressorMode !== "off", 0x8f1 /* ID compressor should be in use */);
1032
1168
  return;
1033
- case ContainerMessageType.Alias:
1034
1169
  case ContainerMessageType.BlobAttach:
1035
1170
  return;
1036
1171
  case ContainerMessageType.ChunkedOp:
@@ -1055,10 +1190,26 @@ export class ContainerRuntime extends TypedEventEmitter {
1055
1190
  this.closeFn(error);
1056
1191
  throw error;
1057
1192
  }
1193
+ // Note: Even if its compat behavior allows it, we don't know how to apply this stashed op.
1194
+ // All we can do is ignore it (similar to on process).
1058
1195
  }
1059
1196
  }
1060
1197
  }
1061
1198
  setConnectionState(connected, clientId) {
1199
+ if (connected && this.idCompressorMode === "delayed" && !this.compressorLoadInitiated) {
1200
+ this.compressorLoadInitiated = true;
1201
+ this.createIdCompressor()
1202
+ .then((compressor) => {
1203
+ this._idCompressor = compressor;
1204
+ for (const range of this.pendingIdCompressorOps) {
1205
+ this._idCompressor.finalizeCreationRange(range);
1206
+ }
1207
+ this.pendingIdCompressorOps = [];
1208
+ })
1209
+ .catch((error) => {
1210
+ this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
1211
+ });
1212
+ }
1062
1213
  if (connected === false && this.delayConnectClientId !== undefined) {
1063
1214
  this.delayConnectClientId = undefined;
1064
1215
  this.mc.logger.sendTelemetryEvent({
@@ -1122,7 +1273,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1122
1273
  if (changeOfState) {
1123
1274
  this.replayPendingStates();
1124
1275
  }
1125
- this.dataStores.setConnectionState(connected, clientId);
1276
+ this.channelCollection.setConnectionState(connected, clientId);
1126
1277
  this.garbageCollector.setConnectionState(connected, clientId);
1127
1278
  raiseConnectedEvent(this.mc.logger, this, connected, clientId);
1128
1279
  }
@@ -1205,23 +1356,28 @@ export class ContainerRuntime extends TypedEventEmitter {
1205
1356
  const { local } = messageWithContext;
1206
1357
  switch (messageWithContext.message.type) {
1207
1358
  case ContainerMessageType.Attach:
1208
- this.dataStores.processAttachMessage(messageWithContext.message, local);
1209
- break;
1210
1359
  case ContainerMessageType.Alias:
1211
- this.dataStores.processAliasMessage(messageWithContext.message, localOpMetadata, local);
1212
- break;
1213
1360
  case ContainerMessageType.FluidDataStoreOp:
1214
- this.dataStores.processFluidDataStoreOp(messageWithContext.message, local, localOpMetadata, (from, to) => this.garbageCollector.addedOutboundReference(from, to));
1361
+ this.channelCollection.process(messageWithContext.message, local, localOpMetadata, (from, to) => this.garbageCollector.addedOutboundReference(from, to));
1215
1362
  break;
1216
1363
  case ContainerMessageType.BlobAttach:
1217
1364
  this.blobManager.processBlobAttachOp(messageWithContext.message, local);
1218
1365
  break;
1219
1366
  case ContainerMessageType.IdAllocation:
1220
- assert(this.idCompressor !== undefined, 0x67c /* IdCompressor should be defined if enabled */);
1221
1367
  // Don't re-finalize the range if we're processing a "savedOp" in
1222
1368
  // stashed ops flow. The compressor is stashed with these ops already processed.
1223
- if (messageWithContext.message.metadata?.savedOp !== true) {
1224
- this.idCompressor.finalizeCreationRange(messageWithContext.message.contents);
1369
+ // That said, in idCompressorMode === "delayed", we might not serialize ID compressor, and
1370
+ // thus we need to process all the ops.
1371
+ if (!(this.skipSavedCompressorOps &&
1372
+ messageWithContext.message.metadata?.savedOp ===
1373
+ true)) {
1374
+ const range = messageWithContext.message.contents;
1375
+ if (this._idCompressor === undefined) {
1376
+ this.pendingIdCompressorOps.push(range);
1377
+ }
1378
+ else {
1379
+ this._idCompressor.finalizeCreationRange(range);
1380
+ }
1225
1381
  }
1226
1382
  break;
1227
1383
  case ContainerMessageType.GC:
@@ -1308,7 +1464,15 @@ export class ContainerRuntime extends TypedEventEmitter {
1308
1464
  this.emit("signal", transformed, local);
1309
1465
  return;
1310
1466
  }
1311
- this.dataStores.processSignal(envelope.address, transformed, local);
1467
+ // Due to a mismatch between different layers in terms of
1468
+ // what is the interface of passing signals, we need to adjust
1469
+ // the signal envelope before sending it to the datastores to be processed
1470
+ const envelope2 = {
1471
+ address: envelope.address,
1472
+ contents: transformed.content,
1473
+ };
1474
+ transformed.content = envelope2;
1475
+ this.channelCollection.processSignal(transformed, local);
1312
1476
  }
1313
1477
  /**
1314
1478
  * Flush the pending ops manually.
@@ -1372,9 +1536,17 @@ export class ContainerRuntime extends TypedEventEmitter {
1372
1536
  * Returns undefined if no data store has been assigned the given alias.
1373
1537
  */
1374
1538
  async getAliasedDataStoreEntryPoint(alias) {
1375
- await this.dataStores.waitIfPendingAlias(alias);
1539
+ // Back-comapatibility:
1540
+ // There are old files that were created without using data store aliasing feature, but
1541
+ // used createRoot*DataStore*() (already removed) API. Such data stores will have isRoot = true,
1542
+ // and internalID provided by user. The expectation is that such files behave as new files, where
1543
+ // same data store instances created using aliasing feature.
1544
+ // Please also see note on name collisions in DataStores.createDataStoreId()
1545
+ await this.channelCollection.waitIfPendingAlias(alias);
1376
1546
  const internalId = this.internalId(alias);
1377
- const context = await this.dataStores.getDataStoreIfAvailable(internalId, { wait: false });
1547
+ const context = await this.channelCollection.getDataStoreIfAvailable(internalId, {
1548
+ wait: false,
1549
+ });
1378
1550
  // If the data store is not available or not an alias, return undefined.
1379
1551
  if (context === undefined || !(await context.isRoot())) {
1380
1552
  return undefined;
@@ -1386,28 +1558,20 @@ export class ContainerRuntime extends TypedEventEmitter {
1386
1558
  this.garbageCollector.nodeUpdated(`/${internalId}`, "Loaded", undefined /* timestampMs */, context.packagePath);
1387
1559
  return channel.entryPoint;
1388
1560
  }
1389
- createDetachedRootDataStore(pkg, rootDataStoreId) {
1390
- if (rootDataStoreId.includes("/")) {
1391
- throw new UsageError(`Id cannot contain slashes: '${rootDataStoreId}'`);
1392
- }
1393
- return this.dataStores.createDetachedDataStoreCore(pkg, true, rootDataStoreId);
1394
- }
1395
- createDetachedDataStore(pkg) {
1396
- return this.dataStores.createDetachedDataStoreCore(pkg, false);
1561
+ createDetachedDataStore(pkg, loadingGroupId) {
1562
+ return this.channelCollection.createDetachedDataStoreCore(pkg, loadingGroupId);
1397
1563
  }
1398
- async createDataStore(pkg) {
1399
- const id = uuid();
1400
- return channelToDataStore(await this.dataStores
1401
- ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id)
1402
- .realize(), id, this, this.dataStores, this.mc.logger);
1564
+ async createDataStore(pkg, loadingGroupId) {
1565
+ const context = this.channelCollection._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], undefined, // props
1566
+ loadingGroupId);
1567
+ return channelToDataStore(await context.realize(), context.id, this.channelCollection, this.mc.logger);
1403
1568
  }
1404
1569
  /**
1405
1570
  * @deprecated 0.16 Issue #1537, #3631
1406
1571
  */
1407
- async _createDataStoreWithProps(pkg, props, id = uuid()) {
1408
- return channelToDataStore(await this.dataStores
1409
- ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props)
1410
- .realize(), id, this, this.dataStores, this.mc.logger);
1572
+ async _createDataStoreWithProps(pkg, props) {
1573
+ const context = this.channelCollection._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], props);
1574
+ return channelToDataStore(await context.realize(), context.id, this.channelCollection, this.mc.logger);
1411
1575
  }
1412
1576
  canSendOps() {
1413
1577
  // Note that the real (non-proxy) delta manager is needed here to get the readonly info. This is because
@@ -1485,16 +1649,6 @@ export class ContainerRuntime extends TypedEventEmitter {
1485
1649
  const envelope = this.createNewSignalEnvelope(undefined /* address */, type, content);
1486
1650
  return this.submitSignalFn(envelope, targetClientId);
1487
1651
  }
1488
- /**
1489
- * Submits the signal to be sent to other clients.
1490
- * @param type - Type of the signal.
1491
- * @param content - Content of the signal.
1492
- * @param targetClientId - When specified, the signal is only sent to the provided client id.
1493
- */
1494
- submitDataStoreSignal(address, type, content, targetClientId) {
1495
- const envelope = this.createNewSignalEnvelope(address, type, content);
1496
- return this.submitSignalFn(envelope, targetClientId);
1497
- }
1498
1652
  setAttachState(attachState) {
1499
1653
  if (attachState === AttachState.Attaching) {
1500
1654
  assert(this.attachState === AttachState.Attaching, 0x12d /* "Container Context should already be in attaching state" */);
@@ -1506,7 +1660,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1506
1660
  if (attachState === AttachState.Attached && !this.hasPendingMessages()) {
1507
1661
  this.updateDocumentDirtyState(false);
1508
1662
  }
1509
- this.dataStores.setAttachState(attachState);
1663
+ this.channelCollection.setAttachState(attachState);
1510
1664
  }
1511
1665
  /**
1512
1666
  * Create a summary. Used when attaching or serializing a detached container.
@@ -1521,18 +1675,18 @@ export class ContainerRuntime extends TypedEventEmitter {
1521
1675
  this.blobManager.setRedirectTable(blobRedirectTable);
1522
1676
  }
1523
1677
  // We can finalize any allocated IDs since we're the only client
1524
- const idRange = this.idCompressor?.takeNextCreationRange();
1678
+ const idRange = this._idCompressor?.takeNextCreationRange();
1525
1679
  if (idRange !== undefined) {
1526
- this.idCompressor?.finalizeCreationRange(idRange);
1680
+ this._idCompressor?.finalizeCreationRange(idRange);
1527
1681
  }
1528
- const summarizeResult = this.dataStores.createSummary(telemetryContext);
1682
+ const summarizeResult = this.channelCollection.getAttachSummary(telemetryContext);
1529
1683
  // Wrap data store summaries in .channels subtree.
1530
1684
  wrapSummaryInChannelsTree(summarizeResult);
1531
1685
  this.addContainerStateToSummary(summarizeResult, true /* fullTree */, false /* trackState */, telemetryContext);
1532
1686
  return summarizeResult.summary;
1533
1687
  }
1534
1688
  async summarizeInternal(fullTree, trackState, telemetryContext) {
1535
- const summarizeResult = await this.dataStores.summarize(fullTree, trackState, telemetryContext);
1689
+ const summarizeResult = await this.channelCollection.summarize(fullTree, trackState, telemetryContext);
1536
1690
  // Wrap data store summaries in .channels subtree.
1537
1691
  wrapSummaryInChannelsTree(summarizeResult);
1538
1692
  const pathPartsForChildren = [channelsTreeName];
@@ -1580,10 +1734,10 @@ export class ContainerRuntime extends TypedEventEmitter {
1580
1734
  * @see IGarbageCollectionRuntime.updateStateBeforeGC
1581
1735
  */
1582
1736
  async updateStateBeforeGC() {
1583
- return this.dataStores.updateStateBeforeGC();
1737
+ return this.channelCollection.updateStateBeforeGC();
1584
1738
  }
1585
1739
  async getGCDataInternal(fullGC) {
1586
- return this.dataStores.getGCData(fullGC);
1740
+ return this.channelCollection.getGCData(fullGC);
1587
1741
  }
1588
1742
  /**
1589
1743
  * Generates and returns the GC data for this container.
@@ -1609,7 +1763,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1609
1763
  // always referenced, so the used routes is only self-route (empty string).
1610
1764
  this.summarizerNode.updateUsedRoutes([""]);
1611
1765
  const { dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(usedRoutes);
1612
- this.dataStores.updateUsedRoutes(dataStoreRoutes);
1766
+ this.channelCollection.updateUsedRoutes(dataStoreRoutes);
1613
1767
  }
1614
1768
  /**
1615
1769
  * This is called to update objects whose routes are unused.
@@ -1618,7 +1772,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1618
1772
  updateUnusedRoutes(unusedRoutes) {
1619
1773
  const { blobManagerRoutes, dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(unusedRoutes);
1620
1774
  this.blobManager.updateUnusedRoutes(blobManagerRoutes);
1621
- this.dataStores.updateUnusedRoutes(dataStoreRoutes);
1775
+ this.channelCollection.updateUnusedRoutes(dataStoreRoutes);
1622
1776
  }
1623
1777
  /**
1624
1778
  * @deprecated Replaced by deleteSweepReadyNodes.
@@ -1633,7 +1787,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1633
1787
  */
1634
1788
  deleteSweepReadyNodes(sweepReadyRoutes) {
1635
1789
  const { dataStoreRoutes, blobManagerRoutes } = this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
1636
- const deletedRoutes = this.dataStores.deleteSweepReadyNodes(dataStoreRoutes);
1790
+ const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
1637
1791
  return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
1638
1792
  }
1639
1793
  /**
@@ -1647,7 +1801,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1647
1801
  updateTombstonedRoutes(tombstonedRoutes) {
1648
1802
  const { blobManagerRoutes, dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(tombstonedRoutes);
1649
1803
  this.blobManager.updateTombstonedRoutes(blobManagerRoutes);
1650
- this.dataStores.updateTombstonedRoutes(dataStoreRoutes);
1804
+ this.channelCollection.updateTombstonedRoutes(dataStoreRoutes);
1651
1805
  }
1652
1806
  /**
1653
1807
  * Returns a server generated referenced timestamp to be used to track unreferenced nodes by GC.
@@ -1665,7 +1819,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1665
1819
  if (this.isBlobPath(nodePath)) {
1666
1820
  return GCNodeType.Blob;
1667
1821
  }
1668
- return this.dataStores.getGCNodeType(nodePath) ?? GCNodeType.Other;
1822
+ return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
1669
1823
  }
1670
1824
  /**
1671
1825
  * Called by GC to retrieve the package path of the node with the given path. The node should belong to a
@@ -1682,7 +1836,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1682
1836
  return [BlobManager.basePath];
1683
1837
  case GCNodeType.DataStore:
1684
1838
  case GCNodeType.SubDataStore:
1685
- return this.dataStores.getDataStorePackagePath(nodePath);
1839
+ return this.channelCollection.getDataStorePackagePath(nodePath);
1686
1840
  default:
1687
1841
  assert(false, 0x2de /* "Package path requested for unsupported node type." */);
1688
1842
  }
@@ -1741,7 +1895,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1741
1895
  * @param options - options controlling how the summary is generated or submitted
1742
1896
  */
1743
1897
  async submitSummary(options) {
1744
- const { fullTree = false, finalAttempt = false, refreshLatestAck, summaryLogger } = options;
1898
+ const { fullTree = false, finalAttempt = false, refreshLatestAck, summaryLogger, latestSummaryRefSeqNum, } = options;
1745
1899
  // The summary number for this summary. This will be updated during the summary process, so get it now and
1746
1900
  // use it for all events logged during this summary.
1747
1901
  const summaryNumber = this.nextSummaryNumber;
@@ -1753,7 +1907,6 @@ export class ContainerRuntime extends TypedEventEmitter {
1753
1907
  });
1754
1908
  assert(this.outbox.isEmpty, 0x3d1 /* Can't trigger summary in the middle of a batch */);
1755
1909
  // We close the summarizer and download a new snapshot and reload the container
1756
- let latestSnapshotVersionId;
1757
1910
  if (refreshLatestAck === true) {
1758
1911
  return this.prefetchLatestSummaryThenClose(createChildLogger({
1759
1912
  logger: summaryNumberLogger,
@@ -1795,6 +1948,7 @@ export class ContainerRuntime extends TypedEventEmitter {
1795
1948
  }
1796
1949
  }
1797
1950
  const shouldPauseInboundSignal = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause") !== true;
1951
+ const shouldValidatePreSummaryState = this.mc.config.getBoolean("Fluid.ContainerRuntime.SubmitSummary.shouldValidatePreSummaryState") === true;
1798
1952
  let summaryRefSeqNum;
1799
1953
  try {
1800
1954
  await this.deltaManager.inbound.pause();
@@ -1805,7 +1959,25 @@ export class ContainerRuntime extends TypedEventEmitter {
1805
1959
  const minimumSequenceNumber = this.deltaManager.minimumSequenceNumber;
1806
1960
  const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
1807
1961
  const lastAck = this.summaryCollection.latestAck;
1808
- this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger);
1962
+ const startSummaryResult = this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger, latestSummaryRefSeqNum);
1963
+ if (startSummaryResult.invalidNodes > 0 ||
1964
+ startSummaryResult.mismatchNumbers.size > 0) {
1965
+ summaryLogger.sendErrorEvent({
1966
+ eventName: "LatestSummaryRefSeqNumMismatch",
1967
+ details: {
1968
+ ...startSummaryResult,
1969
+ mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
1970
+ },
1971
+ });
1972
+ if (shouldValidatePreSummaryState && !finalAttempt) {
1973
+ return {
1974
+ stage: "base",
1975
+ referenceSequenceNumber: summaryRefSeqNum,
1976
+ minimumSequenceNumber,
1977
+ error: `Summarizer node state inconsistent with summarizer state.`,
1978
+ };
1979
+ }
1980
+ }
1809
1981
  // Helper function to check whether we should still continue between each async step.
1810
1982
  const checkContinue = () => {
1811
1983
  // Do not check for loss of connectivity directly! Instead leave it up to
@@ -1901,8 +2073,8 @@ export class ContainerRuntime extends TypedEventEmitter {
1901
2073
  ? calculateStats(summaryTree.tree[gcTreeKey])
1902
2074
  : undefined;
1903
2075
  const summaryStats = {
1904
- dataStoreCount: this.dataStores.size,
1905
- summarizedDataStoreCount: this.dataStores.size - handleCount,
2076
+ dataStoreCount: this.channelCollection.size,
2077
+ summarizedDataStoreCount: this.channelCollection.size - handleCount,
1906
2078
  gcStateUpdatedDataStoreCount: this.garbageCollector.updatedDSCountSinceLastSummary,
1907
2079
  gcBlobNodeCount: gcSummaryTreeStats?.blobNodeCount,
1908
2080
  gcTotalBlobsSize: gcSummaryTreeStats?.totalBlobSize,
@@ -1921,34 +2093,17 @@ export class ContainerRuntime extends TypedEventEmitter {
1921
2093
  if (!continueResult.continue) {
1922
2094
  return { stage: "generate", ...generateSummaryData, error: continueResult.error };
1923
2095
  }
1924
- // It may happen that the lastAck it not correct due to missing summaryAck in case of single commit
1925
- // summary. So if the previous summarizer closes just after submitting the summary and before
1926
- // submitting the summaryOp then we can't rely on summaryAck. So in case we have
1927
- // latestSnapshotVersionId from storage and it does not match with the lastAck ackHandle, then use
1928
- // the one fetched from storage as parent as that is the latest.
1929
- let summaryContext;
1930
- if (lastAck?.summaryAck.contents.handle !== latestSnapshotVersionId &&
1931
- latestSnapshotVersionId !== undefined) {
1932
- summaryContext = {
1933
- proposalHandle: undefined,
1934
- ackHandle: latestSnapshotVersionId,
1935
- referenceSequenceNumber: summaryRefSeqNum,
1936
- };
1937
- }
1938
- else if (lastAck === undefined) {
1939
- summaryContext = {
2096
+ const summaryContext = lastAck === undefined
2097
+ ? {
1940
2098
  proposalHandle: undefined,
1941
2099
  ackHandle: this.loadedFromVersionId,
1942
2100
  referenceSequenceNumber: summaryRefSeqNum,
1943
- };
1944
- }
1945
- else {
1946
- summaryContext = {
2101
+ }
2102
+ : {
1947
2103
  proposalHandle: lastAck.summaryOp.contents.handle,
1948
2104
  ackHandle: lastAck.summaryAck.contents.handle,
1949
2105
  referenceSequenceNumber: summaryRefSeqNum,
1950
2106
  };
1951
- }
1952
2107
  let handle;
1953
2108
  try {
1954
2109
  handle = await this.storage.uploadSummaryWithContext(summarizeResult.summary, summaryContext);
@@ -2073,48 +2228,29 @@ export class ContainerRuntime extends TypedEventEmitter {
2073
2228
  this.emit(dirty ? "dirty" : "saved");
2074
2229
  }
2075
2230
  }
2076
- submitDataStoreOp(id, contents, localOpMetadata = undefined) {
2077
- const envelope = {
2078
- address: id,
2079
- contents,
2080
- };
2081
- this.submit({ type: ContainerMessageType.FluidDataStoreOp, contents: envelope }, localOpMetadata);
2082
- }
2083
- submitDataStoreAliasOp(contents, localOpMetadata) {
2084
- const aliasMessage = contents;
2085
- if (!isDataStoreAliasMessage(aliasMessage)) {
2086
- throw new UsageError("malformedDataStoreAliasMessage");
2087
- }
2088
- this.submit({ type: ContainerMessageType.Alias, contents }, localOpMetadata);
2231
+ submitMessage(type, contents, localOpMetadata = undefined) {
2232
+ this.submit({ type, contents }, localOpMetadata);
2089
2233
  }
2090
2234
  async uploadBlob(blob, signal) {
2091
2235
  this.verifyNotClosed();
2092
2236
  return this.blobManager.createBlob(blob, signal);
2093
2237
  }
2094
- maybeSubmitIdAllocationOp(type) {
2095
- if (type !== ContainerMessageType.IdAllocation) {
2096
- let idAllocationBatchMessage;
2097
- let idRange;
2098
- if (this.idCompressorEnabled) {
2099
- assert(this.idCompressor !== undefined, 0x67d /* IdCompressor should be defined if enabled */);
2100
- idRange = this.idCompressor.takeNextCreationRange();
2101
- // Don't include the idRange if there weren't any Ids allocated
2102
- idRange = idRange?.ids !== undefined ? idRange : undefined;
2103
- }
2104
- if (idRange !== undefined) {
2238
+ submitIdAllocationOpIfNeeded() {
2239
+ if (this._idCompressor) {
2240
+ const idRange = this._idCompressor.takeNextCreationRange();
2241
+ // Don't include the idRange if there weren't any Ids allocated
2242
+ if (idRange?.ids !== undefined) {
2105
2243
  const idAllocationMessage = {
2106
2244
  type: ContainerMessageType.IdAllocation,
2107
2245
  contents: idRange,
2108
2246
  };
2109
- idAllocationBatchMessage = {
2247
+ const idAllocationBatchMessage = {
2110
2248
  contents: JSON.stringify(idAllocationMessage),
2111
2249
  referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
2112
2250
  metadata: undefined,
2113
2251
  localOpMetadata: undefined,
2114
2252
  type: ContainerMessageType.IdAllocation,
2115
2253
  };
2116
- }
2117
- if (idAllocationBatchMessage !== undefined) {
2118
2254
  this.outbox.submitIdAllocation(idAllocationBatchMessage);
2119
2255
  }
2120
2256
  }
@@ -2142,42 +2278,47 @@ export class ContainerRuntime extends TypedEventEmitter {
2142
2278
  referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
2143
2279
  };
2144
2280
  try {
2145
- // Submit an IdAllocation op if any Ids have been generated since
2146
- // the last op was submitted. Don't submit another if it's an IdAllocation
2147
- // op as that means we're in resubmission flow and we don't want to send
2148
- // IdRanges out of order.
2149
- this.maybeSubmitIdAllocationOp(type);
2150
- // If this is attach message for new data store, and we are in a batch, send this op out of order
2151
- // Is it safe:
2152
- // Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
2153
- // They become visible only when aliased, or handle to some sub-element of newly created datastore
2154
- // is stored in some DDS, i.e. only after some other op.
2155
- // Why:
2156
- // Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
2157
- // stores are created, causing issues like relay service throttling (too many ops) and catastrophic
2158
- // failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
2159
- // these issues.
2160
- // Cons:
2161
- // 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
2162
- // This change creates new possibility of a lot of newly created data stores never being referenced
2163
- // because client died before it had a change to submit the rest of the ops. This will create more
2164
- // garbage that needs to be collected leveraging GC (Garbage Collection) feature.
2165
- // 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
2166
- // today as rollback can't undo creation of data store. To some extent not sending them is a bigger
2167
- // issue than sending.
2168
- // Please note that this does not change file format, so it can be disabled in the future if this
2169
- // optimization no longer makes sense (for example, batch compression may make it less appealing).
2170
- if (this.currentlyBatching() &&
2171
- type === ContainerMessageType.Attach &&
2172
- this.disableAttachReorder !== true) {
2173
- this.outbox.submitAttach(message);
2174
- }
2175
- else if (type === ContainerMessageType.BlobAttach) {
2176
- // BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
2177
- this.outbox.submitBlobAttach(message);
2281
+ // If `message` is an allocation op, then we are in the resubmit path and we must redirect the allocation
2282
+ // op into the correct batch to avoid ranges being finalized out of order.
2283
+ // Otherwise, submit an IdAllocation op if any IDs have been generated since the last op was submitted, as
2284
+ // any of the other op types may contain those IDs and thus depend on the allocation op being sent first.
2285
+ if (type === ContainerMessageType.IdAllocation) {
2286
+ this.outbox.submitIdAllocation(message);
2178
2287
  }
2179
2288
  else {
2180
- this.outbox.submit(message);
2289
+ this.submitIdAllocationOpIfNeeded();
2290
+ // If this is attach message for new data store, and we are in a batch, send this op out of order
2291
+ // Is it safe:
2292
+ // Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
2293
+ // They become visible only when aliased, or handle to some sub-element of newly created datastore
2294
+ // is stored in some DDS, i.e. only after some other op.
2295
+ // Why:
2296
+ // Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
2297
+ // stores are created, causing issues like relay service throttling (too many ops) and catastrophic
2298
+ // failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
2299
+ // these issues.
2300
+ // Cons:
2301
+ // 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
2302
+ // This change creates new possibility of a lot of newly created data stores never being referenced
2303
+ // because client died before it had a change to submit the rest of the ops. This will create more
2304
+ // garbage that needs to be collected leveraging GC (Garbage Collection) feature.
2305
+ // 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
2306
+ // today as rollback can't undo creation of data store. To some extent not sending them is a bigger
2307
+ // issue than sending.
2308
+ // Please note that this does not change file format, so it can be disabled in the future if this
2309
+ // optimization no longer makes sense (for example, batch compression may make it less appealing).
2310
+ if (this.currentlyBatching() &&
2311
+ type === ContainerMessageType.Attach &&
2312
+ this.disableAttachReorder !== true) {
2313
+ this.outbox.submitAttach(message);
2314
+ }
2315
+ else if (type === ContainerMessageType.BlobAttach) {
2316
+ // BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
2317
+ this.outbox.submitBlobAttach(message);
2318
+ }
2319
+ else {
2320
+ this.outbox.submit(message);
2321
+ }
2181
2322
  }
2182
2323
  if (!this.currentlyBatching()) {
2183
2324
  this.flush();
@@ -2293,15 +2434,15 @@ export class ContainerRuntime extends TypedEventEmitter {
2293
2434
  * @param localOpMetadata - The local metadata associated with the original message.
2294
2435
  */
2295
2436
  reSubmitCore(message, localOpMetadata, opMetadata) {
2296
- assert(!this.isSummarizerClient, "Summarizer never reconnects so should never resubmit");
2437
+ assert(!this.isSummarizerClient, 0x8f2 /* Summarizer never reconnects so should never resubmit */);
2297
2438
  switch (message.type) {
2298
2439
  case ContainerMessageType.FluidDataStoreOp:
2440
+ case ContainerMessageType.Attach:
2441
+ case ContainerMessageType.Alias:
2299
2442
  // For Operations, call resubmitDataStoreOp which will find the right store
2300
2443
  // and trigger resubmission on it.
2301
- this.dataStores.resubmitDataStoreOp(message.contents, localOpMetadata);
2444
+ this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
2302
2445
  break;
2303
- case ContainerMessageType.Attach:
2304
- case ContainerMessageType.Alias:
2305
2446
  case ContainerMessageType.IdAllocation: {
2306
2447
  this.submit(message, localOpMetadata);
2307
2448
  break;
@@ -2319,9 +2460,10 @@ export class ContainerRuntime extends TypedEventEmitter {
2319
2460
  break;
2320
2461
  default: {
2321
2462
  // This case should be very rare - it would imply an op was stashed from a
2322
- // future version of runtime code and now is being applied on an older version
2463
+ // future version of runtime code and now is being applied on an older version.
2323
2464
  const compatBehavior = message.compatDetails?.behavior;
2324
2465
  if (compatBehaviorAllowsMessageType(message.type, compatBehavior)) {
2466
+ // We do not ultimately resubmit it, to be consistent with this version of the code.
2325
2467
  this.logger.sendTelemetryEvent({
2326
2468
  eventName: "resubmitUnrecognizedMessageTypeAllowed",
2327
2469
  messageDetails: { type: message.type, compatBehavior },
@@ -2347,7 +2489,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2347
2489
  case ContainerMessageType.FluidDataStoreOp:
2348
2490
  // For operations, call rollbackDataStoreOp which will find the right store
2349
2491
  // and trigger rollback on it.
2350
- this.dataStores.rollbackDataStoreOp(contents, localOpMetadata);
2492
+ this.channelCollection.rollback(type, contents, localOpMetadata);
2351
2493
  break;
2352
2494
  default:
2353
2495
  // Don't check message.compatDetails because this is for rolling back a local op so the type will be known
@@ -2368,31 +2510,12 @@ export class ContainerRuntime extends TypedEventEmitter {
2368
2510
  * and then close as the current main client is likely to be re-elected as the parent summarizer again.
2369
2511
  */
2370
2512
  if (!result.isSummaryTracked && result.isSummaryNewer) {
2371
- const fetchResult = await this.fetchLatestSnapshotFromStorage(summaryLogger, {
2513
+ await this.fetchLatestSnapshotFromStorage(summaryLogger, {
2372
2514
  eventName: "RefreshLatestSummaryAckFetch",
2373
2515
  ackHandle,
2374
2516
  targetSequenceNumber: summaryRefSeq,
2375
2517
  }, readAndParseBlob);
2376
- /**
2377
- * If the fetched snapshot is older than the one for which the ack was received, close the container.
2378
- * This should never happen because an ack should be sent after the latest summary is updated in the server.
2379
- * However, there are couple of scenarios where it's possible:
2380
- * 1. A file was modified externally resulting in modifying the snapshot's sequence number. This can lead to
2381
- * the document being unusable and we should not proceed.
2382
- * 2. The server DB failed after the ack was sent which may delete the corresponding snapshot. Ideally, in
2383
- * such cases, the file will be rolled back along with the ack and we will eventually reach a consistent
2384
- * state.
2385
- */
2386
- if (fetchResult.latestSnapshotRefSeq < summaryRefSeq) {
2387
- const error = DataProcessingError.create("Fetched snapshot is older than the received ack", "RefreshLatestSummaryAck", undefined /* sequencedMessage */, {
2388
- ackHandle,
2389
- summaryRefSeq,
2390
- fetchedSnapshotRefSeq: fetchResult.latestSnapshotRefSeq,
2391
- });
2392
- this.disposeFn(error);
2393
- throw error;
2394
- }
2395
- await this.closeStaleSummarizer("RefreshLatestSummaryAckFetch");
2518
+ await this.closeStaleSummarizer();
2396
2519
  return;
2397
2520
  }
2398
2521
  // Notify the garbage collector so it can update its latest summary state.
@@ -2411,7 +2534,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2411
2534
  await this.fetchLatestSnapshotFromStorage(summaryLogger, {
2412
2535
  eventName: "RefreshLatestSummaryFromServerFetch",
2413
2536
  }, readAndParseBlob);
2414
- await this.closeStaleSummarizer("RefreshLatestSummaryFromServerFetch");
2537
+ await this.closeStaleSummarizer();
2415
2538
  return {
2416
2539
  stage: "base",
2417
2540
  error: "summary state stale - Unsupported option 'refreshLatestAck'",
@@ -2419,7 +2542,7 @@ export class ContainerRuntime extends TypedEventEmitter {
2419
2542
  minimumSequenceNumber: this.deltaManager.minimumSequenceNumber,
2420
2543
  };
2421
2544
  }
2422
- async closeStaleSummarizer(codePath) {
2545
+ async closeStaleSummarizer() {
2423
2546
  // Delay before restarting summarizer to prevent the summarizer from restarting too frequently.
2424
2547
  await delay(this.closeSummarizerDelayMs);
2425
2548
  this._summarizer?.stop("latestSummaryStateStale");
@@ -2451,44 +2574,43 @@ export class ContainerRuntime extends TypedEventEmitter {
2451
2574
  };
2452
2575
  });
2453
2576
  }
2454
- async getPendingLocalState(props) {
2455
- return PerformanceEvent.timedExecAsync(this.mc.logger, {
2456
- eventName: "getPendingLocalState",
2457
- notifyImminentClosure: props?.notifyImminentClosure,
2458
- }, async (event) => {
2459
- this.verifyNotClosed();
2460
- // in case imminentClosure is set to true by future code, we don't
2461
- // try to change its value
2462
- if (!this.imminentClosure) {
2463
- this.imminentClosure = props?.notifyImminentClosure ?? this.imminentClosure;
2464
- }
2465
- const stopBlobAttachingSignal = props?.stopBlobAttachingSignal;
2466
- if (this._orderSequentiallyCalls !== 0) {
2467
- throw new UsageError("can't get state during orderSequentially");
2468
- }
2469
- // Flush pending batch.
2470
- // getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
2471
- // to close current batch.
2472
- this.flush();
2473
- const pendingAttachmentBlobs = this.imminentClosure
2474
- ? await this.blobManager.attachAndGetPendingBlobs(stopBlobAttachingSignal)
2475
- : undefined;
2577
+ getPendingLocalState(props) {
2578
+ this.verifyNotClosed();
2579
+ if (this._orderSequentiallyCalls !== 0) {
2580
+ throw new UsageError("can't get state during orderSequentially");
2581
+ }
2582
+ this.imminentClosure || (this.imminentClosure = props?.notifyImminentClosure ?? false);
2583
+ const getSyncState = (pendingAttachmentBlobs) => {
2476
2584
  const pending = this.pendingStateManager.getLocalState();
2477
- if (!pendingAttachmentBlobs && !this.hasPendingMessages()) {
2585
+ if (pendingAttachmentBlobs === undefined && !this.hasPendingMessages()) {
2478
2586
  return; // no pending state to save
2479
2587
  }
2480
- const pendingIdCompressorState = this.idCompressor?.serialize(true);
2481
- const pendingState = {
2588
+ const pendingIdCompressorState = this._idCompressor?.serialize(true);
2589
+ return {
2482
2590
  pending,
2483
- pendingAttachmentBlobs,
2484
2591
  pendingIdCompressorState,
2592
+ pendingAttachmentBlobs,
2593
+ sessionExpiryTimerStarted: this.garbageCollector.sessionExpiryTimerStarted,
2485
2594
  };
2595
+ };
2596
+ const perfEvent = {
2597
+ eventName: "getPendingLocalState",
2598
+ notifyImminentClosure: props?.notifyImminentClosure,
2599
+ };
2600
+ const logAndReturnPendingState = (event, pendingState) => {
2486
2601
  event.end({
2487
- attachmentBlobsSize: Object.keys(pendingAttachmentBlobs ?? {}).length,
2488
- pendingOpsSize: pending?.pendingStates.length,
2602
+ attachmentBlobsSize: Object.keys(pendingState?.pendingAttachmentBlobs ?? {}).length,
2603
+ pendingOpsSize: pendingState?.pending?.pendingStates.length,
2489
2604
  });
2490
2605
  return pendingState;
2491
- });
2606
+ };
2607
+ // Flush pending batch.
2608
+ // getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
2609
+ // to close current batch.
2610
+ this.flush();
2611
+ return props?.notifyImminentClosure === true
2612
+ ? PerformanceEvent.timedExecAsync(this.mc.logger, perfEvent, async (event) => logAndReturnPendingState(event, getSyncState(await this.blobManager.attachAndGetPendingBlobs(props?.stopBlobAttachingSignal))))
2613
+ : PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) => logAndReturnPendingState(event, getSyncState()));
2492
2614
  }
2493
2615
  summarizeOnDemand(options) {
2494
2616
  if (this.isSummarizerClient) {
@@ -2542,4 +2664,4 @@ export class ContainerRuntime extends TypedEventEmitter {
2542
2664
  return killSwitch !== true && this.runtimeOptions.enableGroupedBatching;
2543
2665
  }
2544
2666
  }
2545
- //# sourceMappingURL=containerRuntime.mjs.map
2667
+ //# sourceMappingURL=containerRuntime.js.map