@fluidframework/container-runtime 2.0.0-internal.3.1.0 → 2.0.0-internal.3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (351) hide show
  1. package/dist/blobManager.d.ts +6 -0
  2. package/dist/blobManager.d.ts.map +1 -1
  3. package/dist/blobManager.js +31 -6
  4. package/dist/blobManager.js.map +1 -1
  5. package/dist/containerRuntime.d.ts +17 -15
  6. package/dist/containerRuntime.d.ts.map +1 -1
  7. package/dist/containerRuntime.js +158 -121
  8. package/dist/containerRuntime.js.map +1 -1
  9. package/dist/dataStoreContext.d.ts +21 -12
  10. package/dist/dataStoreContext.d.ts.map +1 -1
  11. package/dist/dataStoreContext.js +76 -50
  12. package/dist/dataStoreContext.js.map +1 -1
  13. package/dist/dataStores.d.ts +9 -10
  14. package/dist/dataStores.d.ts.map +1 -1
  15. package/dist/dataStores.js +42 -49
  16. package/dist/dataStores.js.map +1 -1
  17. package/dist/{garbageCollection.d.ts → gc/garbageCollection.d.ts} +5 -200
  18. package/dist/gc/garbageCollection.d.ts.map +1 -0
  19. package/dist/{garbageCollection.js → gc/garbageCollection.js} +77 -353
  20. package/dist/gc/garbageCollection.js.map +1 -0
  21. package/dist/gc/gcDefinitions.d.ts +189 -0
  22. package/dist/gc/gcDefinitions.d.ts.map +1 -0
  23. package/dist/{garbageCollectionConstants.js → gc/gcDefinitions.js} +24 -2
  24. package/dist/gc/gcDefinitions.js.map +1 -0
  25. package/{lib/garbageCollectionHelpers.d.ts → dist/gc/gcHelpers.d.ts} +5 -1
  26. package/dist/gc/gcHelpers.d.ts.map +1 -0
  27. package/dist/{garbageCollectionHelpers.js → gc/gcHelpers.js} +27 -7
  28. package/dist/gc/gcHelpers.js.map +1 -0
  29. package/dist/gc/gcSummaryStateTracker.d.ts +86 -0
  30. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -0
  31. package/dist/gc/gcSummaryStateTracker.js +246 -0
  32. package/dist/gc/gcSummaryStateTracker.js.map +1 -0
  33. package/dist/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
  34. package/dist/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +2 -2
  35. package/dist/gc/gcSweepReadyUsageDetection.js.map +1 -0
  36. package/dist/gc/gcUnreferencedStateTracker.d.ts +34 -0
  37. package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
  38. package/dist/gc/gcUnreferencedStateTracker.js +94 -0
  39. package/dist/gc/gcUnreferencedStateTracker.js.map +1 -0
  40. package/dist/gc/index.d.ts +11 -0
  41. package/dist/gc/index.d.ts.map +1 -0
  42. package/dist/gc/index.js +40 -0
  43. package/dist/gc/index.js.map +1 -0
  44. package/dist/index.d.ts +2 -5
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +6 -9
  47. package/dist/index.js.map +1 -1
  48. package/dist/opLifecycle/batchManager.d.ts +2 -13
  49. package/dist/opLifecycle/batchManager.d.ts.map +1 -1
  50. package/dist/opLifecycle/batchManager.js +7 -36
  51. package/dist/opLifecycle/batchManager.js.map +1 -1
  52. package/dist/opLifecycle/definitions.d.ts +4 -0
  53. package/dist/opLifecycle/definitions.d.ts.map +1 -1
  54. package/dist/opLifecycle/definitions.js.map +1 -1
  55. package/dist/opLifecycle/opCompressor.d.ts.map +1 -1
  56. package/dist/opLifecycle/opCompressor.js +1 -0
  57. package/dist/opLifecycle/opCompressor.js.map +1 -1
  58. package/dist/opLifecycle/opSplitter.d.ts +1 -1
  59. package/dist/opLifecycle/opSplitter.d.ts.map +1 -1
  60. package/dist/opLifecycle/opSplitter.js +20 -12
  61. package/dist/opLifecycle/opSplitter.js.map +1 -1
  62. package/dist/opLifecycle/outbox.d.ts +19 -3
  63. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  64. package/dist/opLifecycle/outbox.js +59 -28
  65. package/dist/opLifecycle/outbox.js.map +1 -1
  66. package/dist/packageVersion.d.ts +1 -1
  67. package/dist/packageVersion.js +1 -1
  68. package/dist/packageVersion.js.map +1 -1
  69. package/dist/pendingStateManager.d.ts +1 -2
  70. package/dist/pendingStateManager.d.ts.map +1 -1
  71. package/dist/pendingStateManager.js +14 -9
  72. package/dist/pendingStateManager.js.map +1 -1
  73. package/dist/summary/index.d.ts +17 -0
  74. package/dist/summary/index.d.ts.map +1 -0
  75. package/dist/summary/index.js +47 -0
  76. package/dist/summary/index.js.map +1 -0
  77. package/dist/summary/orderedClientElection.d.ts.map +1 -0
  78. package/dist/summary/orderedClientElection.js.map +1 -0
  79. package/dist/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
  80. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -0
  81. package/{lib → dist/summary}/runningSummarizer.d.ts +19 -18
  82. package/dist/summary/runningSummarizer.d.ts.map +1 -0
  83. package/dist/{runningSummarizer.js → summary/runningSummarizer.js} +158 -56
  84. package/dist/summary/runningSummarizer.js.map +1 -0
  85. package/dist/{summarizer.d.ts → summary/summarizer.d.ts} +2 -4
  86. package/dist/summary/summarizer.d.ts.map +1 -0
  87. package/dist/{summarizer.js → summary/summarizer.js} +1 -61
  88. package/dist/summary/summarizer.js.map +1 -0
  89. package/dist/summary/summarizerClientElection.d.ts.map +1 -0
  90. package/dist/summary/summarizerClientElection.js.map +1 -0
  91. package/dist/summary/summarizerHandle.d.ts.map +1 -0
  92. package/dist/summary/summarizerHandle.js.map +1 -0
  93. package/dist/{summarizerHeuristics.d.ts → summary/summarizerHeuristics.d.ts} +1 -1
  94. package/dist/summary/summarizerHeuristics.d.ts.map +1 -0
  95. package/dist/summary/summarizerHeuristics.js.map +1 -0
  96. package/{lib → dist/summary}/summarizerTypes.d.ts +1 -1
  97. package/dist/summary/summarizerTypes.d.ts.map +1 -0
  98. package/dist/summary/summarizerTypes.js.map +1 -0
  99. package/dist/summary/summaryCollection.d.ts.map +1 -0
  100. package/dist/summary/summaryCollection.js.map +1 -0
  101. package/{lib → dist/summary}/summaryFormat.d.ts +1 -43
  102. package/dist/summary/summaryFormat.d.ts.map +1 -0
  103. package/dist/{summaryFormat.js → summary/summaryFormat.js} +1 -10
  104. package/dist/summary/summaryFormat.js.map +1 -0
  105. package/dist/summary/summaryGenerator.d.ts.map +1 -0
  106. package/dist/{summaryGenerator.js → summary/summaryGenerator.js} +1 -2
  107. package/dist/summary/summaryGenerator.js.map +1 -0
  108. package/dist/{summaryManager.d.ts → summary/summaryManager.d.ts} +1 -1
  109. package/dist/summary/summaryManager.d.ts.map +1 -0
  110. package/dist/summary/summaryManager.js.map +1 -0
  111. package/lib/blobManager.d.ts +6 -0
  112. package/lib/blobManager.d.ts.map +1 -1
  113. package/lib/blobManager.js +28 -3
  114. package/lib/blobManager.js.map +1 -1
  115. package/lib/containerRuntime.d.ts +17 -15
  116. package/lib/containerRuntime.d.ts.map +1 -1
  117. package/lib/containerRuntime.js +127 -90
  118. package/lib/containerRuntime.js.map +1 -1
  119. package/lib/dataStoreContext.d.ts +21 -12
  120. package/lib/dataStoreContext.d.ts.map +1 -1
  121. package/lib/dataStoreContext.js +64 -38
  122. package/lib/dataStoreContext.js.map +1 -1
  123. package/lib/dataStores.d.ts +9 -10
  124. package/lib/dataStores.d.ts.map +1 -1
  125. package/lib/dataStores.js +33 -40
  126. package/lib/dataStores.js.map +1 -1
  127. package/lib/{garbageCollection.d.ts → gc/garbageCollection.d.ts} +5 -200
  128. package/lib/gc/garbageCollection.d.ts.map +1 -0
  129. package/lib/{garbageCollection.js → gc/garbageCollection.js} +44 -319
  130. package/lib/gc/garbageCollection.js.map +1 -0
  131. package/lib/gc/gcDefinitions.d.ts +189 -0
  132. package/lib/gc/gcDefinitions.d.ts.map +1 -0
  133. package/lib/{garbageCollectionConstants.js → gc/gcDefinitions.js} +23 -1
  134. package/lib/gc/gcDefinitions.js.map +1 -0
  135. package/{dist/garbageCollectionHelpers.d.ts → lib/gc/gcHelpers.d.ts} +5 -1
  136. package/lib/gc/gcHelpers.d.ts.map +1 -0
  137. package/lib/{garbageCollectionHelpers.js → gc/gcHelpers.js} +20 -2
  138. package/lib/gc/gcHelpers.js.map +1 -0
  139. package/lib/gc/gcSummaryStateTracker.d.ts +86 -0
  140. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -0
  141. package/lib/gc/gcSummaryStateTracker.js +242 -0
  142. package/lib/gc/gcSummaryStateTracker.js.map +1 -0
  143. package/lib/gc/gcSweepReadyUsageDetection.d.ts.map +1 -0
  144. package/lib/{gcSweepReadyUsageDetection.js → gc/gcSweepReadyUsageDetection.js} +1 -1
  145. package/lib/gc/gcSweepReadyUsageDetection.js.map +1 -0
  146. package/lib/gc/gcUnreferencedStateTracker.d.ts +34 -0
  147. package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -0
  148. package/lib/gc/gcUnreferencedStateTracker.js +90 -0
  149. package/lib/gc/gcUnreferencedStateTracker.js.map +1 -0
  150. package/lib/gc/index.d.ts +11 -0
  151. package/lib/gc/index.d.ts.map +1 -0
  152. package/lib/gc/index.js +11 -0
  153. package/lib/gc/index.js.map +1 -0
  154. package/lib/index.d.ts +2 -5
  155. package/lib/index.d.ts.map +1 -1
  156. package/lib/index.js +1 -4
  157. package/lib/index.js.map +1 -1
  158. package/lib/opLifecycle/batchManager.d.ts +2 -13
  159. package/lib/opLifecycle/batchManager.d.ts.map +1 -1
  160. package/lib/opLifecycle/batchManager.js +7 -36
  161. package/lib/opLifecycle/batchManager.js.map +1 -1
  162. package/lib/opLifecycle/definitions.d.ts +4 -0
  163. package/lib/opLifecycle/definitions.d.ts.map +1 -1
  164. package/lib/opLifecycle/definitions.js.map +1 -1
  165. package/lib/opLifecycle/opCompressor.d.ts.map +1 -1
  166. package/lib/opLifecycle/opCompressor.js +1 -0
  167. package/lib/opLifecycle/opCompressor.js.map +1 -1
  168. package/lib/opLifecycle/opSplitter.d.ts +1 -1
  169. package/lib/opLifecycle/opSplitter.d.ts.map +1 -1
  170. package/lib/opLifecycle/opSplitter.js +20 -12
  171. package/lib/opLifecycle/opSplitter.js.map +1 -1
  172. package/lib/opLifecycle/outbox.d.ts +19 -3
  173. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  174. package/lib/opLifecycle/outbox.js +60 -29
  175. package/lib/opLifecycle/outbox.js.map +1 -1
  176. package/lib/packageVersion.d.ts +1 -1
  177. package/lib/packageVersion.js +1 -1
  178. package/lib/packageVersion.js.map +1 -1
  179. package/lib/pendingStateManager.d.ts +1 -2
  180. package/lib/pendingStateManager.d.ts.map +1 -1
  181. package/lib/pendingStateManager.js +14 -9
  182. package/lib/pendingStateManager.js.map +1 -1
  183. package/lib/summary/index.d.ts +17 -0
  184. package/lib/summary/index.d.ts.map +1 -0
  185. package/lib/summary/index.js +16 -0
  186. package/lib/summary/index.js.map +1 -0
  187. package/lib/summary/orderedClientElection.d.ts.map +1 -0
  188. package/lib/summary/orderedClientElection.js.map +1 -0
  189. package/lib/summary/runWhileConnectedCoordinator.d.ts.map +1 -0
  190. package/lib/summary/runWhileConnectedCoordinator.js.map +1 -0
  191. package/{dist → lib/summary}/runningSummarizer.d.ts +19 -18
  192. package/lib/summary/runningSummarizer.d.ts.map +1 -0
  193. package/lib/{runningSummarizer.js → summary/runningSummarizer.js} +159 -57
  194. package/lib/summary/runningSummarizer.js.map +1 -0
  195. package/lib/{summarizer.d.ts → summary/summarizer.d.ts} +2 -4
  196. package/lib/summary/summarizer.d.ts.map +1 -0
  197. package/lib/{summarizer.js → summary/summarizer.js} +3 -63
  198. package/lib/summary/summarizer.js.map +1 -0
  199. package/lib/summary/summarizerClientElection.d.ts.map +1 -0
  200. package/lib/summary/summarizerClientElection.js.map +1 -0
  201. package/lib/summary/summarizerHandle.d.ts.map +1 -0
  202. package/lib/summary/summarizerHandle.js.map +1 -0
  203. package/lib/{summarizerHeuristics.d.ts → summary/summarizerHeuristics.d.ts} +1 -1
  204. package/lib/summary/summarizerHeuristics.d.ts.map +1 -0
  205. package/lib/summary/summarizerHeuristics.js.map +1 -0
  206. package/{dist → lib/summary}/summarizerTypes.d.ts +1 -1
  207. package/lib/summary/summarizerTypes.d.ts.map +1 -0
  208. package/lib/summary/summarizerTypes.js.map +1 -0
  209. package/lib/summary/summaryCollection.d.ts.map +1 -0
  210. package/lib/summary/summaryCollection.js.map +1 -0
  211. package/{dist → lib/summary}/summaryFormat.d.ts +1 -43
  212. package/lib/summary/summaryFormat.d.ts.map +1 -0
  213. package/lib/{summaryFormat.js → summary/summaryFormat.js} +0 -8
  214. package/lib/summary/summaryFormat.js.map +1 -0
  215. package/lib/summary/summaryGenerator.d.ts.map +1 -0
  216. package/lib/{summaryGenerator.js → summary/summaryGenerator.js} +1 -2
  217. package/lib/summary/summaryGenerator.js.map +1 -0
  218. package/lib/{summaryManager.d.ts → summary/summaryManager.d.ts} +1 -1
  219. package/lib/summary/summaryManager.d.ts.map +1 -0
  220. package/lib/summary/summaryManager.js.map +1 -0
  221. package/package.json +125 -122
  222. package/src/blobManager.ts +33 -3
  223. package/src/containerRuntime.ts +178 -106
  224. package/src/dataStoreContext.ts +90 -49
  225. package/src/dataStores.ts +44 -51
  226. package/{garbageCollection.md → src/gc/garbageCollection.md} +2 -2
  227. package/src/{garbageCollection.ts → gc/garbageCollection.ts} +90 -560
  228. package/src/gc/gcDefinitions.ts +244 -0
  229. package/src/{garbageCollectionHelpers.ts → gc/gcHelpers.ts} +26 -1
  230. package/src/gc/gcSummaryStateTracker.ts +339 -0
  231. package/src/{gcSweepReadyUsageDetection.ts → gc/gcSweepReadyUsageDetection.ts} +1 -1
  232. package/src/gc/gcUnreferencedStateTracker.ts +114 -0
  233. package/src/gc/index.ts +40 -0
  234. package/src/index.ts +10 -14
  235. package/src/opLifecycle/batchManager.ts +7 -54
  236. package/src/opLifecycle/definitions.ts +4 -0
  237. package/src/opLifecycle/opCompressor.ts +1 -0
  238. package/src/opLifecycle/opSplitter.ts +33 -14
  239. package/src/opLifecycle/outbox.ts +84 -38
  240. package/src/packageVersion.ts +1 -1
  241. package/src/pendingStateManager.ts +26 -14
  242. package/src/summary/index.ts +99 -0
  243. package/src/{runningSummarizer.ts → summary/runningSummarizer.ts} +279 -139
  244. package/src/{summarizer.ts → summary/summarizer.ts} +5 -76
  245. package/src/{summarizerHeuristics.ts → summary/summarizerHeuristics.ts} +1 -1
  246. package/src/{summarizerTypes.ts → summary/summarizerTypes.ts} +1 -1
  247. package/src/{summaryFormat.ts → summary/summaryFormat.ts} +1 -53
  248. package/src/{summaryGenerator.ts → summary/summaryGenerator.ts} +9 -9
  249. package/src/{summaryManager.ts → summary/summaryManager.ts} +1 -1
  250. package/dist/garbageCollection.d.ts.map +0 -1
  251. package/dist/garbageCollection.js.map +0 -1
  252. package/dist/garbageCollectionConstants.d.ts +0 -26
  253. package/dist/garbageCollectionConstants.d.ts.map +0 -1
  254. package/dist/garbageCollectionConstants.js.map +0 -1
  255. package/dist/garbageCollectionHelpers.d.ts.map +0 -1
  256. package/dist/garbageCollectionHelpers.js.map +0 -1
  257. package/dist/gcSweepReadyUsageDetection.d.ts.map +0 -1
  258. package/dist/gcSweepReadyUsageDetection.js.map +0 -1
  259. package/dist/orderedClientElection.d.ts.map +0 -1
  260. package/dist/orderedClientElection.js.map +0 -1
  261. package/dist/runWhileConnectedCoordinator.d.ts.map +0 -1
  262. package/dist/runWhileConnectedCoordinator.js.map +0 -1
  263. package/dist/runningSummarizer.d.ts.map +0 -1
  264. package/dist/runningSummarizer.js.map +0 -1
  265. package/dist/summarizer.d.ts.map +0 -1
  266. package/dist/summarizer.js.map +0 -1
  267. package/dist/summarizerClientElection.d.ts.map +0 -1
  268. package/dist/summarizerClientElection.js.map +0 -1
  269. package/dist/summarizerHandle.d.ts.map +0 -1
  270. package/dist/summarizerHandle.js.map +0 -1
  271. package/dist/summarizerHeuristics.d.ts.map +0 -1
  272. package/dist/summarizerHeuristics.js.map +0 -1
  273. package/dist/summarizerTypes.d.ts.map +0 -1
  274. package/dist/summarizerTypes.js.map +0 -1
  275. package/dist/summaryCollection.d.ts.map +0 -1
  276. package/dist/summaryCollection.js.map +0 -1
  277. package/dist/summaryFormat.d.ts.map +0 -1
  278. package/dist/summaryFormat.js.map +0 -1
  279. package/dist/summaryGenerator.d.ts.map +0 -1
  280. package/dist/summaryGenerator.js.map +0 -1
  281. package/dist/summaryManager.d.ts.map +0 -1
  282. package/dist/summaryManager.js.map +0 -1
  283. package/lib/garbageCollection.d.ts.map +0 -1
  284. package/lib/garbageCollection.js.map +0 -1
  285. package/lib/garbageCollectionConstants.d.ts +0 -26
  286. package/lib/garbageCollectionConstants.d.ts.map +0 -1
  287. package/lib/garbageCollectionConstants.js.map +0 -1
  288. package/lib/garbageCollectionHelpers.d.ts.map +0 -1
  289. package/lib/garbageCollectionHelpers.js.map +0 -1
  290. package/lib/gcSweepReadyUsageDetection.d.ts.map +0 -1
  291. package/lib/gcSweepReadyUsageDetection.js.map +0 -1
  292. package/lib/orderedClientElection.d.ts.map +0 -1
  293. package/lib/orderedClientElection.js.map +0 -1
  294. package/lib/runWhileConnectedCoordinator.d.ts.map +0 -1
  295. package/lib/runWhileConnectedCoordinator.js.map +0 -1
  296. package/lib/runningSummarizer.d.ts.map +0 -1
  297. package/lib/runningSummarizer.js.map +0 -1
  298. package/lib/summarizer.d.ts.map +0 -1
  299. package/lib/summarizer.js.map +0 -1
  300. package/lib/summarizerClientElection.d.ts.map +0 -1
  301. package/lib/summarizerClientElection.js.map +0 -1
  302. package/lib/summarizerHandle.d.ts.map +0 -1
  303. package/lib/summarizerHandle.js.map +0 -1
  304. package/lib/summarizerHeuristics.d.ts.map +0 -1
  305. package/lib/summarizerHeuristics.js.map +0 -1
  306. package/lib/summarizerTypes.d.ts.map +0 -1
  307. package/lib/summarizerTypes.js.map +0 -1
  308. package/lib/summaryCollection.d.ts.map +0 -1
  309. package/lib/summaryCollection.js.map +0 -1
  310. package/lib/summaryFormat.d.ts.map +0 -1
  311. package/lib/summaryFormat.js.map +0 -1
  312. package/lib/summaryGenerator.d.ts.map +0 -1
  313. package/lib/summaryGenerator.js.map +0 -1
  314. package/lib/summaryManager.d.ts.map +0 -1
  315. package/lib/summaryManager.js.map +0 -1
  316. package/src/garbageCollectionConstants.ts +0 -44
  317. /package/dist/{gcSweepReadyUsageDetection.d.ts → gc/gcSweepReadyUsageDetection.d.ts} +0 -0
  318. /package/dist/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
  319. /package/dist/{orderedClientElection.js → summary/orderedClientElection.js} +0 -0
  320. /package/dist/{runWhileConnectedCoordinator.d.ts → summary/runWhileConnectedCoordinator.d.ts} +0 -0
  321. /package/dist/{runWhileConnectedCoordinator.js → summary/runWhileConnectedCoordinator.js} +0 -0
  322. /package/dist/{summarizerClientElection.d.ts → summary/summarizerClientElection.d.ts} +0 -0
  323. /package/dist/{summarizerClientElection.js → summary/summarizerClientElection.js} +0 -0
  324. /package/dist/{summarizerHandle.d.ts → summary/summarizerHandle.d.ts} +0 -0
  325. /package/dist/{summarizerHandle.js → summary/summarizerHandle.js} +0 -0
  326. /package/dist/{summarizerHeuristics.js → summary/summarizerHeuristics.js} +0 -0
  327. /package/dist/{summarizerTypes.js → summary/summarizerTypes.js} +0 -0
  328. /package/dist/{summaryCollection.d.ts → summary/summaryCollection.d.ts} +0 -0
  329. /package/dist/{summaryCollection.js → summary/summaryCollection.js} +0 -0
  330. /package/dist/{summaryGenerator.d.ts → summary/summaryGenerator.d.ts} +0 -0
  331. /package/dist/{summaryManager.js → summary/summaryManager.js} +0 -0
  332. /package/lib/{gcSweepReadyUsageDetection.d.ts → gc/gcSweepReadyUsageDetection.d.ts} +0 -0
  333. /package/lib/{orderedClientElection.d.ts → summary/orderedClientElection.d.ts} +0 -0
  334. /package/lib/{orderedClientElection.js → summary/orderedClientElection.js} +0 -0
  335. /package/lib/{runWhileConnectedCoordinator.d.ts → summary/runWhileConnectedCoordinator.d.ts} +0 -0
  336. /package/lib/{runWhileConnectedCoordinator.js → summary/runWhileConnectedCoordinator.js} +0 -0
  337. /package/lib/{summarizerClientElection.d.ts → summary/summarizerClientElection.d.ts} +0 -0
  338. /package/lib/{summarizerClientElection.js → summary/summarizerClientElection.js} +0 -0
  339. /package/lib/{summarizerHandle.d.ts → summary/summarizerHandle.d.ts} +0 -0
  340. /package/lib/{summarizerHandle.js → summary/summarizerHandle.js} +0 -0
  341. /package/lib/{summarizerHeuristics.js → summary/summarizerHeuristics.js} +0 -0
  342. /package/lib/{summarizerTypes.js → summary/summarizerTypes.js} +0 -0
  343. /package/lib/{summaryCollection.d.ts → summary/summaryCollection.d.ts} +0 -0
  344. /package/lib/{summaryCollection.js → summary/summaryCollection.js} +0 -0
  345. /package/lib/{summaryGenerator.d.ts → summary/summaryGenerator.d.ts} +0 -0
  346. /package/lib/{summaryManager.js → summary/summaryManager.js} +0 -0
  347. /package/src/{orderedClientElection.ts → summary/orderedClientElection.ts} +0 -0
  348. /package/src/{runWhileConnectedCoordinator.ts → summary/runWhileConnectedCoordinator.ts} +0 -0
  349. /package/src/{summarizerClientElection.ts → summary/summarizerClientElection.ts} +0 -0
  350. /package/src/{summarizerHandle.ts → summary/summarizerHandle.ts} +0 -0
  351. /package/src/{summaryCollection.ts → summary/summaryCollection.ts} +0 -0
@@ -5,7 +5,6 @@
5
5
 
6
6
  import { ITelemetryLogger } from "@fluidframework/common-definitions";
7
7
  import { assert, LazyPromise, Timer } from "@fluidframework/common-utils";
8
- import { ICriticalContainerError } from "@fluidframework/container-definitions";
9
8
  import {
10
9
  ClientSessionExpiredError,
11
10
  DataProcessingError,
@@ -20,28 +19,20 @@ import {
20
19
  runGarbageCollection,
21
20
  trimLeadingSlashes,
22
21
  } from "@fluidframework/garbage-collector";
23
- import { ISnapshotTree, SummaryType } from "@fluidframework/protocol-definitions";
24
22
  import {
25
23
  gcTreeKey,
26
- gcBlobPrefix,
27
- gcTombstoneBlobKey,
28
24
  IGarbageCollectionData,
29
25
  IGarbageCollectionDetailsBase,
30
26
  IGarbageCollectionSnapshotData,
31
27
  IGarbageCollectionState,
32
28
  ISummarizeResult,
33
29
  ITelemetryContext,
34
- IGarbageCollectionNodeData,
35
30
  IGarbageCollectionSummaryDetailsLegacy,
36
- ISummaryTreeWithStats,
37
- gcDeletedBlobKey,
38
31
  } from "@fluidframework/runtime-definitions";
39
32
  import {
40
- mergeStats,
41
33
  packagePathToTelemetryProperty,
42
34
  ReadAndParseBlob,
43
35
  RefreshSummaryResult,
44
- SummaryTreeBuilder,
45
36
  } from "@fluidframework/runtime-utils";
46
37
  import {
47
38
  ChildLogger,
@@ -52,174 +43,38 @@ import {
52
43
  TelemetryDataTag,
53
44
  } from "@fluidframework/telemetry-utils";
54
45
 
55
- import { IGCRuntimeOptions, RuntimeHeaders } from "./containerRuntime";
56
- import { getSummaryForDatastores } from "./dataStores";
46
+ import { IGCRuntimeOptions, RuntimeHeaders } from "../containerRuntime";
47
+ import { getSummaryForDatastores } from "../dataStores";
48
+ import {
49
+ ReadFluidDataStoreAttributes,
50
+ dataStoreAttributesBlobName,
51
+ ICreateContainerMetadata,
52
+ } from "../summary";
57
53
  import {
58
- currentGCVersion,
59
54
  defaultInactiveTimeoutMs,
60
55
  defaultSessionExpiryDurationMs,
61
56
  disableSweepLogKey,
62
57
  disableTombstoneKey,
63
- gcVersionUpgradeToV2Key,
58
+ GCNodeType,
64
59
  gcTestModeKey,
60
+ IGarbageCollector,
61
+ IGarbageCollectorCreateParams,
62
+ IGarbageCollectionRuntime,
63
+ IGCStats,
65
64
  oneDayMs,
66
65
  runGCKey,
67
66
  runSessionExpiryKey,
68
67
  runSweepKey,
69
- stableGCVersion,
70
68
  trackGCStateKey,
71
69
  gcTombstoneGenerationOptionName,
72
- } from "./garbageCollectionConstants";
73
- import { sendGCUnexpectedUsageEvent } from "./garbageCollectionHelpers";
74
- import { SweepReadyUsageDetectionHandler } from "./gcSweepReadyUsageDetection";
75
- import {
76
- getGCVersion,
77
- GCVersion,
78
- IContainerRuntimeMetadata,
79
- metadataBlobName,
80
- ReadFluidDataStoreAttributes,
81
- dataStoreAttributesBlobName,
82
- IGCMetadata,
83
- ICreateContainerMetadata,
70
+ UnreferencedState,
84
71
  GCFeatureMatrix,
85
- } from "./summaryFormat";
86
-
87
- /** The statistics of the system state after a garbage collection run. */
88
- export interface IGCStats {
89
- /** The number of nodes in the container. */
90
- nodeCount: number;
91
- /** The number of data stores in the container. */
92
- dataStoreCount: number;
93
- /** The number of attachment blobs in the container. */
94
- attachmentBlobCount: number;
95
- /** The number of unreferenced nodes in the container. */
96
- unrefNodeCount: number;
97
- /** The number of unreferenced data stores in the container. */
98
- unrefDataStoreCount: number;
99
- /** The number of unreferenced attachment blobs in the container. */
100
- unrefAttachmentBlobCount: number;
101
- /** The number of nodes whose reference state updated since last GC run. */
102
- updatedNodeCount: number;
103
- /** The number of data stores whose reference state updated since last GC run. */
104
- updatedDataStoreCount: number;
105
- /** The number of attachment blobs whose reference state updated since last GC run. */
106
- updatedAttachmentBlobCount: number;
107
- }
108
-
109
- /** The types of GC nodes in the GC reference graph. */
110
- export const GCNodeType = {
111
- // Nodes that are for data stores.
112
- DataStore: "DataStore",
113
- // Nodes that are within a data store. For example, DDS nodes.
114
- SubDataStore: "SubDataStore",
115
- // Nodes that are for attachment blobs, i.e., blobs uploaded via BlobManager.
116
- Blob: "Blob",
117
- // Nodes that are neither of the above. For example, root node.
118
- Other: "Other",
119
- };
120
- export type GCNodeType = typeof GCNodeType[keyof typeof GCNodeType];
121
-
122
- /** Defines the APIs for the runtime object to be passed to the garbage collector. */
123
- export interface IGarbageCollectionRuntime {
124
- /** Before GC runs, called to notify the runtime to update any pending GC state. */
125
- updateStateBeforeGC(): Promise<void>;
126
- /** Returns the garbage collection data of the runtime. */
127
- getGCData(fullGC?: boolean): Promise<IGarbageCollectionData>;
128
- /** After GC has run, called to notify the runtime of routes that are used in it. */
129
- updateUsedRoutes(usedRoutes: string[]): void;
130
- /** After GC has run, called to notify the runtime of routes that are unused in it. */
131
- updateUnusedRoutes(unusedRoutes: string[]): void;
132
- /**
133
- * After GC has run, called to notify the runtime of deletable routes. The runtime is responsible
134
- * for telling the garbage collector the routes of the objects it has deleted
135
- */
136
- deleteUnusedNodes(unusedNodes: string[]): string[];
137
- /** Called to notify the runtime of routes that are tombstones. */
138
- updateTombstonedRoutes(tombstoneRoutes: string[]): void;
139
- /** Returns a referenced timestamp to be used to track unreferenced nodes. */
140
- getCurrentReferenceTimestampMs(): number | undefined;
141
- /** Returns the type of the GC node. */
142
- getNodeType(nodePath: string): GCNodeType;
143
- /** Called when the runtime should close because of an error. */
144
- closeFn: (error?: ICriticalContainerError) => void;
145
- /** If false, loading or using a Tombstoned object should merely log, not fail */
146
- gcTombstoneEnforcementAllowed: boolean;
147
- }
148
-
149
- /** Defines the contract for the garbage collector. */
150
- export interface IGarbageCollector {
151
- /** Tells whether GC should run or not. */
152
- readonly shouldRunGC: boolean;
153
- /** Tells whether the GC state in summary needs to be reset in the next summary. */
154
- readonly summaryStateNeedsReset: boolean;
155
- readonly trackGCState: boolean;
156
- /** Initialize the state from the base snapshot after its creation. */
157
- initializeBaseState(): Promise<void>;
158
- /** Run garbage collection and update the reference / used state of the system. */
159
- collectGarbage(options: {
160
- logger?: ITelemetryLogger;
161
- runSweep?: boolean;
162
- fullGC?: boolean;
163
- }): Promise<IGCStats | undefined>;
164
- /** Summarizes the GC data and returns it as a summary tree. */
165
- summarize(
166
- fullTree: boolean,
167
- trackState: boolean,
168
- telemetryContext?: ITelemetryContext,
169
- ): ISummarizeResult | undefined;
170
- /** Returns the garbage collector specific metadata to be written into the summary. */
171
- getMetadata(): IGCMetadata;
172
- /** Returns the GC details generated from the base snapshot. */
173
- getBaseGCDetails(): Promise<IGarbageCollectionDetailsBase>;
174
- /** Called when the latest summary of the system has been refreshed. */
175
- refreshLatestSummary(
176
- proposalHandle: string | undefined,
177
- result: RefreshSummaryResult,
178
- readAndParseBlob: ReadAndParseBlob,
179
- ): Promise<void>;
180
- /** Called when a node is updated. Used to detect and log when an inactive node is changed or loaded. */
181
- nodeUpdated(
182
- nodePath: string,
183
- reason: "Loaded" | "Changed",
184
- timestampMs?: number,
185
- packagePath?: readonly string[],
186
- requestHeaders?: IRequestHeader,
187
- ): void;
188
- /** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */
189
- addedOutboundReference(fromNodePath: string, toNodePath: string): void;
190
- /** Returns true if this node has been deleted by GC during sweep phase. */
191
- isNodeDeleted(nodePath: string): boolean;
192
- setConnectionState(connected: boolean, clientId?: string): void;
193
- dispose(): void;
194
- }
195
-
196
- /** Parameters necessary for creating a GarbageCollector. */
197
- export interface IGarbageCollectorCreateParams {
198
- readonly runtime: IGarbageCollectionRuntime;
199
- readonly gcOptions: IGCRuntimeOptions;
200
- readonly baseLogger: ITelemetryLogger;
201
- readonly existing: boolean;
202
- readonly metadata: IContainerRuntimeMetadata | undefined;
203
- readonly createContainerMetadata: ICreateContainerMetadata;
204
- readonly baseSnapshot: ISnapshotTree | undefined;
205
- readonly isSummarizerClient: boolean;
206
- readonly getNodePackagePath: (nodePath: string) => Promise<readonly string[] | undefined>;
207
- readonly getLastSummaryTimestampMs: () => number | undefined;
208
- readonly readAndParseBlob: ReadAndParseBlob;
209
- readonly activeConnection: () => boolean;
210
- readonly getContainerDiagnosticId: () => string;
211
- }
212
-
213
- /** The state of node that is unreferenced. */
214
- export const UnreferencedState = {
215
- /** The node is active, i.e., it can become referenced again. */
216
- Active: "Active",
217
- /** The node is inactive, i.e., it should not become referenced. */
218
- Inactive: "Inactive",
219
- /** The node is ready to be deleted by the sweep phase. */
220
- SweepReady: "SweepReady",
221
- } as const;
222
- export type UnreferencedState = typeof UnreferencedState[keyof typeof UnreferencedState];
72
+ IGCMetadata,
73
+ } from "./gcDefinitions";
74
+ import { getGCVersion, sendGCUnexpectedUsageEvent } from "./gcHelpers";
75
+ import { GCSummaryStateTracker } from "./gcSummaryStateTracker";
76
+ import { SweepReadyUsageDetectionHandler } from "./gcSweepReadyUsageDetection";
77
+ import { UnreferencedStateTracker } from "./gcUnreferencedStateTracker";
223
78
 
224
79
  /** The event that is logged when unreferenced node is used after a certain time. */
225
80
  interface IUnreferencedEventProps {
@@ -233,108 +88,9 @@ interface IUnreferencedEventProps {
233
88
  fromId?: string;
234
89
  timeout?: number;
235
90
  lastSummaryTime?: number;
236
- externalRequest?: boolean;
237
91
  viaHandle?: boolean;
238
92
  }
239
93
 
240
- /**
241
- * The GC data that is tracked for a summary that is submitted.
242
- */
243
- interface IGCSummaryTrackingData {
244
- serializedGCState: string | undefined;
245
- serializedTombstones: string | undefined;
246
- serializedDeletedNodes: string | undefined;
247
- }
248
-
249
- /**
250
- * Helper class that tracks the state of an unreferenced node such as the time it was unreferenced and if it can
251
- * be deleted by the sweep phase.
252
- */
253
- export class UnreferencedStateTracker {
254
- private _state: UnreferencedState = UnreferencedState.Active;
255
- public get state(): UnreferencedState {
256
- return this._state;
257
- }
258
-
259
- /** Timer to indicate when an unreferenced object is considered Inactive */
260
- private readonly inactiveTimer: TimerWithNoDefaultTimeout;
261
- /** Timer to indicate when an unreferenced object is Sweep-Ready */
262
- private readonly sweepTimer: TimerWithNoDefaultTimeout;
263
-
264
- constructor(
265
- public readonly unreferencedTimestampMs: number,
266
- /** The time after which node transitions to Inactive state. */
267
- private readonly inactiveTimeoutMs: number,
268
- /** The current reference timestamp used to track how long this node has been unreferenced for. */
269
- currentReferenceTimestampMs: number,
270
- /** The time after which node transitions to SweepReady state; undefined if session expiry is disabled. */
271
- private readonly sweepTimeoutMs: number | undefined,
272
- ) {
273
- if (this.sweepTimeoutMs !== undefined) {
274
- assert(
275
- this.inactiveTimeoutMs <= this.sweepTimeoutMs,
276
- 0x3b0 /* inactive timeout must not be greater than the sweep timeout */,
277
- );
278
- }
279
-
280
- this.sweepTimer = new TimerWithNoDefaultTimeout(() => {
281
- this._state = UnreferencedState.SweepReady;
282
- assert(
283
- !this.inactiveTimer.hasTimer,
284
- 0x3b1 /* inactiveTimer still running after sweepTimer fired! */,
285
- );
286
- });
287
-
288
- this.inactiveTimer = new TimerWithNoDefaultTimeout(() => {
289
- this._state = UnreferencedState.Inactive;
290
-
291
- // After the node becomes inactive, start the sweep timer after which the node will be ready for sweep.
292
- if (this.sweepTimeoutMs !== undefined) {
293
- this.sweepTimer.restart(this.sweepTimeoutMs - this.inactiveTimeoutMs);
294
- }
295
- });
296
- this.updateTracking(currentReferenceTimestampMs);
297
- }
298
-
299
- /* Updates the unreferenced state based on the provided timestamp. */
300
- public updateTracking(currentReferenceTimestampMs: number) {
301
- const unreferencedDurationMs = currentReferenceTimestampMs - this.unreferencedTimestampMs;
302
-
303
- // If the node has been unreferenced for sweep timeout amount of time, update the state to SweepReady.
304
- if (this.sweepTimeoutMs !== undefined && unreferencedDurationMs >= this.sweepTimeoutMs) {
305
- this._state = UnreferencedState.SweepReady;
306
- this.clearTimers();
307
- return;
308
- }
309
-
310
- // If the node has been unreferenced for inactive timeoutMs amount of time, update the state to inactive.
311
- // Also, start a timer for the sweep timeout.
312
- if (unreferencedDurationMs >= this.inactiveTimeoutMs) {
313
- this._state = UnreferencedState.Inactive;
314
- this.inactiveTimer.clear();
315
-
316
- if (this.sweepTimeoutMs !== undefined) {
317
- this.sweepTimer.restart(this.sweepTimeoutMs - unreferencedDurationMs);
318
- }
319
- return;
320
- }
321
-
322
- // The node is still active. Ensure the inactive timer is running with the proper remaining duration.
323
- this.inactiveTimer.restart(this.inactiveTimeoutMs - unreferencedDurationMs);
324
- }
325
-
326
- private clearTimers() {
327
- this.inactiveTimer.clear();
328
- this.sweepTimer.clear();
329
- }
330
-
331
- /** Stop tracking this node. Reset the unreferenced timers and state, if any. */
332
- public stopTracking() {
333
- this.clearTimers();
334
- this._state = UnreferencedState.Active;
335
- }
336
- }
337
-
338
94
  /**
339
95
  * The garbage collector for the container runtime. It consolidates the garbage collection functionality and maintains
340
96
  * its state across summaries.
@@ -362,28 +118,6 @@ export class GarbageCollector implements IGarbageCollector {
362
118
  return new GarbageCollector(createParams);
363
119
  }
364
120
 
365
- /**
366
- * Tells whether the GC state needs to be reset in the next summary. We need to do this if:
367
- *
368
- * 1. GC was enabled and is now disabled. The GC state needs to be removed and everything becomes referenced.
369
- *
370
- * 2. GC was disabled and is now enabled. The GC state needs to be regenerated and added to summary.
371
- *
372
- * 3. GC is enabled and the latest summary state is refreshed from a snapshot that had GC disabled and vice-versa.
373
- *
374
- * 4. The GC version in the latest summary is different from the current GC version. This can happen if:
375
- *
376
- * 4.1. The summary this client loaded with has data from a different GC version.
377
- *
378
- * 4.2. This client's latest summary was updated from a snapshot that has a different GC version.
379
- */
380
- public get summaryStateNeedsReset(): boolean {
381
- return (
382
- this.gcStateNeedsReset ||
383
- (this.shouldRunGC && this.latestSummaryGCVersion !== this.currentGCVersion)
384
- );
385
- }
386
-
387
121
  /**
388
122
  * Tracks if GC is enabled for this document. This is specified during document creation and doesn't change
389
123
  * throughout its lifetime.
@@ -412,31 +146,6 @@ export class GarbageCollector implements IGarbageCollector {
412
146
  private readonly tombstoneMode: boolean;
413
147
  private readonly mc: MonitoringContext;
414
148
 
415
- /**
416
- * Tells whether the GC state needs to be reset. This can happen under 3 conditions:
417
- *
418
- * 1. The base snapshot contains GC state but GC is disabled. This will happen the first time GC is disabled after
419
- * it was enabled before. GC state needs to be removed from summary and all nodes should be marked referenced.
420
- *
421
- * 2. The base snapshot does not have GC state but GC is enabled. This will happen the very first time GC runs on
422
- * a document and the first time GC is enabled after is was disabled before.
423
- *
424
- * 3. GC is enabled and the latest summary state is refreshed from a snapshot that had GC disabled and vice-versa.
425
- *
426
- * Note that the state will be reset only once for the first summary generated after this returns true. After that,
427
- * this will return false.
428
- */
429
- private get gcStateNeedsReset(): boolean {
430
- return this.wasGCRunInLatestSummary !== this.shouldRunGC;
431
- }
432
- // Tracks whether there was GC was run in latest summary being tracked.
433
- private wasGCRunInLatestSummary: boolean;
434
-
435
- // The current GC version that this container is running.
436
- private readonly currentGCVersion: GCVersion;
437
- // This is the version of GC data in the latest summary being tracked.
438
- private latestSummaryGCVersion: GCVersion;
439
-
440
149
  // Feature Support info persisted to this container's summary
441
150
  private readonly persistedGcFeatureMatrix: GCFeatureMatrix | undefined;
442
151
 
@@ -450,15 +159,6 @@ export class GarbageCollector implements IGarbageCollector {
450
159
  // A list of nodes that have been deleted during sweep phase.
451
160
  private deletedNodes: Set<string> = new Set();
452
161
 
453
- /**
454
- * Keeps track of the GC data from the latest summary successfully submitted to and acked from the server.
455
- */
456
- private latestSummaryData: IGCSummaryTrackingData | undefined;
457
- /**
458
- * Keeps track of the GC data from the last summary submitted to the server but not yet acked.
459
- */
460
- private pendingSummaryData: IGCSummaryTrackingData | undefined;
461
-
462
162
  // Promise when resolved returns the GC data data in the base snapshot.
463
163
  private readonly baseSnapshotDataP: Promise<IGarbageCollectionSnapshotData | undefined>;
464
164
  // Promise when resolved initializes the GC state from the data in the base snapshot.
@@ -491,6 +191,8 @@ export class GarbageCollector implements IGarbageCollector {
491
191
  /** The time after which an unreferenced node is ready to be swept. */
492
192
  private readonly sweepTimeoutMs: number | undefined;
493
193
 
194
+ private readonly summaryStateTracker: GCSummaryStateTracker;
195
+
494
196
  /** For a given node path, returns the node's package path. */
495
197
  private readonly getNodePackagePath: (
496
198
  nodePath: string,
@@ -517,6 +219,10 @@ export class GarbageCollector implements IGarbageCollector {
517
219
  };
518
220
  }
519
221
 
222
+ public get summaryStateNeedsReset(): boolean {
223
+ return this.summaryStateTracker.doesSummaryStateNeedReset();
224
+ }
225
+
520
226
  /** Handler to respond to when a SweepReady object is used */
521
227
  private readonly sweepReadyUsageHandler: SweepReadyUsageDetectionHandler;
522
228
 
@@ -539,19 +245,13 @@ export class GarbageCollector implements IGarbageCollector {
539
245
  }),
540
246
  );
541
247
 
542
- // If version upgrade is not enabled, fall back to the stable GC version.
543
- this.currentGCVersion =
544
- this.mc.config.getBoolean(gcVersionUpgradeToV2Key) === true
545
- ? currentGCVersion
546
- : stableGCVersion;
547
-
548
248
  this.sweepReadyUsageHandler = new SweepReadyUsageDetectionHandler(
549
249
  createParams.getContainerDiagnosticId(),
550
250
  this.mc,
551
251
  this.runtime.closeFn,
552
252
  );
553
253
 
554
- let prevSummaryGCVersion: number | undefined;
254
+ let gcVersionInBaseSnapshot: number | undefined;
555
255
 
556
256
  /**
557
257
  * Sweep timeout is the time after which unreferenced content can be swept.
@@ -578,10 +278,10 @@ export class GarbageCollector implements IGarbageCollector {
578
278
  * For existing containers, we get this information from the metadata blob of its summary.
579
279
  */
580
280
  if (createParams.existing) {
581
- prevSummaryGCVersion = getGCVersion(metadata);
281
+ gcVersionInBaseSnapshot = getGCVersion(metadata);
582
282
  // Existing documents which did not have metadata blob or had GC disabled have version as 0. For all
583
283
  // other existing documents, GC is enabled.
584
- this.gcEnabled = prevSummaryGCVersion > 0;
284
+ this.gcEnabled = gcVersionInBaseSnapshot > 0;
585
285
  this.sweepEnabled = metadata?.sweepEnabled ?? false;
586
286
  this.sessionExpiryTimeoutMs = metadata?.sessionExpiryTimeoutMs;
587
287
  this.sweepTimeoutMs =
@@ -637,10 +337,6 @@ export class GarbageCollector implements IGarbageCollector {
637
337
  this.sessionExpiryTimer.start();
638
338
  }
639
339
 
640
- // For existing document, the latest summary is the one that we loaded from. So, use its GC version as the
641
- // latest tracked GC version. For new documents, we will be writing the first summary with the current version.
642
- this.latestSummaryGCVersion = prevSummaryGCVersion ?? this.currentGCVersion;
643
-
644
340
  /**
645
341
  * Whether GC should run or not. The following conditions have to be met to run sweep:
646
342
  *
@@ -693,8 +389,14 @@ export class GarbageCollector implements IGarbageCollector {
693
389
  this.tombstoneMode =
694
390
  !this.shouldRunSweep && this.mc.config.getBoolean(disableTombstoneKey) !== true;
695
391
 
696
- // If GC ran in the container that generated the base snapshot, it will have a GC tree.
697
- this.wasGCRunInLatestSummary = baseSnapshot?.trees[gcTreeKey] !== undefined;
392
+ this.summaryStateTracker = new GCSummaryStateTracker(
393
+ this.shouldRunGC,
394
+ this.trackGCState,
395
+ this.tombstoneMode,
396
+ this.mc,
397
+ baseSnapshot?.trees[gcTreeKey] !== undefined /* wasGCRunInBaseSnapshot */,
398
+ gcVersionInBaseSnapshot,
399
+ );
698
400
 
699
401
  // Get the GC data from the base snapshot. Use LazyPromise because we only want to do this once since it
700
402
  // it involves fetching blobs from storage which is expensive.
@@ -936,10 +638,12 @@ export class GarbageCollector implements IGarbageCollector {
936
638
  this.runtime.updateTombstonedRoutes(this.tombstones);
937
639
  }
938
640
 
641
+ // Update the summary state tracker's state from this snapshot.
642
+ this.summaryStateTracker.updateStateFromSnapshotData(snapshotData);
643
+
939
644
  // If there is no snapshot data, it means this snapshot was generated with GC disabled. Unset all GC state.
940
645
  if (snapshotData === undefined) {
941
646
  this.gcDataFromLastRun = undefined;
942
- this.latestSummaryData = undefined;
943
647
  return;
944
648
  }
945
649
 
@@ -961,15 +665,6 @@ export class GarbageCollector implements IGarbageCollector {
961
665
  gcNodes[nodeId] = Array.from(nodeData.outboundRoutes);
962
666
  }
963
667
  this.gcDataFromLastRun = { gcNodes };
964
-
965
- // If tracking state across summaries, update latest summary data from the snapshot's GC data.
966
- if (this.trackGCState) {
967
- this.latestSummaryData = {
968
- serializedGCState: JSON.stringify(generateSortedGCState(snapshotData.gcState)),
969
- serializedTombstones: JSON.stringify(snapshotData.tombstones),
970
- serializedDeletedNodes: JSON.stringify(snapshotData.deletedNodes),
971
- };
972
- }
973
668
  }
974
669
 
975
670
  /**
@@ -1001,16 +696,21 @@ export class GarbageCollector implements IGarbageCollector {
1001
696
  * Runs garbage collection and updates the reference / used state of the nodes in the container.
1002
697
  * @returns stats of the GC run or undefined if GC did not run.
1003
698
  */
1004
- public async collectGarbage(options: {
1005
- /** Logger to use for logging GC events */
1006
- logger?: ITelemetryLogger;
1007
- /** True to run GC sweep phase after the mark phase */
1008
- runSweep?: boolean;
1009
- /** True to generate full GC data */
1010
- fullGC?: boolean;
1011
- }): Promise<IGCStats | undefined> {
699
+ public async collectGarbage(
700
+ options: {
701
+ /** Logger to use for logging GC events */
702
+ logger?: ITelemetryLogger;
703
+ /** True to run GC sweep phase after the mark phase */
704
+ runSweep?: boolean;
705
+ /** True to generate full GC data */
706
+ fullGC?: boolean;
707
+ },
708
+ telemetryContext?: ITelemetryContext,
709
+ ): Promise<IGCStats | undefined> {
1012
710
  const fullGC =
1013
- options.fullGC ?? (this.gcOptions.runFullGC === true || this.summaryStateNeedsReset);
711
+ options.fullGC ??
712
+ (this.gcOptions.runFullGC === true ||
713
+ this.summaryStateTracker.doesSummaryStateNeedReset());
1014
714
  const logger = options.logger
1015
715
  ? ChildLogger.create(options.logger, undefined, {
1016
716
  all: { completedGCRuns: () => this.completedRuns },
@@ -1035,6 +735,12 @@ export class GarbageCollector implements IGarbageCollector {
1035
735
  return undefined;
1036
736
  }
1037
737
 
738
+ // Add the options that are used to run GC to the telemetry context.
739
+ telemetryContext?.setMultiple("fluid_GC", "Options", {
740
+ fullGC,
741
+ runSweep: options.runSweep,
742
+ });
743
+
1038
744
  return PerformanceEvent.timedExecAsync(
1039
745
  logger,
1040
746
  { eventName: "GarbageCollection" },
@@ -1138,139 +844,22 @@ export class GarbageCollector implements IGarbageCollector {
1138
844
  };
1139
845
  }
1140
846
 
1141
- const serializedGCState = JSON.stringify(generateSortedGCState(gcState));
1142
- // Serialize and write deleted nodes, if any. This is done irrespective of whether sweep is enabled or not so
1143
- // to identify deleted nodes' usage.
1144
- const serializedDeletedNodes =
1145
- this.deletedNodes.size > 0
1146
- ? JSON.stringify(Array.from(this.deletedNodes).sort())
1147
- : undefined;
1148
- // If running in tombstone mode, serialize and write tombstones, if any.
1149
- const serializedTombstones = this.tombstoneMode
1150
- ? this.tombstones.length > 0
1151
- ? JSON.stringify(this.tombstones.sort())
1152
- : undefined
1153
- : undefined;
1154
-
1155
- /**
1156
- * Incremental summary of GC data - If none of GC state, deleted nodes or tombstones changed since last summary,
1157
- * write summary handle instead of summary tree for GC.
1158
- * Otherwise, write the GC summary tree. In the tree, for each of these that changed, write a summary blob and
1159
- * for each of these that did not change, write a summary handle.
1160
- */
1161
- if (this.trackGCState) {
1162
- this.pendingSummaryData = {
1163
- serializedGCState,
1164
- serializedTombstones,
1165
- serializedDeletedNodes,
1166
- };
1167
- if (trackState && !fullTree && this.latestSummaryData !== undefined) {
1168
- // If nothing changed since last summary, send a summary handle for the entire GC data.
1169
- if (
1170
- this.latestSummaryData.serializedGCState === serializedGCState &&
1171
- this.latestSummaryData.serializedTombstones === serializedTombstones
1172
- ) {
1173
- const stats = mergeStats();
1174
- stats.handleNodeCount++;
1175
- return {
1176
- summary: {
1177
- type: SummaryType.Handle,
1178
- handle: `/${gcTreeKey}`,
1179
- handleType: SummaryType.Tree,
1180
- },
1181
- stats,
1182
- };
1183
- }
1184
-
1185
- // If some state changed, build a GC summary tree.
1186
- return this.buildGCSummaryTree(
1187
- serializedGCState,
1188
- serializedTombstones,
1189
- serializedDeletedNodes,
1190
- true /* trackState */,
1191
- );
1192
- }
1193
- }
1194
- // If not tracking GC state, build a GC summary tree without any summary handles.
1195
- return this.buildGCSummaryTree(
1196
- serializedGCState,
1197
- serializedTombstones,
1198
- serializedDeletedNodes,
1199
- false /* trackState */,
847
+ return this.summaryStateTracker.summarize(
848
+ fullTree,
849
+ trackState,
850
+ gcState,
851
+ this.deletedNodes,
852
+ this.tombstones,
1200
853
  );
1201
854
  }
1202
855
 
1203
- /**
1204
- * Builds the GC summary tree which contains GC state, deleted nodes and tombstones.
1205
- * If trackState is false, all of GC state, deleted nodes and tombstones are written as summary blobs.
1206
- * If trackState is true, only states that changed are written. Rest are written as handles.
1207
- * @param serializedGCState - The GC state serialized as string.
1208
- * @param serializedTombstones - The tombstone state serialized as string.
1209
- * @param serializedDeletedNodes - Deleted nodes serialized as string.
1210
- * @param trackState - Whether we are tracking GC state across summaries.
1211
- * @returns the GC summary tree.
1212
- */
1213
- private buildGCSummaryTree(
1214
- serializedGCState: string,
1215
- serializedTombstones: string | undefined,
1216
- serializedDeletedNodes: string | undefined,
1217
- trackState: boolean,
1218
- ): ISummaryTreeWithStats {
1219
- const gcStateBlobKey = `${gcBlobPrefix}_root`;
1220
- const builder = new SummaryTreeBuilder();
1221
-
1222
- // If the GC state hasn't changed, write a summary handle, else write a summary blob for it.
1223
- if (this.latestSummaryData?.serializedGCState === serializedGCState && trackState) {
1224
- builder.addHandle(gcStateBlobKey, SummaryType.Blob, `/${gcTreeKey}/${gcStateBlobKey}`);
1225
- } else {
1226
- builder.addBlob(gcStateBlobKey, serializedGCState);
1227
- }
1228
-
1229
- // If tombstones exist, write a summary handle if it hasn't changed. If it has changed, write a
1230
- // summary blob.
1231
- if (serializedTombstones !== undefined) {
1232
- if (
1233
- this.latestSummaryData?.serializedTombstones === serializedTombstones &&
1234
- trackState
1235
- ) {
1236
- builder.addHandle(
1237
- gcTombstoneBlobKey,
1238
- SummaryType.Blob,
1239
- `/${gcTreeKey}/${gcTombstoneBlobKey}`,
1240
- );
1241
- } else {
1242
- builder.addBlob(gcTombstoneBlobKey, serializedTombstones);
1243
- }
1244
- }
1245
-
1246
- // If there are no deleted nodes, return the summary tree.
1247
- if (serializedDeletedNodes === undefined) {
1248
- return builder.getSummaryTree();
1249
- }
1250
-
1251
- // If the deleted nodes hasn't changed, write a summary handle, else write a summary blob for it.
1252
- if (
1253
- this.latestSummaryData?.serializedDeletedNodes === serializedDeletedNodes &&
1254
- trackState
1255
- ) {
1256
- builder.addHandle(
1257
- gcDeletedBlobKey,
1258
- SummaryType.Blob,
1259
- `/${gcTreeKey}/${gcDeletedBlobKey}`,
1260
- );
1261
- } else {
1262
- builder.addBlob(gcDeletedBlobKey, serializedDeletedNodes);
1263
- }
1264
- return builder.getSummaryTree();
1265
- }
1266
-
1267
856
  public getMetadata(): IGCMetadata {
1268
857
  return {
1269
858
  /**
1270
859
  * If GC is enabled, the GC data is written using the current GC version and that is the gcFeature that goes
1271
860
  * into the metadata blob. If GC is disabled, the gcFeature is 0.
1272
861
  */
1273
- gcFeature: this.gcEnabled ? this.currentGCVersion : 0,
862
+ gcFeature: this.gcEnabled ? this.summaryStateTracker.currentGCVersion : 0,
1274
863
  gcFeatureMatrix: this.persistedGcFeatureMatrix,
1275
864
  sessionExpiryTimeoutMs: this.sessionExpiryTimeoutMs,
1276
865
  sweepEnabled: this.sweepEnabled,
@@ -1295,61 +884,32 @@ export class GarbageCollector implements IGarbageCollector {
1295
884
  result: RefreshSummaryResult,
1296
885
  readAndParseBlob: ReadAndParseBlob,
1297
886
  ): Promise<void> {
1298
- // If the latest summary was updated and the summary was tracked, this client is the one that generated this
1299
- // summary. So, update wasGCRunInLatestSummary.
1300
- // Note that this has to be updated if GC did not run too. Otherwise, `gcStateNeedsReset` will always return
1301
- // true in scenarios where GC is disabled but enabled in the snapshot we loaded from.
1302
- if (result.latestSummaryUpdated && result.wasSummaryTracked) {
1303
- this.wasGCRunInLatestSummary = this.shouldRunGC;
1304
- }
1305
-
1306
- if (!result.latestSummaryUpdated || !this.shouldRunGC) {
1307
- return;
1308
- }
887
+ const latestSnapshotData = await this.summaryStateTracker.refreshLatestSummary(
888
+ proposalHandle,
889
+ result,
890
+ readAndParseBlob,
891
+ );
1309
892
 
1310
- // If the summary was tracked by this client, it was the one that generated the summary in the first place.
1311
- // Update latest state from pending.
1312
- if (result.wasSummaryTracked) {
1313
- this.latestSummaryGCVersion = this.currentGCVersion;
1314
- if (this.trackGCState) {
1315
- this.latestSummaryData = this.pendingSummaryData;
1316
- this.pendingSummaryData = undefined;
893
+ // If the latest summary was updated but it was not tracked by this client, our state needs to be updated from
894
+ // this snapshot data.
895
+ if (this.shouldRunGC && result.latestSummaryUpdated && !result.wasSummaryTracked) {
896
+ // The current reference timestamp should be available if we are refreshing state from a snapshot. There has
897
+ // to be at least one op (summary op / ack, if nothing else) if a snapshot was taken.
898
+ const currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();
899
+ if (currentReferenceTimestampMs === undefined) {
900
+ throw DataProcessingError.create(
901
+ "No reference timestamp when updating GC state from snapshot",
902
+ "refreshLatestSummary",
903
+ undefined,
904
+ {
905
+ proposalHandle,
906
+ summaryRefSeq: result.summaryRefSeq,
907
+ details: JSON.stringify(this.configs),
908
+ },
909
+ );
1317
910
  }
1318
- return;
1319
- }
1320
-
1321
- // If the summary was not tracked by this client, the state should be updated from the downloaded snapshot.
1322
- const snapshotTree = result.snapshotTree;
1323
- const metadataBlobId = snapshotTree.blobs[metadataBlobName];
1324
- if (metadataBlobId) {
1325
- const metadata = await readAndParseBlob<IContainerRuntimeMetadata>(metadataBlobId);
1326
- this.latestSummaryGCVersion = getGCVersion(metadata);
1327
- }
1328
-
1329
- // The current reference timestamp should be available if we are refreshing state from a snapshot. There has
1330
- // to be at least one op (summary op / ack, if nothing else) if a snapshot was taken.
1331
- const currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();
1332
- if (currentReferenceTimestampMs === undefined) {
1333
- throw DataProcessingError.create(
1334
- "No reference timestamp when updating GC state from snapshot",
1335
- "refreshLatestSummary",
1336
- undefined,
1337
- {
1338
- proposalHandle,
1339
- summaryRefSeq: result.summaryRefSeq,
1340
- details: JSON.stringify(this.configs),
1341
- },
1342
- );
1343
- }
1344
- const gcSnapshotTree = snapshotTree.trees[gcTreeKey];
1345
- // If GC ran in the container that generated this snapshot, it will have a GC tree.
1346
- this.wasGCRunInLatestSummary = gcSnapshotTree !== undefined;
1347
- let latestGCData: IGarbageCollectionSnapshotData | undefined;
1348
- if (gcSnapshotTree !== undefined) {
1349
- latestGCData = await getGCDataFromSnapshot(gcSnapshotTree, readAndParseBlob);
911
+ this.updateStateFromSnapshotData(latestSnapshotData, currentReferenceTimestampMs);
1350
912
  }
1351
- this.updateStateFromSnapshotData(latestGCData, currentReferenceTimestampMs);
1352
- this.pendingSummaryData = undefined;
1353
913
  }
1354
914
 
1355
915
  /**
@@ -1515,7 +1075,7 @@ export class GarbageCollector implements IGarbageCollector {
1515
1075
  private runSweepPhase(sweepReadyNodes: string[], gcData: IGarbageCollectionData) {
1516
1076
  // TODO: GC:Validation - validate that removed routes are not double deleted
1517
1077
  // TODO: GC:Validation - validate that the child routes of removed routes are deleted as well
1518
- const sweptRoutes = this.runtime.deleteUnusedNodes(sweepReadyNodes);
1078
+ const sweptRoutes = this.runtime.deleteSweepReadyNodes(sweepReadyNodes);
1519
1079
  const updatedGCData = this.deleteSweptRoutes(sweptRoutes, gcData);
1520
1080
 
1521
1081
  for (const nodeId of sweptRoutes) {
@@ -1855,7 +1415,6 @@ export class GarbageCollector implements IGarbageCollector {
1855
1415
  completedGCRuns: this.completedRuns,
1856
1416
  lastSummaryTime: this.getLastSummaryTimestampMs(),
1857
1417
  ...this.createContainerMetadata,
1858
- externalRequest: requestHeaders?.[RuntimeHeaders.externalRequest],
1859
1418
  viaHandle: requestHeaders?.[RuntimeHeaders.viaHandle],
1860
1419
  fromId: fromNodeId,
1861
1420
  };
@@ -1945,32 +1504,3 @@ export class GarbageCollector implements IGarbageCollector {
1945
1504
  this.pendingEventsQueue = [];
1946
1505
  }
1947
1506
  }
1948
-
1949
- function generateSortedGCState(gcState: IGarbageCollectionState): IGarbageCollectionState {
1950
- const sortableArray: [string, IGarbageCollectionNodeData][] = Object.entries(gcState.gcNodes);
1951
- sortableArray.sort(([a], [b]) => a.localeCompare(b));
1952
- const sortedGCState: IGarbageCollectionState = { gcNodes: {} };
1953
- for (const [nodeId, nodeData] of sortableArray) {
1954
- nodeData.outboundRoutes.sort();
1955
- sortedGCState.gcNodes[nodeId] = nodeData;
1956
- }
1957
- return sortedGCState;
1958
- }
1959
-
1960
- /** A wrapper around common-utils Timer that requires the timeout when calling start/restart */
1961
- class TimerWithNoDefaultTimeout extends Timer {
1962
- constructor(private readonly callback: () => void) {
1963
- // The default timeout/handlers will never be used since start/restart pass overrides below
1964
- super(0, () => {
1965
- throw new Error("DefaultHandler should not be used");
1966
- });
1967
- }
1968
-
1969
- start(timeoutMs: number) {
1970
- super.start(timeoutMs, this.callback);
1971
- }
1972
-
1973
- restart(timeoutMs: number): void {
1974
- super.restart(timeoutMs, this.callback);
1975
- }
1976
- }