@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
@@ -0,0 +1,244 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { ICriticalContainerError } from "@fluidframework/container-definitions";
7
+ import { IRequestHeader } from "@fluidframework/core-interfaces";
8
+ import { ISnapshotTree } from "@fluidframework/protocol-definitions";
9
+ import {
10
+ IGarbageCollectionData,
11
+ IGarbageCollectionDetailsBase,
12
+ ISummarizeResult,
13
+ ITelemetryContext,
14
+ } from "@fluidframework/runtime-definitions";
15
+ import { ReadAndParseBlob, RefreshSummaryResult } from "@fluidframework/runtime-utils";
16
+ import { ITelemetryLogger } from "@fluidframework/common-definitions";
17
+ import { IGCRuntimeOptions } from "../containerRuntime";
18
+ import { IContainerRuntimeMetadata, ICreateContainerMetadata } from "../summary";
19
+
20
+ export type GCVersion = number;
21
+
22
+ /** The stable version of garbage collection in production. */
23
+ export const stableGCVersion: GCVersion = 1;
24
+ /** The current version of garbage collection. */
25
+ export const currentGCVersion: GCVersion = 2;
26
+
27
+ /** This undocumented GC Option (on ContainerRuntime Options) allows an app to disable enforcing GC on old documents by incrementing this value */
28
+ export const gcTombstoneGenerationOptionName = "gcTombstoneGeneration";
29
+
30
+ // Feature gate key to turn GC on / off.
31
+ export const runGCKey = "Fluid.GarbageCollection.RunGC";
32
+ // Feature gate key to turn GC sweep on / off.
33
+ export const runSweepKey = "Fluid.GarbageCollection.RunSweep";
34
+ // Feature gate key to turn GC test mode on / off.
35
+ export const gcTestModeKey = "Fluid.GarbageCollection.GCTestMode";
36
+ // Feature gate key to expire a session after a set period of time.
37
+ export const runSessionExpiryKey = "Fluid.GarbageCollection.RunSessionExpiry";
38
+ // Feature gate key to write the gc blob as a handle if the data is the same.
39
+ export const trackGCStateKey = "Fluid.GarbageCollection.TrackGCState";
40
+ // Feature gate key to turn GC sweep log off.
41
+ export const disableSweepLogKey = "Fluid.GarbageCollection.DisableSweepLog";
42
+ // Feature gate key to disable the tombstone feature, i.e., tombstone information is not read / written into summary.
43
+ export const disableTombstoneKey = "Fluid.GarbageCollection.DisableTombstone";
44
+ // Feature gate to enable throwing an error when tombstone object is loaded (requested).
45
+ export const throwOnTombstoneLoadKey = "Fluid.GarbageCollection.ThrowOnTombstoneLoad";
46
+ // Feature gate to enable throwing an error when tombstone object is used (e.g. outgoing or incoming ops).
47
+ export const throwOnTombstoneUsageKey = "Fluid.GarbageCollection.ThrowOnTombstoneUsage";
48
+ // Feature gate to enable GC version upgrade.
49
+ export const gcVersionUpgradeToV2Key = "Fluid.GarbageCollection.GCVersionUpgradeToV2";
50
+ // Feature gate to enable GC sweep for datastores.
51
+ // TODO: Remove Test from the flag when we are confident to turn on sweep
52
+ export const sweepDatastoresKey = "Fluid.GarbageCollection.Test.SweepDataStores";
53
+ // Feature gate to enable GC sweep for attachment blobs.
54
+ export const sweepAttachmentBlobsKey = "Fluid.GarbageCollection.Test.SweepAttachmentBlobs";
55
+
56
+ // One day in milliseconds.
57
+ export const oneDayMs = 1 * 24 * 60 * 60 * 1000;
58
+
59
+ export const defaultInactiveTimeoutMs = 7 * oneDayMs; // 7 days
60
+ export const defaultSessionExpiryDurationMs = 30 * oneDayMs; // 30 days
61
+
62
+ /** @see IGCMetadata.gcFeatureMatrix */
63
+ export interface GCFeatureMatrix {
64
+ /**
65
+ * The Tombstone Generation value in effect when this file was created.
66
+ * Gives a way for an app to disqualify old files from GC Tombstone enforcement
67
+ * Provided via Container Runtime Options
68
+ */
69
+ tombstoneGeneration?: number;
70
+ }
71
+
72
+ export interface IGCMetadata {
73
+ /**
74
+ * The version of the GC code that was run to generate the GC data that is written in the summary.
75
+ * If the persisted value doesn't match the current value in the code, saved GC data will be discarded and regenerated from scratch.
76
+ * Also, used to determine whether GC is enabled for this container or not:
77
+ * - A value of 0 or undefined means GC is disabled.
78
+ * - A value greater than 0 means GC is enabled.
79
+ */
80
+ readonly gcFeature?: GCVersion;
81
+
82
+ /**
83
+ * A collection of different numerical "Generations" for different features,
84
+ * used to determine feature availability over time.
85
+ * This info may come from multiple sources (FF code, config service, app via Container Runtime Options),
86
+ * and pertains to aspects of the document that may be fixed for its lifetime.
87
+ *
88
+ * For each dimension, if the persisted value doesn't match the currently provided value,
89
+ * then this file does not support the corresponding feature as currently implemented.
90
+ *
91
+ * Guidance is that if no value is provided at runtime, it should result in the current default behavior.
92
+ */
93
+ readonly gcFeatureMatrix?: GCFeatureMatrix;
94
+ /**
95
+ * Tells whether the GC sweep phase is enabled for this container.
96
+ * - True means sweep phase is enabled.
97
+ * - False means sweep phase is disabled. If GC is disabled as per gcFeature, sweep is also disabled.
98
+ */
99
+ readonly sweepEnabled?: boolean;
100
+ /** If this is present, the session for this container will expire after this time and the container will close */
101
+ readonly sessionExpiryTimeoutMs?: number;
102
+ /** How long to wait after an object is unreferenced before deleting it via GC Sweep */
103
+ readonly sweepTimeoutMs?: number;
104
+ }
105
+
106
+ /** The statistics of the system state after a garbage collection run. */
107
+ export interface IGCStats {
108
+ /** The number of nodes in the container. */
109
+ nodeCount: number;
110
+ /** The number of data stores in the container. */
111
+ dataStoreCount: number;
112
+ /** The number of attachment blobs in the container. */
113
+ attachmentBlobCount: number;
114
+ /** The number of unreferenced nodes in the container. */
115
+ unrefNodeCount: number;
116
+ /** The number of unreferenced data stores in the container. */
117
+ unrefDataStoreCount: number;
118
+ /** The number of unreferenced attachment blobs in the container. */
119
+ unrefAttachmentBlobCount: number;
120
+ /** The number of nodes whose reference state updated since last GC run. */
121
+ updatedNodeCount: number;
122
+ /** The number of data stores whose reference state updated since last GC run. */
123
+ updatedDataStoreCount: number;
124
+ /** The number of attachment blobs whose reference state updated since last GC run. */
125
+ updatedAttachmentBlobCount: number;
126
+ }
127
+
128
+ /** The types of GC nodes in the GC reference graph. */
129
+ export const GCNodeType = {
130
+ // Nodes that are for data stores.
131
+ DataStore: "DataStore",
132
+ // Nodes that are within a data store. For example, DDS nodes.
133
+ SubDataStore: "SubDataStore",
134
+ // Nodes that are for attachment blobs, i.e., blobs uploaded via BlobManager.
135
+ Blob: "Blob",
136
+ // Nodes that are neither of the above. For example, root node.
137
+ Other: "Other",
138
+ };
139
+ export type GCNodeType = typeof GCNodeType[keyof typeof GCNodeType];
140
+
141
+ /** Defines the APIs for the runtime object to be passed to the garbage collector. */
142
+ export interface IGarbageCollectionRuntime {
143
+ /** Before GC runs, called to notify the runtime to update any pending GC state. */
144
+ updateStateBeforeGC(): Promise<void>;
145
+ /** Returns the garbage collection data of the runtime. */
146
+ getGCData(fullGC?: boolean): Promise<IGarbageCollectionData>;
147
+ /** After GC has run, called to notify the runtime of routes that are used in it. */
148
+ updateUsedRoutes(usedRoutes: string[]): void;
149
+ /** After GC has run, called to notify the runtime of routes that are unused in it. */
150
+ updateUnusedRoutes(unusedRoutes: string[]): void;
151
+ /**
152
+ * After GC has run and identified nodes that are sweep ready, called to delete the sweep ready nodes. The runtime
153
+ * should return the routes of nodes that were deleted.
154
+ * @param sweepReadyRoutes - The routes of nodes that are sweep ready and should be deleted.
155
+ */
156
+ deleteSweepReadyNodes(sweepReadyRoutes: string[]): string[];
157
+ /** Called to notify the runtime of routes that are tombstones. */
158
+ updateTombstonedRoutes(tombstoneRoutes: string[]): void;
159
+ /** Returns a referenced timestamp to be used to track unreferenced nodes. */
160
+ getCurrentReferenceTimestampMs(): number | undefined;
161
+ /** Returns the type of the GC node. */
162
+ getNodeType(nodePath: string): GCNodeType;
163
+ /** Called when the runtime should close because of an error. */
164
+ closeFn: (error?: ICriticalContainerError) => void;
165
+ /** If false, loading or using a Tombstoned object should merely log, not fail */
166
+ gcTombstoneEnforcementAllowed: boolean;
167
+ }
168
+
169
+ /** Defines the contract for the garbage collector. */
170
+ export interface IGarbageCollector {
171
+ /** Tells whether GC should run or not. */
172
+ readonly shouldRunGC: boolean;
173
+ /** Tells whether the GC state in summary needs to be reset in the next summary. */
174
+ readonly summaryStateNeedsReset: boolean;
175
+ /** Initialize the state from the base snapshot after its creation. */
176
+ initializeBaseState(): Promise<void>;
177
+ /** Run garbage collection and update the reference / used state of the system. */
178
+ collectGarbage(
179
+ options: {
180
+ logger?: ITelemetryLogger;
181
+ runSweep?: boolean;
182
+ fullGC?: boolean;
183
+ },
184
+ telemetryContext?: ITelemetryContext,
185
+ ): Promise<IGCStats | undefined>;
186
+ /** Summarizes the GC data and returns it as a summary tree. */
187
+ summarize(
188
+ fullTree: boolean,
189
+ trackState: boolean,
190
+ telemetryContext?: ITelemetryContext,
191
+ ): ISummarizeResult | undefined;
192
+ /** Returns the garbage collector specific metadata to be written into the summary. */
193
+ getMetadata(): IGCMetadata;
194
+ /** Returns the GC details generated from the base snapshot. */
195
+ getBaseGCDetails(): Promise<IGarbageCollectionDetailsBase>;
196
+ /** Called when the latest summary of the system has been refreshed. */
197
+ refreshLatestSummary(
198
+ proposalHandle: string | undefined,
199
+ result: RefreshSummaryResult,
200
+ readAndParseBlob: ReadAndParseBlob,
201
+ ): Promise<void>;
202
+ /** Called when a node is updated. Used to detect and log when an inactive node is changed or loaded. */
203
+ nodeUpdated(
204
+ nodePath: string,
205
+ reason: "Loaded" | "Changed",
206
+ timestampMs?: number,
207
+ packagePath?: readonly string[],
208
+ requestHeaders?: IRequestHeader,
209
+ ): void;
210
+ /** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */
211
+ addedOutboundReference(fromNodePath: string, toNodePath: string): void;
212
+ /** Returns true if this node has been deleted by GC during sweep phase. */
213
+ isNodeDeleted(nodePath: string): boolean;
214
+ setConnectionState(connected: boolean, clientId?: string): void;
215
+ dispose(): void;
216
+ }
217
+
218
+ /** Parameters necessary for creating a GarbageCollector. */
219
+ export interface IGarbageCollectorCreateParams {
220
+ readonly runtime: IGarbageCollectionRuntime;
221
+ readonly gcOptions: IGCRuntimeOptions;
222
+ readonly baseLogger: ITelemetryLogger;
223
+ readonly existing: boolean;
224
+ readonly metadata: IContainerRuntimeMetadata | undefined;
225
+ readonly createContainerMetadata: ICreateContainerMetadata;
226
+ readonly baseSnapshot: ISnapshotTree | undefined;
227
+ readonly isSummarizerClient: boolean;
228
+ readonly getNodePackagePath: (nodePath: string) => Promise<readonly string[] | undefined>;
229
+ readonly getLastSummaryTimestampMs: () => number | undefined;
230
+ readonly readAndParseBlob: ReadAndParseBlob;
231
+ readonly activeConnection: () => boolean;
232
+ readonly getContainerDiagnosticId: () => string;
233
+ }
234
+
235
+ /** The state of node that is unreferenced. */
236
+ export const UnreferencedState = {
237
+ /** The node is active, i.e., it can become referenced again. */
238
+ Active: "Active",
239
+ /** The node is inactive, i.e., it should not become referenced. */
240
+ Inactive: "Inactive",
241
+ /** The node is ready to be deleted by the sweep phase. */
242
+ SweepReady: "SweepReady",
243
+ } as const;
244
+ export type UnreferencedState = typeof UnreferencedState[keyof typeof UnreferencedState];
@@ -4,14 +4,28 @@
4
4
  */
5
5
 
6
6
  import { ITelemetryGenericEvent } from "@fluidframework/common-definitions";
7
+ import {
8
+ IGarbageCollectionNodeData,
9
+ IGarbageCollectionState,
10
+ } from "@fluidframework/runtime-definitions";
7
11
  import { packagePathToTelemetryProperty } from "@fluidframework/runtime-utils";
8
12
  import { MonitoringContext } from "@fluidframework/telemetry-utils";
9
13
  import {
10
14
  disableTombstoneKey,
15
+ GCVersion,
16
+ IGCMetadata,
11
17
  runSweepKey,
12
18
  throwOnTombstoneLoadKey,
13
19
  throwOnTombstoneUsageKey,
14
- } from "./garbageCollectionConstants";
20
+ } from "./gcDefinitions";
21
+
22
+ export function getGCVersion(metadata?: IGCMetadata): GCVersion {
23
+ if (!metadata) {
24
+ // Force to 0/disallowed in prior versions
25
+ return 0;
26
+ }
27
+ return metadata.gcFeature ?? 0;
28
+ }
15
29
 
16
30
  /**
17
31
  * Consolidates info / logic for logging when we encounter unexpected usage of GC'd objects. For example, when a
@@ -59,3 +73,14 @@ export function shouldAllowGcTombstoneEnforcement(
59
73
  }
60
74
  return persistedGeneration === currentGeneration;
61
75
  }
76
+
77
+ export function generateSortedGCState(gcState: IGarbageCollectionState): IGarbageCollectionState {
78
+ const sortableArray: [string, IGarbageCollectionNodeData][] = Object.entries(gcState.gcNodes);
79
+ sortableArray.sort(([a], [b]) => a.localeCompare(b));
80
+ const sortedGCState: IGarbageCollectionState = { gcNodes: {} };
81
+ for (const [nodeId, nodeData] of sortableArray) {
82
+ nodeData.outboundRoutes.sort();
83
+ sortedGCState.gcNodes[nodeId] = nodeData;
84
+ }
85
+ return sortedGCState;
86
+ }
@@ -0,0 +1,339 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { getGCDataFromSnapshot } from "@fluidframework/garbage-collector";
7
+ import { SummaryType } from "@fluidframework/protocol-definitions";
8
+ import {
9
+ gcBlobPrefix,
10
+ gcDeletedBlobKey,
11
+ gcTombstoneBlobKey,
12
+ gcTreeKey,
13
+ IGarbageCollectionSnapshotData,
14
+ IGarbageCollectionState,
15
+ ISummarizeResult,
16
+ ISummaryTreeWithStats,
17
+ } from "@fluidframework/runtime-definitions";
18
+ import {
19
+ mergeStats,
20
+ ReadAndParseBlob,
21
+ RefreshSummaryResult,
22
+ SummaryTreeBuilder,
23
+ } from "@fluidframework/runtime-utils";
24
+ import { MonitoringContext } from "@fluidframework/telemetry-utils";
25
+ import { IContainerRuntimeMetadata, metadataBlobName } from "../summary";
26
+ import {
27
+ currentGCVersion,
28
+ GCVersion,
29
+ gcVersionUpgradeToV2Key,
30
+ stableGCVersion,
31
+ } from "./gcDefinitions";
32
+ import { generateSortedGCState, getGCVersion } from "./gcHelpers";
33
+
34
+ /**
35
+ * The GC data that is tracked for a summary.
36
+ */
37
+ interface IGCSummaryTrackingData {
38
+ serializedGCState: string | undefined;
39
+ serializedTombstones: string | undefined;
40
+ serializedDeletedNodes: string | undefined;
41
+ }
42
+
43
+ /**
44
+ * Encapsulates the garbage collection state that is tracked across summaries.
45
+ * It maintains the GC state as per the latest summary in by the server. It updates state when a summary tracked by this
46
+ * client is acked by the server or from a snapshot is downloaded from the server.
47
+ * On summarize, it decides whether to write new state or re-use previous summary's state.
48
+ */
49
+ export class GCSummaryStateTracker {
50
+ // The current version of GC running.
51
+ public readonly currentGCVersion: GCVersion;
52
+ // This is the version of GC data in the latest summary being tracked.
53
+ private latestSummaryGCVersion: GCVersion;
54
+
55
+ // Keeps track of the GC data from the latest summary successfully acked by the server.
56
+ private latestSummaryData: IGCSummaryTrackingData | undefined;
57
+ // Keeps track of the GC data from the last summary submitted to the server but not yet acked.
58
+ private pendingSummaryData: IGCSummaryTrackingData | undefined;
59
+
60
+ // Tracks whether there was GC was run in latest summary being tracked.
61
+ private wasGCRunInLatestSummary: boolean;
62
+
63
+ constructor(
64
+ // Tells whether GC should run or not.
65
+ private readonly shouldRunGC: boolean,
66
+ // Tells whether GC state should be tracked across summaries or not.
67
+ private readonly trackGCState: boolean,
68
+ // Tells whether tombstone mode is enabled or not.
69
+ private readonly tombstoneMode: boolean,
70
+ private readonly mc: MonitoringContext,
71
+ // Tells whether GC was run in the base snapshot this container loaded from.
72
+ wasGCRunInBaseSnapshot: boolean,
73
+ // The GC version in the base snapshot this container loaded from.
74
+ gcVersionInBaseSnapshot: GCVersion | undefined,
75
+ ) {
76
+ this.wasGCRunInLatestSummary = wasGCRunInBaseSnapshot;
77
+ // If version upgrade is not enabled, fall back to the stable GC version.
78
+ this.currentGCVersion =
79
+ this.mc.config.getBoolean(gcVersionUpgradeToV2Key) === true
80
+ ? currentGCVersion
81
+ : stableGCVersion;
82
+ // For existing document, the latest summary is the one that we loaded from. So, use its GC version as the
83
+ // latest tracked GC version. For new documents, we will be writing the first summary with the current version.
84
+ this.latestSummaryGCVersion = gcVersionInBaseSnapshot ?? this.currentGCVersion;
85
+ }
86
+
87
+ /**
88
+ * Tells whether the GC state needs to be reset. This can happen under 3 conditions:
89
+ *
90
+ * 1. The base snapshot contains GC state but GC is disabled. This will happen the first time GC is disabled after
91
+ * it was enabled before. GC state needs to be removed from summary and all nodes should be marked referenced.
92
+ *
93
+ * 2. The base snapshot does not have GC state but GC is enabled. This will happen the very first time GC runs on
94
+ * a document and the first time GC is enabled after is was disabled before.
95
+ *
96
+ * 3. GC is enabled and the latest summary state is refreshed from a snapshot that had GC disabled and vice-versa.
97
+ *
98
+ * Note that the state will be reset only once for the first summary generated after this returns true. After that,
99
+ * this will return false.
100
+ */
101
+ public doesGCStateNeedReset(): boolean {
102
+ return this.wasGCRunInLatestSummary !== this.shouldRunGC;
103
+ }
104
+
105
+ /**
106
+ * Tells whether the GC state needs to be reset in the next summary. We need to do this if:
107
+ *
108
+ * 1. GC was enabled and is now disabled. The GC state needs to be removed and everything becomes referenced.
109
+ *
110
+ * 2. GC was disabled and is now enabled. The GC state needs to be regenerated and added to summary.
111
+ *
112
+ * 3. GC is enabled and the latest summary state is refreshed from a snapshot that had GC disabled and vice-versa.
113
+ *
114
+ * 4. The GC version in the latest summary is different from the current GC version. This can happen if:
115
+ *
116
+ * 4.1. The summary this client loaded with has data from a different GC version.
117
+ *
118
+ * 4.2. This client's latest summary was updated from a snapshot that has a different GC version.
119
+ */
120
+ public doesSummaryStateNeedReset(): boolean {
121
+ return (
122
+ this.doesGCStateNeedReset() ||
123
+ (this.shouldRunGC && this.latestSummaryGCVersion !== this.currentGCVersion)
124
+ );
125
+ }
126
+
127
+ /**
128
+ * Summarizes three component of the GC data - GC state, tombstones and deleted nodes.
129
+ * It does incremental summary, i.e., it writes summary tree / summary blob only for the component that changed.
130
+ * For components that did not change, a summary handle is returned that points to the previous successful summary.
131
+ * If none of the components changed, it returns a summary handle for the entire GC data.
132
+ */
133
+ public summarize(
134
+ fullTree: boolean,
135
+ trackState: boolean,
136
+ gcState: IGarbageCollectionState,
137
+ deletedNodes: Set<string>,
138
+ tombstones: string[],
139
+ ): ISummarizeResult | undefined {
140
+ if (!this.shouldRunGC) {
141
+ return;
142
+ }
143
+
144
+ const serializedGCState = JSON.stringify(generateSortedGCState(gcState));
145
+ // Serialize and write deleted nodes, if any. This is done irrespective of whether sweep is enabled or not so
146
+ // to identify deleted nodes' usage.
147
+ const serializedDeletedNodes =
148
+ deletedNodes.size > 0 ? JSON.stringify(Array.from(deletedNodes).sort()) : undefined;
149
+ // If running in tombstone mode, serialize and write tombstones, if any.
150
+ const serializedTombstones = this.tombstoneMode
151
+ ? tombstones.length > 0
152
+ ? JSON.stringify(tombstones.sort())
153
+ : undefined
154
+ : undefined;
155
+
156
+ /**
157
+ * Incremental summary of GC data - If none of GC state, deleted nodes or tombstones changed since last summary,
158
+ * write summary handle instead of summary tree for GC.
159
+ * Otherwise, write the GC summary tree. In the tree, for each of these that changed, write a summary blob and
160
+ * for each of these that did not change, write a summary handle.
161
+ */
162
+ if (this.trackGCState) {
163
+ this.pendingSummaryData = {
164
+ serializedGCState,
165
+ serializedTombstones,
166
+ serializedDeletedNodes,
167
+ };
168
+ if (trackState && !fullTree && this.latestSummaryData !== undefined) {
169
+ // If nothing changed since last summary, send a summary handle for the entire GC data.
170
+ if (
171
+ this.latestSummaryData.serializedGCState === serializedGCState &&
172
+ this.latestSummaryData.serializedTombstones === serializedTombstones
173
+ ) {
174
+ const stats = mergeStats();
175
+ stats.handleNodeCount++;
176
+ return {
177
+ summary: {
178
+ type: SummaryType.Handle,
179
+ handle: `/${gcTreeKey}`,
180
+ handleType: SummaryType.Tree,
181
+ },
182
+ stats,
183
+ };
184
+ }
185
+
186
+ // If some state changed, build a GC summary tree.
187
+ return this.buildGCSummaryTree(
188
+ serializedGCState,
189
+ serializedTombstones,
190
+ serializedDeletedNodes,
191
+ true /* trackState */,
192
+ );
193
+ }
194
+ }
195
+ // If not tracking GC state, build a GC summary tree without any summary handles.
196
+ return this.buildGCSummaryTree(
197
+ serializedGCState,
198
+ serializedTombstones,
199
+ serializedDeletedNodes,
200
+ false /* trackState */,
201
+ );
202
+ }
203
+
204
+ /**
205
+ * Builds the GC summary tree which contains GC state, deleted nodes and tombstones.
206
+ * If trackState is false, all of GC state, deleted nodes and tombstones are written as summary blobs.
207
+ * If trackState is true, only states that changed are written. Rest are written as handles.
208
+ * @param serializedGCState - The GC state serialized as string.
209
+ * @param serializedTombstones - The tombstone state serialized as string.
210
+ * @param serializedDeletedNodes - Deleted nodes serialized as string.
211
+ * @param trackState - Whether we are tracking GC state across summaries.
212
+ * @returns the GC summary tree.
213
+ */
214
+ private buildGCSummaryTree(
215
+ serializedGCState: string,
216
+ serializedTombstones: string | undefined,
217
+ serializedDeletedNodes: string | undefined,
218
+ trackState: boolean,
219
+ ): ISummaryTreeWithStats {
220
+ const gcStateBlobKey = `${gcBlobPrefix}_root`;
221
+ const builder = new SummaryTreeBuilder();
222
+
223
+ // If the GC state hasn't changed, write a summary handle, else write a summary blob for it.
224
+ if (this.latestSummaryData?.serializedGCState === serializedGCState && trackState) {
225
+ builder.addHandle(gcStateBlobKey, SummaryType.Blob, `/${gcTreeKey}/${gcStateBlobKey}`);
226
+ } else {
227
+ builder.addBlob(gcStateBlobKey, serializedGCState);
228
+ }
229
+
230
+ // If tombstones exist, write a summary handle if it hasn't changed. If it has changed, write a
231
+ // summary blob.
232
+ if (serializedTombstones !== undefined) {
233
+ if (
234
+ this.latestSummaryData?.serializedTombstones === serializedTombstones &&
235
+ trackState
236
+ ) {
237
+ builder.addHandle(
238
+ gcTombstoneBlobKey,
239
+ SummaryType.Blob,
240
+ `/${gcTreeKey}/${gcTombstoneBlobKey}`,
241
+ );
242
+ } else {
243
+ builder.addBlob(gcTombstoneBlobKey, serializedTombstones);
244
+ }
245
+ }
246
+
247
+ // If there are no deleted nodes, return the summary tree.
248
+ if (serializedDeletedNodes === undefined) {
249
+ return builder.getSummaryTree();
250
+ }
251
+
252
+ // If the deleted nodes hasn't changed, write a summary handle, else write a summary blob for it.
253
+ if (
254
+ this.latestSummaryData?.serializedDeletedNodes === serializedDeletedNodes &&
255
+ trackState
256
+ ) {
257
+ builder.addHandle(
258
+ gcDeletedBlobKey,
259
+ SummaryType.Blob,
260
+ `/${gcTreeKey}/${gcDeletedBlobKey}`,
261
+ );
262
+ } else {
263
+ builder.addBlob(gcDeletedBlobKey, serializedDeletedNodes);
264
+ }
265
+ return builder.getSummaryTree();
266
+ }
267
+
268
+ /**
269
+ * Called to refresh the latest summary state. This happens when either a pending summary is acked or a snapshot
270
+ * is downloaded and should be used to update the state.
271
+ */
272
+ public async refreshLatestSummary(
273
+ proposalHandle: string | undefined,
274
+ result: RefreshSummaryResult,
275
+ readAndParseBlob: ReadAndParseBlob,
276
+ ): Promise<IGarbageCollectionSnapshotData | undefined> {
277
+ // If the latest summary was updated and the summary was tracked, this client is the one that generated this
278
+ // summary. So, update wasGCRunInLatestSummary.
279
+ // Note that this has to be updated if GC did not run too. Otherwise, `gcStateNeedsReset` will always return
280
+ // true in scenarios where GC is disabled but enabled in the snapshot we loaded from.
281
+ if (result.latestSummaryUpdated && result.wasSummaryTracked) {
282
+ this.wasGCRunInLatestSummary = this.shouldRunGC;
283
+ }
284
+
285
+ if (!result.latestSummaryUpdated || !this.shouldRunGC) {
286
+ return undefined;
287
+ }
288
+
289
+ // If the summary was tracked by this client, it was the one that generated the summary in the first place.
290
+ // Update latest state from pending.
291
+ if (result.wasSummaryTracked) {
292
+ this.latestSummaryGCVersion = this.currentGCVersion;
293
+ if (this.trackGCState) {
294
+ this.latestSummaryData = this.pendingSummaryData;
295
+ this.pendingSummaryData = undefined;
296
+ }
297
+ return undefined;
298
+ }
299
+
300
+ // If the summary was not tracked by this client, the state should be updated from the downloaded snapshot.
301
+ const snapshotTree = result.snapshotTree;
302
+ const metadataBlobId = snapshotTree.blobs[metadataBlobName];
303
+ if (metadataBlobId) {
304
+ const metadata = await readAndParseBlob<IContainerRuntimeMetadata>(metadataBlobId);
305
+ this.latestSummaryGCVersion = getGCVersion(metadata);
306
+ }
307
+
308
+ const gcSnapshotTree = snapshotTree.trees[gcTreeKey];
309
+ // If GC ran in the container that generated this snapshot, it will have a GC tree.
310
+ this.wasGCRunInLatestSummary = gcSnapshotTree !== undefined;
311
+ let latestGCData: IGarbageCollectionSnapshotData | undefined;
312
+ if (gcSnapshotTree !== undefined) {
313
+ latestGCData = await getGCDataFromSnapshot(gcSnapshotTree, readAndParseBlob);
314
+ }
315
+ this.pendingSummaryData = undefined;
316
+ return latestGCData;
317
+ }
318
+
319
+ /**
320
+ * Update state from the given snapshot data. This is done during load and during refreshing state from a snapshot.
321
+ * @param gcSnapshotData - The GC snapshot data to update state from.
322
+ */
323
+ public updateStateFromSnapshotData(gcSnapshotData: IGarbageCollectionSnapshotData | undefined) {
324
+ // If there is no snapshot data, it means this snapshot was generated with GC disabled. Unset all GC state.
325
+ if (gcSnapshotData === undefined) {
326
+ this.latestSummaryData = undefined;
327
+ return;
328
+ }
329
+
330
+ // If tracking state across summaries, update latest summary data from the snapshot's GC data.
331
+ if (this.trackGCState) {
332
+ this.latestSummaryData = {
333
+ serializedGCState: JSON.stringify(generateSortedGCState(gcSnapshotData.gcState)),
334
+ serializedTombstones: JSON.stringify(gcSnapshotData.tombstones),
335
+ serializedDeletedNodes: JSON.stringify(gcSnapshotData.deletedNodes),
336
+ };
337
+ }
338
+ }
339
+ }
@@ -11,7 +11,7 @@ import {
11
11
  LoggingError,
12
12
  MonitoringContext,
13
13
  } from "@fluidframework/telemetry-utils";
14
- import { oneDayMs } from "./garbageCollectionConstants";
14
+ import { oneDayMs } from "./gcDefinitions";
15
15
 
16
16
  /**
17
17
  * Feature Gate Key -