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

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