@fluidframework/container-runtime 2.0.0-dev-rc.1.0.0.232845 → 2.0.0-dev-rc.2.0.0.246488

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 (700) hide show
  1. package/.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 +426 -33
  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.d.ts +0 -5
  13. package/dist/blobManager.d.ts.map +1 -1
  14. package/dist/blobManager.js +0 -12
  15. package/dist/blobManager.js.map +1 -1
  16. package/dist/channelCollection.d.ts +226 -0
  17. package/dist/channelCollection.d.ts.map +1 -0
  18. package/dist/{dataStores.js → channelCollection.js} +455 -150
  19. package/dist/channelCollection.js.map +1 -0
  20. package/dist/connectionTelemetry.d.ts +11 -1
  21. package/dist/connectionTelemetry.d.ts.map +1 -1
  22. package/dist/connectionTelemetry.js +42 -4
  23. package/dist/connectionTelemetry.js.map +1 -1
  24. package/dist/container-runtime-alpha.d.ts +128 -48
  25. package/dist/container-runtime-beta.d.ts +67 -9
  26. package/dist/container-runtime-public.d.ts +67 -9
  27. package/dist/container-runtime-untrimmed.d.ts +692 -49
  28. package/dist/containerHandleContext.d.ts +1 -1
  29. package/dist/containerHandleContext.d.ts.map +1 -1
  30. package/dist/containerHandleContext.js.map +1 -1
  31. package/dist/containerRuntime.d.ts +81 -64
  32. package/dist/containerRuntime.d.ts.map +1 -1
  33. package/dist/containerRuntime.js +522 -379
  34. package/dist/containerRuntime.js.map +1 -1
  35. package/dist/dataStore.d.ts +2 -3
  36. package/dist/dataStore.d.ts.map +1 -1
  37. package/dist/dataStore.js +12 -11
  38. package/dist/dataStore.js.map +1 -1
  39. package/dist/dataStoreContext.d.ts +118 -41
  40. package/dist/dataStoreContext.d.ts.map +1 -1
  41. package/dist/dataStoreContext.js +248 -159
  42. package/dist/dataStoreContext.js.map +1 -1
  43. package/dist/dataStoreContexts.d.ts +2 -1
  44. package/dist/dataStoreContexts.d.ts.map +1 -1
  45. package/dist/dataStoreContexts.js +1 -0
  46. package/dist/dataStoreContexts.js.map +1 -1
  47. package/dist/dataStoreRegistry.d.ts +4 -0
  48. package/dist/dataStoreRegistry.d.ts.map +1 -1
  49. package/dist/dataStoreRegistry.js +2 -2
  50. package/dist/dataStoreRegistry.js.map +1 -1
  51. package/dist/deltaManagerSummarizerProxy.d.ts +29 -4
  52. package/dist/deltaManagerSummarizerProxy.d.ts.map +1 -1
  53. package/dist/deltaManagerSummarizerProxy.js +91 -5
  54. package/dist/deltaManagerSummarizerProxy.js.map +1 -1
  55. package/dist/gc/garbageCollection.d.ts +12 -6
  56. package/dist/gc/garbageCollection.d.ts.map +1 -1
  57. package/dist/gc/garbageCollection.js +116 -78
  58. package/dist/gc/garbageCollection.js.map +1 -1
  59. package/dist/gc/gcConfigs.d.ts +2 -2
  60. package/dist/gc/gcConfigs.d.ts.map +1 -1
  61. package/dist/gc/gcConfigs.js +30 -23
  62. package/dist/gc/gcConfigs.js.map +1 -1
  63. package/dist/gc/gcDefinitions.d.ts +22 -13
  64. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  65. package/dist/gc/gcDefinitions.js +7 -4
  66. package/dist/gc/gcDefinitions.js.map +1 -1
  67. package/dist/gc/gcHelpers.d.ts +2 -2
  68. package/dist/gc/gcHelpers.d.ts.map +1 -1
  69. package/dist/gc/gcHelpers.js.map +1 -1
  70. package/dist/gc/gcReferenceGraphAlgorithm.d.ts +1 -1
  71. package/dist/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -1
  72. package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -1
  73. package/dist/gc/gcSummaryStateTracker.d.ts +12 -5
  74. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
  75. package/dist/gc/gcSummaryStateTracker.js +18 -6
  76. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  77. package/dist/gc/gcTelemetry.d.ts +6 -7
  78. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  79. package/dist/gc/gcTelemetry.js +20 -18
  80. package/dist/gc/gcTelemetry.js.map +1 -1
  81. package/dist/gc/gcUnreferencedStateTracker.d.ts +1 -1
  82. package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
  83. package/dist/gc/gcUnreferencedStateTracker.js +10 -10
  84. package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
  85. package/dist/gc/index.d.ts +8 -8
  86. package/dist/gc/index.d.ts.map +1 -1
  87. package/dist/gc/index.js +40 -39
  88. package/dist/gc/index.js.map +1 -1
  89. package/dist/index.d.ts +11 -21
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +36 -42
  92. package/dist/index.js.map +1 -1
  93. package/dist/messageTypes.d.ts +3 -3
  94. package/dist/messageTypes.d.ts.map +1 -1
  95. package/dist/messageTypes.js.map +1 -1
  96. package/dist/opLifecycle/batchManager.d.ts +2 -2
  97. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  98. package/dist/opLifecycle/batchManager.js.map +1 -1
  99. package/dist/opLifecycle/definitions.d.ts +2 -2
  100. package/dist/opLifecycle/definitions.d.ts.map +1 -1
  101. package/dist/opLifecycle/definitions.js.map +1 -1
  102. package/dist/opLifecycle/index.d.ts +8 -8
  103. package/dist/opLifecycle/index.d.ts.map +1 -1
  104. package/dist/opLifecycle/index.js +18 -18
  105. package/dist/opLifecycle/index.js.map +1 -1
  106. package/dist/opLifecycle/opCompressor.d.ts +1 -1
  107. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  108. package/dist/opLifecycle/opCompressor.js +4 -4
  109. package/dist/opLifecycle/opCompressor.js.map +1 -1
  110. package/dist/opLifecycle/opDecompressor.d.ts +1 -1
  111. package/dist/opLifecycle/opDecompressor.d.ts.map +1 -1
  112. package/dist/opLifecycle/opDecompressor.js +3 -3
  113. package/dist/opLifecycle/opDecompressor.js.map +1 -1
  114. package/dist/opLifecycle/opGroupingManager.d.ts +1 -1
  115. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  116. package/dist/opLifecycle/opGroupingManager.js +1 -10
  117. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  118. package/dist/opLifecycle/opSplitter.d.ts +1 -1
  119. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  120. package/dist/opLifecycle/opSplitter.js +5 -5
  121. package/dist/opLifecycle/opSplitter.js.map +1 -1
  122. package/dist/opLifecycle/outbox.d.ts +7 -7
  123. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  124. package/dist/opLifecycle/outbox.js +32 -18
  125. package/dist/opLifecycle/outbox.js.map +1 -1
  126. package/dist/opLifecycle/remoteMessageProcessor.d.ts +4 -4
  127. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  128. package/dist/opLifecycle/remoteMessageProcessor.js +7 -4
  129. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  130. package/dist/package.json +3 -0
  131. package/dist/packageVersion.d.ts +1 -1
  132. package/dist/packageVersion.js +1 -1
  133. package/dist/packageVersion.js.map +1 -1
  134. package/dist/pendingStateManager.d.ts +2 -1
  135. package/dist/pendingStateManager.d.ts.map +1 -1
  136. package/dist/pendingStateManager.js +18 -10
  137. package/dist/pendingStateManager.js.map +1 -1
  138. package/dist/scheduleManager.d.ts +1 -2
  139. package/dist/scheduleManager.d.ts.map +1 -1
  140. package/dist/scheduleManager.js +9 -5
  141. package/dist/scheduleManager.js.map +1 -1
  142. package/dist/summary/index.d.ts +12 -12
  143. package/dist/summary/index.d.ts.map +1 -1
  144. package/dist/summary/index.js +43 -43
  145. package/dist/summary/index.js.map +1 -1
  146. package/dist/summary/orderedClientElection.d.ts.map +1 -1
  147. package/dist/summary/orderedClientElection.js +12 -8
  148. package/dist/summary/orderedClientElection.js.map +1 -1
  149. package/dist/summary/runWhileConnectedCoordinator.d.ts +1 -1
  150. package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -1
  151. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
  152. package/dist/summary/runningSummarizer.d.ts +5 -4
  153. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  154. package/dist/summary/runningSummarizer.js +47 -32
  155. package/dist/summary/runningSummarizer.js.map +1 -1
  156. package/dist/summary/summarizer.d.ts +4 -4
  157. package/dist/summary/summarizer.d.ts.map +1 -1
  158. package/dist/summary/summarizer.js +6 -6
  159. package/dist/summary/summarizer.js.map +1 -1
  160. package/dist/summary/summarizerClientElection.d.ts +2 -2
  161. package/dist/summary/summarizerClientElection.d.ts.map +1 -1
  162. package/dist/summary/summarizerClientElection.js.map +1 -1
  163. package/dist/summary/summarizerHeuristics.d.ts +3 -3
  164. package/dist/summary/summarizerHeuristics.d.ts.map +1 -1
  165. package/dist/summary/summarizerHeuristics.js.map +1 -1
  166. package/dist/summary/summarizerNode/index.d.ts +3 -3
  167. package/dist/summary/summarizerNode/index.d.ts.map +1 -1
  168. package/dist/summary/summarizerNode/index.js +4 -4
  169. package/dist/summary/summarizerNode/index.js.map +1 -1
  170. package/dist/summary/summarizerNode/summarizerNode.d.ts +16 -5
  171. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  172. package/dist/summary/summarizerNode/summarizerNode.js +40 -10
  173. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  174. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +9 -1
  175. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  176. package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -1
  177. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -4
  178. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  179. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +12 -12
  180. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  181. package/dist/summary/summarizerTypes.d.ts +9 -20
  182. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  183. package/dist/summary/summarizerTypes.js.map +1 -1
  184. package/dist/summary/summaryFormat.d.ts +15 -2
  185. package/dist/summary/summaryFormat.d.ts.map +1 -1
  186. package/dist/summary/summaryFormat.js.map +1 -1
  187. package/dist/summary/summaryGenerator.d.ts +6 -5
  188. package/dist/summary/summaryGenerator.d.ts.map +1 -1
  189. package/dist/summary/summaryGenerator.js +10 -1
  190. package/dist/summary/summaryGenerator.js.map +1 -1
  191. package/dist/summary/summaryManager.d.ts +5 -6
  192. package/dist/summary/summaryManager.d.ts.map +1 -1
  193. package/dist/summary/summaryManager.js +4 -5
  194. package/dist/summary/summaryManager.js.map +1 -1
  195. package/dist/tsdoc-metadata.json +1 -1
  196. package/lib/{batchTracker.d.mts → batchTracker.d.ts} +2 -3
  197. package/lib/batchTracker.d.ts.map +1 -0
  198. package/lib/{batchTracker.mjs → batchTracker.js} +1 -1
  199. package/lib/batchTracker.js.map +1 -0
  200. package/lib/{blobManager.d.mts → blobManager.d.ts} +1 -6
  201. package/lib/blobManager.d.ts.map +1 -0
  202. package/lib/{blobManager.mjs → blobManager.js} +1 -13
  203. package/lib/blobManager.js.map +1 -0
  204. package/lib/channelCollection.d.ts +226 -0
  205. package/lib/channelCollection.d.ts.map +1 -0
  206. package/lib/{dataStores.mjs → channelCollection.js} +442 -140
  207. package/lib/channelCollection.js.map +1 -0
  208. package/lib/{connectionTelemetry.d.mts → connectionTelemetry.d.ts} +12 -2
  209. package/lib/connectionTelemetry.d.ts.map +1 -0
  210. package/lib/{connectionTelemetry.mjs → connectionTelemetry.js} +43 -5
  211. package/lib/connectionTelemetry.js.map +1 -0
  212. package/lib/{container-runtime-alpha.d.mts → container-runtime-alpha.d.ts} +128 -48
  213. package/lib/{container-runtime-beta.d.mts → container-runtime-beta.d.ts} +67 -9
  214. package/lib/{container-runtime-public.d.mts → container-runtime-public.d.ts} +67 -9
  215. package/lib/{container-runtime-untrimmed.d.mts → container-runtime-untrimmed.d.ts} +692 -49
  216. package/lib/{containerHandleContext.d.mts → containerHandleContext.d.ts} +2 -2
  217. package/lib/containerHandleContext.d.ts.map +1 -0
  218. package/lib/{containerHandleContext.mjs → containerHandleContext.js} +1 -1
  219. package/lib/containerHandleContext.js.map +1 -0
  220. package/lib/{containerRuntime.d.mts → containerRuntime.d.ts} +86 -65
  221. package/lib/containerRuntime.d.ts.map +1 -0
  222. package/lib/{containerRuntime.mjs → containerRuntime.js} +444 -303
  223. package/lib/containerRuntime.js.map +1 -0
  224. package/lib/{dataStore.d.mts → dataStore.d.ts} +3 -4
  225. package/lib/dataStore.d.ts.map +1 -0
  226. package/lib/{dataStore.mjs → dataStore.js} +13 -12
  227. package/lib/dataStore.js.map +1 -0
  228. package/lib/{dataStoreContext.d.mts → dataStoreContext.d.ts} +119 -42
  229. package/lib/dataStoreContext.d.ts.map +1 -0
  230. package/lib/{dataStoreContext.mjs → dataStoreContext.js} +240 -151
  231. package/lib/dataStoreContext.js.map +1 -0
  232. package/lib/{dataStoreContexts.d.mts → dataStoreContexts.d.ts} +3 -2
  233. package/lib/dataStoreContexts.d.ts.map +1 -0
  234. package/lib/{dataStoreContexts.mjs → dataStoreContexts.js} +2 -1
  235. package/lib/dataStoreContexts.js.map +1 -0
  236. package/lib/{dataStoreRegistry.d.mts → dataStoreRegistry.d.ts} +5 -1
  237. package/lib/dataStoreRegistry.d.ts.map +1 -0
  238. package/lib/{dataStoreRegistry.mjs → dataStoreRegistry.js} +5 -1
  239. package/lib/dataStoreRegistry.js.map +1 -0
  240. package/{dist/deltaManagerProxyBase.d.ts → lib/deltaManagerSummarizerProxy.d.ts} +16 -7
  241. package/lib/deltaManagerSummarizerProxy.d.ts.map +1 -0
  242. package/lib/deltaManagerSummarizerProxy.js +124 -0
  243. package/lib/deltaManagerSummarizerProxy.js.map +1 -0
  244. package/lib/{deltaScheduler.d.mts → deltaScheduler.d.ts} +1 -1
  245. package/lib/deltaScheduler.d.ts.map +1 -0
  246. package/lib/{deltaScheduler.mjs → deltaScheduler.js} +1 -1
  247. package/lib/deltaScheduler.js.map +1 -0
  248. package/lib/{error.d.mts → error.d.ts} +1 -1
  249. package/lib/error.d.ts.map +1 -0
  250. package/lib/{error.mjs → error.js} +1 -1
  251. package/lib/error.js.map +1 -0
  252. package/lib/gc/{garbageCollection.d.mts → garbageCollection.d.ts} +13 -7
  253. package/lib/gc/garbageCollection.d.ts.map +1 -0
  254. package/lib/gc/{garbageCollection.mjs → garbageCollection.js} +79 -41
  255. package/lib/gc/garbageCollection.js.map +1 -0
  256. package/lib/gc/{gcConfigs.d.mts → gcConfigs.d.ts} +3 -3
  257. package/lib/gc/gcConfigs.d.ts.map +1 -0
  258. package/lib/gc/{gcConfigs.mjs → gcConfigs.js} +14 -7
  259. package/lib/gc/gcConfigs.js.map +1 -0
  260. package/lib/gc/{gcDefinitions.d.mts → gcDefinitions.d.ts} +23 -14
  261. package/lib/gc/gcDefinitions.d.ts.map +1 -0
  262. package/lib/gc/{gcDefinitions.mjs → gcDefinitions.js} +7 -4
  263. package/lib/gc/gcDefinitions.js.map +1 -0
  264. package/lib/gc/{gcHelpers.d.mts → gcHelpers.d.ts} +3 -3
  265. package/lib/gc/{gcHelpers.d.mts.map → gcHelpers.d.ts.map} +1 -1
  266. package/lib/gc/{gcHelpers.mjs → gcHelpers.js} +1 -1
  267. package/lib/gc/gcHelpers.js.map +1 -0
  268. package/lib/gc/{gcReferenceGraphAlgorithm.d.mts → gcReferenceGraphAlgorithm.d.ts} +2 -2
  269. package/lib/gc/gcReferenceGraphAlgorithm.d.ts.map +1 -0
  270. package/lib/gc/{gcReferenceGraphAlgorithm.mjs → gcReferenceGraphAlgorithm.js} +1 -1
  271. package/lib/gc/gcReferenceGraphAlgorithm.js.map +1 -0
  272. package/lib/gc/{gcSummaryDefinitions.d.mts → gcSummaryDefinitions.d.ts} +1 -1
  273. package/lib/gc/gcSummaryDefinitions.d.ts.map +1 -0
  274. package/lib/gc/{gcSummaryDefinitions.mjs → gcSummaryDefinitions.js} +1 -1
  275. package/lib/gc/gcSummaryDefinitions.js.map +1 -0
  276. package/lib/gc/{gcSummaryStateTracker.d.mts → gcSummaryStateTracker.d.ts} +13 -6
  277. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -0
  278. package/lib/gc/{gcSummaryStateTracker.mjs → gcSummaryStateTracker.js} +17 -5
  279. package/lib/gc/gcSummaryStateTracker.js.map +1 -0
  280. package/lib/gc/{gcTelemetry.d.mts → gcTelemetry.d.ts} +7 -8
  281. package/lib/gc/gcTelemetry.d.ts.map +1 -0
  282. package/lib/gc/{gcTelemetry.mjs → gcTelemetry.js} +5 -3
  283. package/lib/gc/gcTelemetry.js.map +1 -0
  284. package/lib/gc/{gcUnreferencedStateTracker.d.mts → gcUnreferencedStateTracker.d.ts} +2 -2
  285. package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
  286. package/lib/gc/{gcUnreferencedStateTracker.mjs → gcUnreferencedStateTracker.js} +2 -2
  287. package/lib/gc/gcUnreferencedStateTracker.js.map +1 -0
  288. package/lib/gc/index.d.ts +13 -0
  289. package/lib/gc/index.d.ts.map +1 -0
  290. package/lib/gc/{index.mjs → index.js} +8 -8
  291. package/lib/gc/index.js.map +1 -0
  292. package/lib/{index.d.mts → index.d.ts} +12 -22
  293. package/lib/index.d.ts.map +1 -0
  294. package/lib/index.js +15 -0
  295. package/lib/index.js.map +1 -0
  296. package/lib/{messageTypes.d.mts → messageTypes.d.ts} +4 -4
  297. package/lib/messageTypes.d.ts.map +1 -0
  298. package/lib/{messageTypes.mjs → messageTypes.js} +1 -1
  299. package/lib/messageTypes.js.map +1 -0
  300. package/lib/{metadata.d.mts → metadata.d.ts} +1 -1
  301. package/lib/metadata.d.ts.map +1 -0
  302. package/lib/{metadata.mjs → metadata.js} +1 -1
  303. package/lib/metadata.js.map +1 -0
  304. package/lib/opLifecycle/{batchManager.d.mts → batchManager.d.ts} +3 -3
  305. package/lib/opLifecycle/batchManager.d.ts.map +1 -0
  306. package/lib/opLifecycle/{batchManager.mjs → batchManager.js} +1 -1
  307. package/lib/opLifecycle/batchManager.js.map +1 -0
  308. package/lib/opLifecycle/{definitions.d.mts → definitions.d.ts} +3 -3
  309. package/lib/opLifecycle/definitions.d.ts.map +1 -0
  310. package/lib/opLifecycle/{definitions.mjs → definitions.js} +1 -1
  311. package/lib/opLifecycle/definitions.js.map +1 -0
  312. package/lib/opLifecycle/index.d.ts +13 -0
  313. package/lib/opLifecycle/index.d.ts.map +1 -0
  314. package/lib/opLifecycle/index.js +12 -0
  315. package/lib/opLifecycle/index.js.map +1 -0
  316. package/lib/opLifecycle/{opCompressor.d.mts → opCompressor.d.ts} +2 -2
  317. package/lib/opLifecycle/opCompressor.d.ts.map +1 -0
  318. package/lib/opLifecycle/{opCompressor.mjs → opCompressor.js} +3 -3
  319. package/lib/opLifecycle/opCompressor.js.map +1 -0
  320. package/lib/opLifecycle/{opDecompressor.d.mts → opDecompressor.d.ts} +2 -2
  321. package/lib/opLifecycle/opDecompressor.d.ts.map +1 -0
  322. package/lib/opLifecycle/{opDecompressor.mjs → opDecompressor.js} +2 -2
  323. package/lib/opLifecycle/opDecompressor.js.map +1 -0
  324. package/lib/opLifecycle/{opGroupingManager.d.mts → opGroupingManager.d.ts} +2 -2
  325. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -0
  326. package/lib/opLifecycle/{opGroupingManager.mjs → opGroupingManager.js} +2 -11
  327. package/lib/opLifecycle/opGroupingManager.js.map +1 -0
  328. package/lib/opLifecycle/{opSplitter.d.mts → opSplitter.d.ts} +2 -2
  329. package/lib/opLifecycle/opSplitter.d.ts.map +1 -0
  330. package/lib/opLifecycle/{opSplitter.mjs → opSplitter.js} +3 -3
  331. package/lib/opLifecycle/opSplitter.js.map +1 -0
  332. package/lib/opLifecycle/{outbox.d.mts → outbox.d.ts} +8 -8
  333. package/lib/opLifecycle/outbox.d.ts.map +1 -0
  334. package/lib/opLifecycle/{outbox.mjs → outbox.js} +24 -10
  335. package/lib/opLifecycle/outbox.js.map +1 -0
  336. package/lib/opLifecycle/{remoteMessageProcessor.d.mts → remoteMessageProcessor.d.ts} +5 -5
  337. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -0
  338. package/lib/opLifecycle/{remoteMessageProcessor.mjs → remoteMessageProcessor.js} +7 -4
  339. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -0
  340. package/lib/{opProperties.d.mts → opProperties.d.ts} +1 -1
  341. package/lib/opProperties.d.ts.map +1 -0
  342. package/lib/{opProperties.mjs → opProperties.js} +1 -1
  343. package/lib/opProperties.js.map +1 -0
  344. package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
  345. package/lib/packageVersion.d.ts.map +1 -0
  346. package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
  347. package/lib/packageVersion.js.map +1 -0
  348. package/lib/{pendingStateManager.d.mts → pendingStateManager.d.ts} +3 -2
  349. package/lib/pendingStateManager.d.ts.map +1 -0
  350. package/lib/{pendingStateManager.mjs → pendingStateManager.js} +18 -10
  351. package/lib/pendingStateManager.js.map +1 -0
  352. package/lib/{scheduleManager.d.mts → scheduleManager.d.ts} +6 -3
  353. package/lib/scheduleManager.d.ts.map +1 -0
  354. package/lib/{scheduleManager.mjs → scheduleManager.js} +7 -3
  355. package/lib/scheduleManager.js.map +1 -0
  356. package/lib/{storageServiceWithAttachBlobs.d.mts → storageServiceWithAttachBlobs.d.ts} +1 -1
  357. package/lib/storageServiceWithAttachBlobs.d.ts.map +1 -0
  358. package/lib/{storageServiceWithAttachBlobs.mjs → storageServiceWithAttachBlobs.js} +1 -1
  359. package/lib/storageServiceWithAttachBlobs.js.map +1 -0
  360. package/lib/summary/{index.d.mts → index.d.ts} +13 -13
  361. package/lib/summary/index.d.ts.map +1 -0
  362. package/lib/summary/{index.mjs → index.js} +12 -12
  363. package/lib/summary/index.js.map +1 -0
  364. package/lib/summary/{orderedClientElection.d.mts → orderedClientElection.d.ts} +5 -1
  365. package/lib/summary/orderedClientElection.d.ts.map +1 -0
  366. package/lib/summary/{orderedClientElection.mjs → orderedClientElection.js} +6 -2
  367. package/lib/summary/orderedClientElection.js.map +1 -0
  368. package/lib/summary/{runWhileConnectedCoordinator.d.mts → runWhileConnectedCoordinator.d.ts} +2 -2
  369. package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
  370. package/lib/summary/{runWhileConnectedCoordinator.mjs → runWhileConnectedCoordinator.js} +1 -1
  371. package/lib/summary/runWhileConnectedCoordinator.js.map +1 -0
  372. package/lib/summary/{runningSummarizer.d.mts → runningSummarizer.d.ts} +6 -5
  373. package/lib/summary/runningSummarizer.d.ts.map +1 -0
  374. package/lib/summary/{runningSummarizer.mjs → runningSummarizer.js} +41 -26
  375. package/lib/summary/runningSummarizer.js.map +1 -0
  376. package/lib/summary/{summarizer.d.mts → summarizer.d.ts} +5 -5
  377. package/lib/summary/summarizer.d.ts.map +1 -0
  378. package/lib/summary/{summarizer.mjs → summarizer.js} +4 -4
  379. package/lib/summary/summarizer.js.map +1 -0
  380. package/lib/summary/{summarizerClientElection.d.mts → summarizerClientElection.d.ts} +3 -3
  381. package/lib/summary/summarizerClientElection.d.ts.map +1 -0
  382. package/lib/summary/{summarizerClientElection.mjs → summarizerClientElection.js} +1 -1
  383. package/lib/summary/summarizerClientElection.js.map +1 -0
  384. package/lib/summary/{summarizerHeuristics.d.mts → summarizerHeuristics.d.ts} +4 -4
  385. package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
  386. package/lib/summary/{summarizerHeuristics.mjs → summarizerHeuristics.js} +1 -1
  387. package/lib/summary/summarizerHeuristics.js.map +1 -0
  388. package/lib/summary/summarizerNode/{index.d.mts → index.d.ts} +4 -4
  389. package/lib/summary/summarizerNode/index.d.ts.map +1 -0
  390. package/lib/summary/summarizerNode/index.js +7 -0
  391. package/lib/summary/summarizerNode/index.js.map +1 -0
  392. package/lib/summary/summarizerNode/{summarizerNode.d.mts → summarizerNode.d.ts} +17 -6
  393. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -0
  394. package/lib/summary/summarizerNode/{summarizerNode.mjs → summarizerNode.js} +34 -4
  395. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -0
  396. package/lib/summary/summarizerNode/{summarizerNodeUtils.d.mts → summarizerNodeUtils.d.ts} +10 -2
  397. package/lib/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -0
  398. package/lib/summary/summarizerNode/{summarizerNodeUtils.mjs → summarizerNodeUtils.js} +1 -1
  399. package/lib/summary/summarizerNode/summarizerNodeUtils.js.map +1 -0
  400. package/lib/summary/summarizerNode/{summarizerNodeWithGc.d.mts → summarizerNodeWithGc.d.ts} +4 -5
  401. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -0
  402. package/lib/summary/summarizerNode/{summarizerNodeWithGc.mjs → summarizerNodeWithGc.js} +7 -7
  403. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -0
  404. package/lib/summary/{summarizerTypes.d.mts → summarizerTypes.d.ts} +10 -21
  405. package/lib/summary/summarizerTypes.d.ts.map +1 -0
  406. package/lib/summary/{summarizerTypes.mjs → summarizerTypes.js} +1 -1
  407. package/lib/summary/summarizerTypes.js.map +1 -0
  408. package/lib/summary/{summaryCollection.d.mts → summaryCollection.d.ts} +1 -1
  409. package/lib/summary/summaryCollection.d.ts.map +1 -0
  410. package/lib/summary/{summaryCollection.mjs → summaryCollection.js} +1 -1
  411. package/lib/summary/summaryCollection.js.map +1 -0
  412. package/lib/summary/{summaryFormat.d.mts → summaryFormat.d.ts} +16 -3
  413. package/lib/summary/summaryFormat.d.ts.map +1 -0
  414. package/lib/summary/{summaryFormat.mjs → summaryFormat.js} +1 -1
  415. package/lib/summary/summaryFormat.js.map +1 -0
  416. package/lib/summary/{summaryGenerator.d.mts → summaryGenerator.d.ts} +7 -6
  417. package/lib/summary/summaryGenerator.d.ts.map +1 -0
  418. package/lib/summary/{summaryGenerator.mjs → summaryGenerator.js} +11 -2
  419. package/lib/summary/summaryGenerator.js.map +1 -0
  420. package/lib/summary/{summaryManager.d.mts → summaryManager.d.ts} +6 -7
  421. package/lib/summary/summaryManager.d.ts.map +1 -0
  422. package/lib/summary/{summaryManager.mjs → summaryManager.js} +4 -5
  423. package/lib/summary/summaryManager.js.map +1 -0
  424. package/lib/test/batchTracker.spec.js +88 -0
  425. package/lib/test/batchTracker.spec.js.map +1 -0
  426. package/lib/test/blobManager.spec.js +835 -0
  427. package/lib/test/blobManager.spec.js.map +1 -0
  428. package/lib/test/channelCollection.spec.js +138 -0
  429. package/lib/test/channelCollection.spec.js.map +1 -0
  430. package/lib/test/containerRuntime.spec.js +1748 -0
  431. package/lib/test/containerRuntime.spec.js.map +1 -0
  432. package/lib/test/dataStoreContext.spec.js +771 -0
  433. package/lib/test/dataStoreContext.spec.js.map +1 -0
  434. package/lib/test/dataStoreCreation.spec.js +303 -0
  435. package/lib/test/dataStoreCreation.spec.js.map +1 -0
  436. package/lib/test/dataStoreRegistry.spec.js +26 -0
  437. package/lib/test/dataStoreRegistry.spec.js.map +1 -0
  438. package/lib/test/fuzz/fuzzUtils.js +66 -0
  439. package/lib/test/fuzz/fuzzUtils.js.map +1 -0
  440. package/lib/test/fuzz/summarizer.fuzz.spec.js +31 -0
  441. package/lib/test/fuzz/summarizer.fuzz.spec.js.map +1 -0
  442. package/lib/test/fuzz/summarizerFuzzMocks.js +162 -0
  443. package/lib/test/fuzz/summarizerFuzzMocks.js.map +1 -0
  444. package/lib/test/fuzz/summarizerFuzzSuite.js +106 -0
  445. package/lib/test/fuzz/summarizerFuzzSuite.js.map +1 -0
  446. package/lib/test/gc/garbageCollection.spec.js +1464 -0
  447. package/lib/test/gc/garbageCollection.spec.js.map +1 -0
  448. package/lib/test/gc/gcConfigs.spec.js +689 -0
  449. package/lib/test/gc/gcConfigs.spec.js.map +1 -0
  450. package/lib/test/gc/gcHelpers.spec.js +110 -0
  451. package/lib/test/gc/gcHelpers.spec.js.map +1 -0
  452. package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js +68 -0
  453. package/lib/test/gc/gcReferenceGraphAlgorithm.spec.js.map +1 -0
  454. package/lib/test/gc/gcStats.spec.js +390 -0
  455. package/lib/test/gc/gcStats.spec.js.map +1 -0
  456. package/lib/test/gc/gcSummaryStateTracker.spec.js +228 -0
  457. package/lib/test/gc/gcSummaryStateTracker.spec.js.map +1 -0
  458. package/lib/test/gc/gcTelemetry.spec.js +530 -0
  459. package/lib/test/gc/gcTelemetry.spec.js.map +1 -0
  460. package/lib/test/gc/gcUnitTestHelpers.js +29 -0
  461. package/lib/test/gc/gcUnitTestHelpers.js.map +1 -0
  462. package/lib/test/gc/gcUnreferencedStateTracker.spec.js +192 -0
  463. package/lib/test/gc/gcUnreferencedStateTracker.spec.js.map +1 -0
  464. package/lib/test/getPendingBlobs.spec.js +193 -0
  465. package/lib/test/getPendingBlobs.spec.js.map +1 -0
  466. package/lib/test/hardwareStats.spec.js +93 -0
  467. package/lib/test/hardwareStats.spec.js.map +1 -0
  468. package/lib/test/index.js +6 -0
  469. package/lib/test/index.js.map +1 -0
  470. package/lib/test/opLifecycle/OpGroupingManager.spec.js +225 -0
  471. package/lib/test/opLifecycle/OpGroupingManager.spec.js.map +1 -0
  472. package/lib/test/opLifecycle/batchManager.spec.js +189 -0
  473. package/lib/test/opLifecycle/batchManager.spec.js.map +1 -0
  474. package/lib/test/opLifecycle/opCompressor.spec.js +74 -0
  475. package/lib/test/opLifecycle/opCompressor.spec.js.map +1 -0
  476. package/lib/test/opLifecycle/opDecompressor.spec.js +218 -0
  477. package/lib/test/opLifecycle/opDecompressor.spec.js.map +1 -0
  478. package/lib/test/opLifecycle/opSplitter.spec.js +272 -0
  479. package/lib/test/opLifecycle/opSplitter.spec.js.map +1 -0
  480. package/lib/test/opLifecycle/outbox.spec.js +675 -0
  481. package/lib/test/opLifecycle/outbox.spec.js.map +1 -0
  482. package/lib/test/opLifecycle/remoteMessageProcessor.spec.js +196 -0
  483. package/lib/test/opLifecycle/remoteMessageProcessor.spec.js.map +1 -0
  484. package/lib/test/pendingStateManager.spec.js +329 -0
  485. package/lib/test/pendingStateManager.spec.js.map +1 -0
  486. package/lib/test/scheduleManager.spec.js +270 -0
  487. package/lib/test/scheduleManager.spec.js.map +1 -0
  488. package/lib/test/summarizerNode.spec.js +326 -0
  489. package/lib/test/summarizerNode.spec.js.map +1 -0
  490. package/lib/test/summarizerNodeWithGc.spec.js +318 -0
  491. package/lib/test/summarizerNodeWithGc.spec.js.map +1 -0
  492. package/lib/test/summary/orderedClientElection.spec.js +535 -0
  493. package/lib/test/summary/orderedClientElection.spec.js.map +1 -0
  494. package/lib/test/summary/runningSummarizer.spec.js +1349 -0
  495. package/lib/test/summary/runningSummarizer.spec.js.map +1 -0
  496. package/lib/test/summary/summarizer.spec.js +29 -0
  497. package/lib/test/summary/summarizer.spec.js.map +1 -0
  498. package/lib/test/summary/summarizerClientElection.spec.js +436 -0
  499. package/lib/test/summary/summarizerClientElection.spec.js.map +1 -0
  500. package/lib/test/summary/summarizerHeuristics.spec.js +289 -0
  501. package/lib/test/summary/summarizerHeuristics.spec.js.map +1 -0
  502. package/lib/test/summary/summaryCollection.spec.js +200 -0
  503. package/lib/test/summary/summaryCollection.spec.js.map +1 -0
  504. package/lib/test/summary/summaryManager.spec.js +430 -0
  505. package/lib/test/summary/summaryManager.spec.js.map +1 -0
  506. package/lib/test/summary/testQuorumClients.js +34 -0
  507. package/lib/test/summary/testQuorumClients.js.map +1 -0
  508. package/lib/test/throttler.spec.js +175 -0
  509. package/lib/test/throttler.spec.js.map +1 -0
  510. package/lib/test/types/validateContainerRuntimePrevious.generated.js +180 -0
  511. package/lib/test/types/validateContainerRuntimePrevious.generated.js.map +1 -0
  512. package/lib/{throttler.d.mts → throttler.d.ts} +1 -1
  513. package/lib/throttler.d.ts.map +1 -0
  514. package/lib/{throttler.mjs → throttler.js} +1 -1
  515. package/lib/throttler.js.map +1 -0
  516. package/package.json +101 -88
  517. package/src/batchTracker.ts +1 -1
  518. package/src/blobManager.ts +1 -15
  519. package/src/{dataStores.ts → channelCollection.ts} +629 -178
  520. package/src/connectionTelemetry.ts +42 -3
  521. package/src/containerHandleContext.ts +1 -1
  522. package/src/containerRuntime.ts +626 -430
  523. package/src/dataStore.ts +16 -15
  524. package/src/dataStoreContext.ts +376 -216
  525. package/src/dataStoreContexts.ts +2 -1
  526. package/src/dataStoreRegistry.ts +1 -0
  527. package/src/deltaManagerSummarizerProxy.ts +132 -7
  528. package/src/gc/garbageCollection.ts +84 -44
  529. package/src/gc/gcConfigs.ts +17 -7
  530. package/src/gc/gcDefinitions.ts +23 -13
  531. package/src/gc/gcHelpers.ts +2 -2
  532. package/src/gc/gcReferenceGraphAlgorithm.ts +1 -1
  533. package/src/gc/gcSummaryStateTracker.ts +19 -7
  534. package/src/gc/gcTelemetry.ts +9 -7
  535. package/src/gc/gcUnreferencedStateTracker.ts +1 -1
  536. package/src/gc/index.ts +10 -9
  537. package/src/index.ts +28 -27
  538. package/src/messageTypes.ts +3 -3
  539. package/src/opLifecycle/README.md +2 -4
  540. package/src/opLifecycle/batchManager.ts +2 -2
  541. package/src/opLifecycle/definitions.ts +2 -2
  542. package/src/opLifecycle/index.ts +8 -8
  543. package/src/opLifecycle/opCompressor.ts +3 -3
  544. package/src/opLifecycle/opDecompressor.ts +3 -3
  545. package/src/opLifecycle/opGroupingManager.ts +3 -12
  546. package/src/opLifecycle/opSplitter.ts +3 -3
  547. package/src/opLifecycle/outbox.ts +43 -16
  548. package/src/opLifecycle/remoteMessageProcessor.ts +10 -6
  549. package/src/packageVersion.ts +1 -1
  550. package/src/pendingStateManager.ts +19 -13
  551. package/src/scheduleManager.ts +5 -4
  552. package/src/summary/index.ts +13 -12
  553. package/src/summary/orderedClientElection.ts +2 -1
  554. package/src/summary/runWhileConnectedCoordinator.ts +1 -1
  555. package/src/summary/runningSummarizer.ts +52 -32
  556. package/src/summary/summarizer.ts +7 -7
  557. package/src/summary/summarizerClientElection.ts +2 -2
  558. package/src/summary/summarizerHeuristics.ts +3 -3
  559. package/src/summary/summarizerNode/index.ts +6 -3
  560. package/src/summary/summarizerNode/summarizerNode.ts +50 -5
  561. package/src/summary/summarizerNode/summarizerNodeUtils.ts +14 -1
  562. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +11 -11
  563. package/src/summary/summarizerTypes.ts +11 -23
  564. package/src/summary/summaryFormat.ts +16 -2
  565. package/src/summary/summaryGenerator.ts +16 -4
  566. package/src/summary/summaryManager.ts +6 -7
  567. package/tsconfig.cjs.json +7 -0
  568. package/tsconfig.json +2 -5
  569. package/dist/dataStores.d.ts +0 -151
  570. package/dist/dataStores.d.ts.map +0 -1
  571. package/dist/dataStores.js.map +0 -1
  572. package/dist/deltaManagerProxyBase.d.ts.map +0 -1
  573. package/dist/deltaManagerProxyBase.js +0 -77
  574. package/dist/deltaManagerProxyBase.js.map +0 -1
  575. package/lib/batchTracker.d.mts.map +0 -1
  576. package/lib/batchTracker.mjs.map +0 -1
  577. package/lib/blobManager.d.mts.map +0 -1
  578. package/lib/blobManager.mjs.map +0 -1
  579. package/lib/connectionTelemetry.d.mts.map +0 -1
  580. package/lib/connectionTelemetry.mjs.map +0 -1
  581. package/lib/containerHandleContext.d.mts.map +0 -1
  582. package/lib/containerHandleContext.mjs.map +0 -1
  583. package/lib/containerRuntime.d.mts.map +0 -1
  584. package/lib/containerRuntime.mjs.map +0 -1
  585. package/lib/dataStore.d.mts.map +0 -1
  586. package/lib/dataStore.mjs.map +0 -1
  587. package/lib/dataStoreContext.d.mts.map +0 -1
  588. package/lib/dataStoreContext.mjs.map +0 -1
  589. package/lib/dataStoreContexts.d.mts.map +0 -1
  590. package/lib/dataStoreContexts.mjs.map +0 -1
  591. package/lib/dataStoreRegistry.d.mts.map +0 -1
  592. package/lib/dataStoreRegistry.mjs.map +0 -1
  593. package/lib/dataStores.d.mts +0 -151
  594. package/lib/dataStores.d.mts.map +0 -1
  595. package/lib/dataStores.mjs.map +0 -1
  596. package/lib/deltaManagerProxyBase.d.mts +0 -35
  597. package/lib/deltaManagerProxyBase.d.mts.map +0 -1
  598. package/lib/deltaManagerProxyBase.mjs +0 -73
  599. package/lib/deltaManagerProxyBase.mjs.map +0 -1
  600. package/lib/deltaManagerSummarizerProxy.d.mts +0 -19
  601. package/lib/deltaManagerSummarizerProxy.d.mts.map +0 -1
  602. package/lib/deltaManagerSummarizerProxy.mjs +0 -38
  603. package/lib/deltaManagerSummarizerProxy.mjs.map +0 -1
  604. package/lib/deltaScheduler.d.mts.map +0 -1
  605. package/lib/deltaScheduler.mjs.map +0 -1
  606. package/lib/error.d.mts.map +0 -1
  607. package/lib/error.mjs.map +0 -1
  608. package/lib/gc/garbageCollection.d.mts.map +0 -1
  609. package/lib/gc/garbageCollection.mjs.map +0 -1
  610. package/lib/gc/gcConfigs.d.mts.map +0 -1
  611. package/lib/gc/gcConfigs.mjs.map +0 -1
  612. package/lib/gc/gcDefinitions.d.mts.map +0 -1
  613. package/lib/gc/gcDefinitions.mjs.map +0 -1
  614. package/lib/gc/gcHelpers.mjs.map +0 -1
  615. package/lib/gc/gcReferenceGraphAlgorithm.d.mts.map +0 -1
  616. package/lib/gc/gcReferenceGraphAlgorithm.mjs.map +0 -1
  617. package/lib/gc/gcSummaryDefinitions.d.mts.map +0 -1
  618. package/lib/gc/gcSummaryDefinitions.mjs.map +0 -1
  619. package/lib/gc/gcSummaryStateTracker.d.mts.map +0 -1
  620. package/lib/gc/gcSummaryStateTracker.mjs.map +0 -1
  621. package/lib/gc/gcTelemetry.d.mts.map +0 -1
  622. package/lib/gc/gcTelemetry.mjs.map +0 -1
  623. package/lib/gc/gcUnreferencedStateTracker.d.mts.map +0 -1
  624. package/lib/gc/gcUnreferencedStateTracker.mjs.map +0 -1
  625. package/lib/gc/index.d.mts +0 -13
  626. package/lib/gc/index.d.mts.map +0 -1
  627. package/lib/gc/index.mjs.map +0 -1
  628. package/lib/index.d.mts.map +0 -1
  629. package/lib/index.mjs +0 -25
  630. package/lib/index.mjs.map +0 -1
  631. package/lib/messageTypes.d.mts.map +0 -1
  632. package/lib/messageTypes.mjs.map +0 -1
  633. package/lib/metadata.d.mts.map +0 -1
  634. package/lib/metadata.mjs.map +0 -1
  635. package/lib/opLifecycle/batchManager.d.mts.map +0 -1
  636. package/lib/opLifecycle/batchManager.mjs.map +0 -1
  637. package/lib/opLifecycle/definitions.d.mts.map +0 -1
  638. package/lib/opLifecycle/definitions.mjs.map +0 -1
  639. package/lib/opLifecycle/index.d.mts +0 -13
  640. package/lib/opLifecycle/index.d.mts.map +0 -1
  641. package/lib/opLifecycle/index.mjs +0 -12
  642. package/lib/opLifecycle/index.mjs.map +0 -1
  643. package/lib/opLifecycle/opCompressor.d.mts.map +0 -1
  644. package/lib/opLifecycle/opCompressor.mjs.map +0 -1
  645. package/lib/opLifecycle/opDecompressor.d.mts.map +0 -1
  646. package/lib/opLifecycle/opDecompressor.mjs.map +0 -1
  647. package/lib/opLifecycle/opGroupingManager.d.mts.map +0 -1
  648. package/lib/opLifecycle/opGroupingManager.mjs.map +0 -1
  649. package/lib/opLifecycle/opSplitter.d.mts.map +0 -1
  650. package/lib/opLifecycle/opSplitter.mjs.map +0 -1
  651. package/lib/opLifecycle/outbox.d.mts.map +0 -1
  652. package/lib/opLifecycle/outbox.mjs.map +0 -1
  653. package/lib/opLifecycle/remoteMessageProcessor.d.mts.map +0 -1
  654. package/lib/opLifecycle/remoteMessageProcessor.mjs.map +0 -1
  655. package/lib/opProperties.d.mts.map +0 -1
  656. package/lib/opProperties.mjs.map +0 -1
  657. package/lib/packageVersion.d.mts.map +0 -1
  658. package/lib/packageVersion.mjs.map +0 -1
  659. package/lib/pendingStateManager.d.mts.map +0 -1
  660. package/lib/pendingStateManager.mjs.map +0 -1
  661. package/lib/scheduleManager.d.mts.map +0 -1
  662. package/lib/scheduleManager.mjs.map +0 -1
  663. package/lib/storageServiceWithAttachBlobs.d.mts.map +0 -1
  664. package/lib/storageServiceWithAttachBlobs.mjs.map +0 -1
  665. package/lib/summary/index.d.mts.map +0 -1
  666. package/lib/summary/index.mjs.map +0 -1
  667. package/lib/summary/orderedClientElection.d.mts.map +0 -1
  668. package/lib/summary/orderedClientElection.mjs.map +0 -1
  669. package/lib/summary/runWhileConnectedCoordinator.d.mts.map +0 -1
  670. package/lib/summary/runWhileConnectedCoordinator.mjs.map +0 -1
  671. package/lib/summary/runningSummarizer.d.mts.map +0 -1
  672. package/lib/summary/runningSummarizer.mjs.map +0 -1
  673. package/lib/summary/summarizer.d.mts.map +0 -1
  674. package/lib/summary/summarizer.mjs.map +0 -1
  675. package/lib/summary/summarizerClientElection.d.mts.map +0 -1
  676. package/lib/summary/summarizerClientElection.mjs.map +0 -1
  677. package/lib/summary/summarizerHeuristics.d.mts.map +0 -1
  678. package/lib/summary/summarizerHeuristics.mjs.map +0 -1
  679. package/lib/summary/summarizerNode/index.d.mts.map +0 -1
  680. package/lib/summary/summarizerNode/index.mjs +0 -7
  681. package/lib/summary/summarizerNode/index.mjs.map +0 -1
  682. package/lib/summary/summarizerNode/summarizerNode.d.mts.map +0 -1
  683. package/lib/summary/summarizerNode/summarizerNode.mjs.map +0 -1
  684. package/lib/summary/summarizerNode/summarizerNodeUtils.d.mts.map +0 -1
  685. package/lib/summary/summarizerNode/summarizerNodeUtils.mjs.map +0 -1
  686. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.mts.map +0 -1
  687. package/lib/summary/summarizerNode/summarizerNodeWithGc.mjs.map +0 -1
  688. package/lib/summary/summarizerTypes.d.mts.map +0 -1
  689. package/lib/summary/summarizerTypes.mjs.map +0 -1
  690. package/lib/summary/summaryCollection.d.mts.map +0 -1
  691. package/lib/summary/summaryCollection.mjs.map +0 -1
  692. package/lib/summary/summaryFormat.d.mts.map +0 -1
  693. package/lib/summary/summaryFormat.mjs.map +0 -1
  694. package/lib/summary/summaryGenerator.d.mts.map +0 -1
  695. package/lib/summary/summaryGenerator.mjs.map +0 -1
  696. package/lib/summary/summaryManager.d.mts.map +0 -1
  697. package/lib/summary/summaryManager.mjs.map +0 -1
  698. package/lib/throttler.d.mts.map +0 -1
  699. package/lib/throttler.mjs.map +0 -1
  700. package/src/deltaManagerProxyBase.ts +0 -111
@@ -2,9 +2,9 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+
5
6
  import {
6
7
  ITelemetryBaseLogger,
7
- ITelemetryGenericEvent,
8
8
  FluidObject,
9
9
  IFluidHandle,
10
10
  IFluidHandleContext,
@@ -21,7 +21,6 @@ import {
21
21
  IRuntime,
22
22
  ICriticalContainerError,
23
23
  AttachState,
24
- ILoaderOptions,
25
24
  ILoader,
26
25
  LoaderHeader,
27
26
  IGetPendingLocalStateProps,
@@ -30,7 +29,7 @@ import {
30
29
  IContainerRuntime,
31
30
  IContainerRuntimeEvents,
32
31
  } from "@fluidframework/container-runtime-definitions";
33
- import { assert, delay, LazyPromise } from "@fluidframework/core-utils";
32
+ import { assert, Deferred, delay, LazyPromise, PromiseCache } from "@fluidframework/core-utils";
34
33
  import { Trace, TypedEventEmitter } from "@fluid-internal/client-utils";
35
34
  import {
36
35
  createChildLogger,
@@ -40,7 +39,6 @@ import {
40
39
  GenericError,
41
40
  raiseConnectedEvent,
42
41
  PerformanceEvent,
43
- // eslint-disable-next-line import/no-deprecated
44
42
  TaggedLoggerAdapter,
45
43
  MonitoringContext,
46
44
  wrapError,
@@ -49,11 +47,14 @@ import {
49
47
  LoggingError,
50
48
  createSampledLogger,
51
49
  IEventSampler,
50
+ type ITelemetryGenericEventExt,
51
+ loggerToMonitoringContext,
52
52
  } from "@fluidframework/telemetry-utils";
53
53
  import {
54
54
  DriverHeader,
55
55
  FetchSource,
56
56
  IDocumentStorageService,
57
+ type ISnapshot,
57
58
  } from "@fluidframework/driver-definitions";
58
59
  import { readAndParse } from "@fluidframework/driver-utils";
59
60
  import {
@@ -75,9 +76,7 @@ import {
75
76
  InboundAttachMessage,
76
77
  IFluidDataStoreContextDetached,
77
78
  IFluidDataStoreRegistry,
78
- IFluidDataStoreChannel,
79
79
  IGarbageCollectionData,
80
- IEnvelope,
81
80
  IInboundSignalMessage,
82
81
  NamedFluidDataStoreRegistryEntries,
83
82
  ISummaryTreeWithStats,
@@ -87,18 +86,18 @@ import {
87
86
  channelsTreeName,
88
87
  IDataStore,
89
88
  ITelemetryContext,
89
+ IEnvelope,
90
90
  } from "@fluidframework/runtime-definitions";
91
91
  import type {
92
92
  SerializedIdCompressorWithNoSession,
93
93
  IIdCompressor,
94
94
  IIdCompressorCore,
95
- IdCreationRange,
96
95
  SerializedIdCompressorWithOngoingSession,
96
+ IdCreationRange,
97
97
  } from "@fluidframework/id-compressor";
98
98
  import {
99
99
  addBlobToSummary,
100
100
  addSummarizeResultToSummary,
101
- addTreeToSummary,
102
101
  RequestParser,
103
102
  create404Response,
104
103
  exceptionToResponse,
@@ -110,17 +109,17 @@ import {
110
109
  responseToException,
111
110
  } from "@fluidframework/runtime-utils";
112
111
  import { v4 as uuid } from "uuid";
113
- import { ContainerFluidHandleContext } from "./containerHandleContext";
114
- import { FluidDataStoreRegistry } from "./dataStoreRegistry";
115
- import { ReportOpPerfTelemetry, IPerfSignalReport } from "./connectionTelemetry";
112
+ import { ContainerFluidHandleContext } from "./containerHandleContext.js";
113
+ import { FluidDataStoreRegistry } from "./dataStoreRegistry.js";
114
+ import { ReportOpPerfTelemetry, IPerfSignalReport } from "./connectionTelemetry.js";
116
115
  import {
117
116
  IPendingBatchMessage,
118
117
  IPendingLocalState,
119
118
  PendingStateManager,
120
- } from "./pendingStateManager";
121
- import { pkgVersion } from "./packageVersion";
122
- import { BlobManager, IBlobManagerLoadInfo, IPendingBlobs } from "./blobManager";
123
- import { DataStores, getSummaryForDatastores } from "./dataStores";
119
+ } from "./pendingStateManager.js";
120
+ import { pkgVersion } from "./packageVersion.js";
121
+ import { BlobManager, IBlobManagerLoadInfo, IPendingBlobs } from "./blobManager.js";
122
+ import { ChannelCollection, getSummaryForDatastores, wrapContext } from "./channelCollection.js";
124
123
  import {
125
124
  aliasBlobName,
126
125
  blobsTreeName,
@@ -160,8 +159,10 @@ import {
160
159
  ISummarizerEvents,
161
160
  IBaseSummarizeResult,
162
161
  ISummarizer,
163
- } from "./summary";
164
- import { formExponentialFn, Throttler } from "./throttler";
162
+ rootHasIsolatedChannels,
163
+ IdCompressorMode,
164
+ } from "./summary/index.js";
165
+ import { formExponentialFn, Throttler } from "./throttler.js";
165
166
  import {
166
167
  GarbageCollector,
167
168
  GCNodeType,
@@ -169,11 +170,10 @@ import {
169
170
  IGarbageCollector,
170
171
  IGCRuntimeOptions,
171
172
  IGCStats,
172
- trimLeadingAndTrailingSlashes,
173
- } from "./gc";
174
- import { channelToDataStore, IDataStoreAliasMessage, isDataStoreAliasMessage } from "./dataStore";
175
- import { BindBatchTracker } from "./batchTracker";
176
- import { ScheduleManager } from "./scheduleManager";
173
+ } from "./gc/index.js";
174
+ import { channelToDataStore } from "./dataStore.js";
175
+ import { BindBatchTracker } from "./batchTracker.js";
176
+ import { ScheduleManager } from "./scheduleManager.js";
177
177
  import {
178
178
  BatchMessage,
179
179
  IBatch,
@@ -185,9 +185,9 @@ import {
185
185
  RemoteMessageProcessor,
186
186
  OpGroupingManager,
187
187
  getLongStack,
188
- } from "./opLifecycle";
189
- import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy";
190
- import { IBatchMetadata, IIdAllocationMetadata } from "./metadata";
188
+ } from "./opLifecycle/index.js";
189
+ import { DeltaManagerSummarizerProxy } from "./deltaManagerSummarizerProxy.js";
190
+ import { IBatchMetadata, IIdAllocationMetadata } from "./metadata.js";
191
191
  import {
192
192
  ContainerMessageType,
193
193
  type InboundSequencedContainerRuntimeMessage,
@@ -197,7 +197,7 @@ import {
197
197
  type OutboundContainerRuntimeMessage,
198
198
  type UnknownContainerRuntimeMessage,
199
199
  ContainerRuntimeGCMessage,
200
- } from "./messageTypes";
200
+ } from "./messageTypes.js";
201
201
 
202
202
  /**
203
203
  * Utility to implement compat behaviors given an unknown message type
@@ -442,7 +442,7 @@ export interface IContainerRuntimeOptions {
442
442
  * Enable the IdCompressor in the runtime.
443
443
  * @experimental Not ready for use.
444
444
  */
445
- readonly enableRuntimeIdCompressor?: boolean;
445
+ readonly enableRuntimeIdCompressor?: IdCompressorMode;
446
446
 
447
447
  /**
448
448
  * If enabled, the runtime will block all attempts to send an op inside the
@@ -467,27 +467,6 @@ export interface IContainerRuntimeOptions {
467
467
  readonly enableGroupedBatching?: boolean;
468
468
  }
469
469
 
470
- /**
471
- * Accepted header keys for requests coming to the runtime.
472
- * @internal
473
- */
474
- export enum RuntimeHeaders {
475
- /** True to wait for a data store to be created and loaded before returning it. */
476
- wait = "wait",
477
- /** True if the request is coming from an IFluidHandle. */
478
- viaHandle = "viaHandle",
479
- }
480
-
481
- /** True if a tombstoned object should be returned without erroring
482
- * @alpha
483
- */
484
- export const AllowTombstoneRequestHeaderKey = "allowTombstone"; // Belongs in the enum above, but avoiding the breaking change
485
- /**
486
- * [IRRELEVANT IF throwOnInactiveLoad OPTION NOT SET] True if an inactive object should be returned without erroring
487
- * @internal
488
- */
489
- export const AllowInactiveRequestHeaderKey = "allowInactive"; // Belongs in the enum above, but avoiding the breaking change
490
-
491
470
  /**
492
471
  * Tombstone error responses will have this header set to true
493
472
  * @alpha
@@ -501,6 +480,7 @@ export const InactiveResponseHeaderKey = "isInactive";
501
480
 
502
481
  /**
503
482
  * The full set of parsed header data that may be found on Runtime requests
483
+ * @internal
504
484
  */
505
485
  export interface RuntimeHeaderData {
506
486
  wait?: boolean;
@@ -554,6 +534,11 @@ export interface IPendingRuntimeState {
554
534
  * Pending idCompressor state
555
535
  */
556
536
  pendingIdCompressorState?: SerializedIdCompressorWithOngoingSession;
537
+
538
+ /**
539
+ * Time at which session expiry timer started.
540
+ */
541
+ sessionExpiryTimerStarted?: number | undefined;
557
542
  }
558
543
 
559
544
  const maxConsecutiveReconnectsKey = "Fluid.ContainerRuntime.MaxConsecutiveReconnects";
@@ -768,7 +753,6 @@ export class ContainerRuntime
768
753
  const backCompatContext: IContainerContext | OldContainerContextWithLogger = context;
769
754
  const passLogger =
770
755
  backCompatContext.taggedLogger ??
771
- // eslint-disable-next-line import/no-deprecated
772
756
  new TaggedLoggerAdapter((backCompatContext as OldContainerContextWithLogger).logger);
773
757
  const logger = createChildLogger({
774
758
  logger: passLogger,
@@ -779,6 +763,8 @@ export class ContainerRuntime
779
763
  },
780
764
  });
781
765
 
766
+ const mc = loggerToMonitoringContext(logger);
767
+
782
768
  const {
783
769
  summaryOptions = {},
784
770
  gcOptions = {},
@@ -786,7 +772,7 @@ export class ContainerRuntime
786
772
  flushMode = defaultFlushMode,
787
773
  compressionOptions = defaultCompressionConfig,
788
774
  maxBatchSizeInBytes = defaultMaxBatchSizeInBytes,
789
- enableRuntimeIdCompressor = false,
775
+ enableRuntimeIdCompressor = "off",
790
776
  chunkSizeInBytes = defaultChunkSizeInBytes,
791
777
  enableOpReentryCheck = false,
792
778
  enableGroupedBatching = false,
@@ -855,10 +841,37 @@ export class ContainerRuntime
855
841
  }
856
842
  }
857
843
 
858
- const idCompressorEnabled =
859
- metadata?.idCompressorEnabled ?? runtimeOptions.enableRuntimeIdCompressor ?? false;
860
- let idCompressor: (IIdCompressor & IIdCompressorCore) | undefined;
861
- if (idCompressorEnabled) {
844
+ // Enabling the IdCompressor is a one-way operation and we only want to
845
+ // allow new containers to turn it on
846
+ let idCompressorMode: IdCompressorMode;
847
+ if (existing) {
848
+ // This setting has to be sticky for correctness:
849
+ // 1) if compressior is OFF, it can't be enabled, as already running clients (in given document session) do not know
850
+ // how to process compressor ops
851
+ // 2) if it's ON, then all sessions should load compressor right away
852
+ // 3) Same logic applies for "delayed" mode
853
+ // Maybe in the future we will need to enabled (and figure how to do it safely) "delayed" -> "on" change.
854
+ // We could do "off" -> "on" transtition too, if all clients start loading compressor (but not using it initially) and do so for a while -
855
+ // this will allow clients to eventually to disregard "off" setting (when it's safe so) and start using compressor in future sessions.
856
+ // Everyting is possible, but it needs to be designed and executed carefully, when such need arises.
857
+ idCompressorMode = metadata?.idCompressorMode ?? "off";
858
+ } else {
859
+ // FG overwrite
860
+ const enabled = mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled");
861
+ switch (enabled) {
862
+ case true:
863
+ idCompressorMode = "on";
864
+ break;
865
+ case false:
866
+ idCompressorMode = "off";
867
+ break;
868
+ default:
869
+ idCompressorMode = enableRuntimeIdCompressor;
870
+ break;
871
+ }
872
+ }
873
+
874
+ const createIdCompressorFn = async () => {
862
875
  const { createIdCompressor, deserializeIdCompressor, createSessionId } = await import(
863
876
  "@fluidframework/id-compressor"
864
877
  );
@@ -878,21 +891,22 @@ export class ContainerRuntime
878
891
 
879
892
  const compressorLogger = createSampledLogger(logger, idCompressorEventSampler);
880
893
  const pendingLocalState = context.pendingLocalState as IPendingRuntimeState;
894
+
881
895
  if (pendingLocalState?.pendingIdCompressorState !== undefined) {
882
- idCompressor = deserializeIdCompressor(
896
+ return deserializeIdCompressor(
883
897
  pendingLocalState.pendingIdCompressorState,
884
898
  compressorLogger,
885
899
  );
886
900
  } else if (serializedIdCompressor !== undefined) {
887
- idCompressor = deserializeIdCompressor(
901
+ return deserializeIdCompressor(
888
902
  serializedIdCompressor,
889
903
  createSessionId(),
890
904
  compressorLogger,
891
905
  );
892
906
  } else {
893
- idCompressor = createIdCompressor(compressorLogger);
907
+ return createIdCompressor(compressorLogger);
894
908
  }
895
- }
909
+ };
896
910
 
897
911
  const runtime = new containerRuntimeCtor(
898
912
  context,
@@ -918,7 +932,8 @@ export class ContainerRuntime
918
932
  existing,
919
933
  blobManagerSnapshot,
920
934
  context.storage,
921
- idCompressor,
935
+ createIdCompressorFn,
936
+ idCompressorMode,
922
937
  provideEntryPoint,
923
938
  requestHandler,
924
939
  undefined, // summaryConfiguration
@@ -934,7 +949,7 @@ export class ContainerRuntime
934
949
  return runtime;
935
950
  }
936
951
 
937
- public readonly options: ILoaderOptions;
952
+ public readonly options: Record<string | number, any>;
938
953
  private imminentClosure: boolean = false;
939
954
 
940
955
  private readonly _getClientId: () => string | undefined;
@@ -948,6 +963,10 @@ export class ContainerRuntime
948
963
  return this._storage;
949
964
  }
950
965
 
966
+ public get containerRuntime() {
967
+ return this;
968
+ }
969
+
951
970
  private readonly submitFn: (
952
971
  type: MessageType,
953
972
  contents: any,
@@ -985,7 +1004,47 @@ export class ContainerRuntime
985
1004
  return this._getAttachState();
986
1005
  }
987
1006
 
988
- public idCompressor: (IIdCompressor & IIdCompressorCore) | undefined;
1007
+ private _idCompressor: (IIdCompressor & IIdCompressorCore) | undefined;
1008
+
1009
+ // We accumulate Id compressor Ops while Id compressor is not loaded yet (only for "delayed" mode)
1010
+ // Once it loads, it will process all such ops and we will stop accumulating further ops - ops will be processes as they come in.
1011
+ private pendingIdCompressorOps: IdCreationRange[] = [];
1012
+
1013
+ // Id Compressor serializes final state (see getPendingLocalState()). As result, it needs to skip all ops that preceeded that state
1014
+ // (such ops will be marked by Loader layer as savedOp === true)
1015
+ // That said, in "delayed" mode it's possible that Id Compressor was never initialized before getPendingLocalState() is called.
1016
+ // In such case we have to process all ops, including those marked with saveOp === true.
1017
+ private readonly skipSavedCompressorOps: boolean;
1018
+
1019
+ /**
1020
+ * See IContainerRuntimeBase.idCompressor() for details.
1021
+ */
1022
+ public get idCompressor() {
1023
+ // Expose ID Compressor only if it's On from the start.
1024
+ // If container uses delayed mode, then we can only expose generateDocumentUniqueId() and nothing else.
1025
+ // That's because any other usage will require immidiate loading of ID Compressor in next sessions in order
1026
+ // to reason over such things as session ID space.
1027
+ if (this.idCompressorMode === "on") {
1028
+ assert(
1029
+ this._idCompressor !== undefined,
1030
+ 0x8ea /* compressor should have been loaded */,
1031
+ );
1032
+ return this._idCompressor;
1033
+ }
1034
+ }
1035
+
1036
+ /**
1037
+ * True if we have ID compressor loading in-flight (async operation). Useful only for
1038
+ * this.idCompressorMode === "delayed" mode
1039
+ */
1040
+ protected compressorLoadInitiated = false;
1041
+
1042
+ /**
1043
+ * See IContainerRuntimeBase.generateDocumentUniqueId() for details.
1044
+ */
1045
+ public generateDocumentUniqueId() {
1046
+ return this._idCompressor?.generateDocumentUniqueId() ?? uuid();
1047
+ }
989
1048
 
990
1049
  public get IFluidHandleContext(): IFluidHandleContext {
991
1050
  return this.handleContext;
@@ -1109,7 +1168,7 @@ export class ContainerRuntime
1109
1168
  private readonly outbox: Outbox;
1110
1169
  private readonly garbageCollector: IGarbageCollector;
1111
1170
 
1112
- private readonly dataStores: DataStores;
1171
+ private readonly channelCollection: ChannelCollection;
1113
1172
  private readonly remoteMessageProcessor: RemoteMessageProcessor;
1114
1173
 
1115
1174
  /** The last message processed at the time of the last summary. */
@@ -1125,11 +1184,6 @@ export class ContainerRuntime
1125
1184
  return this.summaryConfiguration.state === "disabled";
1126
1185
  }
1127
1186
 
1128
- private readonly heuristicsDisabled: boolean;
1129
- private isHeuristicsDisabled(): boolean {
1130
- return this.summaryConfiguration.state === "disableHeuristics";
1131
- }
1132
-
1133
1187
  private readonly maxOpsSinceLastSummary: number;
1134
1188
  private getMaxOpsSinceLastSummary(): number {
1135
1189
  return this.summaryConfiguration.state !== "disabled"
@@ -1172,11 +1226,6 @@ export class ContainerRuntime
1172
1226
  */
1173
1227
  private readonly telemetryDocumentId: string;
1174
1228
 
1175
- /**
1176
- * If true, the runtime has access to an IdCompressor
1177
- */
1178
- private readonly idCompressorEnabled: boolean;
1179
-
1180
1229
  /**
1181
1230
  * Whether this client is the summarizer client itself (type is summarizerClientType)
1182
1231
  */
@@ -1187,11 +1236,19 @@ export class ContainerRuntime
1187
1236
  */
1188
1237
  private readonly loadedFromVersionId: string | undefined;
1189
1238
 
1239
+ /**
1240
+ * It a cache for holding mapping for loading groupIds with its snapshot from the service. Add expiry policy of 1 minute.
1241
+ * Starting with 1 min and based on recorded usage we can tweak it later on.
1242
+ */
1243
+ private readonly snapshotCacheForLoadingGroupIds = new PromiseCache<string, ISnapshot>({
1244
+ expiry: { policy: "absolute", durationMs: 60000 },
1245
+ });
1246
+
1190
1247
  /***/
1191
1248
  protected constructor(
1192
1249
  context: IContainerContext,
1193
1250
  private readonly registry: IFluidDataStoreRegistry,
1194
- metadata: IContainerRuntimeMetadata | undefined,
1251
+ private readonly metadata: IContainerRuntimeMetadata | undefined,
1195
1252
  electedSummarizerData: ISerializedElection | undefined,
1196
1253
  chunks: [string, string[]][],
1197
1254
  dataStoreAliasMap: [string, string][],
@@ -1201,7 +1258,8 @@ export class ContainerRuntime
1201
1258
  existing: boolean,
1202
1259
  blobManagerSnapshot: IBlobManagerLoadInfo,
1203
1260
  private readonly _storage: IDocumentStorageService,
1204
- idCompressor: (IIdCompressor & IIdCompressorCore) | undefined,
1261
+ private readonly createIdCompressor: () => Promise<IIdCompressor & IIdCompressorCore>,
1262
+ private readonly idCompressorMode: IdCompressorMode,
1205
1263
  provideEntryPoint: (containerRuntime: IContainerRuntime) => Promise<FluidObject>,
1206
1264
  private readonly requestHandler?: (
1207
1265
  request: IRequest,
@@ -1245,7 +1303,9 @@ export class ContainerRuntime
1245
1303
  this.submitSummaryFn = submitSummaryFn;
1246
1304
  this.submitSignalFn = submitSignalFn;
1247
1305
 
1248
- this.options = options;
1306
+ // TODO: After IContainerContext.options is removed, we'll just create a new blank object {} here.
1307
+ // Values are generally expected to be set from the runtime side.
1308
+ this.options = options ?? {};
1249
1309
  this.clientDetails = clientDetails;
1250
1310
  this.isSummarizerClient = this.clientDetails.type === summarizerClientType;
1251
1311
  this.loadedFromVersionId = context.getLoadedFromVersion()?.id;
@@ -1286,20 +1346,12 @@ export class ContainerRuntime
1286
1346
  // summaryNumber was renamed from summaryCount. For older docs that haven't been opened for a long time,
1287
1347
  // the count is reset to 0.
1288
1348
  loadSummaryNumber = metadata?.summaryNumber ?? 0;
1289
-
1290
- // Enabling the IdCompressor is a one-way operation and we only want to
1291
- // allow new containers to turn it on
1292
- this.idCompressorEnabled = metadata?.idCompressorEnabled ?? false;
1293
1349
  } else {
1294
1350
  this.createContainerMetadata = {
1295
1351
  createContainerRuntimeVersion: pkgVersion,
1296
1352
  createContainerTimestamp: Date.now(),
1297
1353
  };
1298
1354
  loadSummaryNumber = 0;
1299
-
1300
- this.idCompressorEnabled =
1301
- this.mc.config.getBoolean("Fluid.ContainerRuntime.IdCompressorEnabled") ??
1302
- idCompressor !== undefined;
1303
1355
  }
1304
1356
  this.nextSummaryNumber = loadSummaryNumber + 1;
1305
1357
 
@@ -1367,14 +1419,9 @@ export class ContainerRuntime
1367
1419
  disableOpReentryCheck !== true;
1368
1420
 
1369
1421
  this.summariesDisabled = this.isSummariesDisabled();
1370
- this.heuristicsDisabled = this.isHeuristicsDisabled();
1371
1422
  this.maxOpsSinceLastSummary = this.getMaxOpsSinceLastSummary();
1372
1423
  this.initialSummarizerDelayMs = this.getInitialSummarizerDelayMs();
1373
1424
 
1374
- if (this.idCompressorEnabled) {
1375
- this.idCompressor = idCompressor;
1376
- }
1377
-
1378
1425
  this.maxConsecutiveReconnects =
1379
1426
  this.mc.config.getNumber(maxConsecutiveReconnectsKey) ??
1380
1427
  this.defaultMaxConsecutiveReconnects;
@@ -1418,6 +1465,7 @@ export class ContainerRuntime
1418
1465
  getLastSummaryTimestampMs: () => this.messageAtLastSummary?.timestamp,
1419
1466
  readAndParseBlob: async <T>(id: string) => readAndParse<T>(this.storage, id),
1420
1467
  submitMessage: (message: ContainerRuntimeGCMessage) => this.submit(message),
1468
+ sessionExpiryTimerStarted: pendingRuntimeState?.sessionExpiryTimerStarted,
1421
1469
  });
1422
1470
 
1423
1471
  const loadedFromSequenceNumber = this.deltaManager.initialSequenceNumber;
@@ -1447,28 +1495,44 @@ export class ContainerRuntime
1447
1495
  this.summarizerNode.updateBaseSummaryState(baseSnapshot);
1448
1496
  }
1449
1497
 
1450
- this.dataStores = new DataStores(
1498
+ const parentContext = wrapContext(this);
1499
+
1500
+ // Due to a mismatch between different layers in terms of
1501
+ // what is the interface of passing signals, we need the
1502
+ // downstream stores to wrap the signal.
1503
+ parentContext.submitSignal = (type: string, content: any, targetClientId?: string) => {
1504
+ const envelope1 = content as IEnvelope;
1505
+ const envelope2 = this.createNewSignalEnvelope(
1506
+ envelope1.address,
1507
+ type,
1508
+ envelope1.contents,
1509
+ );
1510
+ return this.submitSignalFn(envelope2, targetClientId);
1511
+ };
1512
+
1513
+ this.channelCollection = new ChannelCollection(
1451
1514
  getSummaryForDatastores(baseSnapshot, metadata),
1452
- this,
1453
- (attachMsg) => this.submit({ type: ContainerMessageType.Attach, contents: attachMsg }),
1454
- (id: string, createParam: CreateChildSummarizerNodeParam) =>
1455
- (
1456
- summarizeInternal: SummarizeInternalFn,
1457
- getGCDataFn: (fullGC?: boolean) => Promise<IGarbageCollectionData>,
1458
- ) =>
1459
- this.summarizerNode.createChild(
1460
- summarizeInternal,
1461
- id,
1462
- createParam,
1463
- undefined,
1464
- getGCDataFn,
1465
- ),
1466
- (id: string) => this.summarizerNode.deleteChild(id),
1515
+ parentContext,
1467
1516
  this.mc.logger,
1468
- (path: string, timestampMs: number, packagePath?: readonly string[]) =>
1469
- this.garbageCollector.nodeUpdated(path, "Changed", timestampMs, packagePath),
1517
+ (
1518
+ path: string,
1519
+ reason: "Loaded" | "Changed",
1520
+ timestampMs?: number,
1521
+ packagePath?: readonly string[],
1522
+ request?: IRequest,
1523
+ headerData?: RuntimeHeaderData,
1524
+ ) =>
1525
+ this.garbageCollector.nodeUpdated(
1526
+ path,
1527
+ reason,
1528
+ timestampMs,
1529
+ packagePath,
1530
+ request,
1531
+ headerData,
1532
+ ),
1470
1533
  (path: string) => this.garbageCollector.isNodeDeleted(path),
1471
1534
  new Map<string, string>(dataStoreAliasMap),
1535
+ async (runtime: ChannelCollection) => provideEntryPoint,
1472
1536
  );
1473
1537
 
1474
1538
  this.blobManager = new BlobManager(
@@ -1507,9 +1571,13 @@ export class ContainerRuntime
1507
1571
  clientId: () => this.clientId,
1508
1572
  close: this.closeFn,
1509
1573
  connected: () => this.connected,
1510
- reSubmit: this.reSubmit.bind(this),
1574
+ reSubmit: (message: IPendingBatchMessage) => {
1575
+ this.reSubmit(message);
1576
+ this.flush();
1577
+ },
1511
1578
  reSubmitBatch: this.reSubmitBatch.bind(this),
1512
1579
  isActiveConnection: () => this.innerDeltaManager.active,
1580
+ isAttached: () => this.attachState !== AttachState.Detached,
1513
1581
  },
1514
1582
  pendingRuntimeState?.pending,
1515
1583
  this.logger,
@@ -1656,7 +1724,6 @@ export class ContainerRuntime
1656
1724
  {
1657
1725
  initialDelayMs: this.initialSummarizerDelayMs,
1658
1726
  },
1659
- this.heuristicsDisabled,
1660
1727
  );
1661
1728
  this.summaryManager.on("summarize", (eventProps) => {
1662
1729
  this.emit("summarize", eventProps);
@@ -1674,26 +1741,27 @@ export class ContainerRuntime
1674
1741
  this.mc.logger.sendTelemetryEvent({
1675
1742
  eventName: "ContainerLoadStats",
1676
1743
  ...this.createContainerMetadata,
1677
- ...this.dataStores.containerLoadStats,
1744
+ ...this.channelCollection.containerLoadStats,
1678
1745
  summaryNumber: loadSummaryNumber,
1679
1746
  summaryFormatVersion: metadata?.summaryFormatVersion,
1680
1747
  disableIsolatedChannels: metadata?.disableIsolatedChannels,
1681
1748
  gcVersion: metadata?.gcFeature,
1682
1749
  options: JSON.stringify(runtimeOptions),
1750
+ idCompressorModeMetadata: metadata?.idCompressorMode,
1751
+ idCompressorMode: this.idCompressorMode,
1683
1752
  featureGates: JSON.stringify({
1684
1753
  disableCompression,
1685
1754
  disableOpReentryCheck,
1686
1755
  disableChunking,
1687
1756
  disableAttachReorder: this.disableAttachReorder,
1688
1757
  disablePartialFlush,
1689
- idCompressorEnabled: this.idCompressorEnabled,
1690
1758
  closeSummarizerDelayOverride,
1691
1759
  }),
1692
1760
  telemetryDocumentId: this.telemetryDocumentId,
1693
1761
  groupedBatchingEnabled: this.groupedBatchingEnabled,
1694
1762
  });
1695
1763
 
1696
- ReportOpPerfTelemetry(this.clientId, this.deltaManager, this.logger);
1764
+ ReportOpPerfTelemetry(this.clientId, this.deltaManager, this, this.logger);
1697
1765
  BindBatchTracker(this, this.logger);
1698
1766
 
1699
1767
  this.entryPoint = new LazyPromise(async () => {
@@ -1706,12 +1774,52 @@ export class ContainerRuntime
1706
1774
  }
1707
1775
  return provideEntryPoint(this);
1708
1776
  });
1777
+
1778
+ // If we loaded from pending state, then we need to skip any ops that are already accounted in such
1779
+ // saved state, i.e. all the ops marked by Loader layer sa savedOp === true.
1780
+ this.skipSavedCompressorOps = pendingRuntimeState?.pendingIdCompressorState !== undefined;
1781
+ }
1782
+
1783
+ public getCreateChildSummarizerNodeFn(id: string, createParam: CreateChildSummarizerNodeParam) {
1784
+ return (
1785
+ summarizeInternal: SummarizeInternalFn,
1786
+ getGCDataFn: (fullGC?: boolean) => Promise<IGarbageCollectionData>,
1787
+ ) =>
1788
+ this.summarizerNode.createChild(
1789
+ summarizeInternal,
1790
+ id,
1791
+ createParam,
1792
+ undefined,
1793
+ getGCDataFn,
1794
+ );
1795
+ }
1796
+
1797
+ public deleteChildSummarizerNode(id: string) {
1798
+ return this.summarizerNode.deleteChild(id);
1799
+ }
1800
+
1801
+ /* IFluidParentContext APIs that should not be called on Root */
1802
+ public makeLocallyVisible() {
1803
+ assert(false, 0x8eb /* should not be called */);
1804
+ }
1805
+
1806
+ public setChannelDirty(address: string) {
1807
+ assert(false, 0x909 /* should not be called */);
1709
1808
  }
1710
1809
 
1711
1810
  /**
1712
1811
  * Initializes the state from the base snapshot this container runtime loaded from.
1713
1812
  */
1714
1813
  private async initializeBaseState(): Promise<void> {
1814
+ if (
1815
+ this.idCompressorMode === "on" ||
1816
+ (this.idCompressorMode === "delayed" && this.connected)
1817
+ ) {
1818
+ // This is called from loadRuntime(), long before we process any ops, so there should be no ops accumulated yet.
1819
+ assert(this.pendingIdCompressorOps.length === 0, 0x8ec /* no pending ops */);
1820
+ this._idCompressor = await this.createIdCompressor();
1821
+ }
1822
+
1715
1823
  await this.garbageCollector.initializeBaseState();
1716
1824
  }
1717
1825
 
@@ -1736,12 +1844,145 @@ export class ContainerRuntime
1736
1844
  }
1737
1845
  this.garbageCollector.dispose();
1738
1846
  this._summarizer?.dispose();
1739
- this.dataStores.dispose();
1847
+ this.channelCollection.dispose();
1740
1848
  this.pendingStateManager.dispose();
1741
1849
  this.emit("dispose");
1742
1850
  this.removeAllListeners();
1743
1851
  }
1744
1852
 
1853
+ /**
1854
+ * Api to fetch the snapshot from the service for a loadingGroupIds.
1855
+ * @param loadingGroupIds - LoadingGroupId for which the snapshot is asked for.
1856
+ * @param pathParts - Parts of the path, which we want to extract from the snapshot tree.
1857
+ * @returns - snapshotTree and the sequence number of the snapshot.
1858
+ */
1859
+ public async getSnapshotForLoadingGroupId(
1860
+ loadingGroupIds: string[],
1861
+ pathParts: string[],
1862
+ ): Promise<{ snapshotTree: ISnapshotTree; sequenceNumber: number }> {
1863
+ const sortedLoadingGroupIds = loadingGroupIds.sort();
1864
+ assert(
1865
+ this.storage.getSnapshot !== undefined,
1866
+ 0x8ed /* getSnapshot api should be defined if used */,
1867
+ );
1868
+ let loadedFromCache = true;
1869
+ // Lookup up in the cache, if not present then make the network call as multiple datastores could
1870
+ // be in same loading group. So, once we have fetched the snapshot for that loading group on
1871
+ // any request, then cache that as same group could be requested in future too.
1872
+ const snapshot = await this.snapshotCacheForLoadingGroupIds.addOrGet(
1873
+ sortedLoadingGroupIds.join(),
1874
+ async () => {
1875
+ assert(
1876
+ this.storage.getSnapshot !== undefined,
1877
+ 0x8ee /* getSnapshot api should be defined if used */,
1878
+ );
1879
+ loadedFromCache = false;
1880
+ return this.storage.getSnapshot({
1881
+ cacheSnapshot: false,
1882
+ scenarioName: "snapshotForLoadingGroupId",
1883
+ loadingGroupIds: sortedLoadingGroupIds,
1884
+ });
1885
+ },
1886
+ );
1887
+
1888
+ this.logger.sendTelemetryEvent({
1889
+ eventName: "GroupIdSnapshotFetched",
1890
+ details: JSON.stringify({
1891
+ fromCache: loadedFromCache,
1892
+ loadingGroupIds: loadingGroupIds.join(","),
1893
+ }),
1894
+ });
1895
+ // Find the snapshotTree inside the returned snapshot based on the path as given in the request.
1896
+ const hasIsolatedChannels = rootHasIsolatedChannels(this.metadata);
1897
+ const snapshotTreeForPath = this.getSnapshotTreeForPath(
1898
+ snapshot.snapshotTree,
1899
+ pathParts,
1900
+ hasIsolatedChannels,
1901
+ );
1902
+ assert(snapshotTreeForPath !== undefined, 0x8ef /* no snapshotTree for the path */);
1903
+ const snapshotSeqNumber = snapshot.sequenceNumber;
1904
+ assert(snapshotSeqNumber !== undefined, 0x8f0 /* snapshotSeqNumber should be present */);
1905
+
1906
+ // This assert fires if we get a snapshot older than the snapshot we loaded from. This is a service issue.
1907
+ // Snapshots should only move forward. If we observe an older snapshot than the one we loaded from, then likely
1908
+ // the file has been overwritten or service lost data.
1909
+ if (snapshotSeqNumber < this.deltaManager.initialSequenceNumber) {
1910
+ throw DataProcessingError.create(
1911
+ "Downloaded snapshot older than snapshot we loaded from",
1912
+ "getSnapshotForLoadingGroupId",
1913
+ undefined,
1914
+ {
1915
+ loadingGroupIds: sortedLoadingGroupIds.join(","),
1916
+ snapshotSeqNumber,
1917
+ initialSequenceNumber: this.deltaManager.initialSequenceNumber,
1918
+ },
1919
+ );
1920
+ }
1921
+
1922
+ // If the snapshot is ahead of the last seq number of the delta manager, then catch up before
1923
+ // returning the snapshot.
1924
+ if (snapshotSeqNumber > this.deltaManager.lastSequenceNumber) {
1925
+ // If this is a summarizer client, which is trying to load a group and it finds that there is
1926
+ // another snapshot from which the summarizer loaded and it is behind, then just give up as
1927
+ // the summarizer state is not up to date.
1928
+ // This should be a recoverable scenario and shouldn't happen as we should process the ack first.
1929
+ if (this.isSummarizerClient) {
1930
+ throw new Error(
1931
+ "Summarizer client behind, loaded newer snapshot with loadingGroupId",
1932
+ );
1933
+ }
1934
+
1935
+ // We want to catchup from sequenceNumber to targetSequenceNumber
1936
+ const props: ITelemetryGenericEventExt = {
1937
+ eventName: "GroupIdSnapshotCatchup",
1938
+ loadingGroupIds: sortedLoadingGroupIds.join(","),
1939
+ targetSequenceNumber: snapshotSeqNumber, // This is so we reuse some columns in telemetry
1940
+ sequenceNumber: this.deltaManager.lastSequenceNumber, // This is so we reuse some columns in telemetry
1941
+ };
1942
+
1943
+ const event = PerformanceEvent.start(this.mc.logger, {
1944
+ ...props,
1945
+ });
1946
+ // If the inbound deltas queue is paused or disconnected, we expect a reconnect and unpause
1947
+ // as long as it's not a summarizer client.
1948
+ if (this.deltaManager.inbound.paused) {
1949
+ props.inboundPaused = this.deltaManager.inbound.paused; // reusing telemetry
1950
+ }
1951
+ const defP = new Deferred<boolean>();
1952
+ this.deltaManager.on("op", (message: ISequencedDocumentMessage) => {
1953
+ if (message.sequenceNumber >= snapshotSeqNumber) {
1954
+ defP.resolve(true);
1955
+ }
1956
+ });
1957
+ await defP.promise;
1958
+ event.end(props);
1959
+ }
1960
+ return { snapshotTree: snapshotTreeForPath, sequenceNumber: snapshotSeqNumber };
1961
+ }
1962
+
1963
+ /**
1964
+ * Api to find a snapshot tree inside a bigger snapshot tree based on the path in the pathParts array.
1965
+ * @param snapshotTree - snapshot tree to look into.
1966
+ * @param pathParts - Part of the path, which we want to extract from the snapshot tree.
1967
+ * @param hasIsolatedChannels - whether the channels are present inside ".channels" subtree. Older
1968
+ * snapshots will not have trees inside ".channels", so check that.
1969
+ * @returns - requested snapshot tree based on the path parts.
1970
+ */
1971
+ private getSnapshotTreeForPath(
1972
+ snapshotTree: ISnapshotTree,
1973
+ pathParts: string[],
1974
+ hasIsolatedChannels: boolean,
1975
+ ): ISnapshotTree | undefined {
1976
+ let childTree = snapshotTree;
1977
+ for (const part of pathParts) {
1978
+ if (hasIsolatedChannels) {
1979
+ childTree = childTree?.trees[channelsTreeName];
1980
+ }
1981
+ childTree = childTree?.trees[part];
1982
+ }
1983
+ return childTree;
1984
+ }
1985
+
1745
1986
  /**
1746
1987
  * Notifies this object about the request made to the container.
1747
1988
  * @param request - Request made to the handler.
@@ -1798,19 +2039,7 @@ export class ContainerRuntime
1798
2039
  }
1799
2040
  : create404Response(request);
1800
2041
  } else if (requestParser.pathParts.length > 0) {
1801
- // Differentiate between requesting the dataStore directly, or one of its children
1802
- const requestForChild = !requestParser.isLeaf(1);
1803
- const dataStore = await this.getDataStoreFromRequest(id, request, requestForChild);
1804
-
1805
- const subRequest = requestParser.createSubRequest(1);
1806
- // We always expect createSubRequest to include a leading slash, but asserting here to protect against
1807
- // unintentionally modifying the url if that changes.
1808
- assert(
1809
- subRequest.url.startsWith("/"),
1810
- 0x126 /* "Expected createSubRequest url to include a leading slash" */,
1811
- );
1812
- // eslint-disable-next-line @typescript-eslint/return-await -- Adding an await here causes test failures
1813
- return dataStore.request(subRequest);
2042
+ return await this.channelCollection.request(request);
1814
2043
  }
1815
2044
 
1816
2045
  return create404Response(request);
@@ -1828,54 +2057,7 @@ export class ContainerRuntime
1828
2057
  private readonly entryPoint: LazyPromise<FluidObject>;
1829
2058
 
1830
2059
  private internalId(maybeAlias: string): string {
1831
- return this.dataStores.aliases.get(maybeAlias) ?? maybeAlias;
1832
- }
1833
-
1834
- private async getDataStoreFromRequest(
1835
- id: string,
1836
- request: IRequest,
1837
- requestForChild: boolean,
1838
- ): Promise<IFluidDataStoreChannel> {
1839
- const headerData: RuntimeHeaderData = {};
1840
- if (typeof request.headers?.[RuntimeHeaders.wait] === "boolean") {
1841
- headerData.wait = request.headers[RuntimeHeaders.wait];
1842
- }
1843
- if (typeof request.headers?.[RuntimeHeaders.viaHandle] === "boolean") {
1844
- headerData.viaHandle = request.headers[RuntimeHeaders.viaHandle];
1845
- }
1846
- if (typeof request.headers?.[AllowTombstoneRequestHeaderKey] === "boolean") {
1847
- headerData.allowTombstone = request.headers[AllowTombstoneRequestHeaderKey];
1848
- }
1849
- if (typeof request.headers?.[AllowInactiveRequestHeaderKey] === "boolean") {
1850
- headerData.allowInactive = request.headers[AllowInactiveRequestHeaderKey];
1851
- }
1852
-
1853
- // We allow Tombstone requests for sub-DataStore objects
1854
- if (requestForChild) {
1855
- headerData.allowTombstone = true;
1856
- }
1857
-
1858
- await this.dataStores.waitIfPendingAlias(id);
1859
- const internalId = this.internalId(id);
1860
- const dataStoreContext = await this.dataStores.getDataStore(internalId, headerData);
1861
-
1862
- // Remove query params, leading and trailing slashes from the url. This is done to make sure the format is
1863
- // the same as GC nodes id.
1864
- const urlWithoutQuery = trimLeadingAndTrailingSlashes(request.url.split("?")[0]);
1865
- // Get the initial snapshot details which contain the data store package path.
1866
- const details = await dataStoreContext.getInitialSnapshotDetails();
1867
-
1868
- // Note that this will throw if the data store is inactive or tombstoned and throwing on incorrect usage
1869
- // is configured.
1870
- this.garbageCollector.nodeUpdated(
1871
- `/${urlWithoutQuery}`,
1872
- "Loaded",
1873
- undefined /* timestampMs */,
1874
- details.pkg,
1875
- request,
1876
- headerData,
1877
- );
1878
- return dataStoreContext.realize();
2060
+ return this.channelCollection.internalId(maybeAlias);
1879
2061
  }
1880
2062
 
1881
2063
  /** Adds the container's metadata to the given summary tree. */
@@ -1892,7 +2074,7 @@ export class ContainerRuntime
1892
2074
  extractSummaryMetadataMessage(this.deltaManager.lastMessage) ??
1893
2075
  this.messageAtLastSummary,
1894
2076
  telemetryDocumentId: this.telemetryDocumentId,
1895
- idCompressorEnabled: this.idCompressorEnabled ? true : undefined,
2077
+ idCompressorMode: this.idCompressorMode,
1896
2078
  };
1897
2079
  addBlobToSummary(summaryTree, metadataBlobName, JSON.stringify(metadata));
1898
2080
  }
@@ -1905,12 +2087,8 @@ export class ContainerRuntime
1905
2087
  ) {
1906
2088
  this.addMetadataToSummary(summaryTree);
1907
2089
 
1908
- if (this.idCompressorEnabled) {
1909
- assert(
1910
- this.idCompressor !== undefined,
1911
- 0x67a /* IdCompressor should be defined if enabled */,
1912
- );
1913
- const idCompressorState = JSON.stringify(this.idCompressor.serialize(false));
2090
+ if (this._idCompressor) {
2091
+ const idCompressorState = JSON.stringify(this._idCompressor.serialize(false));
1914
2092
  addBlobToSummary(summaryTree, idCompressorBlobName, idCompressorState);
1915
2093
  }
1916
2094
 
@@ -1919,7 +2097,7 @@ export class ContainerRuntime
1919
2097
  addBlobToSummary(summaryTree, chunksBlobName, content);
1920
2098
  }
1921
2099
 
1922
- const dataStoreAliases = this.dataStores.aliases;
2100
+ const dataStoreAliases = this.channelCollection.aliases;
1923
2101
  if (dataStoreAliases.size > 0) {
1924
2102
  addBlobToSummary(summaryTree, aliasBlobName, JSON.stringify([...dataStoreAliases]));
1925
2103
  }
@@ -1935,7 +2113,7 @@ export class ContainerRuntime
1935
2113
  // Some storage (like git) doesn't allow empty tree, so we can omit it.
1936
2114
  // and the blob manager can handle the tree not existing when loading
1937
2115
  if (Object.keys(blobManagerSummary.summary.tree).length > 0) {
1938
- addTreeToSummary(summaryTree, blobsTreeName, blobManagerSummary);
2116
+ addSummarizeResultToSummary(summaryTree, blobsTreeName, blobManagerSummary);
1939
2117
  }
1940
2118
 
1941
2119
  const gcSummary = this.garbageCollector.summarize(fullTree, trackState, telemetryContext);
@@ -1976,14 +2154,8 @@ export class ContainerRuntime
1976
2154
  return this.consecutiveReconnects < this.maxConsecutiveReconnects;
1977
2155
  }
1978
2156
 
1979
- private resetReconnectCount(message?: ISequencedDocumentMessage) {
1980
- // Chunked ops don't count towards making progress as they are sent
1981
- // in their own batches before the originating batch is sent.
1982
- // Therefore, receiving them while attempting to send the originating batch
1983
- // does not mean that the container is making any progress.
1984
- if (message?.type !== ContainerMessageType.ChunkedOp) {
1985
- this.consecutiveReconnects = 0;
1986
- }
2157
+ private resetReconnectCount() {
2158
+ this.consecutiveReconnects = 0;
1987
2159
  }
1988
2160
 
1989
2161
  private replayPendingStates() {
@@ -2035,16 +2207,12 @@ export class ContainerRuntime
2035
2207
  const opContents = this.parseLocalOpContent(serializedOpContent);
2036
2208
  switch (opContents.type) {
2037
2209
  case ContainerMessageType.FluidDataStoreOp:
2038
- return this.dataStores.applyStashedOp(opContents.contents);
2039
2210
  case ContainerMessageType.Attach:
2040
- return this.dataStores.applyStashedAttachOp(opContents.contents);
2211
+ case ContainerMessageType.Alias:
2212
+ return this.channelCollection.applyStashedOp(opContents);
2041
2213
  case ContainerMessageType.IdAllocation:
2042
- assert(
2043
- this.idCompressor !== undefined,
2044
- 0x67b /* IdCompressor should be defined if enabled */,
2045
- );
2214
+ assert(this.idCompressorMode !== "off", 0x8f1 /* ID compressor should be in use */);
2046
2215
  return;
2047
- case ContainerMessageType.Alias:
2048
2216
  case ContainerMessageType.BlobAttach:
2049
2217
  return;
2050
2218
  case ContainerMessageType.ChunkedOp:
@@ -2081,6 +2249,20 @@ export class ContainerRuntime
2081
2249
  }
2082
2250
 
2083
2251
  public setConnectionState(connected: boolean, clientId?: string) {
2252
+ if (connected && this.idCompressorMode === "delayed" && !this.compressorLoadInitiated) {
2253
+ this.compressorLoadInitiated = true;
2254
+ this.createIdCompressor()
2255
+ .then((compressor) => {
2256
+ this._idCompressor = compressor;
2257
+ for (const range of this.pendingIdCompressorOps) {
2258
+ this._idCompressor.finalizeCreationRange(range);
2259
+ }
2260
+ this.pendingIdCompressorOps = [];
2261
+ })
2262
+ .catch((error) => {
2263
+ this.logger.sendErrorEvent({ eventName: "IdCompressorDelayedLoad" }, error);
2264
+ });
2265
+ }
2084
2266
  if (connected === false && this.delayConnectClientId !== undefined) {
2085
2267
  this.delayConnectClientId = undefined;
2086
2268
  this.mc.logger.sendTelemetryEvent({
@@ -2173,7 +2355,7 @@ export class ContainerRuntime
2173
2355
  this.replayPendingStates();
2174
2356
  }
2175
2357
 
2176
- this.dataStores.setConnectionState(connected, clientId);
2358
+ this.channelCollection.setConnectionState(connected, clientId);
2177
2359
  this.garbageCollector.setConnectionState(connected, clientId);
2178
2360
 
2179
2361
  raiseConnectedEvent(this.mc.logger, this, connected, clientId);
@@ -2229,12 +2411,17 @@ export class ContainerRuntime
2229
2411
  this._processedClientSequenceNumber = message.clientSequenceNumber;
2230
2412
 
2231
2413
  try {
2414
+ // See commit that added this assert for more details.
2415
+ // These calls should be made for all but chunked ops:
2416
+ // 1) this.pendingStateManager.processPendingLocalMessage() below
2417
+ // 2) this.resetReconnectCount() below
2418
+ assert(
2419
+ message.type !== ContainerMessageType.ChunkedOp,
2420
+ "we should never get here with chunked ops",
2421
+ );
2422
+
2232
2423
  let localOpMetadata: unknown;
2233
- if (
2234
- local &&
2235
- messageWithContext.modernRuntimeMessage &&
2236
- message.type !== ContainerMessageType.ChunkedOp
2237
- ) {
2424
+ if (local && messageWithContext.modernRuntimeMessage) {
2238
2425
  localOpMetadata = this.pendingStateManager.processPendingLocalMessage(
2239
2426
  messageWithContext.message,
2240
2427
  );
@@ -2256,7 +2443,7 @@ export class ContainerRuntime
2256
2443
  // If we have processed a local op, this means that the container is
2257
2444
  // making progress and we can reset the counter for how many times
2258
2445
  // we have consecutively replayed the pending states
2259
- this.resetReconnectCount(message);
2446
+ this.resetReconnectCount();
2260
2447
  }
2261
2448
  } catch (e) {
2262
2449
  this.scheduleManager.afterOpProcessing(e, message);
@@ -2276,17 +2463,9 @@ export class ContainerRuntime
2276
2463
  const { local } = messageWithContext;
2277
2464
  switch (messageWithContext.message.type) {
2278
2465
  case ContainerMessageType.Attach:
2279
- this.dataStores.processAttachMessage(messageWithContext.message, local);
2280
- break;
2281
2466
  case ContainerMessageType.Alias:
2282
- this.dataStores.processAliasMessage(
2283
- messageWithContext.message,
2284
- localOpMetadata,
2285
- local,
2286
- );
2287
- break;
2288
2467
  case ContainerMessageType.FluidDataStoreOp:
2289
- this.dataStores.processFluidDataStoreOp(
2468
+ this.channelCollection.process(
2290
2469
  messageWithContext.message,
2291
2470
  local,
2292
2471
  localOpMetadata,
@@ -2297,23 +2476,32 @@ export class ContainerRuntime
2297
2476
  this.blobManager.processBlobAttachOp(messageWithContext.message, local);
2298
2477
  break;
2299
2478
  case ContainerMessageType.IdAllocation:
2300
- assert(
2301
- this.idCompressor !== undefined,
2302
- 0x67c /* IdCompressor should be defined if enabled */,
2303
- );
2304
-
2305
2479
  // Don't re-finalize the range if we're processing a "savedOp" in
2306
2480
  // stashed ops flow. The compressor is stashed with these ops already processed.
2481
+ // That said, in idCompressorMode === "delayed", we might not serialize ID compressor, and
2482
+ // thus we need to process all the ops.
2307
2483
  if (
2308
- (messageWithContext.message.metadata as IIdAllocationMetadata)?.savedOp !== true
2484
+ !(
2485
+ this.skipSavedCompressorOps &&
2486
+ (messageWithContext.message.metadata as IIdAllocationMetadata)?.savedOp ===
2487
+ true
2488
+ )
2309
2489
  ) {
2310
- this.idCompressor.finalizeCreationRange(messageWithContext.message.contents);
2490
+ const range = messageWithContext.message.contents;
2491
+ if (this._idCompressor === undefined) {
2492
+ this.pendingIdCompressorOps.push(range);
2493
+ } else {
2494
+ this._idCompressor.finalizeCreationRange(range);
2495
+ }
2311
2496
  }
2312
2497
  break;
2313
2498
  case ContainerMessageType.GC:
2314
2499
  this.garbageCollector.processMessage(messageWithContext.message, local);
2315
2500
  break;
2316
2501
  case ContainerMessageType.ChunkedOp:
2502
+ // From observability POV, we should not exppse the rest of the system (including "op" events on object) to these messages.
2503
+ // Also resetReconnectCount() would be wrong - see comment that was there before this change was made.
2504
+ assert(false, "should not even get here");
2317
2505
  case ContainerMessageType.Rejoin:
2318
2506
  break;
2319
2507
  default: {
@@ -2413,7 +2601,16 @@ export class ContainerRuntime
2413
2601
  return;
2414
2602
  }
2415
2603
 
2416
- this.dataStores.processSignal(envelope.address, transformed, local);
2604
+ // Due to a mismatch between different layers in terms of
2605
+ // what is the interface of passing signals, we need to adjust
2606
+ // the signal envelope before sending it to the datastores to be processed
2607
+ const envelope2: IEnvelope = {
2608
+ address: envelope.address,
2609
+ contents: transformed.content,
2610
+ };
2611
+ transformed.content = envelope2;
2612
+
2613
+ this.channelCollection.processSignal(transformed, local);
2417
2614
  }
2418
2615
 
2419
2616
  /**
@@ -2500,9 +2697,17 @@ export class ContainerRuntime
2500
2697
  public async getAliasedDataStoreEntryPoint(
2501
2698
  alias: string,
2502
2699
  ): Promise<IFluidHandle<FluidObject> | undefined> {
2503
- await this.dataStores.waitIfPendingAlias(alias);
2700
+ // Back-comapatibility:
2701
+ // There are old files that were created without using data store aliasing feature, but
2702
+ // used createRoot*DataStore*() (already removed) API. Such data stores will have isRoot = true,
2703
+ // and internalID provided by user. The expectation is that such files behave as new files, where
2704
+ // same data store instances created using aliasing feature.
2705
+ // Please also see note on name collisions in DataStores.createDataStoreId()
2706
+ await this.channelCollection.waitIfPendingAlias(alias);
2504
2707
  const internalId = this.internalId(alias);
2505
- const context = await this.dataStores.getDataStoreIfAvailable(internalId, { wait: false });
2708
+ const context = await this.channelCollection.getDataStoreIfAvailable(internalId, {
2709
+ wait: false,
2710
+ });
2506
2711
  // If the data store is not available or not an alias, return undefined.
2507
2712
  if (context === undefined || !(await context.isRoot())) {
2508
2713
  return undefined;
@@ -2523,37 +2728,26 @@ export class ContainerRuntime
2523
2728
  return channel.entryPoint;
2524
2729
  }
2525
2730
 
2526
- public createDetachedRootDataStore(
2527
- pkg: Readonly<string[]>,
2528
- rootDataStoreId: string,
2529
- ): IFluidDataStoreContextDetached {
2530
- if (rootDataStoreId.includes("/")) {
2531
- throw new UsageError(`Id cannot contain slashes: '${rootDataStoreId}'`);
2532
- }
2533
- return this.dataStores.createDetachedDataStoreCore(pkg, true, rootDataStoreId);
2534
- }
2535
-
2536
2731
  public createDetachedDataStore(
2537
2732
  pkg: Readonly<string[]>,
2538
- groupId?: string,
2733
+ loadingGroupId?: string,
2539
2734
  ): IFluidDataStoreContextDetached {
2540
- return this.dataStores.createDetachedDataStoreCore(pkg, false, undefined, groupId);
2735
+ return this.channelCollection.createDetachedDataStore(pkg, loadingGroupId);
2541
2736
  }
2542
2737
 
2543
- public async createDataStore(pkg: string | string[], groupId?: string): Promise<IDataStore> {
2544
- const id = uuid();
2738
+ public async createDataStore(
2739
+ pkg: Readonly<string | string[]>,
2740
+ loadingGroupId?: string,
2741
+ ): Promise<IDataStore> {
2742
+ const context = this.channelCollection.createDataStoreContext(
2743
+ Array.isArray(pkg) ? pkg : [pkg],
2744
+ undefined, // props
2745
+ loadingGroupId,
2746
+ );
2545
2747
  return channelToDataStore(
2546
- await this.dataStores
2547
- ._createFluidDataStoreContext(
2548
- Array.isArray(pkg) ? pkg : [pkg],
2549
- id,
2550
- undefined,
2551
- groupId,
2552
- )
2553
- .realize(),
2554
- id,
2555
- this,
2556
- this.dataStores,
2748
+ await context.realize(),
2749
+ context.id,
2750
+ this.channelCollection,
2557
2751
  this.mc.logger,
2558
2752
  );
2559
2753
  }
@@ -2562,17 +2756,17 @@ export class ContainerRuntime
2562
2756
  * @deprecated 0.16 Issue #1537, #3631
2563
2757
  */
2564
2758
  public async _createDataStoreWithProps(
2565
- pkg: string | string[],
2759
+ pkg: Readonly<string | string[]>,
2566
2760
  props?: any,
2567
- id = uuid(),
2568
2761
  ): Promise<IDataStore> {
2762
+ const context = this.channelCollection.createDataStoreContext(
2763
+ Array.isArray(pkg) ? pkg : [pkg],
2764
+ props,
2765
+ );
2569
2766
  return channelToDataStore(
2570
- await this.dataStores
2571
- ._createFluidDataStoreContext(Array.isArray(pkg) ? pkg : [pkg], id, props)
2572
- .realize(),
2573
- id,
2574
- this,
2575
- this.dataStores,
2767
+ await context.realize(),
2768
+ context.id,
2769
+ this.channelCollection,
2576
2770
  this.mc.logger,
2577
2771
  );
2578
2772
  }
@@ -2628,6 +2822,7 @@ export class ContainerRuntime
2628
2822
  }
2629
2823
  break;
2630
2824
  }
2825
+ case ContainerMessageType.IdAllocation:
2631
2826
  case ContainerMessageType.GC: {
2632
2827
  return false;
2633
2828
  }
@@ -2673,22 +2868,6 @@ export class ContainerRuntime
2673
2868
  return this.submitSignalFn(envelope, targetClientId);
2674
2869
  }
2675
2870
 
2676
- /**
2677
- * Submits the signal to be sent to other clients.
2678
- * @param type - Type of the signal.
2679
- * @param content - Content of the signal.
2680
- * @param targetClientId - When specified, the signal is only sent to the provided client id.
2681
- */
2682
- public submitDataStoreSignal(
2683
- address: string,
2684
- type: string,
2685
- content: any,
2686
- targetClientId?: string,
2687
- ) {
2688
- const envelope = this.createNewSignalEnvelope(address, type, content);
2689
- return this.submitSignalFn(envelope, targetClientId);
2690
- }
2691
-
2692
2871
  public setAttachState(attachState: AttachState.Attaching | AttachState.Attached): void {
2693
2872
  if (attachState === AttachState.Attaching) {
2694
2873
  assert(
@@ -2706,7 +2885,7 @@ export class ContainerRuntime
2706
2885
  if (attachState === AttachState.Attached && !this.hasPendingMessages()) {
2707
2886
  this.updateDocumentDirtyState(false);
2708
2887
  }
2709
- this.dataStores.setAttachState(attachState);
2888
+ this.channelCollection.setAttachState(attachState);
2710
2889
  }
2711
2890
 
2712
2891
  /**
@@ -2726,12 +2905,12 @@ export class ContainerRuntime
2726
2905
  }
2727
2906
 
2728
2907
  // We can finalize any allocated IDs since we're the only client
2729
- const idRange = this.idCompressor?.takeNextCreationRange();
2908
+ const idRange = this._idCompressor?.takeNextCreationRange();
2730
2909
  if (idRange !== undefined) {
2731
- this.idCompressor?.finalizeCreationRange(idRange);
2910
+ this._idCompressor?.finalizeCreationRange(idRange);
2732
2911
  }
2733
2912
 
2734
- const summarizeResult = this.dataStores.createSummary(telemetryContext);
2913
+ const summarizeResult = this.channelCollection.getAttachSummary(telemetryContext);
2735
2914
  // Wrap data store summaries in .channels subtree.
2736
2915
  wrapSummaryInChannelsTree(summarizeResult);
2737
2916
 
@@ -2751,7 +2930,7 @@ export class ContainerRuntime
2751
2930
  trackState: boolean,
2752
2931
  telemetryContext?: ITelemetryContext,
2753
2932
  ): Promise<ISummarizeInternalResult> {
2754
- const summarizeResult = await this.dataStores.summarize(
2933
+ const summarizeResult = await this.channelCollection.summarize(
2755
2934
  fullTree,
2756
2935
  trackState,
2757
2936
  telemetryContext,
@@ -2842,11 +3021,11 @@ export class ContainerRuntime
2842
3021
  * @see IGarbageCollectionRuntime.updateStateBeforeGC
2843
3022
  */
2844
3023
  public async updateStateBeforeGC() {
2845
- return this.dataStores.updateStateBeforeGC();
3024
+ return this.channelCollection.updateStateBeforeGC();
2846
3025
  }
2847
3026
 
2848
3027
  private async getGCDataInternal(fullGC?: boolean): Promise<IGarbageCollectionData> {
2849
- return this.dataStores.getGCData(fullGC);
3028
+ return this.channelCollection.getGCData(fullGC);
2850
3029
  }
2851
3030
 
2852
3031
  /**
@@ -2876,25 +3055,7 @@ export class ContainerRuntime
2876
3055
  this.summarizerNode.updateUsedRoutes([""]);
2877
3056
 
2878
3057
  const { dataStoreRoutes } = this.getDataStoreAndBlobManagerRoutes(usedRoutes);
2879
- this.dataStores.updateUsedRoutes(dataStoreRoutes);
2880
- }
2881
-
2882
- /**
2883
- * This is called to update objects whose routes are unused.
2884
- * @param unusedRoutes - Data store and attachment blob routes that are unused in this Container.
2885
- */
2886
- public updateUnusedRoutes(unusedRoutes: readonly string[]) {
2887
- const { blobManagerRoutes, dataStoreRoutes } =
2888
- this.getDataStoreAndBlobManagerRoutes(unusedRoutes);
2889
- this.blobManager.updateUnusedRoutes(blobManagerRoutes);
2890
- this.dataStores.updateUnusedRoutes(dataStoreRoutes);
2891
- }
2892
-
2893
- /**
2894
- * @deprecated Replaced by deleteSweepReadyNodes.
2895
- */
2896
- public deleteUnusedNodes(unusedRoutes: readonly string[]): string[] {
2897
- throw new Error("deleteUnusedRoutes should not be called");
3058
+ this.channelCollection.updateUsedRoutes(dataStoreRoutes);
2898
3059
  }
2899
3060
 
2900
3061
  /**
@@ -2906,7 +3067,7 @@ export class ContainerRuntime
2906
3067
  const { dataStoreRoutes, blobManagerRoutes } =
2907
3068
  this.getDataStoreAndBlobManagerRoutes(sweepReadyRoutes);
2908
3069
 
2909
- const deletedRoutes = this.dataStores.deleteSweepReadyNodes(dataStoreRoutes);
3070
+ const deletedRoutes = this.channelCollection.deleteSweepReadyNodes(dataStoreRoutes);
2910
3071
  return deletedRoutes.concat(this.blobManager.deleteSweepReadyNodes(blobManagerRoutes));
2911
3072
  }
2912
3073
 
@@ -2922,7 +3083,7 @@ export class ContainerRuntime
2922
3083
  const { blobManagerRoutes, dataStoreRoutes } =
2923
3084
  this.getDataStoreAndBlobManagerRoutes(tombstonedRoutes);
2924
3085
  this.blobManager.updateTombstonedRoutes(blobManagerRoutes);
2925
- this.dataStores.updateTombstonedRoutes(dataStoreRoutes);
3086
+ this.channelCollection.updateTombstonedRoutes(dataStoreRoutes);
2926
3087
  }
2927
3088
 
2928
3089
  /**
@@ -2942,7 +3103,7 @@ export class ContainerRuntime
2942
3103
  if (this.isBlobPath(nodePath)) {
2943
3104
  return GCNodeType.Blob;
2944
3105
  }
2945
- return this.dataStores.getGCNodeType(nodePath) ?? GCNodeType.Other;
3106
+ return this.channelCollection.getGCNodeType(nodePath) ?? GCNodeType.Other;
2946
3107
  }
2947
3108
 
2948
3109
  /**
@@ -2953,7 +3114,7 @@ export class ContainerRuntime
2953
3114
  // GC uses "/" when adding "root" references, e.g. for Aliasing or as part of Tombstone Auto-Recovery.
2954
3115
  // These have no package path so return a special value.
2955
3116
  if (nodePath === "/") {
2956
- return ["<GCROOT>"];
3117
+ return ["_gcRoot"];
2957
3118
  }
2958
3119
 
2959
3120
  switch (this.getNodeType(nodePath)) {
@@ -2961,7 +3122,7 @@ export class ContainerRuntime
2961
3122
  return [BlobManager.basePath];
2962
3123
  case GCNodeType.DataStore:
2963
3124
  case GCNodeType.SubDataStore:
2964
- return this.dataStores.getDataStorePackagePath(nodePath);
3125
+ return this.channelCollection.getDataStorePackagePath(nodePath);
2965
3126
  default:
2966
3127
  assert(false, 0x2de /* "Package path requested for unsupported node type." */);
2967
3128
  }
@@ -3021,7 +3182,10 @@ export class ContainerRuntime
3021
3182
  * @param srcHandle - The handle of the node that added the reference.
3022
3183
  * @param outboundHandle - The handle of the outbound node that is referenced.
3023
3184
  */
3024
- public addedGCOutboundReference(srcHandle: IFluidHandle, outboundHandle: IFluidHandle) {
3185
+ public addedGCOutboundReference(
3186
+ srcHandle: { absolutePath: string },
3187
+ outboundHandle: { absolutePath: string },
3188
+ ) {
3025
3189
  this.garbageCollector.addedOutboundReference(
3026
3190
  srcHandle.absolutePath,
3027
3191
  outboundHandle.absolutePath,
@@ -3037,7 +3201,13 @@ export class ContainerRuntime
3037
3201
  * @param options - options controlling how the summary is generated or submitted
3038
3202
  */
3039
3203
  public async submitSummary(options: ISubmitSummaryOptions): Promise<SubmitSummaryResult> {
3040
- const { fullTree = false, finalAttempt = false, refreshLatestAck, summaryLogger } = options;
3204
+ const {
3205
+ fullTree = false,
3206
+ finalAttempt = false,
3207
+ refreshLatestAck,
3208
+ summaryLogger,
3209
+ latestSummaryRefSeqNum,
3210
+ } = options;
3041
3211
  // The summary number for this summary. This will be updated during the summary process, so get it now and
3042
3212
  // use it for all events logged during this summary.
3043
3213
  const summaryNumber = this.nextSummaryNumber;
@@ -3108,6 +3278,10 @@ export class ContainerRuntime
3108
3278
  this.mc.config.getBoolean(
3109
3279
  "Fluid.ContainerRuntime.SubmitSummary.disableInboundSignalPause",
3110
3280
  ) !== true;
3281
+ const shouldValidatePreSummaryState =
3282
+ this.mc.config.getBoolean(
3283
+ "Fluid.ContainerRuntime.SubmitSummary.shouldValidatePreSummaryState",
3284
+ ) === true;
3111
3285
 
3112
3286
  let summaryRefSeqNum: number | undefined;
3113
3287
 
@@ -3122,7 +3296,33 @@ export class ContainerRuntime
3122
3296
  const message = `Summary @${summaryRefSeqNum}:${this.deltaManager.minimumSequenceNumber}`;
3123
3297
  const lastAck = this.summaryCollection.latestAck;
3124
3298
 
3125
- this.summarizerNode.startSummary(summaryRefSeqNum, summaryNumberLogger);
3299
+ const startSummaryResult = this.summarizerNode.startSummary(
3300
+ summaryRefSeqNum,
3301
+ summaryNumberLogger,
3302
+ latestSummaryRefSeqNum,
3303
+ );
3304
+
3305
+ if (
3306
+ startSummaryResult.invalidNodes > 0 ||
3307
+ startSummaryResult.mismatchNumbers.size > 0
3308
+ ) {
3309
+ summaryLogger.sendErrorEvent({
3310
+ eventName: "LatestSummaryRefSeqNumMismatch",
3311
+ details: {
3312
+ ...startSummaryResult,
3313
+ mismatchNumbers: Array.from(startSummaryResult.mismatchNumbers),
3314
+ },
3315
+ });
3316
+
3317
+ if (shouldValidatePreSummaryState && !finalAttempt) {
3318
+ return {
3319
+ stage: "base",
3320
+ referenceSequenceNumber: summaryRefSeqNum,
3321
+ minimumSequenceNumber,
3322
+ error: `Summarizer node state inconsistent with summarizer state.`,
3323
+ };
3324
+ }
3325
+ }
3126
3326
 
3127
3327
  // Helper function to check whether we should still continue between each async step.
3128
3328
  const checkContinue = (): { continue: true } | { continue: false; error: string } => {
@@ -3244,8 +3444,8 @@ export class ContainerRuntime
3244
3444
  : undefined;
3245
3445
 
3246
3446
  const summaryStats: IGeneratedSummaryStats = {
3247
- dataStoreCount: this.dataStores.size,
3248
- summarizedDataStoreCount: this.dataStores.size - handleCount,
3447
+ dataStoreCount: this.channelCollection.size,
3448
+ summarizedDataStoreCount: this.channelCollection.size - handleCount,
3249
3449
  gcStateUpdatedDataStoreCount: this.garbageCollector.updatedDSCountSinceLastSummary,
3250
3450
  gcBlobNodeCount: gcSummaryTreeStats?.blobNodeCount,
3251
3451
  gcTotalBlobsSize: gcSummaryTreeStats?.totalBlobSize,
@@ -3442,28 +3642,15 @@ export class ContainerRuntime
3442
3642
  }
3443
3643
  }
3444
3644
 
3445
- public submitDataStoreOp(
3446
- id: string,
3645
+ public submitMessage(
3646
+ type:
3647
+ | ContainerMessageType.FluidDataStoreOp
3648
+ | ContainerMessageType.Alias
3649
+ | ContainerMessageType.Attach,
3447
3650
  contents: any,
3448
3651
  localOpMetadata: unknown = undefined,
3449
3652
  ): void {
3450
- const envelope: IEnvelope = {
3451
- address: id,
3452
- contents,
3453
- };
3454
- this.submit(
3455
- { type: ContainerMessageType.FluidDataStoreOp, contents: envelope },
3456
- localOpMetadata,
3457
- );
3458
- }
3459
-
3460
- public submitDataStoreAliasOp(contents: any, localOpMetadata: unknown): void {
3461
- const aliasMessage = contents as IDataStoreAliasMessage;
3462
- if (!isDataStoreAliasMessage(aliasMessage)) {
3463
- throw new UsageError("malformedDataStoreAliasMessage");
3464
- }
3465
-
3466
- this.submit({ type: ContainerMessageType.Alias, contents }, localOpMetadata);
3653
+ this.submit({ type, contents }, localOpMetadata);
3467
3654
  }
3468
3655
 
3469
3656
  public async uploadBlob(
@@ -3474,35 +3661,22 @@ export class ContainerRuntime
3474
3661
  return this.blobManager.createBlob(blob, signal);
3475
3662
  }
3476
3663
 
3477
- private maybeSubmitIdAllocationOp(type: ContainerMessageType) {
3478
- if (type !== ContainerMessageType.IdAllocation) {
3479
- let idAllocationBatchMessage: BatchMessage | undefined;
3480
- let idRange: IdCreationRange | undefined;
3481
- if (this.idCompressorEnabled) {
3482
- assert(
3483
- this.idCompressor !== undefined,
3484
- 0x67d /* IdCompressor should be defined if enabled */,
3485
- );
3486
- idRange = this.idCompressor.takeNextCreationRange();
3487
- // Don't include the idRange if there weren't any Ids allocated
3488
- idRange = idRange?.ids !== undefined ? idRange : undefined;
3489
- }
3490
-
3491
- if (idRange !== undefined) {
3664
+ private submitIdAllocationOpIfNeeded(): void {
3665
+ if (this._idCompressor) {
3666
+ const idRange = this._idCompressor.takeNextCreationRange();
3667
+ // Don't include the idRange if there weren't any Ids allocated
3668
+ if (idRange?.ids !== undefined) {
3492
3669
  const idAllocationMessage: ContainerRuntimeIdAllocationMessage = {
3493
3670
  type: ContainerMessageType.IdAllocation,
3494
3671
  contents: idRange,
3495
3672
  };
3496
- idAllocationBatchMessage = {
3673
+ const idAllocationBatchMessage: BatchMessage = {
3497
3674
  contents: JSON.stringify(idAllocationMessage),
3498
3675
  referenceSequenceNumber: this.deltaManager.lastSequenceNumber,
3499
3676
  metadata: undefined,
3500
3677
  localOpMetadata: undefined,
3501
3678
  type: ContainerMessageType.IdAllocation,
3502
3679
  };
3503
- }
3504
-
3505
- if (idAllocationBatchMessage !== undefined) {
3506
3680
  this.outbox.submitIdAllocation(idAllocationBatchMessage);
3507
3681
  }
3508
3682
  }
@@ -3543,43 +3717,47 @@ export class ContainerRuntime
3543
3717
  };
3544
3718
 
3545
3719
  try {
3546
- // Submit an IdAllocation op if any Ids have been generated since
3547
- // the last op was submitted. Don't submit another if it's an IdAllocation
3548
- // op as that means we're in resubmission flow and we don't want to send
3549
- // IdRanges out of order.
3550
- this.maybeSubmitIdAllocationOp(type);
3551
-
3552
- // If this is attach message for new data store, and we are in a batch, send this op out of order
3553
- // Is it safe:
3554
- // Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
3555
- // They become visible only when aliased, or handle to some sub-element of newly created datastore
3556
- // is stored in some DDS, i.e. only after some other op.
3557
- // Why:
3558
- // Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
3559
- // stores are created, causing issues like relay service throttling (too many ops) and catastrophic
3560
- // failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
3561
- // these issues.
3562
- // Cons:
3563
- // 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
3564
- // This change creates new possibility of a lot of newly created data stores never being referenced
3565
- // because client died before it had a change to submit the rest of the ops. This will create more
3566
- // garbage that needs to be collected leveraging GC (Garbage Collection) feature.
3567
- // 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
3568
- // today as rollback can't undo creation of data store. To some extent not sending them is a bigger
3569
- // issue than sending.
3570
- // Please note that this does not change file format, so it can be disabled in the future if this
3571
- // optimization no longer makes sense (for example, batch compression may make it less appealing).
3572
- if (
3573
- this.currentlyBatching() &&
3574
- type === ContainerMessageType.Attach &&
3575
- this.disableAttachReorder !== true
3576
- ) {
3577
- this.outbox.submitAttach(message);
3578
- } else if (type === ContainerMessageType.BlobAttach) {
3579
- // BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
3580
- this.outbox.submitBlobAttach(message);
3720
+ // If `message` is an allocation op, then we are in the resubmit path and we must redirect the allocation
3721
+ // op into the correct batch to avoid ranges being finalized out of order.
3722
+ // Otherwise, submit an IdAllocation op if any IDs have been generated since the last op was submitted, as
3723
+ // any of the other op types may contain those IDs and thus depend on the allocation op being sent first.
3724
+ if (type === ContainerMessageType.IdAllocation) {
3725
+ this.outbox.submitIdAllocation(message);
3581
3726
  } else {
3582
- this.outbox.submit(message);
3727
+ this.submitIdAllocationOpIfNeeded();
3728
+
3729
+ // If this is attach message for new data store, and we are in a batch, send this op out of order
3730
+ // Is it safe:
3731
+ // Yes, this should be safe reordering. Newly created data stores are not visible through API surface.
3732
+ // They become visible only when aliased, or handle to some sub-element of newly created datastore
3733
+ // is stored in some DDS, i.e. only after some other op.
3734
+ // Why:
3735
+ // Attach ops are large, and expensive to process. Plus there are scenarios where a lot of new data
3736
+ // stores are created, causing issues like relay service throttling (too many ops) and catastrophic
3737
+ // failure (batch is too large). Pushing them earlier and outside of main batch should alleviate
3738
+ // these issues.
3739
+ // Cons:
3740
+ // 1. With large batches, relay service may throttle clients. Clients may disconnect while throttled.
3741
+ // This change creates new possibility of a lot of newly created data stores never being referenced
3742
+ // because client died before it had a change to submit the rest of the ops. This will create more
3743
+ // garbage that needs to be collected leveraging GC (Garbage Collection) feature.
3744
+ // 2. Sending ops out of order means they are excluded from rollback functionality. This is not an issue
3745
+ // today as rollback can't undo creation of data store. To some extent not sending them is a bigger
3746
+ // issue than sending.
3747
+ // Please note that this does not change file format, so it can be disabled in the future if this
3748
+ // optimization no longer makes sense (for example, batch compression may make it less appealing).
3749
+ if (
3750
+ this.currentlyBatching() &&
3751
+ type === ContainerMessageType.Attach &&
3752
+ this.disableAttachReorder !== true
3753
+ ) {
3754
+ this.outbox.submitAttach(message);
3755
+ } else if (type === ContainerMessageType.BlobAttach) {
3756
+ // BlobAttach ops must have their metadata visible and cannot be grouped (see opGroupingManager.ts)
3757
+ this.outbox.submitBlobAttach(message);
3758
+ } else {
3759
+ this.outbox.submit(message);
3760
+ }
3583
3761
  }
3584
3762
 
3585
3763
  if (!this.currentlyBatching()) {
@@ -3721,15 +3899,18 @@ export class ContainerRuntime
3721
3899
  localOpMetadata: unknown,
3722
3900
  opMetadata: Record<string, unknown> | undefined,
3723
3901
  ) {
3724
- assert(!this.isSummarizerClient, "Summarizer never reconnects so should never resubmit");
3902
+ assert(
3903
+ !this.isSummarizerClient,
3904
+ 0x8f2 /* Summarizer never reconnects so should never resubmit */,
3905
+ );
3725
3906
  switch (message.type) {
3726
3907
  case ContainerMessageType.FluidDataStoreOp:
3908
+ case ContainerMessageType.Attach:
3909
+ case ContainerMessageType.Alias:
3727
3910
  // For Operations, call resubmitDataStoreOp which will find the right store
3728
3911
  // and trigger resubmission on it.
3729
- this.dataStores.resubmitDataStoreOp(message.contents, localOpMetadata);
3912
+ this.channelCollection.reSubmit(message.type, message.contents, localOpMetadata);
3730
3913
  break;
3731
- case ContainerMessageType.Attach:
3732
- case ContainerMessageType.Alias:
3733
3914
  case ContainerMessageType.IdAllocation: {
3734
3915
  this.submit(message, localOpMetadata);
3735
3916
  break;
@@ -3781,7 +3962,7 @@ export class ContainerRuntime
3781
3962
  case ContainerMessageType.FluidDataStoreOp:
3782
3963
  // For operations, call rollbackDataStoreOp which will find the right store
3783
3964
  // and trigger rollback on it.
3784
- this.dataStores.rollbackDataStoreOp(contents, localOpMetadata);
3965
+ this.channelCollection.rollback(type, contents, localOpMetadata);
3785
3966
  break;
3786
3967
  default:
3787
3968
  // Don't check message.compatDetails because this is for rolling back a local op so the type will be known
@@ -3870,7 +4051,7 @@ export class ContainerRuntime
3870
4051
  */
3871
4052
  private async fetchLatestSnapshotFromStorage(
3872
4053
  logger: ITelemetryLoggerExt,
3873
- event: ITelemetryGenericEvent,
4054
+ event: ITelemetryGenericEventExt,
3874
4055
  readAndParseBlob: ReadAndParseBlob,
3875
4056
  ): Promise<{ snapshotTree: ISnapshotTree; versionId: string; latestSnapshotRefSeq: number }> {
3876
4057
  return PerformanceEvent.timedExecAsync(
@@ -3921,50 +4102,65 @@ export class ContainerRuntime
3921
4102
  );
3922
4103
  }
3923
4104
 
3924
- public async getPendingLocalState(props?: IGetPendingLocalStateProps): Promise<unknown> {
3925
- return PerformanceEvent.timedExecAsync(
3926
- this.mc.logger,
3927
- {
3928
- eventName: "getPendingLocalState",
3929
- notifyImminentClosure: props?.notifyImminentClosure,
3930
- },
3931
- async (event) => {
3932
- this.verifyNotClosed();
3933
- // in case imminentClosure is set to true by future code, we don't
3934
- // try to change its value
3935
- if (!this.imminentClosure) {
3936
- this.imminentClosure = props?.notifyImminentClosure ?? this.imminentClosure;
3937
- }
3938
- const stopBlobAttachingSignal = props?.stopBlobAttachingSignal;
3939
- if (this._orderSequentiallyCalls !== 0) {
3940
- throw new UsageError("can't get state during orderSequentially");
3941
- }
3942
- // Flush pending batch.
3943
- // getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
3944
- // to close current batch.
3945
- this.flush();
3946
- const pendingAttachmentBlobs = this.imminentClosure
3947
- ? await this.blobManager.attachAndGetPendingBlobs(stopBlobAttachingSignal)
3948
- : undefined;
3949
- const pending = this.pendingStateManager.getLocalState();
3950
- if (!pendingAttachmentBlobs && !this.hasPendingMessages()) {
3951
- return; // no pending state to save
3952
- }
4105
+ public getPendingLocalState(props?: IGetPendingLocalStateProps): unknown {
4106
+ this.verifyNotClosed();
4107
+
4108
+ if (this._orderSequentiallyCalls !== 0) {
4109
+ throw new UsageError("can't get state during orderSequentially");
4110
+ }
4111
+ this.imminentClosure ||= props?.notifyImminentClosure ?? false;
4112
+
4113
+ const getSyncState = (
4114
+ pendingAttachmentBlobs?: IPendingBlobs,
4115
+ ): IPendingRuntimeState | undefined => {
4116
+ const pending = this.pendingStateManager.getLocalState();
4117
+ if (pendingAttachmentBlobs === undefined && !this.hasPendingMessages()) {
4118
+ return; // no pending state to save
4119
+ }
3953
4120
 
3954
- const pendingIdCompressorState = this.idCompressor?.serialize(true);
4121
+ const pendingIdCompressorState = this._idCompressor?.serialize(true);
3955
4122
 
3956
- const pendingState: IPendingRuntimeState = {
3957
- pending,
3958
- pendingAttachmentBlobs,
3959
- pendingIdCompressorState,
3960
- };
3961
- event.end({
3962
- attachmentBlobsSize: Object.keys(pendingAttachmentBlobs ?? {}).length,
3963
- pendingOpsSize: pending?.pendingStates.length,
3964
- });
3965
- return pendingState;
3966
- },
3967
- );
4123
+ return {
4124
+ pending,
4125
+ pendingIdCompressorState,
4126
+ pendingAttachmentBlobs,
4127
+ sessionExpiryTimerStarted: this.garbageCollector.sessionExpiryTimerStarted,
4128
+ };
4129
+ };
4130
+ const perfEvent = {
4131
+ eventName: "getPendingLocalState",
4132
+ notifyImminentClosure: props?.notifyImminentClosure,
4133
+ };
4134
+ const logAndReturnPendingState = (
4135
+ event: PerformanceEvent,
4136
+ pendingState?: IPendingRuntimeState,
4137
+ ) => {
4138
+ event.end({
4139
+ attachmentBlobsSize: Object.keys(pendingState?.pendingAttachmentBlobs ?? {}).length,
4140
+ pendingOpsSize: pendingState?.pending?.pendingStates.length,
4141
+ });
4142
+ return pendingState;
4143
+ };
4144
+
4145
+ // Flush pending batch.
4146
+ // getPendingLocalState() is only exposed through Container.closeAndGetPendingLocalState(), so it's safe
4147
+ // to close current batch.
4148
+ this.flush();
4149
+
4150
+ return props?.notifyImminentClosure === true
4151
+ ? PerformanceEvent.timedExecAsync(this.mc.logger, perfEvent, async (event) =>
4152
+ logAndReturnPendingState(
4153
+ event,
4154
+ getSyncState(
4155
+ await this.blobManager.attachAndGetPendingBlobs(
4156
+ props?.stopBlobAttachingSignal,
4157
+ ),
4158
+ ),
4159
+ ),
4160
+ )
4161
+ : PerformanceEvent.timedExec(this.mc.logger, perfEvent, (event) =>
4162
+ logAndReturnPendingState(event, getSyncState()),
4163
+ );
3968
4164
  }
3969
4165
 
3970
4166
  public summarizeOnDemand(options: IOnDemandSummarizeOptions): ISummarizeResults {