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

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 (299) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +0 -6
  3. package/api-report/container-runtime.api.md +14 -3
  4. package/dist/{batchTracker.cjs → batchTracker.js} +1 -1
  5. package/dist/batchTracker.js.map +1 -0
  6. package/dist/blobManager.d.ts.map +1 -1
  7. package/dist/{blobManager.cjs → blobManager.js} +9 -3
  8. package/dist/blobManager.js.map +1 -0
  9. package/dist/{connectionTelemetry.cjs → connectionTelemetry.js} +1 -1
  10. package/dist/connectionTelemetry.js.map +1 -0
  11. package/dist/container-runtime-alpha.d.ts +13 -3
  12. package/dist/container-runtime-beta.d.ts +7 -0
  13. package/dist/container-runtime-public.d.ts +7 -0
  14. package/dist/container-runtime-untrimmed.d.ts +30 -3
  15. package/dist/{containerHandleContext.cjs → containerHandleContext.js} +1 -1
  16. package/dist/containerHandleContext.js.map +1 -0
  17. package/dist/containerRuntime.d.ts +5 -2
  18. package/dist/containerRuntime.d.ts.map +1 -1
  19. package/dist/{containerRuntime.cjs → containerRuntime.js} +78 -85
  20. package/dist/containerRuntime.js.map +1 -0
  21. package/dist/{dataStore.cjs → dataStore.js} +1 -1
  22. package/dist/dataStore.js.map +1 -0
  23. package/dist/dataStoreContext.d.ts +7 -1
  24. package/dist/dataStoreContext.d.ts.map +1 -1
  25. package/dist/{dataStoreContext.cjs → dataStoreContext.js} +13 -7
  26. package/dist/dataStoreContext.js.map +1 -0
  27. package/dist/{dataStoreContexts.cjs → dataStoreContexts.js} +1 -1
  28. package/dist/dataStoreContexts.js.map +1 -0
  29. package/dist/{dataStoreRegistry.cjs → dataStoreRegistry.js} +1 -1
  30. package/dist/dataStoreRegistry.js.map +1 -0
  31. package/dist/dataStores.d.ts +9 -3
  32. package/dist/dataStores.d.ts.map +1 -1
  33. package/dist/{dataStores.cjs → dataStores.js} +62 -16
  34. package/dist/dataStores.js.map +1 -0
  35. package/dist/{deltaManagerProxyBase.cjs → deltaManagerProxyBase.js} +1 -1
  36. package/dist/deltaManagerProxyBase.js.map +1 -0
  37. package/dist/{deltaManagerSummarizerProxy.cjs → deltaManagerSummarizerProxy.js} +3 -3
  38. package/dist/deltaManagerSummarizerProxy.js.map +1 -0
  39. package/dist/{deltaScheduler.cjs → deltaScheduler.js} +1 -1
  40. package/dist/deltaScheduler.js.map +1 -0
  41. package/dist/{error.cjs → error.js} +1 -1
  42. package/dist/error.js.map +1 -0
  43. package/dist/gc/garbageCollection.d.ts +17 -1
  44. package/dist/gc/garbageCollection.d.ts.map +1 -1
  45. package/dist/gc/{garbageCollection.cjs → garbageCollection.js} +111 -42
  46. package/dist/gc/garbageCollection.js.map +1 -0
  47. package/dist/gc/{gcConfigs.cjs → gcConfigs.js} +3 -3
  48. package/dist/gc/gcConfigs.js.map +1 -0
  49. package/dist/gc/gcDefinitions.d.ts +20 -2
  50. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  51. package/dist/gc/{gcDefinitions.cjs → gcDefinitions.js} +8 -2
  52. package/dist/gc/gcDefinitions.js.map +1 -0
  53. package/dist/gc/{gcHelpers.cjs → gcHelpers.js} +1 -1
  54. package/dist/gc/gcHelpers.js.map +1 -0
  55. package/dist/gc/{gcReferenceGraphAlgorithm.cjs → gcReferenceGraphAlgorithm.js} +1 -1
  56. package/dist/gc/gcReferenceGraphAlgorithm.js.map +1 -0
  57. package/dist/gc/{gcSummaryDefinitions.cjs → gcSummaryDefinitions.js} +1 -1
  58. package/dist/gc/gcSummaryDefinitions.js.map +1 -0
  59. package/dist/gc/{gcSummaryStateTracker.cjs → gcSummaryStateTracker.js} +2 -2
  60. package/dist/gc/gcSummaryStateTracker.js.map +1 -0
  61. package/dist/gc/gcTelemetry.d.ts +1 -0
  62. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  63. package/dist/gc/{gcTelemetry.cjs → gcTelemetry.js} +2 -4
  64. package/dist/gc/gcTelemetry.js.map +1 -0
  65. package/dist/gc/gcUnreferencedStateTracker.d.ts +5 -0
  66. package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
  67. package/dist/gc/{gcUnreferencedStateTracker.cjs → gcUnreferencedStateTracker.js} +14 -3
  68. package/dist/gc/{gcUnreferencedStateTracker.cjs.map → gcUnreferencedStateTracker.js.map} +1 -1
  69. package/dist/gc/index.d.ts +1 -1
  70. package/dist/gc/index.d.ts.map +1 -1
  71. package/dist/gc/{index.cjs → index.js} +11 -9
  72. package/dist/gc/index.js.map +1 -0
  73. package/dist/index.d.ts +2 -1
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/{index.cjs → index.js} +10 -8
  76. package/dist/index.js.map +1 -0
  77. package/dist/messageTypes.d.ts +1 -1
  78. package/dist/{messageTypes.cjs → messageTypes.js} +1 -1
  79. package/dist/messageTypes.js.map +1 -0
  80. package/dist/{metadata.cjs → metadata.js} +1 -1
  81. package/dist/metadata.js.map +1 -0
  82. package/dist/opLifecycle/{batchManager.cjs → batchManager.js} +1 -1
  83. package/dist/opLifecycle/batchManager.js.map +1 -0
  84. package/dist/opLifecycle/{definitions.cjs → definitions.js} +1 -1
  85. package/dist/opLifecycle/definitions.js.map +1 -0
  86. package/dist/opLifecycle/{index.cjs → index.js} +8 -8
  87. package/dist/opLifecycle/index.js.map +1 -0
  88. package/dist/opLifecycle/{opCompressor.cjs → opCompressor.js} +3 -3
  89. package/dist/opLifecycle/opCompressor.js.map +1 -0
  90. package/dist/opLifecycle/{opDecompressor.cjs → opDecompressor.js} +2 -2
  91. package/dist/opLifecycle/opDecompressor.js.map +1 -0
  92. package/dist/opLifecycle/{opGroupingManager.cjs → opGroupingManager.js} +1 -1
  93. package/dist/opLifecycle/opGroupingManager.js.map +1 -0
  94. package/dist/opLifecycle/{opSplitter.cjs → opSplitter.js} +3 -3
  95. package/dist/opLifecycle/opSplitter.js.map +1 -0
  96. package/dist/opLifecycle/{outbox.cjs → outbox.js} +2 -2
  97. package/dist/opLifecycle/outbox.js.map +1 -0
  98. package/dist/opLifecycle/{remoteMessageProcessor.cjs → remoteMessageProcessor.js} +2 -2
  99. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -0
  100. package/dist/{opProperties.cjs → opProperties.js} +1 -1
  101. package/dist/opProperties.js.map +1 -0
  102. package/dist/packageVersion.d.ts +1 -1
  103. package/dist/{packageVersion.cjs → packageVersion.js} +2 -2
  104. package/dist/packageVersion.js.map +1 -0
  105. package/dist/{pendingStateManager.cjs → pendingStateManager.js} +2 -2
  106. package/dist/pendingStateManager.js.map +1 -0
  107. package/dist/{scheduleManager.cjs → scheduleManager.js} +3 -3
  108. package/dist/scheduleManager.js.map +1 -0
  109. package/dist/{storageServiceWithAttachBlobs.cjs → storageServiceWithAttachBlobs.js} +1 -1
  110. package/dist/storageServiceWithAttachBlobs.js.map +1 -0
  111. package/dist/summary/{index.cjs → index.js} +12 -12
  112. package/dist/summary/index.js.map +1 -0
  113. package/dist/summary/{orderedClientElection.cjs → orderedClientElection.js} +2 -2
  114. package/dist/summary/orderedClientElection.js.map +1 -0
  115. package/dist/summary/{runWhileConnectedCoordinator.cjs → runWhileConnectedCoordinator.js} +1 -1
  116. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -0
  117. package/dist/summary/runningSummarizer.d.ts +11 -6
  118. package/dist/summary/runningSummarizer.d.ts.map +1 -1
  119. package/dist/summary/{runningSummarizer.cjs → runningSummarizer.js} +140 -93
  120. package/dist/summary/runningSummarizer.js.map +1 -0
  121. package/dist/summary/{summarizer.cjs → summarizer.js} +4 -4
  122. package/dist/summary/summarizer.js.map +1 -0
  123. package/dist/summary/{summarizerClientElection.cjs → summarizerClientElection.js} +1 -1
  124. package/dist/summary/summarizerClientElection.js.map +1 -0
  125. package/dist/summary/{summarizerHeuristics.cjs → summarizerHeuristics.js} +1 -1
  126. package/dist/summary/summarizerHeuristics.js.map +1 -0
  127. package/dist/summary/summarizerNode/{index.cjs → index.js} +3 -3
  128. package/dist/summary/summarizerNode/index.js.map +1 -0
  129. package/dist/summary/summarizerNode/summarizerNode.d.ts +2 -3
  130. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  131. package/dist/summary/summarizerNode/{summarizerNode.cjs → summarizerNode.js} +8 -50
  132. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -0
  133. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts +1 -18
  134. package/dist/summary/summarizerNode/summarizerNodeUtils.d.ts.map +1 -1
  135. package/dist/summary/summarizerNode/{summarizerNodeUtils.cjs → summarizerNodeUtils.js} +2 -22
  136. package/dist/summary/summarizerNode/summarizerNodeUtils.js.map +1 -0
  137. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -3
  138. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  139. package/dist/summary/summarizerNode/{summarizerNodeWithGc.cjs → summarizerNodeWithGc.js} +9 -9
  140. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -0
  141. package/dist/summary/summarizerTypes.d.ts +3 -1
  142. package/dist/summary/summarizerTypes.d.ts.map +1 -1
  143. package/dist/summary/{summarizerTypes.cjs → summarizerTypes.js} +1 -1
  144. package/dist/summary/summarizerTypes.js.map +1 -0
  145. package/dist/summary/{summaryCollection.cjs → summaryCollection.js} +1 -1
  146. package/dist/summary/summaryCollection.js.map +1 -0
  147. package/dist/summary/{summaryFormat.cjs → summaryFormat.js} +1 -1
  148. package/dist/summary/summaryFormat.js.map +1 -0
  149. package/dist/summary/{summaryGenerator.cjs → summaryGenerator.js} +1 -1
  150. package/dist/summary/summaryGenerator.js.map +1 -0
  151. package/dist/summary/{summaryManager.cjs → summaryManager.js} +2 -2
  152. package/dist/summary/summaryManager.js.map +1 -0
  153. package/dist/{throttler.cjs → throttler.js} +1 -1
  154. package/dist/throttler.js.map +1 -0
  155. package/dist/tsdoc-metadata.json +1 -1
  156. package/lib/blobManager.d.mts.map +1 -1
  157. package/lib/blobManager.mjs +7 -1
  158. package/lib/blobManager.mjs.map +1 -1
  159. package/lib/container-runtime-alpha.d.mts +13 -3
  160. package/lib/container-runtime-beta.d.mts +7 -0
  161. package/lib/container-runtime-public.d.mts +7 -0
  162. package/lib/container-runtime-untrimmed.d.mts +30 -3
  163. package/lib/containerRuntime.d.mts +5 -2
  164. package/lib/containerRuntime.d.mts.map +1 -1
  165. package/lib/containerRuntime.mjs +62 -69
  166. package/lib/containerRuntime.mjs.map +1 -1
  167. package/lib/dataStoreContext.d.mts +7 -1
  168. package/lib/dataStoreContext.d.mts.map +1 -1
  169. package/lib/dataStoreContext.mjs +11 -5
  170. package/lib/dataStoreContext.mjs.map +1 -1
  171. package/lib/dataStores.d.mts +9 -3
  172. package/lib/dataStores.d.mts.map +1 -1
  173. package/lib/dataStores.mjs +54 -9
  174. package/lib/dataStores.mjs.map +1 -1
  175. package/lib/gc/garbageCollection.d.mts +17 -1
  176. package/lib/gc/garbageCollection.d.mts.map +1 -1
  177. package/lib/gc/garbageCollection.mjs +103 -34
  178. package/lib/gc/garbageCollection.mjs.map +1 -1
  179. package/lib/gc/gcDefinitions.d.mts +20 -2
  180. package/lib/gc/gcDefinitions.d.mts.map +1 -1
  181. package/lib/gc/gcDefinitions.mjs +6 -0
  182. package/lib/gc/gcDefinitions.mjs.map +1 -1
  183. package/lib/gc/gcTelemetry.d.mts +1 -0
  184. package/lib/gc/gcTelemetry.d.mts.map +1 -1
  185. package/lib/gc/gcTelemetry.mjs +0 -2
  186. package/lib/gc/gcTelemetry.mjs.map +1 -1
  187. package/lib/gc/gcUnreferencedStateTracker.d.mts +5 -0
  188. package/lib/gc/gcUnreferencedStateTracker.d.mts.map +1 -1
  189. package/lib/gc/gcUnreferencedStateTracker.mjs +10 -0
  190. package/lib/gc/gcUnreferencedStateTracker.mjs.map +1 -1
  191. package/lib/gc/index.d.mts +1 -1
  192. package/lib/gc/index.d.mts.map +1 -1
  193. package/lib/gc/index.mjs +1 -1
  194. package/lib/gc/index.mjs.map +1 -1
  195. package/lib/index.d.mts +2 -1
  196. package/lib/index.d.mts.map +1 -1
  197. package/lib/index.mjs +1 -0
  198. package/lib/index.mjs.map +1 -1
  199. package/lib/messageTypes.d.mts +1 -1
  200. package/lib/messageTypes.mjs.map +1 -1
  201. package/lib/packageVersion.d.mts +1 -1
  202. package/lib/packageVersion.mjs +1 -1
  203. package/lib/packageVersion.mjs.map +1 -1
  204. package/lib/summary/runningSummarizer.d.mts +11 -6
  205. package/lib/summary/runningSummarizer.d.mts.map +1 -1
  206. package/lib/summary/runningSummarizer.mjs +136 -89
  207. package/lib/summary/runningSummarizer.mjs.map +1 -1
  208. package/lib/summary/summarizerNode/summarizerNode.d.mts +2 -3
  209. package/lib/summary/summarizerNode/summarizerNode.d.mts.map +1 -1
  210. package/lib/summary/summarizerNode/summarizerNode.mjs +8 -50
  211. package/lib/summary/summarizerNode/summarizerNode.mjs.map +1 -1
  212. package/lib/summary/summarizerNode/summarizerNodeUtils.d.mts +1 -18
  213. package/lib/summary/summarizerNode/summarizerNodeUtils.d.mts.map +1 -1
  214. package/lib/summary/summarizerNode/summarizerNodeUtils.mjs +0 -19
  215. package/lib/summary/summarizerNode/summarizerNodeUtils.mjs.map +1 -1
  216. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.mts +3 -3
  217. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.mts.map +1 -1
  218. package/lib/summary/summarizerNode/summarizerNodeWithGc.mjs +5 -5
  219. package/lib/summary/summarizerNode/summarizerNodeWithGc.mjs.map +1 -1
  220. package/lib/summary/summarizerTypes.d.mts +3 -1
  221. package/lib/summary/summarizerTypes.d.mts.map +1 -1
  222. package/lib/summary/summarizerTypes.mjs.map +1 -1
  223. package/package.json +48 -38
  224. package/src/blobManager.ts +7 -1
  225. package/src/containerRuntime.ts +103 -85
  226. package/src/dataStoreContext.ts +15 -6
  227. package/src/dataStores.ts +64 -6
  228. package/src/gc/garbageCollection.ts +118 -32
  229. package/src/gc/gcDefinitions.ts +21 -3
  230. package/src/gc/gcTelemetry.ts +1 -2
  231. package/src/gc/gcUnreferencedStateTracker.ts +11 -0
  232. package/src/gc/index.ts +3 -0
  233. package/src/index.ts +2 -0
  234. package/src/messageTypes.ts +1 -1
  235. package/src/packageVersion.ts +1 -1
  236. package/src/summary/runningSummarizer.ts +174 -113
  237. package/src/summary/summarizerNode/summarizerNode.ts +4 -64
  238. package/src/summary/summarizerNode/summarizerNodeUtils.ts +2 -33
  239. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +0 -6
  240. package/src/summary/summarizerTypes.ts +3 -1
  241. package/dist/batchTracker.cjs.map +0 -1
  242. package/dist/blobManager.cjs.map +0 -1
  243. package/dist/connectionTelemetry.cjs.map +0 -1
  244. package/dist/containerHandleContext.cjs.map +0 -1
  245. package/dist/containerRuntime.cjs.map +0 -1
  246. package/dist/dataStore.cjs.map +0 -1
  247. package/dist/dataStoreContext.cjs.map +0 -1
  248. package/dist/dataStoreContexts.cjs.map +0 -1
  249. package/dist/dataStoreRegistry.cjs.map +0 -1
  250. package/dist/dataStores.cjs.map +0 -1
  251. package/dist/deltaManagerProxyBase.cjs.map +0 -1
  252. package/dist/deltaManagerSummarizerProxy.cjs.map +0 -1
  253. package/dist/deltaScheduler.cjs.map +0 -1
  254. package/dist/error.cjs.map +0 -1
  255. package/dist/gc/garbageCollection.cjs.map +0 -1
  256. package/dist/gc/gcConfigs.cjs.map +0 -1
  257. package/dist/gc/gcDefinitions.cjs.map +0 -1
  258. package/dist/gc/gcHelpers.cjs.map +0 -1
  259. package/dist/gc/gcReferenceGraphAlgorithm.cjs.map +0 -1
  260. package/dist/gc/gcSummaryDefinitions.cjs.map +0 -1
  261. package/dist/gc/gcSummaryStateTracker.cjs.map +0 -1
  262. package/dist/gc/gcTelemetry.cjs.map +0 -1
  263. package/dist/gc/index.cjs.map +0 -1
  264. package/dist/index.cjs.map +0 -1
  265. package/dist/messageTypes.cjs.map +0 -1
  266. package/dist/metadata.cjs.map +0 -1
  267. package/dist/opLifecycle/batchManager.cjs.map +0 -1
  268. package/dist/opLifecycle/definitions.cjs.map +0 -1
  269. package/dist/opLifecycle/index.cjs.map +0 -1
  270. package/dist/opLifecycle/opCompressor.cjs.map +0 -1
  271. package/dist/opLifecycle/opDecompressor.cjs.map +0 -1
  272. package/dist/opLifecycle/opGroupingManager.cjs.map +0 -1
  273. package/dist/opLifecycle/opSplitter.cjs.map +0 -1
  274. package/dist/opLifecycle/outbox.cjs.map +0 -1
  275. package/dist/opLifecycle/remoteMessageProcessor.cjs.map +0 -1
  276. package/dist/opProperties.cjs.map +0 -1
  277. package/dist/packageVersion.cjs.map +0 -1
  278. package/dist/pendingStateManager.cjs.map +0 -1
  279. package/dist/scheduleManager.cjs.map +0 -1
  280. package/dist/storageServiceWithAttachBlobs.cjs.map +0 -1
  281. package/dist/summary/index.cjs.map +0 -1
  282. package/dist/summary/orderedClientElection.cjs.map +0 -1
  283. package/dist/summary/runWhileConnectedCoordinator.cjs.map +0 -1
  284. package/dist/summary/runningSummarizer.cjs.map +0 -1
  285. package/dist/summary/summarizer.cjs.map +0 -1
  286. package/dist/summary/summarizerClientElection.cjs.map +0 -1
  287. package/dist/summary/summarizerHeuristics.cjs.map +0 -1
  288. package/dist/summary/summarizerNode/index.cjs.map +0 -1
  289. package/dist/summary/summarizerNode/summarizerNode.cjs.map +0 -1
  290. package/dist/summary/summarizerNode/summarizerNodeUtils.cjs.map +0 -1
  291. package/dist/summary/summarizerNode/summarizerNodeWithGc.cjs.map +0 -1
  292. package/dist/summary/summarizerTypes.cjs.map +0 -1
  293. package/dist/summary/summaryCollection.cjs.map +0 -1
  294. package/dist/summary/summaryFormat.cjs.map +0 -1
  295. package/dist/summary/summaryGenerator.cjs.map +0 -1
  296. package/dist/summary/summaryManager.cjs.map +0 -1
  297. package/dist/throttler.cjs.map +0 -1
  298. package/tsc-multi.test.json +0 -4
  299. /package/{.eslintrc.js → .eslintrc.cjs} +0 -0
@@ -20,7 +20,9 @@ import {
20
20
  ITelemetryLoggerExt,
21
21
  MonitoringContext,
22
22
  PerformanceEvent,
23
+ tagCodeArtifacts,
23
24
  } from "@fluidframework/telemetry-utils";
25
+ import { BlobManager } from "../blobManager";
24
26
  import {
25
27
  InactiveResponseHeaderKey,
26
28
  RuntimeHeaderData,
@@ -44,6 +46,7 @@ import {
44
46
  ISweepPhaseStats,
45
47
  GarbageCollectionMessage,
46
48
  GarbageCollectionMessageType,
49
+ disableAutoRecoveryKey,
47
50
  } from "./gcDefinitions";
48
51
  import {
49
52
  cloneGCData,
@@ -54,7 +57,10 @@ import {
54
57
  import { runGarbageCollection } from "./gcReferenceGraphAlgorithm";
55
58
  import { IGarbageCollectionSnapshotData, IGarbageCollectionState } from "./gcSummaryDefinitions";
56
59
  import { GCSummaryStateTracker } from "./gcSummaryStateTracker";
57
- import { UnreferencedStateTracker } from "./gcUnreferencedStateTracker";
60
+ import {
61
+ UnreferencedStateTracker,
62
+ UnreferencedStateTrackerMap,
63
+ } from "./gcUnreferencedStateTracker";
58
64
  import { GCTelemetryTracker } from "./gcTelemetry";
59
65
 
60
66
  /**
@@ -108,8 +114,15 @@ export class GarbageCollector implements IGarbageCollector {
108
114
  private readonly initializeGCStateFromBaseSnapshotP: Promise<void>;
109
115
  // The GC details generated from the base snapshot.
110
116
  private readonly baseGCDetailsP: Promise<IGarbageCollectionDetailsBase>;
111
- // Map of node ids to their unreferenced state tracker.
112
- private readonly unreferencedNodesState: Map<string, UnreferencedStateTracker> = new Map();
117
+
118
+ /**
119
+ * Map of node ids to their unreferenced state tracker
120
+ * NOTE: The set of keys in this map is considered as the set of unreferenced nodes
121
+ * as of the last GC run. So in between runs, nothing should be added or removed.
122
+ */
123
+ private readonly unreferencedNodesState: UnreferencedStateTrackerMap =
124
+ new UnreferencedStateTrackerMap();
125
+
113
126
  // The Timer responsible for closing the container when the session has expired
114
127
  private sessionExpiryTimer: Timer | undefined;
115
128
 
@@ -261,7 +274,7 @@ export class GarbageCollector implements IGarbageCollector {
261
274
  const currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();
262
275
  assert(
263
276
  currentReferenceTimestampMs !== undefined,
264
- "Trying to initialize GC state without current timestamp",
277
+ 0x8a4 /* Trying to initialize GC state without current timestamp */,
265
278
  );
266
279
 
267
280
  /**
@@ -590,16 +603,10 @@ export class GarbageCollector implements IGarbageCollector {
590
603
  ): { tombstoneReadyNodeIds: Set<string>; sweepReadyNodeIds: Set<string> } {
591
604
  // 1. Marks all referenced nodes by clearing their unreferenced tracker, if any.
592
605
  for (const nodeId of allReferencedNodeIds) {
593
- const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
594
- if (nodeStateTracker !== undefined) {
595
- // Stop tracking so as to clear out any running timers.
596
- nodeStateTracker.stopTracking();
597
- // Delete the node as we don't need to track it any more.
598
- this.unreferencedNodesState.delete(nodeId);
599
- }
606
+ this.unreferencedNodesState.delete(nodeId);
600
607
  }
601
608
 
602
- // 2. Mark unreferenced nodes in this run by starting unreferenced tracking for them.
609
+ // 2. Mark unreferenced nodes in this run by starting or updating unreferenced tracking for them.
603
610
  const tombstoneReadyNodeIds: Set<string> = new Set();
604
611
  const sweepReadyNodeIds: Set<string> = new Set();
605
612
  for (const nodeId of gcResult.deletedNodeIds) {
@@ -854,21 +861,33 @@ export class GarbageCollector implements IGarbageCollector {
854
861
  * @param local - Whether it was send by this client.
855
862
  */
856
863
  public processMessage(message: ContainerRuntimeGCMessage, local: boolean) {
857
- switch (message.contents.type) {
858
- case "Sweep": {
864
+ const gcMessageType = message.contents.type;
865
+ switch (gcMessageType) {
866
+ case GarbageCollectionMessageType.Sweep: {
859
867
  // Delete the nodes whose ids are present in the contents.
860
868
  this.deleteSweepReadyNodes(message.contents.deletedNodeIds);
861
869
  break;
862
870
  }
871
+ case GarbageCollectionMessageType.TombstoneLoaded: {
872
+ if (this.mc.config.getBoolean(disableAutoRecoveryKey) === true) {
873
+ break;
874
+ }
875
+
876
+ // Mark the node as referenced to ensure it isn't Swept
877
+ const tombstonedNodePath = message.contents.nodePath;
878
+ this.addedOutboundReference("/", tombstonedNodePath);
879
+
880
+ break;
881
+ }
863
882
  default: {
864
883
  if (
865
884
  !compatBehaviorAllowsGCMessageType(
866
- message.contents.type,
885
+ gcMessageType,
867
886
  message.compatDetails?.behavior,
868
887
  )
869
888
  ) {
870
889
  const error = DataProcessingError.create(
871
- `Garbage collection message of unknown type ${message.contents.type}`,
890
+ `Garbage collection message of unknown type ${gcMessageType}`,
872
891
  "processMessage",
873
892
  );
874
893
  throw error;
@@ -909,13 +928,9 @@ export class GarbageCollector implements IGarbageCollector {
909
928
 
910
929
  // Clear unreferenced state tracking for deleted nodes.
911
930
  for (const nodeId of deletedNodeIds) {
912
- const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
913
- if (nodeStateTracker !== undefined) {
914
- // Stop tracking so as to clear out any running timers.
915
- nodeStateTracker.stopTracking();
916
- // Delete the node as we don't need to track it any more.
917
- this.unreferencedNodesState.delete(nodeId);
918
- }
931
+ // Usually we avoid modifying the set of unreferencedNodesState keys in between GC runs,
932
+ // but this is ok since this node won't exist at all in the next GC run.
933
+ this.unreferencedNodesState.delete(nodeId);
919
934
  this.deletedNodes.add(nodeId);
920
935
  }
921
936
  }
@@ -957,6 +972,15 @@ export class GarbageCollector implements IGarbageCollector {
957
972
  headers: headerData,
958
973
  });
959
974
 
975
+ // Any time we log a Tombstone Loaded error (via Telemetry Tracker),
976
+ // we want to also trigger autorecovery to avoid the object being deleted
977
+ // Note: We don't need to trigger on "Changed" because any change will cause the object
978
+ // to be loaded by the Summarizer, and auto-recovery will be triggered then.
979
+ if (isTombstoned && reason === "Loaded") {
980
+ // Note that when a DataStore and its DDS are all loaded, each will trigger AutoRecovery for itself.
981
+ this.triggerAutoRecovery(nodePath);
982
+ }
983
+
960
984
  const nodeType = this.runtime.getNodeType(nodePath);
961
985
 
962
986
  // Unless this is a Loaded event for a Blob or DataStore, we're done after telemetry tracking
@@ -965,7 +989,6 @@ export class GarbageCollector implements IGarbageCollector {
965
989
  }
966
990
 
967
991
  const errorRequest: IRequest = request ?? { url: nodePath };
968
- // If the object is tombstoned and tombstone enforcement is configured, throw an error.
969
992
  if (isTombstoned && this.throwOnTombstoneLoad && headerData?.allowTombstone !== true) {
970
993
  // The requested data store is removed by gc. Create a 404 gc response exception.
971
994
  throw responseToException(
@@ -993,18 +1016,58 @@ export class GarbageCollector implements IGarbageCollector {
993
1016
  }
994
1017
  }
995
1018
 
1019
+ /**
1020
+ * The given node should have its unreferenced state reset in the next GC,
1021
+ * even if the true GC graph shows it is unreferenced. This will
1022
+ * prevent it from being deleted by Sweep (after the Grace Period).
1023
+ *
1024
+ * Submit a GC op indicating that the Tombstone with the given path has been loaded.
1025
+ * Broadcasting this information in the op stream allows the Summarizer to reset unreferenced state
1026
+ * before runnint GC next.
1027
+ */
1028
+ private triggerAutoRecovery(nodePath: string) {
1029
+ if (this.mc.config.getBoolean(disableAutoRecoveryKey) === true) {
1030
+ return;
1031
+ }
1032
+
1033
+ // Use compat behavior "Ignore" since this is an optimization to opportunistically protect
1034
+ // objects from deletion, so it's fine for older clients to ignore this op.
1035
+ const containerGCMessage: ContainerRuntimeGCMessage = {
1036
+ type: ContainerMessageType.GC,
1037
+ contents: {
1038
+ type: "TombstoneLoaded",
1039
+ nodePath,
1040
+ },
1041
+ compatDetails: { behavior: "Ignore" },
1042
+ };
1043
+ this.submitMessage(containerGCMessage);
1044
+ }
1045
+
996
1046
  /**
997
1047
  * Called when an outbound reference is added to a node. This is used to identify all nodes that have been
998
1048
  * referenced between summaries so that their unreferenced timestamp can be reset.
999
1049
  *
1000
1050
  * @param fromNodePath - The node from which the reference is added.
1001
1051
  * @param toNodePath - The node to which the reference is added.
1052
+ * @param autorecovery - This reference is added artificially, for autorecovery. Used for logging.
1002
1053
  */
1003
- public addedOutboundReference(fromNodePath: string, toNodePath: string) {
1054
+ public addedOutboundReference(fromNodePath: string, toNodePath: string, autorecovery?: true) {
1004
1055
  if (!this.configs.shouldRunGC) {
1005
1056
  return;
1006
1057
  }
1007
1058
 
1059
+ if (!toNodePath.startsWith("/")) {
1060
+ // A long time ago we stored handles with relatives paths. We don't expect to see these cases though
1061
+ // because GC was enabled only after we made the switch to always using absolute paths.
1062
+ this.mc.logger.sendErrorEvent({
1063
+ eventName: "InvalidRelativeOutboundRoute",
1064
+ ...tagCodeArtifacts({ fromId: fromNodePath, id: toNodePath }),
1065
+ });
1066
+ return;
1067
+ }
1068
+
1069
+ assert(fromNodePath.startsWith("/"), 0x8a5 /* fromNodePath must be an absolute path */);
1070
+
1008
1071
  const outboundRoutes = this.newReferencesSinceLastRun.get(fromNodePath) ?? [];
1009
1072
  outboundRoutes.push(toNodePath);
1010
1073
  this.newReferencesSinceLastRun.set(fromNodePath, outboundRoutes);
@@ -1018,7 +1081,14 @@ export class GarbageCollector implements IGarbageCollector {
1018
1081
  isTombstoned: this.tombstones.includes(toNodePath),
1019
1082
  lastSummaryTime: this.getLastSummaryTimestampMs(),
1020
1083
  fromId: fromNodePath,
1084
+ autorecovery,
1021
1085
  });
1086
+
1087
+ // This node is referenced - Clear its unreferenced state
1088
+ // But don't delete the node id from the map yet.
1089
+ // When generating GC stats, the set of nodes in here is used as the baseline for
1090
+ // what was unreferenced in the last GC run.
1091
+ this.unreferencedNodesState.get(toNodePath)?.stopTracking();
1022
1092
  }
1023
1093
 
1024
1094
  /**
@@ -1052,17 +1122,17 @@ export class GarbageCollector implements IGarbageCollector {
1052
1122
  updatedAttachmentBlobCount: 0,
1053
1123
  };
1054
1124
 
1055
- const updateNodeStats = (nodeId: string, referenced: boolean) => {
1125
+ const updateNodeStats = (nodeId: string, isReferenced: boolean) => {
1056
1126
  markPhaseStats.nodeCount++;
1057
1127
  // If there is no previous GC data, every node's state is generated and is considered as updated.
1058
1128
  // Otherwise, find out if any node went from referenced to unreferenced or vice-versa.
1129
+ const wasNotReferenced = this.unreferencedNodesState.has(nodeId);
1059
1130
  const stateUpdated =
1060
- this.gcDataFromLastRun === undefined ||
1061
- this.unreferencedNodesState.has(nodeId) === referenced;
1131
+ this.gcDataFromLastRun === undefined || wasNotReferenced === isReferenced;
1062
1132
  if (stateUpdated) {
1063
1133
  markPhaseStats.updatedNodeCount++;
1064
1134
  }
1065
- if (!referenced) {
1135
+ if (!isReferenced) {
1066
1136
  markPhaseStats.unrefNodeCount++;
1067
1137
  }
1068
1138
 
@@ -1071,7 +1141,7 @@ export class GarbageCollector implements IGarbageCollector {
1071
1141
  if (stateUpdated) {
1072
1142
  markPhaseStats.updatedDataStoreCount++;
1073
1143
  }
1074
- if (!referenced) {
1144
+ if (!isReferenced) {
1075
1145
  markPhaseStats.unrefDataStoreCount++;
1076
1146
  }
1077
1147
  }
@@ -1080,7 +1150,7 @@ export class GarbageCollector implements IGarbageCollector {
1080
1150
  if (stateUpdated) {
1081
1151
  markPhaseStats.updatedAttachmentBlobCount++;
1082
1152
  }
1083
- if (!referenced) {
1153
+ if (!isReferenced) {
1084
1154
  markPhaseStats.unrefAttachmentBlobCount++;
1085
1155
  }
1086
1156
  }
@@ -1120,9 +1190,25 @@ export class GarbageCollector implements IGarbageCollector {
1120
1190
  deletedAttachmentBlobCount: 0,
1121
1191
  };
1122
1192
 
1193
+ // The runtime can't reliably identify the type of deleted nodes. So, get the type here. This should
1194
+ // be good enough because the only types that participate in GC today are data stores, DDSes and blobs.
1195
+ const getDeletedNodeType = (nodeId: string): GCNodeType => {
1196
+ const pathParts = nodeId.split("/");
1197
+ if (pathParts[1] === BlobManager.basePath) {
1198
+ return GCNodeType.Blob;
1199
+ }
1200
+ if (pathParts.length === 2) {
1201
+ return GCNodeType.DataStore;
1202
+ }
1203
+ if (pathParts.length === 3) {
1204
+ return GCNodeType.SubDataStore;
1205
+ }
1206
+ return GCNodeType.Other;
1207
+ };
1208
+
1123
1209
  for (const nodeId of deletedNodes) {
1124
1210
  sweepPhaseStats.deletedNodeCount++;
1125
- const nodeType = this.runtime.getNodeType(nodeId);
1211
+ const nodeType = getDeletedNodeType(nodeId);
1126
1212
  if (nodeType === GCNodeType.DataStore) {
1127
1213
  sweepPhaseStats.deletedDataStoreCount++;
1128
1214
  } else if (nodeType === GCNodeType.Blob) {
@@ -74,6 +74,10 @@ export const gcVersionUpgradeToV4Key = "Fluid.GarbageCollection.GCVersionUpgrade
74
74
  export const disableDatastoreSweepKey = "Fluid.GarbageCollection.DisableDataStoreSweep";
75
75
  /** Config key to disable GC sweep for attachment blobs. */
76
76
  export const disableAttachmentBlobSweepKey = "Fluid.GarbageCollection.DisableAttachmentBlobSweep";
77
+ /** Config key to revert new paradigm of detecting outbound routes in ContainerRuntime layer (use true) */
78
+ export const detectOutboundRoutesViaDDSKey = "Fluid.GarbageCollection.DetectOutboundRoutesViaDDS";
79
+ /** Config key to disable auto-recovery mechanism that protects Tombstones that are loaded from being swept (use true) */
80
+ export const disableAutoRecoveryKey = "Fluid.GarbageCollection.DisableAutoRecovery";
77
81
 
78
82
  // One day in milliseconds.
79
83
  export const oneDayMs = 1 * 24 * 60 * 60 * 1000;
@@ -251,6 +255,8 @@ export type GCNodeType = (typeof GCNodeType)[keyof typeof GCNodeType];
251
255
  export const GarbageCollectionMessageType = {
252
256
  /** Message sent directing GC to delete the given nodes */
253
257
  Sweep: "Sweep",
258
+ /** Message sent notifying GC that a Tombstoned object was Loaded */
259
+ TombstoneLoaded: "TombstoneLoaded",
254
260
  } as const;
255
261
 
256
262
  /**
@@ -264,16 +270,28 @@ export type GarbageCollectionMessageType =
264
270
  * @internal
265
271
  */
266
272
  export interface ISweepMessage {
267
- type: "Sweep";
268
- // The ids of nodes that are deleted.
273
+ /** @see GarbageCollectionMessageType.Sweep */
274
+ type: typeof GarbageCollectionMessageType.Sweep;
275
+ /** The ids of nodes that are deleted. */
269
276
  deletedNodeIds: string[];
270
277
  }
271
278
 
279
+ /**
280
+ * The GC TombstoneLoaded message.
281
+ * @internal
282
+ */
283
+ export interface ITombstoneLoadedMessage {
284
+ /** @see GarbageCollectionMessageType.TombstoneLoaded */
285
+ type: typeof GarbageCollectionMessageType.TombstoneLoaded;
286
+ /** The id of Tombstoned node that was loaded. */
287
+ nodePath: string;
288
+ }
289
+
272
290
  /**
273
291
  * Type for a message to be used for sending / received garbage collection messages.
274
292
  * @internal
275
293
  */
276
- export type GarbageCollectionMessage = ISweepMessage;
294
+ export type GarbageCollectionMessage = ISweepMessage | ITombstoneLoadedMessage;
277
295
 
278
296
  /**
279
297
  * Defines the APIs for the runtime object to be passed to the garbage collector.
@@ -63,6 +63,7 @@ interface INodeUsageProps extends ICommonProps {
63
63
  currentReferenceTimestampMs: number | undefined;
64
64
  packagePath: readonly string[] | undefined;
65
65
  fromId?: string;
66
+ autorecovery?: true;
66
67
  }
67
68
 
68
69
  /**
@@ -189,8 +190,6 @@ export class GCTelemetryTracker {
189
190
  };
190
191
 
191
192
  // If the node that is used is tombstoned, log a tombstone telemetry.
192
- // Note that this is done before checking if "nodeStateTracker" is undefined below because unreferenced
193
- // tracking may not have yet been enabled. That happens only after the client transitions to write mode.
194
193
  if (nodeUsageProps.isTombstoned) {
195
194
  this.logTombstoneUsageTelemetry(nodeUsageProps, unrefEventProps, nodeType, usageType);
196
195
  }
@@ -25,6 +25,17 @@ class TimerWithNoDefaultTimeout extends Timer {
25
25
  }
26
26
  }
27
27
 
28
+ /** The collection of UnreferencedStateTrackers for all unreferenced nodes. Ensures stopTracking is called when deleting */
29
+ export class UnreferencedStateTrackerMap extends Map<string, UnreferencedStateTracker> {
30
+ /** Delete the given key, and stop tracking if that node was actually unreferenced */
31
+ delete(key: string): boolean {
32
+ // Stop tracking so as to clear out any running timers.
33
+ this.get(key)?.stopTracking();
34
+ // Delete the node as we don't need to track it any more.
35
+ return super.delete(key);
36
+ }
37
+ }
38
+
28
39
  /**
29
40
  * Helper class that tracks the state of an unreferenced node such as the time it was unreferenced and if it can
30
41
  * be tombstoned or deleted by the sweep phase.
package/src/gc/index.ts CHANGED
@@ -33,10 +33,13 @@ export {
33
33
  runSweepKey,
34
34
  stableGCVersion,
35
35
  disableAttachmentBlobSweepKey,
36
+ disableAutoRecoveryKey,
36
37
  disableDatastoreSweepKey,
38
+ detectOutboundRoutesViaDDSKey,
37
39
  UnreferencedState,
38
40
  throwOnTombstoneLoadOverrideKey,
39
41
  GarbageCollectionMessage,
42
+ ISweepMessage,
40
43
  } from "./gcDefinitions";
41
44
  export {
42
45
  cloneGCData,
package/src/index.ts CHANGED
@@ -30,9 +30,11 @@ export {
30
30
  IContainerRuntimeMessageCompatDetails,
31
31
  CompatModeBehavior,
32
32
  RecentlyAddedContainerRuntimeMessageDetails,
33
+ UnknownContainerRuntimeMessage,
33
34
  } from "./messageTypes";
34
35
  export { IBlobManagerLoadInfo } from "./blobManager";
35
36
  export { FluidDataStoreRegistry } from "./dataStoreRegistry";
37
+ export { detectOutboundReferences } from "./dataStores";
36
38
  export {
37
39
  GCNodeType,
38
40
  IGCMetadata,
@@ -133,7 +133,7 @@ export type ContainerRuntimeGCMessage = TypedContainerRuntimeMessage<
133
133
  >;
134
134
 
135
135
  /**
136
- * Represents an unrecognized {@link TypedContainerRuntimeMessage}, e.g. a message from a future version of the container runtime.
136
+ * Represents an unrecognized TypedContainerRuntimeMessage, e.g. a message from a future version of the container runtime.
137
137
  * @internal
138
138
  */
139
139
  export interface UnknownContainerRuntimeMessage
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "2.0.0-dev-rc.1.0.0.225277";
9
+ export const pkgVersion = "2.0.0-dev-rc.1.0.0.232845";