@fluidframework/container-runtime 2.0.0-internal.7.2.2 → 2.0.0-internal.7.4.0

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 (302) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +1 -2
  3. package/api-extractor-lint.json +13 -0
  4. package/api-extractor.json +9 -1
  5. package/api-report/container-runtime.api.md +124 -107
  6. package/dist/batchTracker.d.ts +1 -0
  7. package/dist/batchTracker.d.ts.map +1 -1
  8. package/dist/blobManager.d.ts +4 -4
  9. package/dist/blobManager.d.ts.map +1 -1
  10. package/dist/blobManager.js.map +1 -1
  11. package/dist/connectionTelemetry.js +1 -1
  12. package/dist/connectionTelemetry.js.map +1 -1
  13. package/dist/container-runtime-alpha.d.ts +1473 -0
  14. package/dist/container-runtime-beta.d.ts +300 -0
  15. package/dist/container-runtime-public.d.ts +300 -0
  16. package/dist/container-runtime-untrimmed.d.ts +1836 -0
  17. package/dist/containerRuntime.d.ts +34 -40
  18. package/dist/containerRuntime.d.ts.map +1 -1
  19. package/dist/containerRuntime.js +79 -67
  20. package/dist/containerRuntime.js.map +1 -1
  21. package/dist/dataStoreRegistry.d.ts +1 -1
  22. package/dist/dataStoreRegistry.js +1 -1
  23. package/dist/dataStoreRegistry.js.map +1 -1
  24. package/dist/dataStores.d.ts +10 -15
  25. package/dist/dataStores.d.ts.map +1 -1
  26. package/dist/dataStores.js +77 -40
  27. package/dist/dataStores.js.map +1 -1
  28. package/dist/gc/garbageCollection.d.ts +41 -13
  29. package/dist/gc/garbageCollection.d.ts.map +1 -1
  30. package/dist/gc/garbageCollection.js +215 -78
  31. package/dist/gc/garbageCollection.js.map +1 -1
  32. package/dist/gc/gcConfigs.d.ts.map +1 -1
  33. package/dist/gc/gcConfigs.js +34 -37
  34. package/dist/gc/gcConfigs.js.map +1 -1
  35. package/dist/gc/gcDefinitions.d.ts +121 -46
  36. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  37. package/dist/gc/gcDefinitions.js +26 -18
  38. package/dist/gc/gcDefinitions.js.map +1 -1
  39. package/dist/gc/gcHelpers.d.ts +18 -25
  40. package/dist/gc/gcHelpers.d.ts.map +1 -1
  41. package/dist/gc/gcHelpers.js +29 -45
  42. package/dist/gc/gcHelpers.js.map +1 -1
  43. package/dist/gc/gcTelemetry.d.ts +0 -5
  44. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  45. package/dist/gc/gcTelemetry.js +14 -42
  46. package/dist/gc/gcTelemetry.js.map +1 -1
  47. package/dist/gc/gcUnreferencedStateTracker.d.ts +11 -5
  48. package/dist/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
  49. package/dist/gc/gcUnreferencedStateTracker.js +43 -19
  50. package/dist/gc/gcUnreferencedStateTracker.js.map +1 -1
  51. package/dist/gc/index.d.ts +1 -1
  52. package/dist/gc/index.d.ts.map +1 -1
  53. package/dist/gc/index.js +4 -5
  54. package/dist/gc/index.js.map +1 -1
  55. package/dist/index.d.ts +14 -2
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +16 -5
  58. package/dist/index.js.map +1 -1
  59. package/dist/messageTypes.d.ts +16 -11
  60. package/dist/messageTypes.d.ts.map +1 -1
  61. package/dist/messageTypes.js +6 -1
  62. package/dist/messageTypes.js.map +1 -1
  63. package/dist/metadata.d.ts +6 -0
  64. package/dist/metadata.d.ts.map +1 -1
  65. package/dist/metadata.js.map +1 -1
  66. package/dist/opLifecycle/definitions.d.ts +1 -1
  67. package/dist/opLifecycle/definitions.js.map +1 -1
  68. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  69. package/dist/opLifecycle/opGroupingManager.js +10 -1
  70. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  71. package/dist/opLifecycle/outbox.d.ts +2 -0
  72. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  73. package/dist/opLifecycle/outbox.js +21 -0
  74. package/dist/opLifecycle/outbox.js.map +1 -1
  75. package/dist/packageVersion.d.ts +1 -1
  76. package/dist/packageVersion.js +1 -1
  77. package/dist/packageVersion.js.map +1 -1
  78. package/dist/pendingStateManager.d.ts +1 -1
  79. package/dist/pendingStateManager.d.ts.map +1 -1
  80. package/dist/pendingStateManager.js +2 -11
  81. package/dist/pendingStateManager.js.map +1 -1
  82. package/dist/scheduleManager.d.ts +1 -0
  83. package/dist/scheduleManager.d.ts.map +1 -1
  84. package/dist/summary/orderedClientElection.d.ts +1 -1
  85. package/dist/summary/orderedClientElection.js.map +1 -1
  86. package/dist/summary/runWhileConnectedCoordinator.d.ts +2 -2
  87. package/dist/summary/runWhileConnectedCoordinator.js +1 -1
  88. package/dist/summary/runWhileConnectedCoordinator.js.map +1 -1
  89. package/dist/summary/summarizer.d.ts +1 -1
  90. package/dist/summary/summarizer.js +1 -1
  91. package/dist/summary/summarizer.js.map +1 -1
  92. package/dist/summary/summarizerTypes.d.ts +30 -30
  93. package/dist/summary/summarizerTypes.js.map +1 -1
  94. package/dist/summary/summaryCollection.d.ts +10 -10
  95. package/dist/summary/summaryCollection.js +1 -1
  96. package/dist/summary/summaryCollection.js.map +1 -1
  97. package/dist/summary/summaryFormat.d.ts +3 -3
  98. package/dist/summary/summaryFormat.js.map +1 -1
  99. package/dist/tsdoc-metadata.json +1 -1
  100. package/lib/batchTracker.d.ts +1 -0
  101. package/lib/batchTracker.d.ts.map +1 -1
  102. package/lib/blobManager.d.ts +4 -4
  103. package/lib/blobManager.d.ts.map +1 -1
  104. package/lib/blobManager.js.map +1 -1
  105. package/lib/connectionTelemetry.js +1 -1
  106. package/lib/connectionTelemetry.js.map +1 -1
  107. package/lib/container-runtime-alpha.d.ts +1473 -0
  108. package/lib/container-runtime-beta.d.ts +300 -0
  109. package/lib/container-runtime-public.d.ts +300 -0
  110. package/lib/container-runtime-untrimmed.d.ts +1836 -0
  111. package/lib/containerRuntime.d.ts +34 -40
  112. package/lib/containerRuntime.d.ts.map +1 -1
  113. package/lib/containerRuntime.js +81 -69
  114. package/lib/containerRuntime.js.map +1 -1
  115. package/lib/dataStoreRegistry.d.ts +1 -1
  116. package/lib/dataStoreRegistry.js +1 -1
  117. package/lib/dataStoreRegistry.js.map +1 -1
  118. package/lib/dataStores.d.ts +10 -15
  119. package/lib/dataStores.d.ts.map +1 -1
  120. package/lib/dataStores.js +80 -43
  121. package/lib/dataStores.js.map +1 -1
  122. package/lib/gc/garbageCollection.d.ts +41 -13
  123. package/lib/gc/garbageCollection.d.ts.map +1 -1
  124. package/lib/gc/garbageCollection.js +217 -80
  125. package/lib/gc/garbageCollection.js.map +1 -1
  126. package/lib/gc/gcConfigs.d.ts.map +1 -1
  127. package/lib/gc/gcConfigs.js +37 -40
  128. package/lib/gc/gcConfigs.js.map +1 -1
  129. package/lib/gc/gcDefinitions.d.ts +121 -46
  130. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  131. package/lib/gc/gcDefinitions.js +25 -17
  132. package/lib/gc/gcDefinitions.js.map +1 -1
  133. package/lib/gc/gcHelpers.d.ts +18 -25
  134. package/lib/gc/gcHelpers.d.ts.map +1 -1
  135. package/lib/gc/gcHelpers.js +27 -43
  136. package/lib/gc/gcHelpers.js.map +1 -1
  137. package/lib/gc/gcTelemetry.d.ts +0 -5
  138. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  139. package/lib/gc/gcTelemetry.js +15 -43
  140. package/lib/gc/gcTelemetry.js.map +1 -1
  141. package/lib/gc/gcUnreferencedStateTracker.d.ts +11 -5
  142. package/lib/gc/gcUnreferencedStateTracker.d.ts.map +1 -1
  143. package/lib/gc/gcUnreferencedStateTracker.js +43 -19
  144. package/lib/gc/gcUnreferencedStateTracker.js.map +1 -1
  145. package/lib/gc/index.d.ts +1 -1
  146. package/lib/gc/index.d.ts.map +1 -1
  147. package/lib/gc/index.js +1 -1
  148. package/lib/gc/index.js.map +1 -1
  149. package/lib/index.d.ts +14 -2
  150. package/lib/index.d.ts.map +1 -1
  151. package/lib/index.js +15 -1
  152. package/lib/index.js.map +1 -1
  153. package/lib/messageTypes.d.ts +16 -11
  154. package/lib/messageTypes.d.ts.map +1 -1
  155. package/lib/messageTypes.js +6 -1
  156. package/lib/messageTypes.js.map +1 -1
  157. package/lib/metadata.d.ts +6 -0
  158. package/lib/metadata.d.ts.map +1 -1
  159. package/lib/metadata.js.map +1 -1
  160. package/lib/opLifecycle/definitions.d.ts +1 -1
  161. package/lib/opLifecycle/definitions.js.map +1 -1
  162. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
  163. package/lib/opLifecycle/opGroupingManager.js +10 -1
  164. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  165. package/lib/opLifecycle/outbox.d.ts +2 -0
  166. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  167. package/lib/opLifecycle/outbox.js +21 -0
  168. package/lib/opLifecycle/outbox.js.map +1 -1
  169. package/lib/packageVersion.d.ts +1 -1
  170. package/lib/packageVersion.js +1 -1
  171. package/lib/packageVersion.js.map +1 -1
  172. package/lib/pendingStateManager.d.ts +1 -1
  173. package/lib/pendingStateManager.d.ts.map +1 -1
  174. package/lib/pendingStateManager.js +2 -11
  175. package/lib/pendingStateManager.js.map +1 -1
  176. package/lib/scheduleManager.d.ts +1 -0
  177. package/lib/scheduleManager.d.ts.map +1 -1
  178. package/lib/summary/orderedClientElection.d.ts +1 -1
  179. package/lib/summary/orderedClientElection.js.map +1 -1
  180. package/lib/summary/runWhileConnectedCoordinator.d.ts +2 -2
  181. package/lib/summary/runWhileConnectedCoordinator.js +1 -1
  182. package/lib/summary/runWhileConnectedCoordinator.js.map +1 -1
  183. package/lib/summary/summarizer.d.ts +1 -1
  184. package/lib/summary/summarizer.js +1 -1
  185. package/lib/summary/summarizer.js.map +1 -1
  186. package/lib/summary/summarizerTypes.d.ts +30 -30
  187. package/lib/summary/summarizerTypes.js.map +1 -1
  188. package/lib/summary/summaryCollection.d.ts +10 -10
  189. package/lib/summary/summaryCollection.js +1 -1
  190. package/lib/summary/summaryCollection.js.map +1 -1
  191. package/lib/summary/summaryFormat.d.ts +3 -3
  192. package/lib/summary/summaryFormat.js.map +1 -1
  193. package/package.json +56 -29
  194. package/src/blobManager.ts +5 -5
  195. package/src/connectionTelemetry.ts +1 -1
  196. package/src/containerRuntime.ts +113 -90
  197. package/src/dataStoreRegistry.ts +1 -1
  198. package/src/dataStores.ts +140 -69
  199. package/src/gc/garbageCollection.md +14 -15
  200. package/src/gc/garbageCollection.ts +256 -96
  201. package/src/gc/gcConfigs.ts +50 -52
  202. package/src/gc/gcDefinitions.ts +137 -52
  203. package/src/gc/gcHelpers.ts +31 -52
  204. package/src/gc/gcTelemetry.ts +16 -57
  205. package/src/gc/gcUnreferencedStateTracker.ts +61 -22
  206. package/src/gc/index.ts +6 -4
  207. package/src/index.ts +19 -1
  208. package/src/messageTypes.ts +21 -11
  209. package/src/metadata.ts +7 -0
  210. package/src/opLifecycle/definitions.ts +1 -1
  211. package/src/opLifecycle/opGroupingManager.ts +10 -1
  212. package/src/opLifecycle/outbox.ts +34 -0
  213. package/src/packageVersion.ts +1 -1
  214. package/src/pendingStateManager.ts +3 -13
  215. package/src/summary/orderedClientElection.ts +1 -1
  216. package/src/summary/runWhileConnectedCoordinator.ts +2 -2
  217. package/src/summary/summarizer.ts +1 -1
  218. package/src/summary/summarizerTypes.ts +30 -30
  219. package/src/summary/summaryCollection.ts +10 -10
  220. package/src/summary/summaryFormat.ts +3 -3
  221. package/dist/id-compressor/appendOnlySortedMap.d.ts +0 -124
  222. package/dist/id-compressor/appendOnlySortedMap.d.ts.map +0 -1
  223. package/dist/id-compressor/appendOnlySortedMap.js +0 -318
  224. package/dist/id-compressor/appendOnlySortedMap.js.map +0 -1
  225. package/dist/id-compressor/finalSpace.d.ts +0 -29
  226. package/dist/id-compressor/finalSpace.d.ts.map +0 -1
  227. package/dist/id-compressor/finalSpace.js +0 -62
  228. package/dist/id-compressor/finalSpace.js.map +0 -1
  229. package/dist/id-compressor/idCompressor.d.ts +0 -54
  230. package/dist/id-compressor/idCompressor.d.ts.map +0 -1
  231. package/dist/id-compressor/idCompressor.js +0 -495
  232. package/dist/id-compressor/idCompressor.js.map +0 -1
  233. package/dist/id-compressor/identifiers.d.ts +0 -32
  234. package/dist/id-compressor/identifiers.d.ts.map +0 -1
  235. package/dist/id-compressor/identifiers.js +0 -15
  236. package/dist/id-compressor/identifiers.js.map +0 -1
  237. package/dist/id-compressor/index.d.ts +0 -13
  238. package/dist/id-compressor/index.d.ts.map +0 -1
  239. package/dist/id-compressor/index.js +0 -32
  240. package/dist/id-compressor/index.js.map +0 -1
  241. package/dist/id-compressor/persistanceUtilities.d.ts +0 -22
  242. package/dist/id-compressor/persistanceUtilities.d.ts.map +0 -1
  243. package/dist/id-compressor/persistanceUtilities.js +0 -43
  244. package/dist/id-compressor/persistanceUtilities.js.map +0 -1
  245. package/dist/id-compressor/sessionSpaceNormalizer.d.ts +0 -46
  246. package/dist/id-compressor/sessionSpaceNormalizer.d.ts.map +0 -1
  247. package/dist/id-compressor/sessionSpaceNormalizer.js +0 -80
  248. package/dist/id-compressor/sessionSpaceNormalizer.js.map +0 -1
  249. package/dist/id-compressor/sessions.d.ts +0 -115
  250. package/dist/id-compressor/sessions.d.ts.map +0 -1
  251. package/dist/id-compressor/sessions.js +0 -305
  252. package/dist/id-compressor/sessions.js.map +0 -1
  253. package/dist/id-compressor/utilities.d.ts +0 -52
  254. package/dist/id-compressor/utilities.d.ts.map +0 -1
  255. package/dist/id-compressor/utilities.js +0 -169
  256. package/dist/id-compressor/utilities.js.map +0 -1
  257. package/lib/id-compressor/appendOnlySortedMap.d.ts +0 -124
  258. package/lib/id-compressor/appendOnlySortedMap.d.ts.map +0 -1
  259. package/lib/id-compressor/appendOnlySortedMap.js +0 -314
  260. package/lib/id-compressor/appendOnlySortedMap.js.map +0 -1
  261. package/lib/id-compressor/finalSpace.d.ts +0 -29
  262. package/lib/id-compressor/finalSpace.d.ts.map +0 -1
  263. package/lib/id-compressor/finalSpace.js +0 -58
  264. package/lib/id-compressor/finalSpace.js.map +0 -1
  265. package/lib/id-compressor/idCompressor.d.ts +0 -54
  266. package/lib/id-compressor/idCompressor.d.ts.map +0 -1
  267. package/lib/id-compressor/idCompressor.js +0 -491
  268. package/lib/id-compressor/idCompressor.js.map +0 -1
  269. package/lib/id-compressor/identifiers.d.ts +0 -32
  270. package/lib/id-compressor/identifiers.d.ts.map +0 -1
  271. package/lib/id-compressor/identifiers.js +0 -11
  272. package/lib/id-compressor/identifiers.js.map +0 -1
  273. package/lib/id-compressor/index.d.ts +0 -13
  274. package/lib/id-compressor/index.d.ts.map +0 -1
  275. package/lib/id-compressor/index.js +0 -13
  276. package/lib/id-compressor/index.js.map +0 -1
  277. package/lib/id-compressor/persistanceUtilities.d.ts +0 -22
  278. package/lib/id-compressor/persistanceUtilities.d.ts.map +0 -1
  279. package/lib/id-compressor/persistanceUtilities.js +0 -34
  280. package/lib/id-compressor/persistanceUtilities.js.map +0 -1
  281. package/lib/id-compressor/sessionSpaceNormalizer.d.ts +0 -46
  282. package/lib/id-compressor/sessionSpaceNormalizer.d.ts.map +0 -1
  283. package/lib/id-compressor/sessionSpaceNormalizer.js +0 -76
  284. package/lib/id-compressor/sessionSpaceNormalizer.js.map +0 -1
  285. package/lib/id-compressor/sessions.d.ts +0 -115
  286. package/lib/id-compressor/sessions.d.ts.map +0 -1
  287. package/lib/id-compressor/sessions.js +0 -290
  288. package/lib/id-compressor/sessions.js.map +0 -1
  289. package/lib/id-compressor/utilities.d.ts +0 -52
  290. package/lib/id-compressor/utilities.d.ts.map +0 -1
  291. package/lib/id-compressor/utilities.js +0 -151
  292. package/lib/id-compressor/utilities.js.map +0 -1
  293. package/src/id-compressor/README.md +0 -3
  294. package/src/id-compressor/appendOnlySortedMap.ts +0 -366
  295. package/src/id-compressor/finalSpace.ts +0 -67
  296. package/src/id-compressor/idCompressor.ts +0 -630
  297. package/src/id-compressor/identifiers.ts +0 -42
  298. package/src/id-compressor/index.ts +0 -26
  299. package/src/id-compressor/persistanceUtilities.ts +0 -58
  300. package/src/id-compressor/sessionSpaceNormalizer.ts +0 -83
  301. package/src/id-compressor/sessions.ts +0 -405
  302. package/src/id-compressor/utilities.ts +0 -190
@@ -3,7 +3,11 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { MonitoringContext, UsageError } from "@fluidframework/telemetry-utils";
6
+ import {
7
+ MonitoringContext,
8
+ UsageError,
9
+ validatePrecondition,
10
+ } from "@fluidframework/telemetry-utils";
7
11
  import { IContainerRuntimeMetadata } from "../summary";
8
12
  import {
9
13
  nextGCVersion,
@@ -11,9 +15,7 @@ import {
11
15
  defaultSessionExpiryDurationMs,
12
16
  disableTombstoneKey,
13
17
  GCFeatureMatrix,
14
- gcSweepGenerationOptionName,
15
18
  gcTestModeKey,
16
- gcTombstoneGenerationOptionName,
17
19
  GCVersion,
18
20
  gcVersionUpgradeToV4Key,
19
21
  IGarbageCollectorConfigs,
@@ -26,9 +28,11 @@ import {
26
28
  stableGCVersion,
27
29
  throwOnTombstoneLoadOverrideKey,
28
30
  throwOnTombstoneUsageKey,
29
- gcThrowOnTombstoneLoadOptionName,
31
+ gcDisableThrowOnTombstoneLoadOptionName,
32
+ defaultSweepGracePeriodMs,
33
+ gcGenerationOptionName,
30
34
  } from "./gcDefinitions";
31
- import { getGCVersion, shouldAllowGcSweep, shouldAllowGcTombstoneEnforcement } from "./gcHelpers";
35
+ import { getGCVersion, shouldAllowGcSweep } from "./gcHelpers";
32
36
 
33
37
  /**
34
38
  * Generates configurations for the Garbage Collector that it uses to determine what to run and how.
@@ -71,14 +75,6 @@ export function generateGCConfigs(
71
75
  createParams.metadata?.sweepTimeoutMs ?? computeSweepTimeout(sessionExpiryTimeoutMs); // Backfill old documents that didn't persist this
72
76
  persistedGcFeatureMatrix = createParams.metadata?.gcFeatureMatrix;
73
77
  } else {
74
- const tombstoneGeneration = createParams.gcOptions[gcTombstoneGenerationOptionName];
75
- const sweepGeneration = createParams.gcOptions[gcSweepGenerationOptionName];
76
-
77
- // Sweep should not be enabled (via sweepGeneration value) without enabling GC mark phase.
78
- if (sweepGeneration !== undefined && createParams.gcOptions.gcAllowed === false) {
79
- throw new UsageError("GC sweep phase cannot be enabled without enabling GC mark phase");
80
- }
81
-
82
78
  // This Test Override only applies for new containers
83
79
  const testOverrideSweepTimeoutMs = mc.config.getNumber(
84
80
  "Fluid.GarbageCollection.TestOverride.SweepTimeoutMs",
@@ -95,18 +91,18 @@ export function generateGCConfigs(
95
91
  }
96
92
  sweepTimeoutMs = testOverrideSweepTimeoutMs ?? computeSweepTimeout(sessionExpiryTimeoutMs);
97
93
 
98
- if (tombstoneGeneration !== undefined || sweepGeneration !== undefined) {
99
- persistedGcFeatureMatrix = {
100
- tombstoneGeneration,
101
- sweepGeneration,
102
- };
94
+ const gcGeneration = createParams.gcOptions[gcGenerationOptionName];
95
+ if (gcGeneration !== undefined) {
96
+ persistedGcFeatureMatrix = { gcGeneration };
103
97
  }
104
98
  }
105
99
 
106
- // Is sweepEnabled for this document?
107
- const sweepEnabled = shouldAllowGcSweep(
108
- persistedGcFeatureMatrix ?? {} /* persistedGenerations */,
109
- createParams.gcOptions[gcSweepGenerationOptionName] /* currentGeneration */,
100
+ // The persisted GC generation must indicate Sweep is allowed for this document,
101
+ // according to the GC Generation option provided this session.
102
+ // Note that if no generation option is provided, Sweep is allowed for any document.
103
+ const sweepAllowed = shouldAllowGcSweep(
104
+ persistedGcFeatureMatrix ?? {} /* featureMatrix */,
105
+ createParams.gcOptions[gcGenerationOptionName] /* currentGeneration */,
110
106
  );
111
107
 
112
108
  // If version upgrade is not enabled, fall back to the stable GC version.
@@ -123,27 +119,30 @@ export function generateGCConfigs(
123
119
  * Whether GC should run or not. The following conditions have to be met to run sweep:
124
120
  * 1. GC should be enabled for this container.
125
121
  * 2. GC should not be disabled via disableGC GC option.
126
- * 3. The current GC version should be greater of equal to the GC version in the base snapshot.
127
- * These conditions can be overridden via runGCKey feature flag.
122
+ * 3. The current GC version should be greater or equal to the GC version in the base snapshot.
123
+ *
124
+ * These conditions can be overridden via the RunGC feature flag.
128
125
  */
129
126
  const shouldRunGC =
130
127
  mc.config.getBoolean(runGCKey) ??
131
128
  (gcEnabled && !createParams.gcOptions.disableGC && isGCVersionUpToDate);
132
129
 
133
130
  /**
134
- * Whether sweep should run or not. The following conditions have to be met to run sweep:
131
+ * Whether sweep should run or not. This refers to whether Tombstones should fail on load and whether
132
+ * sweep-ready nodes should be deleted.
135
133
  *
136
- * 1. Overall GC or mark phase must be enabled (this.configs.shouldRunGC).
137
- * 2. Sweep timeout should be available. Without this, we wouldn't know when an object should be deleted.
138
- * 3. The driver must implement the policy limiting the age of snapshots used for loading. Otherwise
139
- * the Sweep Timeout calculation is not valid. We use the persisted value to ensure consistency over time.
140
- * 4. Sweep should be enabled for this container. This can be overridden via runSweep
141
- * feature flag.
134
+ * Assuming overall GC is enabled and sweepTimeout is provided, the following conditions have to be met to run sweep:
135
+ *
136
+ * 1. Sweep should be enabled for this container.
137
+ * 2. Sweep should be enabled for this session.
138
+ *
139
+ * These conditions can be overridden via the RunSweep feature flag.
142
140
  */
143
141
  const shouldRunSweep =
144
- shouldRunGC &&
145
- sweepTimeoutMs !== undefined &&
146
- (mc.config.getBoolean(runSweepKey) ?? sweepEnabled);
142
+ !shouldRunGC || sweepTimeoutMs === undefined
143
+ ? false
144
+ : mc.config.getBoolean(runSweepKey) ??
145
+ (sweepAllowed && createParams.gcOptions.enableGCSweep === true);
147
146
 
148
147
  // Override inactive timeout if test config or gc options to override it is set.
149
148
  const inactiveTimeoutMs =
@@ -159,46 +158,45 @@ export function generateGCConfigs(
159
158
  // Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
160
159
  const testMode =
161
160
  mc.config.getBoolean(gcTestModeKey) ?? createParams.gcOptions.runGCInTestMode === true;
162
- // Whether we are running in tombstone mode. This is enabled by default if sweep won't run. It can be disabled
163
- // via feature flags.
164
- const tombstoneMode = !shouldRunSweep && mc.config.getBoolean(disableTombstoneKey) !== true;
161
+ // Whether we are running in tombstone mode. If disabled, tombstone data will not be written to or read from snapshots,
162
+ // and objects will not be marked as tombstoned even if they pass to the "TombstoneReady" state during the session.
163
+ const tombstoneMode = mc.config.getBoolean(disableTombstoneKey) !== true;
165
164
  const runFullGC = createParams.gcOptions.runFullGC;
166
165
 
166
+ const sweepGracePeriodMs =
167
+ createParams.gcOptions.sweepGracePeriodMs ?? defaultSweepGracePeriodMs;
168
+ validatePrecondition(sweepGracePeriodMs >= 0, "sweepGracePeriodMs must be non-negative", {
169
+ sweepGracePeriodMs,
170
+ });
171
+
167
172
  const throwOnInactiveLoad: boolean | undefined = createParams.gcOptions.throwOnInactiveLoad;
168
- const tombstoneEnforcementAllowed = shouldAllowGcTombstoneEnforcement(
169
- createParams.metadata?.gcFeatureMatrix?.tombstoneGeneration /* persisted */,
170
- createParams.gcOptions[gcTombstoneGenerationOptionName] /* current */,
171
- );
172
173
 
173
174
  const throwOnTombstoneLoadConfig =
174
175
  mc.config.getBoolean(throwOnTombstoneLoadOverrideKey) ??
175
- createParams.gcOptions[gcThrowOnTombstoneLoadOptionName] ??
176
- false;
176
+ createParams.gcOptions[gcDisableThrowOnTombstoneLoadOptionName] !== true;
177
177
  const throwOnTombstoneLoad =
178
- throwOnTombstoneLoadConfig &&
179
- tombstoneEnforcementAllowed &&
180
- !createParams.isSummarizerClient;
178
+ throwOnTombstoneLoadConfig && sweepAllowed && !createParams.isSummarizerClient;
181
179
  const throwOnTombstoneUsage =
182
180
  mc.config.getBoolean(throwOnTombstoneUsageKey) === true &&
183
- tombstoneEnforcementAllowed &&
181
+ sweepAllowed &&
184
182
  !createParams.isSummarizerClient;
185
183
 
186
184
  return {
187
- gcEnabled,
188
- sweepEnabled,
189
- shouldRunGC,
190
- shouldRunSweep,
185
+ gcEnabled, // For this document
186
+ sweepEnabled: sweepAllowed, // For this document (based on current GC Generation option)
187
+ shouldRunGC, // For this session
188
+ shouldRunSweep, // For this session
191
189
  runFullGC,
192
190
  testMode,
193
191
  tombstoneMode,
194
192
  sessionExpiryTimeoutMs,
195
193
  sweepTimeoutMs,
194
+ sweepGracePeriodMs,
196
195
  inactiveTimeoutMs,
197
196
  persistedGcFeatureMatrix,
198
197
  gcVersionInBaseSnapshot,
199
198
  gcVersionInEffect,
200
199
  throwOnInactiveLoad,
201
- tombstoneEnforcementAllowed,
202
200
  throwOnTombstoneLoad,
203
201
  throwOnTombstoneUsage,
204
202
  };
@@ -20,9 +20,10 @@ import {
20
20
  IRefreshSummaryResult,
21
21
  } from "../summary";
22
22
  import { RuntimeHeaderData } from "../containerRuntime";
23
+ import { ContainerRuntimeGCMessage } from "../messageTypes";
23
24
 
24
25
  /**
25
- * @public
26
+ * @alpha
26
27
  */
27
28
  export type GCVersion = number;
28
29
 
@@ -32,27 +33,25 @@ export const stableGCVersion: GCVersion = 3;
32
33
  export const nextGCVersion: GCVersion = 4;
33
34
 
34
35
  /**
35
- * This undocumented GC Option (on ContainerRuntime Options) allows an app to disable enforcing GC on old documents by incrementing this value
36
+ * This undocumented GC Option (on ContainerRuntime Options) allows an app to disable throwing an error when tombstone
37
+ * object is loaded (requested), merely logging a message instead.
36
38
  *
37
- * If unset, GC Tombstone phase will operate as otherwise configured
38
- * Otherwise, only enforce GC Tombstone if the passed in value matches the persisted value
39
+ * By default, attempting to load a Tombstoned object will result in an error.
39
40
  */
40
- export const gcTombstoneGenerationOptionName = "gcTombstoneGeneration";
41
+ export const gcDisableThrowOnTombstoneLoadOptionName = "gcDisableThrowOnTombstoneLoad";
41
42
 
42
43
  /**
43
- * This undocumented GC Option (on ContainerRuntime Options) allows an app to enable throwing an error when tombstone
44
- * object is loaded (requested).
45
- */
46
- export const gcThrowOnTombstoneLoadOptionName = "gcThrowOnTombstoneLoad";
47
-
48
- /**
49
- * This GC Option (on ContainerRuntime Options) allows an app to disable GC Sweep on old documents by incrementing this value.
44
+ * This undocumented GC Option (on ContainerRuntime Options) allows configuring which documents can have Sweep enabled.
45
+ * This provides a way to disable both Tombstone Enforcement and Sweep.
50
46
  *
51
- * If unset altogether, Sweep will be disabled.
52
- * If 0 is passed in, Sweep will be enabled for any document with gcSweepGeneration OR gcTombstoneGeneration as 0.
53
- * If any other number is passed in, Sweep will be enabled only for documents with the same value persisted.
47
+ * If unset, Tombstone Enforcement + Sweep will operate as otherwise configured.
48
+ * Otherwise, the Sweep Phase will be disabled for documents where persisted value doesn't match what is passed into this session.
49
+ * This provides a way to disallow Sweep for old documents that may be too difficult for an app to repair,
50
+ * in case a bug is found that violates GC's assumptions.
51
+ *
52
+ * @see GCFeatureMatrix (gcGeneration)
54
53
  */
55
- export const gcSweepGenerationOptionName = "gcSweepGeneration";
54
+ export const gcGenerationOptionName = "gcGeneration";
56
55
 
57
56
  /** Config key to turn GC on / off. */
58
57
  export const runGCKey = "Fluid.GarbageCollection.RunGC";
@@ -62,8 +61,6 @@ export const runSweepKey = "Fluid.GarbageCollection.RunSweep";
62
61
  export const gcTestModeKey = "Fluid.GarbageCollection.GCTestMode";
63
62
  /** Config key to expire a session after a set period of time. Defaults to true. */
64
63
  export const runSessionExpiryKey = "Fluid.GarbageCollection.RunSessionExpiry";
65
- /** Config key to turn GC sweep log off. */
66
- export const disableSweepLogKey = "Fluid.GarbageCollection.DisableSweepLog";
67
64
  /** Config key to disable the tombstone feature, i.e., tombstone information is not read / written into summary. */
68
65
  export const disableTombstoneKey = "Fluid.GarbageCollection.DisableTombstone";
69
66
  /** Config key to override throwing an error when tombstone object is loaded (requested). */
@@ -91,28 +88,33 @@ export const maxSnapshotCacheExpiryMs = 5 * oneDayMs;
91
88
 
92
89
  export const defaultInactiveTimeoutMs = 7 * oneDayMs; // 7 days
93
90
  export const defaultSessionExpiryDurationMs = 30 * oneDayMs; // 30 days
91
+ export const defaultSweepGracePeriodMs = 1 * oneDayMs; // 1 day
94
92
 
95
93
  /**
96
- * @see IGCMetadata.gcFeatureMatrix
97
- * @public
94
+ * @see IGCMetadata.gcFeatureMatrix and @see gcGenerationOptionName
95
+ * @alpha
98
96
  */
99
- export interface GCFeatureMatrix {
100
- /**
101
- * The Tombstone Generation value in effect when this file was created.
102
- * Gives a way for an app to disqualify old files from GC Tombstone enforcement.
103
- * Provided via Container Runtime Options.
104
- */
105
- tombstoneGeneration?: number;
106
- /**
107
- * The Sweep Generation value in effect when this file was created.
108
- * Gives a way for an app to disqualify old files from GC Sweep.
109
- * Provided via Container Runtime Options.
110
- */
111
- sweepGeneration?: number;
112
- }
97
+ export type GCFeatureMatrix =
98
+ | {
99
+ /**
100
+ * The GC Generation value in effect when this file was created.
101
+ * Gives a way for an app to disqualify old files from GC Sweep.
102
+ * Provided via Container Runtime Options.
103
+ */
104
+ gcGeneration?: number;
105
+ /** Deprecated property from legacy type. Will not be set concurrently with gcGeneration */
106
+ tombstoneGeneration?: undefined;
107
+ }
108
+ | {
109
+ /**
110
+ * The Tombstone Generation value in effect when this file was created.
111
+ * Legacy - new containers would get gcGeneration instead (if anything)
112
+ */
113
+ tombstoneGeneration: number;
114
+ };
113
115
 
114
116
  /**
115
- * @public
117
+ * @alpha
116
118
  */
117
119
  export interface IGCMetadata {
118
120
  /**
@@ -141,7 +143,7 @@ export interface IGCMetadata {
141
143
  * - True means sweep phase is enabled.
142
144
  * - False means sweep phase is disabled. If GC is disabled as per gcFeature, sweep is also disabled.
143
145
  *
144
- * @deprecated use GCFeatureMatrix.sweepGeneration instead. @see GCFeatureMatrix.sweepGeneration
146
+ * @deprecated use GCFeatureMatrix.gcGeneration instead. @see GCFeatureMatrix.gcGeneration
145
147
  */
146
148
  readonly sweepEnabled?: boolean;
147
149
  /** If this is present, the session for this container will expire after this time and the container will close */
@@ -151,10 +153,10 @@ export interface IGCMetadata {
151
153
  }
152
154
 
153
155
  /**
154
- * The statistics of the system state after a garbage collection run.
155
- * @public
156
+ * The statistics of the system state after a garbage collection mark phase run.
157
+ * @alpha
156
158
  */
157
- export interface IGCStats {
159
+ export interface IMarkPhaseStats {
158
160
  /** The number of nodes in the container. */
159
161
  nodeCount: number;
160
162
  /** The number of data stores in the container. */
@@ -175,9 +177,34 @@ export interface IGCStats {
175
177
  updatedAttachmentBlobCount: number;
176
178
  }
177
179
 
180
+ /**
181
+ * The statistics of the system state after a garbage collection sweep phase run.
182
+ * @alpha
183
+ */
184
+ export interface ISweepPhaseStats {
185
+ /** The number of nodes in the lifetime of the container. */
186
+ lifetimeNodeCount: number;
187
+ /** The number of data stores in the lifetime of the container. */
188
+ lifetimeDataStoreCount: number;
189
+ /** The number of attachment blobs in the lifetime of the container. */
190
+ lifetimeAttachmentBlobCount: number;
191
+ /** The number of deleted nodes in the container. */
192
+ deletedNodeCount: number;
193
+ /** The number of deleted data stores in the container. */
194
+ deletedDataStoreCount: number;
195
+ /** The number of deleted attachment blobs in the container. */
196
+ deletedAttachmentBlobCount: number;
197
+ }
198
+
199
+ /**
200
+ * The statistics of the system state after a garbage collection run.
201
+ * @alpha
202
+ */
203
+ export interface IGCStats extends IMarkPhaseStats, ISweepPhaseStats {}
204
+
178
205
  /**
179
206
  * The types of GC nodes in the GC reference graph.
180
- * @public
207
+ * @alpha
181
208
  */
182
209
  export const GCNodeType = {
183
210
  // Nodes that are for data stores.
@@ -191,10 +218,41 @@ export const GCNodeType = {
191
218
  };
192
219
 
193
220
  /**
194
- * @public
221
+ * @alpha
195
222
  */
196
223
  export type GCNodeType = (typeof GCNodeType)[keyof typeof GCNodeType];
197
224
 
225
+ /**
226
+ * The type of a garbage collection message.
227
+ * @internal
228
+ */
229
+ export const GarbageCollectionMessageType = {
230
+ /** Message sent directing GC to delete the given nodes */
231
+ Sweep: "Sweep",
232
+ } as const;
233
+
234
+ /**
235
+ * @internal
236
+ */
237
+ export type GarbageCollectionMessageType =
238
+ (typeof GarbageCollectionMessageType)[keyof typeof GarbageCollectionMessageType];
239
+
240
+ /**
241
+ * The garbage collection sweep message.
242
+ * @internal
243
+ */
244
+ export interface ISweepMessage {
245
+ type: "Sweep";
246
+ // The ids of nodes that are deleted.
247
+ deletedNodeIds: string[];
248
+ }
249
+
250
+ /**
251
+ * Type for a message to be used for sending / received garbage collection messages.
252
+ * @internal
253
+ */
254
+ export type GarbageCollectionMessage = ISweepMessage;
255
+
198
256
  /**
199
257
  * Defines the APIs for the runtime object to be passed to the garbage collector.
200
258
  */
@@ -204,17 +262,17 @@ export interface IGarbageCollectionRuntime {
204
262
  /** Returns the garbage collection data of the runtime. */
205
263
  getGCData(fullGC?: boolean): Promise<IGarbageCollectionData>;
206
264
  /** After GC has run, called to notify the runtime of routes that are used in it. */
207
- updateUsedRoutes(usedRoutes: string[]): void;
265
+ updateUsedRoutes(usedRoutes: readonly string[]): void;
208
266
  /** After GC has run, called to notify the runtime of routes that are unused in it. */
209
- updateUnusedRoutes(unusedRoutes: string[]): void;
267
+ updateUnusedRoutes(unusedRoutes: readonly string[]): void;
210
268
  /**
211
269
  * After GC has run and identified nodes that are sweep ready, called to delete the sweep ready nodes. The runtime
212
270
  * should return the routes of nodes that were deleted.
213
271
  * @param sweepReadyRoutes - The routes of nodes that are sweep ready and should be deleted.
214
272
  */
215
- deleteSweepReadyNodes(sweepReadyRoutes: string[]): string[];
273
+ deleteSweepReadyNodes(sweepReadyRoutes: readonly string[]): readonly string[];
216
274
  /** Called to notify the runtime of routes that are tombstones. */
217
- updateTombstonedRoutes(tombstoneRoutes: string[]): void;
275
+ updateTombstonedRoutes(tombstoneRoutes: readonly string[]): void;
218
276
  /** Returns a referenced timestamp to be used to track unreferenced nodes. */
219
277
  getCurrentReferenceTimestampMs(): number | undefined;
220
278
  /** Returns the type of the GC node. */
@@ -274,6 +332,8 @@ export interface IGarbageCollector {
274
332
  ): void;
275
333
  /** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */
276
334
  addedOutboundReference(fromNodePath: string, toNodePath: string): void;
335
+ /** Called to process a garbage collection message. */
336
+ processMessage(message: ContainerRuntimeGCMessage, local: boolean): void;
277
337
  /** Returns true if this node has been deleted by GC during sweep phase. */
278
338
  isNodeDeleted(nodePath: string): boolean;
279
339
  setConnectionState(connected: boolean, clientId?: string): void;
@@ -294,10 +354,11 @@ export interface IGarbageCollectorCreateParams {
294
354
  readonly getLastSummaryTimestampMs: () => number | undefined;
295
355
  readonly readAndParseBlob: ReadAndParseBlob;
296
356
  readonly activeConnection: () => boolean;
357
+ readonly submitMessage: (message: ContainerRuntimeGCMessage) => void;
297
358
  }
298
359
 
299
360
  /**
300
- * @public
361
+ * @alpha
301
362
  */
302
363
  export interface IGCRuntimeOptions {
303
364
  /**
@@ -306,7 +367,7 @@ export interface IGCRuntimeOptions {
306
367
  * GC has mark phase and sweep phase. In mark phase, unreferenced objects are identified
307
368
  * and marked as such in the summary. This option enables the mark phase.
308
369
  * In sweep phase, unreferenced objects are eventually deleted from the container if they meet certain conditions.
309
- * Sweep phase can be enabled using the "gcSweepGeneration" option.
370
+ * Sweep phase can be enabled using the "enableGCSweep" option.
310
371
  *
311
372
  * Note: This setting is persisted in the container's summary and cannot be changed.
312
373
  */
@@ -318,6 +379,17 @@ export interface IGCRuntimeOptions {
318
379
  */
319
380
  disableGC?: boolean;
320
381
 
382
+ /**
383
+ * Flag that if true, will enable the full Sweep Phase of garbage collection for this session,
384
+ * where Tombstoned objects are permanently deleted from the container.
385
+ *
386
+ * IMPORTANT: This only applies if this document is allowed to run Sweep Phase.
387
+ *
388
+ * Current default behavior is for Sweep Phase not to delete Tombstoned objects,
389
+ * but merely to prevent them from being loaded.
390
+ */
391
+ enableGCSweep?: true;
392
+
321
393
  /**
322
394
  * Flag that will bypass optimizations and generate GC data for all nodes irrespective of whether a node
323
395
  * changed or not.
@@ -331,6 +403,13 @@ export interface IGCRuntimeOptions {
331
403
  */
332
404
  sessionExpiryTimeoutMs?: number;
333
405
 
406
+ /**
407
+ * Delay between when Tombstone should run and when the object should be deleted.
408
+ * This grace period gives a chance to intervene to recover if needed, before Sweep deletes the object.
409
+ * If not present, a default (non-zero) value will be used.
410
+ */
411
+ sweepGracePeriodMs?: number;
412
+
334
413
  /**
335
414
  * Allows additional GC options to be passed.
336
415
  */
@@ -369,15 +448,21 @@ export interface IGarbageCollectorConfigs {
369
448
  readonly sessionExpiryTimeoutMs: number | undefined;
370
449
  /** The time after which an unreferenced node is ready to be swept. */
371
450
  readonly sweepTimeoutMs: number | undefined;
451
+ /**
452
+ * The delay between tombstone and sweep. Not persisted, so concurrent sessions may use different values.
453
+ * Sweep is implemented in an eventually-consistent way so this is acceptable.
454
+ */
455
+ readonly sweepGracePeriodMs: number;
372
456
  /** The time after which an unreferenced node is inactive. */
373
457
  readonly inactiveTimeoutMs: number;
374
458
  /** Tracks whether GC should run in test mode. In this mode, unreferenced objects are deleted immediately. */
375
459
  readonly testMode: boolean;
376
460
  /**
377
- * Tracks whether GC should run in tombstone mode. In this mode, sweep ready objects are marked as tombstones.
461
+ * Tracks whether GC should run in tombstone mode. In this mode, objects are marked as tombstones as a step along the
462
+ * way before they are fully deleted.
378
463
  * In interactive (non-summarizer) clients, tombstone objects behave as if they are deleted, i.e., access to them
379
- * is not allowed. However, these objects can be accessed after referencing them first. It is used as a staging
380
- * step for sweep where accidental sweep ready objects can be recovered.
464
+ * is not allowed. However, these objects can be accessed after referencing them first. It is used as a "warning"
465
+ * step before sweep, where objects wrongly marked as unreferenced can be recovered.
381
466
  */
382
467
  readonly tombstoneMode: boolean;
383
468
  /** @see GCFeatureMatrix. */
@@ -388,8 +473,6 @@ export interface IGarbageCollectorConfigs {
388
473
  readonly gcVersionInEffect: GCVersion;
389
474
  /** It is easier for users to diagnose InactiveObject usage if we throw on load, which this option enables */
390
475
  readonly throwOnInactiveLoad: boolean | undefined;
391
- /** If false, loading or using a Tombstoned object should merely log, not fail */
392
- readonly tombstoneEnforcementAllowed: boolean;
393
476
  /** If true, throw an error when a tombstone data store is retrieved */
394
477
  readonly throwOnTombstoneLoad: boolean;
395
478
  /** If true, throw an error when a tombstone data store is used. */
@@ -402,6 +485,8 @@ export const UnreferencedState = {
402
485
  Active: "Active",
403
486
  /** The node is inactive, i.e., it should not become referenced. */
404
487
  Inactive: "Inactive",
488
+ /** The node is ready to be tombstoned */
489
+ TombstoneReady: "TombstoneReady",
405
490
  /** The node is ready to be deleted by the sweep phase. */
406
491
  SweepReady: "SweepReady",
407
492
  } as const;
@@ -28,64 +28,34 @@ export function getGCVersion(metadata?: IGCMetadata): GCVersion {
28
28
  }
29
29
 
30
30
  /**
31
- * Indicates whether Tombstone Enforcement is allowed for this document based on the current/persisted
32
- * TombstoneGeneration values
33
- *
34
- * In order to protect old documents that were created at a time when known bugs exist that violate GC's invariants
35
- * such that enforcing GC Tombstone (Failing on Tombstone load/usage) would cause legitimate data loss,
36
- * the container author may increment the generation value for Tombstone such that containers created
37
- * with a different value will not be subjected to GC enforcement.
38
- *
39
- * If no generation is provided at runtime, this defaults to return true to maintain expected default behavior
40
- *
41
- * @param persistedGeneration - The persisted tombstoneGeneration value
42
- * @param currentGeneration - The current app-provided tombstoneGeneration value
43
- * @returns true if GC Tombstone enforcement (Fail on Tombstone load/usage) should be allowed for this document
44
- */
45
- export function shouldAllowGcTombstoneEnforcement(
46
- persistedGeneration: number | undefined,
47
- currentGeneration: number | undefined,
48
- ): boolean {
49
- // If no Generation value is provided for this session, then we should default to letting Tombstone feature behave as intended.
50
- if (currentGeneration === undefined) {
51
- return true;
52
- }
53
- return persistedGeneration === currentGeneration;
54
- }
55
-
56
- /**
57
- * Indicates whether Sweep is allowed for this document based on the GC Feature Matrix and current SweepGeneration
31
+ * Indicates whether Sweep is allowed for this document based on the persisted GC Feature Matrix and current gcGeneration.
32
+ * This applies to the entire Sweep Phase the same - both Tombstone Enforcement (i.e. should loading a Tombstone fail?) and Deletion.
58
33
  *
59
34
  * In order to protect old documents that were created at a time when known bugs exist that violate GC's invariants
60
35
  * such that enforcing GC Sweep would cause legitimate data loss, the container author may increment the generation value for Sweep
61
36
  * such that containers created with a different value will not be subjected to GC Sweep.
62
37
  *
63
- * If no generation is provided, Sweep will be disabled.
64
- * Passing 0 is a special case: Sweep will be enabled for any document with gcSweepGeneration OR gcTombstoneGeneration as 0.
38
+ * If no generation is provided, Sweep will be enabled for all documents.
39
+ *
40
+ * For backwards compatibility, the current generation value is also compared against the persisted gcTombstoneGeneration if present.
65
41
  *
66
- * @param persistedGenerations - The persisted sweep/tombstone generations from the GC Feature Matrix
67
- * @param currentGeneration - The current app-provided sweepGeneration value
42
+ * @param featureMatrix - The GC Feature Matrix, containing the persisted generation value
43
+ * @param currentGeneration - The current app-provided gcGeneration value
68
44
  * @returns true if GC Sweep should be allowed for this document
69
45
  */
70
46
  export function shouldAllowGcSweep(
71
- persistedGenerations: Pick<GCFeatureMatrix, "sweepGeneration" | "tombstoneGeneration">,
47
+ featureMatrix: GCFeatureMatrix,
72
48
  currentGeneration: number | undefined,
73
49
  ): boolean {
74
- // If no Generation value is provided for this session, default to false
50
+ // If no Generation value is provided for this session, default to true
75
51
  if (currentGeneration === undefined) {
76
- return false;
52
+ return true;
77
53
  }
78
54
 
79
- // 0 is a special case: It matches both SweepGeneration and TombstoneGeneration
80
- // This is an optimistic measure to maximize coverage of GC Sweep if no bumps to TombstoneGeneration are needed before enabling Sweep.
81
- if (currentGeneration === 0) {
82
- return (
83
- persistedGenerations.sweepGeneration === 0 ||
84
- persistedGenerations.tombstoneGeneration === 0
85
- );
86
- }
55
+ // tombstoneGeneration is the predecessor and needs to be supported for back-compat reasons
56
+ const targetGeneration = featureMatrix.tombstoneGeneration ?? featureMatrix.gcGeneration;
87
57
 
88
- return persistedGenerations.sweepGeneration === currentGeneration;
58
+ return currentGeneration === targetGeneration;
89
59
  }
90
60
 
91
61
  /**
@@ -151,19 +121,12 @@ export function concatGarbageCollectionStates(
151
121
  /**
152
122
  * Helper function that clones the GC data.
153
123
  * @param gcData - The GC data to clone.
154
- * @param filter - Optional function to filter out node ids not to be included in the cloned GC data. Returns
155
- * true to filter out nodes.
156
124
  * @returns a clone of the given GC data.
157
125
  */
158
- export function cloneGCData(
159
- gcData: IGarbageCollectionData,
160
- filter?: (id: string) => boolean,
161
- ): IGarbageCollectionData {
126
+ export function cloneGCData(gcData: IGarbageCollectionData): IGarbageCollectionData {
162
127
  const clonedGCNodes: { [id: string]: string[] } = {};
163
128
  for (const [id, outboundRoutes] of Object.entries(gcData.gcNodes)) {
164
- if (filter?.(id) !== true) {
165
- clonedGCNodes[id] = Array.from(outboundRoutes);
166
- }
129
+ clonedGCNodes[id] = Array.from(outboundRoutes);
167
130
  }
168
131
  return {
169
132
  gcNodes: clonedGCNodes,
@@ -303,3 +266,19 @@ export function unpackChildNodesGCDetails(gcDetails: IGarbageCollectionDetailsBa
303
266
  export function trimLeadingAndTrailingSlashes(str: string) {
304
267
  return str.replace(/^\/+|\/+$/g, "");
305
268
  }
269
+
270
+ /**
271
+ * Utility to implement compat behaviors given an unknown message type
272
+ * The parameters are typed to support compile-time enforcement of handling all known types/behaviors
273
+ *
274
+ * @param _unknownGCMessageType - Typed as never to ensure all known types have been
275
+ * handled before calling this function (e.g. in a switch statement).
276
+ * @param compatBehavior - Typed redundantly with CompatModeBehavior to ensure handling is added when updating that type
277
+ */
278
+ export function compatBehaviorAllowsGCMessageType(
279
+ _unknownGCMessageType: never,
280
+ compatBehavior: "Ignore" | "FailToProcess" | undefined,
281
+ ): boolean {
282
+ // undefined defaults to same behavior as "FailToProcess"
283
+ return compatBehavior === "Ignore";
284
+ }