@fluidframework/container-runtime 2.1.0 → 2.2.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 (196) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +2 -2
  3. package/api-report/container-runtime.legacy.alpha.api.md +4 -3
  4. package/container-runtime.test-files.tar +0 -0
  5. package/dist/batchTracker.d.ts.map +1 -1
  6. package/dist/batchTracker.js.map +1 -1
  7. package/dist/blobManager/blobManager.d.ts.map +1 -1
  8. package/dist/blobManager/blobManager.js +9 -0
  9. package/dist/blobManager/blobManager.js.map +1 -1
  10. package/dist/channelCollection.d.ts +0 -14
  11. package/dist/channelCollection.d.ts.map +1 -1
  12. package/dist/channelCollection.js +2 -12
  13. package/dist/channelCollection.js.map +1 -1
  14. package/dist/containerRuntime.d.ts +34 -6
  15. package/dist/containerRuntime.d.ts.map +1 -1
  16. package/dist/containerRuntime.js +176 -81
  17. package/dist/containerRuntime.js.map +1 -1
  18. package/dist/dataStoreContext.d.ts +9 -18
  19. package/dist/dataStoreContext.d.ts.map +1 -1
  20. package/dist/dataStoreContext.js +40 -78
  21. package/dist/dataStoreContext.js.map +1 -1
  22. package/dist/gc/garbageCollection.d.ts +0 -6
  23. package/dist/gc/garbageCollection.d.ts.map +1 -1
  24. package/dist/gc/garbageCollection.js +23 -66
  25. package/dist/gc/garbageCollection.js.map +1 -1
  26. package/dist/gc/gcConfigs.d.ts.map +1 -1
  27. package/dist/gc/gcConfigs.js +11 -34
  28. package/dist/gc/gcConfigs.js.map +1 -1
  29. package/dist/gc/gcDefinitions.d.ts +9 -52
  30. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  31. package/dist/gc/gcDefinitions.js +3 -23
  32. package/dist/gc/gcDefinitions.js.map +1 -1
  33. package/dist/gc/gcHelpers.d.ts.map +1 -1
  34. package/dist/gc/gcHelpers.js +2 -6
  35. package/dist/gc/gcHelpers.js.map +1 -1
  36. package/dist/gc/gcSummaryStateTracker.d.ts +1 -1
  37. package/dist/gc/gcSummaryStateTracker.d.ts.map +1 -1
  38. package/dist/gc/gcSummaryStateTracker.js +4 -8
  39. package/dist/gc/gcSummaryStateTracker.js.map +1 -1
  40. package/dist/gc/gcTelemetry.d.ts +1 -9
  41. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  42. package/dist/gc/gcTelemetry.js +3 -25
  43. package/dist/gc/gcTelemetry.js.map +1 -1
  44. package/dist/gc/index.d.ts +2 -2
  45. package/dist/gc/index.d.ts.map +1 -1
  46. package/dist/gc/index.js +2 -7
  47. package/dist/gc/index.js.map +1 -1
  48. package/dist/index.d.ts +1 -1
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +1 -2
  51. package/dist/index.js.map +1 -1
  52. package/dist/messageTypes.d.ts +6 -5
  53. package/dist/messageTypes.d.ts.map +1 -1
  54. package/dist/messageTypes.js.map +1 -1
  55. package/dist/metadata.d.ts +9 -1
  56. package/dist/metadata.d.ts.map +1 -1
  57. package/dist/metadata.js +6 -1
  58. package/dist/metadata.js.map +1 -1
  59. package/dist/opLifecycle/index.d.ts +1 -1
  60. package/dist/opLifecycle/index.d.ts.map +1 -1
  61. package/dist/opLifecycle/index.js.map +1 -1
  62. package/dist/opLifecycle/opGroupingManager.d.ts +8 -0
  63. package/dist/opLifecycle/opGroupingManager.d.ts.map +1 -1
  64. package/dist/opLifecycle/opGroupingManager.js +34 -2
  65. package/dist/opLifecycle/opGroupingManager.js.map +1 -1
  66. package/dist/opLifecycle/outbox.d.ts +1 -0
  67. package/dist/opLifecycle/outbox.d.ts.map +1 -1
  68. package/dist/opLifecycle/outbox.js +20 -0
  69. package/dist/opLifecycle/outbox.js.map +1 -1
  70. package/dist/opLifecycle/remoteMessageProcessor.d.ts +34 -15
  71. package/dist/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  72. package/dist/opLifecycle/remoteMessageProcessor.js +59 -46
  73. package/dist/opLifecycle/remoteMessageProcessor.js.map +1 -1
  74. package/dist/packageVersion.d.ts +1 -1
  75. package/dist/packageVersion.js +1 -1
  76. package/dist/packageVersion.js.map +1 -1
  77. package/dist/pendingStateManager.d.ts +28 -27
  78. package/dist/pendingStateManager.d.ts.map +1 -1
  79. package/dist/pendingStateManager.js +143 -112
  80. package/dist/pendingStateManager.js.map +1 -1
  81. package/dist/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  82. package/dist/summary/summarizerNode/summarizerNode.js +5 -1
  83. package/dist/summary/summarizerNode/summarizerNode.js.map +1 -1
  84. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -4
  85. package/dist/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  86. package/dist/summary/summarizerNode/summarizerNodeWithGc.js +16 -15
  87. package/dist/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  88. package/lib/batchTracker.d.ts.map +1 -1
  89. package/lib/batchTracker.js.map +1 -1
  90. package/lib/blobManager/blobManager.d.ts.map +1 -1
  91. package/lib/blobManager/blobManager.js +9 -0
  92. package/lib/blobManager/blobManager.js.map +1 -1
  93. package/lib/channelCollection.d.ts +0 -14
  94. package/lib/channelCollection.d.ts.map +1 -1
  95. package/lib/channelCollection.js +2 -11
  96. package/lib/channelCollection.js.map +1 -1
  97. package/lib/containerRuntime.d.ts +34 -6
  98. package/lib/containerRuntime.d.ts.map +1 -1
  99. package/lib/containerRuntime.js +176 -81
  100. package/lib/containerRuntime.js.map +1 -1
  101. package/lib/dataStoreContext.d.ts +9 -18
  102. package/lib/dataStoreContext.d.ts.map +1 -1
  103. package/lib/dataStoreContext.js +27 -65
  104. package/lib/dataStoreContext.js.map +1 -1
  105. package/lib/gc/garbageCollection.d.ts +0 -6
  106. package/lib/gc/garbageCollection.d.ts.map +1 -1
  107. package/lib/gc/garbageCollection.js +25 -68
  108. package/lib/gc/garbageCollection.js.map +1 -1
  109. package/lib/gc/gcConfigs.d.ts.map +1 -1
  110. package/lib/gc/gcConfigs.js +12 -35
  111. package/lib/gc/gcConfigs.js.map +1 -1
  112. package/lib/gc/gcDefinitions.d.ts +9 -52
  113. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  114. package/lib/gc/gcDefinitions.js +2 -22
  115. package/lib/gc/gcDefinitions.js.map +1 -1
  116. package/lib/gc/gcHelpers.d.ts.map +1 -1
  117. package/lib/gc/gcHelpers.js +2 -6
  118. package/lib/gc/gcHelpers.js.map +1 -1
  119. package/lib/gc/gcSummaryStateTracker.d.ts +1 -1
  120. package/lib/gc/gcSummaryStateTracker.d.ts.map +1 -1
  121. package/lib/gc/gcSummaryStateTracker.js +4 -8
  122. package/lib/gc/gcSummaryStateTracker.js.map +1 -1
  123. package/lib/gc/gcTelemetry.d.ts +1 -9
  124. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  125. package/lib/gc/gcTelemetry.js +3 -24
  126. package/lib/gc/gcTelemetry.js.map +1 -1
  127. package/lib/gc/index.d.ts +2 -2
  128. package/lib/gc/index.d.ts.map +1 -1
  129. package/lib/gc/index.js +2 -2
  130. package/lib/gc/index.js.map +1 -1
  131. package/lib/index.d.ts +1 -1
  132. package/lib/index.d.ts.map +1 -1
  133. package/lib/index.js +1 -1
  134. package/lib/index.js.map +1 -1
  135. package/lib/messageTypes.d.ts +6 -5
  136. package/lib/messageTypes.d.ts.map +1 -1
  137. package/lib/messageTypes.js.map +1 -1
  138. package/lib/metadata.d.ts +9 -1
  139. package/lib/metadata.d.ts.map +1 -1
  140. package/lib/metadata.js +4 -0
  141. package/lib/metadata.js.map +1 -1
  142. package/lib/opLifecycle/index.d.ts +1 -1
  143. package/lib/opLifecycle/index.d.ts.map +1 -1
  144. package/lib/opLifecycle/index.js.map +1 -1
  145. package/lib/opLifecycle/opGroupingManager.d.ts +8 -0
  146. package/lib/opLifecycle/opGroupingManager.d.ts.map +1 -1
  147. package/lib/opLifecycle/opGroupingManager.js +34 -2
  148. package/lib/opLifecycle/opGroupingManager.js.map +1 -1
  149. package/lib/opLifecycle/outbox.d.ts +1 -0
  150. package/lib/opLifecycle/outbox.d.ts.map +1 -1
  151. package/lib/opLifecycle/outbox.js +20 -0
  152. package/lib/opLifecycle/outbox.js.map +1 -1
  153. package/lib/opLifecycle/remoteMessageProcessor.d.ts +34 -15
  154. package/lib/opLifecycle/remoteMessageProcessor.d.ts.map +1 -1
  155. package/lib/opLifecycle/remoteMessageProcessor.js +59 -46
  156. package/lib/opLifecycle/remoteMessageProcessor.js.map +1 -1
  157. package/lib/packageVersion.d.ts +1 -1
  158. package/lib/packageVersion.js +1 -1
  159. package/lib/packageVersion.js.map +1 -1
  160. package/lib/pendingStateManager.d.ts +28 -27
  161. package/lib/pendingStateManager.d.ts.map +1 -1
  162. package/lib/pendingStateManager.js +144 -113
  163. package/lib/pendingStateManager.js.map +1 -1
  164. package/lib/summary/summarizerNode/summarizerNode.d.ts.map +1 -1
  165. package/lib/summary/summarizerNode/summarizerNode.js +5 -1
  166. package/lib/summary/summarizerNode/summarizerNode.js.map +1 -1
  167. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts +3 -4
  168. package/lib/summary/summarizerNode/summarizerNodeWithGc.d.ts.map +1 -1
  169. package/lib/summary/summarizerNode/summarizerNodeWithGc.js +16 -15
  170. package/lib/summary/summarizerNode/summarizerNodeWithGc.js.map +1 -1
  171. package/package.json +22 -31
  172. package/src/batchTracker.ts +4 -2
  173. package/src/blobManager/blobManager.ts +9 -0
  174. package/src/channelCollection.ts +2 -11
  175. package/src/containerRuntime.ts +211 -109
  176. package/src/dataStoreContext.ts +29 -93
  177. package/src/gc/garbageCollection.ts +26 -79
  178. package/src/gc/gcConfigs.ts +12 -45
  179. package/src/gc/gcDefinitions.ts +10 -55
  180. package/src/gc/gcHelpers.ts +10 -8
  181. package/src/gc/gcSummaryStateTracker.ts +6 -9
  182. package/src/gc/gcTelemetry.ts +3 -38
  183. package/src/gc/index.ts +2 -6
  184. package/src/index.ts +0 -1
  185. package/src/messageTypes.ts +12 -11
  186. package/src/metadata.ts +16 -2
  187. package/src/opLifecycle/index.ts +1 -0
  188. package/src/opLifecycle/opGroupingManager.ts +42 -3
  189. package/src/opLifecycle/outbox.ts +30 -0
  190. package/src/opLifecycle/remoteMessageProcessor.ts +98 -62
  191. package/src/packageVersion.ts +1 -1
  192. package/src/pendingStateManager.ts +199 -177
  193. package/src/summary/README.md +31 -28
  194. package/src/summary/summarizerNode/summarizerNode.ts +6 -1
  195. package/src/summary/summarizerNode/summarizerNodeWithGc.ts +20 -43
  196. package/src/summary/summaryFormats.md +25 -22
@@ -69,7 +69,6 @@ import {
69
69
  tagCodeArtifacts,
70
70
  } from "@fluidframework/telemetry-utils/internal";
71
71
 
72
- import { sendGCUnexpectedUsageEvent } from "./gc/index.js";
73
72
  import {
74
73
  // eslint-disable-next-line import/no-deprecated
75
74
  ReadFluidDataStoreAttributes,
@@ -254,9 +253,15 @@ export abstract class FluidDataStoreContext
254
253
  public get tombstoned() {
255
254
  return this._tombstoned;
256
255
  }
257
- /** If true, throw an error when a tombstone data store is used. */
258
- public readonly gcThrowOnTombstoneUsage: boolean;
259
- public readonly gcTombstoneEnforcementAllowed: boolean;
256
+ /**
257
+ * If true, throw an error when a tombstone data store is used.
258
+ * @deprecated NOT SUPPORTED - hardcoded to return false since it's deprecated.
259
+ */
260
+ public readonly gcThrowOnTombstoneUsage: boolean = false;
261
+ /**
262
+ * @deprecated NOT SUPPORTED - hardcoded to return false since it's deprecated.
263
+ */
264
+ public readonly gcTombstoneEnforcementAllowed: boolean = false;
260
265
 
261
266
  /** If true, this means that this data store context and its children have been removed from the runtime */
262
267
  protected deleted: boolean = false;
@@ -333,10 +338,6 @@ export abstract class FluidDataStoreContext
333
338
  */
334
339
  private localChangesTelemetryCount: number;
335
340
 
336
- // The used routes of this node as per the last GC run. This is used to update the used routes of the channel
337
- // if it realizes after GC is run.
338
- private lastUsedRoutes: string[] | undefined;
339
-
340
341
  public readonly id: string;
341
342
  private readonly _containerRuntime: IContainerRuntimeBase;
342
343
  private readonly parentContext: IFluidParentContext;
@@ -399,9 +400,6 @@ export abstract class FluidDataStoreContext
399
400
  this.mc.logger,
400
401
  );
401
402
 
402
- this.gcThrowOnTombstoneUsage = this.parentContext.gcThrowOnTombstoneUsage;
403
- this.gcTombstoneEnforcementAllowed = this.parentContext.gcTombstoneEnforcementAllowed;
404
-
405
403
  // By default, a data store can log maximum 10 local changes telemetry in summarizer.
406
404
  this.localChangesTelemetryCount =
407
405
  this.mc.config.getNumber("Fluid.Telemetry.LocalChangesTelemetryCount") ?? 10;
@@ -570,16 +568,8 @@ export abstract class FluidDataStoreContext
570
568
  ): void {
571
569
  const safeTelemetryProps = extractSafePropertiesFromMessage(message);
572
570
  // On op process, tombstone error is logged in garbage collector. So, set "checkTombstone" to false when calling
573
- // "verifyNotClosed" which logs tombstone errors. Throw error if tombstoned and throwing on load is configured.
571
+ // "verifyNotClosed" which logs tombstone errors.
574
572
  this.verifyNotClosed("process", false /* checkTombstone */, safeTelemetryProps);
575
- if (this.tombstoned && this.gcThrowOnTombstoneUsage) {
576
- throw DataProcessingError.create(
577
- "Context is tombstoned! Call site [process]",
578
- "process",
579
- undefined /* sequencedMessage */,
580
- safeTelemetryProps,
581
- );
582
- }
583
573
 
584
574
  this.summarizerNode.recordChange(message);
585
575
 
@@ -698,17 +688,10 @@ export abstract class FluidDataStoreContext
698
688
 
699
689
  /**
700
690
  * After GC has run, called to notify the data store of routes used in it. These are used for the following:
701
- *
702
691
  * 1. To identify if this data store is being referenced in the document or not.
703
- *
704
692
  * 2. To determine if it needs to re-summarize in case used routes changed since last summary.
705
- *
706
- * 3. These are added to the summary generated by the data store.
707
- *
708
- * 4. To notify child contexts of their used routes. This is done immediately if the data store is loaded.
709
- * Else, it is done when realizing the data store.
710
- *
711
- * 5. To update the timestamp when this data store or any children are marked as unreferenced.
693
+ * 3. To notify child contexts of their used routes. This is done immediately if the data store is loaded.
694
+ * Else, it is done by the data stores's summarizer node when child summarizer nodes are created.
712
695
  *
713
696
  * @param usedRoutes - The routes that are used in this data store.
714
697
  */
@@ -716,18 +699,17 @@ export abstract class FluidDataStoreContext
716
699
  // Update the used routes in this data store's summarizer node.
717
700
  this.summarizerNode.updateUsedRoutes(usedRoutes);
718
701
 
719
- /**
720
- * Store the used routes to update the channel if the data store is not loaded yet. If the used routes changed
721
- * since the previous run, the data store will be loaded during summarize since the used state changed. So, it's
722
- * safe to only store the last used routes.
723
- */
724
- this.lastUsedRoutes = usedRoutes;
725
-
726
- // If we are loaded, call the channel so it can update the used routes of the child contexts.
727
- // If we are not loaded, we will update this when we are realized.
728
- if (this.loaded) {
729
- this.updateChannelUsedRoutes();
702
+ // If the channel doesn't exist yet (data store is not realized), the summarizer node will update it
703
+ // when it creates child nodes.
704
+ if (!this.channel) {
705
+ return;
730
706
  }
707
+
708
+ // Remove the route to this data store, if it exists.
709
+ const usedChannelRoutes = usedRoutes.filter((id: string) => {
710
+ return id !== "/" && id !== "";
711
+ });
712
+ this.channel.updateUsedRoutes(usedChannelRoutes);
731
713
  }
732
714
 
733
715
  /**
@@ -742,31 +724,6 @@ export abstract class FluidDataStoreContext
742
724
  this.parentContext.addedGCOutboundRoute(fromPath, toPath, messageTimestampMs);
743
725
  }
744
726
 
745
- /**
746
- * Updates the used routes of the channel and its child contexts. The channel must be loaded before calling this.
747
- * It is called in these two scenarios:
748
- * 1. When the used routes of the data store is updated and the data store is loaded.
749
- * 2. When the data store is realized. This updates the channel's used routes as per last GC run.
750
- */
751
- private updateChannelUsedRoutes() {
752
- assert(this.loaded, 0x144 /* "Channel should be loaded when updating used routes" */);
753
- assert(
754
- this.channel !== undefined,
755
- 0x145 /* "Channel should be present when data store is loaded" */,
756
- );
757
-
758
- // If there is no lastUsedRoutes, GC has not run up until this point.
759
- if (this.lastUsedRoutes === undefined) {
760
- return;
761
- }
762
-
763
- // Remove the route to this data store, if it exists.
764
- const usedChannelRoutes = this.lastUsedRoutes.filter((id: string) => {
765
- return id !== "/" && id !== "";
766
- });
767
- this.channel.updateUsedRoutes(usedChannelRoutes);
768
- }
769
-
770
727
  /**
771
728
  * @deprecated 0.18.Should call request on the runtime directly
772
729
  */
@@ -861,15 +818,6 @@ export abstract class FluidDataStoreContext
861
818
  // Freeze the package path to ensure that someone doesn't modify it when it is
862
819
  // returned in packagePath().
863
820
  Object.freeze(this.pkg);
864
-
865
- /**
866
- * Update the used routes of the channel. If GC has run before this data store was realized, we will have
867
- * the used routes saved. So, this will ensure that all the child contexts have up-to-date used routes as
868
- * per the last time GC was run.
869
- * Also, this data store may have been realized during summarize. In that case, the child contexts need to
870
- * have their used routes updated to determine if its needs to summarize again and to add it to the summary.
871
- */
872
- this.updateChannelUsedRoutes();
873
821
  }
874
822
 
875
823
  protected async bindRuntime(channel: IFluidDataStoreChannel, existing: boolean) {
@@ -999,20 +947,14 @@ export abstract class FluidDataStoreContext
999
947
  safeTelemetryProps,
1000
948
  );
1001
949
 
1002
- sendGCUnexpectedUsageEvent(
1003
- this.mc,
950
+ this.mc.logger.sendTelemetryEvent(
1004
951
  {
1005
952
  eventName: "GC_Tombstone_DataStore_Changed",
1006
- category: this.gcThrowOnTombstoneUsage ? "error" : "generic",
1007
- gcTombstoneEnforcementAllowed: this.gcTombstoneEnforcementAllowed,
953
+ category: "generic",
1008
954
  callSite,
1009
955
  },
1010
- this.pkg,
1011
956
  error,
1012
957
  );
1013
- if (this.gcThrowOnTombstoneUsage) {
1014
- throw error;
1015
- }
1016
958
  }
1017
959
  }
1018
960
 
@@ -1036,7 +978,7 @@ export abstract class FluidDataStoreContext
1036
978
  eventName,
1037
979
  type,
1038
980
  isSummaryInProgress: this.summarizerNode.isSummaryInProgress?.(),
1039
- stack: generateStack(),
981
+ stack: generateStack(30),
1040
982
  });
1041
983
  this.localChangesTelemetryCount--;
1042
984
  }
@@ -1378,16 +1320,10 @@ export class LocalFluidDataStoreContextBase extends FluidDataStoreContext {
1378
1320
  */
1379
1321
  public delete() {
1380
1322
  // TODO: GC:Validation - potentially prevent this from happening or asserting. Maybe throw here.
1381
- sendGCUnexpectedUsageEvent(
1382
- this.mc,
1383
- {
1384
- eventName: "GC_Deleted_DataStore_Unexpected_Delete",
1385
- message: "Unexpected deletion of a local data store context",
1386
- category: "error",
1387
- gcTombstoneEnforcementAllowed: undefined,
1388
- },
1389
- this.pkg,
1390
- );
1323
+ this.mc.logger.sendErrorEvent({
1324
+ eventName: "GC_Deleted_DataStore_Unexpected_Delete",
1325
+ message: "Unexpected deletion of a local data store context",
1326
+ });
1391
1327
  super.delete();
1392
1328
  }
1393
1329
  }
@@ -27,7 +27,7 @@ import {
27
27
  } from "@fluidframework/telemetry-utils/internal";
28
28
 
29
29
  import { blobManagerBasePath } from "../blobManager/index.js";
30
- import { InactiveResponseHeaderKey, TombstoneResponseHeaderKey } from "../containerRuntime.js";
30
+ import { TombstoneResponseHeaderKey } from "../containerRuntime.js";
31
31
  import { ClientSessionExpiredError } from "../error.js";
32
32
  import { ContainerMessageType, ContainerRuntimeGCMessage } from "../messageTypes.js";
33
33
  import { IRefreshSummaryResult } from "../summary/index.js";
@@ -47,7 +47,6 @@ import {
47
47
  IMarkPhaseStats,
48
48
  ISweepPhaseStats,
49
49
  UnreferencedState,
50
- disableAutoRecoveryKey,
51
50
  type IGCNodeUpdatedProps,
52
51
  } from "./gcDefinitions.js";
53
52
  import {
@@ -102,7 +101,7 @@ export class GarbageCollector implements IGarbageCollector {
102
101
  private readonly configs: IGarbageCollectorConfigs;
103
102
 
104
103
  public get shouldRunGC(): boolean {
105
- return this.configs.gcEnabled;
104
+ return this.configs.gcAllowed;
106
105
  }
107
106
 
108
107
  public readonly sessionExpiryTimerStarted: number | undefined;
@@ -143,19 +142,6 @@ export class GarbageCollector implements IGarbageCollector {
143
142
  private readonly summaryStateTracker: GCSummaryStateTracker;
144
143
  private readonly telemetryTracker: GCTelemetryTracker;
145
144
 
146
- /** If false, loading or using a Tombstoned object should merely log, not fail */
147
- public get tombstoneEnforcementAllowed(): boolean {
148
- return this.configs.sweepEnabled;
149
- }
150
- /** If true, throw an error when a tombstone data store is retrieved */
151
- public get throwOnTombstoneLoad(): boolean {
152
- return this.configs.throwOnTombstoneLoad;
153
- }
154
- /** If true, throw an error when a tombstone data store is used */
155
- public get throwOnTombstoneUsage(): boolean {
156
- return this.configs.throwOnTombstoneUsage;
157
- }
158
-
159
145
  /** For a given node path, returns the node's package path. */
160
146
  private readonly getNodePackagePath: (
161
147
  nodePath: string,
@@ -377,9 +363,8 @@ export class GarbageCollector implements IGarbageCollector {
377
363
  this.deletedNodes = new Set(baseSnapshotData.deletedNodes);
378
364
  }
379
365
 
380
- // If running in tombstone mode, initialize the tombstone state from the snapshot. Also, notify the runtime of
381
- // tombstone routes.
382
- if (this.configs.tombstoneMode && baseSnapshotData.tombstones !== undefined) {
366
+ // Initialize the tombstone state from the snapshot. Also, notify the runtime of tombstone routes.
367
+ if (baseSnapshotData.tombstones !== undefined) {
383
368
  // Create a copy since we are writing from a source we don't control
384
369
  this.tombstones = Array.from(baseSnapshotData.tombstones);
385
370
  this.runtime.updateTombstonedRoutes(this.tombstones);
@@ -525,7 +510,7 @@ export class GarbageCollector implements IGarbageCollector {
525
510
  ...gcStats,
526
511
  details: {
527
512
  timestamp: currentReferenceTimestampMs,
528
- sweep: this.configs.shouldRunSweep,
513
+ sweep: this.configs.sweepEnabled,
529
514
  tombstone: this.configs.throwOnTombstoneLoad,
530
515
  },
531
516
  });
@@ -699,34 +684,18 @@ export class GarbageCollector implements IGarbageCollector {
699
684
  // This is important because a container may never load during a node's Sweep Grace Period,
700
685
  // so that node would directly become sweep-ready skipping over tombstone-ready state,
701
686
  // but should be Tombstoned since Sweep is disabled.
702
- const { nodesToTombstone, nodesToDelete } = {
703
- nodesToTombstone: [...tombstoneReadyNodes],
704
- nodesToDelete: [] as string[],
705
- };
706
- switch (this.configs.shouldRunSweep) {
707
- case "YES":
708
- nodesToDelete.push(...sweepReadyNodes);
709
- break;
710
- case "ONLY_BLOBS":
711
- sweepReadyNodes.forEach((nodeId) => {
712
- const nodeType = this.runtime.getNodeType(nodeId);
713
- if (nodeType === GCNodeType.Blob) {
714
- nodesToDelete.push(nodeId);
715
- } else {
716
- nodesToTombstone.push(nodeId);
717
- }
718
- });
719
- break;
720
- default: // case "NO":
721
- nodesToTombstone.push(...sweepReadyNodes);
722
- break;
723
- }
687
+ const { nodesToTombstone, nodesToDelete } = this.configs.sweepEnabled
688
+ ? {
689
+ nodesToDelete: [...sweepReadyNodes],
690
+ nodesToTombstone: [...tombstoneReadyNodes],
691
+ }
692
+ : {
693
+ nodesToDelete: [],
694
+ nodesToTombstone: [...tombstoneReadyNodes, ...sweepReadyNodes],
695
+ };
724
696
 
725
- if (this.configs.tombstoneMode) {
726
- this.tombstones = nodesToTombstone;
727
- // If we are running in GC tombstone mode, update tombstoned routes.
728
- this.runtime.updateTombstonedRoutes(this.tombstones);
729
- }
697
+ this.tombstones = nodesToTombstone;
698
+ this.runtime.updateTombstonedRoutes(this.tombstones);
730
699
 
731
700
  if (nodesToDelete.length > 0) {
732
701
  // Do not send DDS node ids in the GC op. This is an optimization to reduce its size. Since GC applies to
@@ -876,10 +845,10 @@ export class GarbageCollector implements IGarbageCollector {
876
845
  public getMetadata(): IGCMetadata {
877
846
  return {
878
847
  /**
879
- * If GC is enabled, the GC data is written using the GC version in effect and that is the gcFeature that goes
848
+ * If GC is allowed, the GC data is written using the GC version in effect and that is the gcFeature that goes
880
849
  * into the metadata blob. If GC is disabled, the gcFeature is 0.
881
850
  */
882
- gcFeature: this.configs.gcEnabled ? this.configs.gcVersionInEffect : 0,
851
+ gcFeature: this.configs.gcAllowed ? this.configs.gcVersionInEffect : 0,
883
852
  gcFeatureMatrix: this.configs.persistedGcFeatureMatrix,
884
853
  sessionExpiryTimeoutMs: this.configs.sessionExpiryTimeoutMs,
885
854
  sweepEnabled: false, // DEPRECATED - to be removed
@@ -913,13 +882,6 @@ export class GarbageCollector implements IGarbageCollector {
913
882
  break;
914
883
  }
915
884
  case GarbageCollectionMessageType.TombstoneLoaded: {
916
- if (
917
- !this.configs.tombstoneAutorecoveryEnabled ||
918
- this.mc.config.getBoolean(disableAutoRecoveryKey) === true
919
- ) {
920
- break;
921
- }
922
-
923
885
  // Mark the node as referenced to ensure it isn't Swept
924
886
  const tombstonedNodePath = message.contents.nodePath;
925
887
  this.addedOutboundReference(
@@ -1015,8 +977,6 @@ export class GarbageCollector implements IGarbageCollector {
1015
977
  // trackedId will be either DataStore or Blob ID (not sub-DataStore ID, since some of those are unrecognized by GC)
1016
978
  const trackedId = node.path;
1017
979
  const isTombstoned = this.tombstones.includes(trackedId);
1018
- const isInactive = this.unreferencedNodesState.get(trackedId)?.state === "Inactive";
1019
-
1020
980
  const fullPath = request !== undefined ? urlToGCNodePath(request.url) : trackedId;
1021
981
 
1022
982
  // This will log if appropriate
@@ -1054,7 +1014,11 @@ export class GarbageCollector implements IGarbageCollector {
1054
1014
  }
1055
1015
 
1056
1016
  const errorRequest: IRequest = request ?? { url: fullPath };
1057
- if (isTombstoned && this.throwOnTombstoneLoad && headerData?.allowTombstone !== true) {
1017
+ if (
1018
+ isTombstoned &&
1019
+ this.configs.throwOnTombstoneLoad &&
1020
+ headerData?.allowTombstone !== true
1021
+ ) {
1058
1022
  // The requested data store is removed by gc. Create a 404 gc response exception.
1059
1023
  throw responseToException(
1060
1024
  createResponseError(404, `${nodeType} was tombstoned`, errorRequest, {
@@ -1063,22 +1027,6 @@ export class GarbageCollector implements IGarbageCollector {
1063
1027
  errorRequest,
1064
1028
  );
1065
1029
  }
1066
-
1067
- // If the object is inactive and inactive enforcement is configured, throw an error.
1068
- if (isInactive) {
1069
- const shouldThrowOnInactiveLoad =
1070
- !this.isSummarizerClient &&
1071
- this.configs.throwOnInactiveLoad === true &&
1072
- headerData?.allowInactive !== true;
1073
- if (shouldThrowOnInactiveLoad) {
1074
- throw responseToException(
1075
- createResponseError(404, `${nodeType} is inactive`, errorRequest, {
1076
- [InactiveResponseHeaderKey]: true,
1077
- }),
1078
- errorRequest,
1079
- );
1080
- }
1081
- }
1082
1030
  }
1083
1031
 
1084
1032
  /**
@@ -1091,10 +1039,9 @@ export class GarbageCollector implements IGarbageCollector {
1091
1039
  * before runnint GC next.
1092
1040
  */
1093
1041
  private triggerAutoRecovery(nodePath: string) {
1094
- if (
1095
- !this.configs.tombstoneAutorecoveryEnabled ||
1096
- this.mc.config.getBoolean(disableAutoRecoveryKey) === true
1097
- ) {
1042
+ // If sweep isn't enabled, auto-recovery isn't needed since its purpose is to prevent this object from being
1043
+ // deleted. It also would end up sending a GC op which can break clients running FF version 1.x.
1044
+ if (!this.configs.sweepEnabled) {
1098
1045
  return;
1099
1046
  }
1100
1047
 
@@ -20,17 +20,12 @@ import {
20
20
  defaultInactiveTimeoutMs,
21
21
  defaultSessionExpiryDurationMs,
22
22
  defaultSweepGracePeriodMs,
23
- disableDatastoreSweepKey,
24
- disableTombstoneKey,
25
- gcDisableDataStoreSweepOptionName,
26
- gcDisableThrowOnTombstoneLoadOptionName,
27
23
  gcGenerationOptionName,
28
24
  gcTestModeKey,
29
25
  maxSnapshotCacheExpiryMs,
30
26
  oneDayMs,
31
27
  runSessionExpiryKey,
32
- throwOnTombstoneLoadOverrideKey,
33
- throwOnTombstoneUsageKey,
28
+ disableThrowOnTombstoneLoadKey,
34
29
  } from "./gcDefinitions.js";
35
30
  import { getGCVersion, getGCVersionInEffect, shouldAllowGcSweep } from "./gcHelpers.js";
36
31
 
@@ -52,7 +47,7 @@ export function generateGCConfigs(
52
47
  isSummarizerClient: boolean;
53
48
  },
54
49
  ): IGarbageCollectorConfigs {
55
- let gcEnabled: boolean = true;
50
+ let gcAllowed: boolean = true;
56
51
  let sessionExpiryTimeoutMs: number | undefined;
57
52
  let tombstoneTimeoutMs: number | undefined;
58
53
  let persistedGcFeatureMatrix: GCFeatureMatrix | undefined;
@@ -70,7 +65,7 @@ export function generateGCConfigs(
70
65
  gcVersionInBaseSnapshot = getGCVersion(metadata);
71
66
  // Existing documents which did not have metadata blob or had GC disabled have GC version as 0. GC will be
72
67
  // disabled for these documents.
73
- gcEnabled = gcVersionInBaseSnapshot !== 0;
68
+ gcAllowed = gcVersionInBaseSnapshot !== 0;
74
69
  sessionExpiryTimeoutMs = metadata?.sessionExpiryTimeoutMs;
75
70
  const legacyPersistedSweepTimeoutMs = (metadata as IGCMetadata_Deprecated)?.sweepTimeoutMs;
76
71
  tombstoneTimeoutMs =
@@ -107,32 +102,18 @@ export function generateGCConfigs(
107
102
  );
108
103
 
109
104
  /**
110
- * Whether sweep should run or not. This refers to whether Tombstones should fail on load and whether
105
+ * Whether sweep is enabled for this session or not. If sweep is enabled, Tombstones should fail on load and
111
106
  * sweep-ready nodes should be deleted.
112
107
  *
113
- * Assuming overall GC is enabled and tombstoneTimeout is provided, the following conditions have to be met to run sweep:
108
+ * Assuming overall GC is allowed and tombstoneTimeout is provided, the following conditions have to be met to run sweep:
114
109
  *
115
110
  * 1. Sweep should be allowed in this container.
116
- * 2. Sweep should be enabled for this session, optionally restricted to attachment blobs only.
117
- *
118
- * These conditions can be overridden via the RunSweep feature flag.
111
+ * 2. Sweep should be enabled for this session.
119
112
  */
120
113
  const sweepEnabled: boolean =
121
- !gcEnabled || tombstoneTimeoutMs === undefined
114
+ !gcAllowed || tombstoneTimeoutMs === undefined
122
115
  ? false
123
116
  : sweepAllowed && createParams.gcOptions.enableGCSweep === true;
124
- const disableDatastoreSweep =
125
- mc.config.getBoolean(disableDatastoreSweepKey) === true ||
126
- createParams.gcOptions[gcDisableDataStoreSweepOptionName] === true;
127
- const shouldRunSweep: IGarbageCollectorConfigs["shouldRunSweep"] = sweepEnabled
128
- ? disableDatastoreSweep
129
- ? "ONLY_BLOBS"
130
- : "YES"
131
- : "NO";
132
-
133
- // If we aren't running sweep, also disable AutoRecovery which also emits the GC op.
134
- // This gives a simple control surface for compability concerns around introducing the new op.
135
- const tombstoneAutorecoveryEnabled = shouldRunSweep !== "NO";
136
117
 
137
118
  // Override inactive timeout if test config or gc options to override it is set.
138
119
  const inactiveTimeoutMs =
@@ -148,9 +129,6 @@ export function generateGCConfigs(
148
129
  // Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
149
130
  const testMode =
150
131
  mc.config.getBoolean(gcTestModeKey) ?? createParams.gcOptions.runGCInTestMode === true;
151
- // Whether we are running in tombstone mode. If disabled, tombstone data will not be written to or read from snapshots,
152
- // and objects will not be marked as tombstoned even if they pass to the "TombstoneReady" state during the session.
153
- const tombstoneMode = mc.config.getBoolean(disableTombstoneKey) !== true;
154
132
  const runFullGC = createParams.gcOptions.runFullGC;
155
133
 
156
134
  const sweepGracePeriodMs =
@@ -159,26 +137,17 @@ export function generateGCConfigs(
159
137
  sweepGracePeriodMs,
160
138
  });
161
139
 
162
- const throwOnInactiveLoad: boolean | undefined = createParams.gcOptions.throwOnInactiveLoad;
163
-
164
- const throwOnTombstoneLoadConfig =
165
- mc.config.getBoolean(throwOnTombstoneLoadOverrideKey) ??
166
- createParams.gcOptions[gcDisableThrowOnTombstoneLoadOptionName] !== true;
167
140
  const throwOnTombstoneLoad =
168
- throwOnTombstoneLoadConfig && sweepAllowed && !createParams.isSummarizerClient;
169
- const throwOnTombstoneUsage =
170
- mc.config.getBoolean(throwOnTombstoneUsageKey) === true &&
171
- sweepAllowed &&
141
+ mc.config.getBoolean(disableThrowOnTombstoneLoadKey) !== true &&
142
+ sweepEnabled &&
172
143
  !createParams.isSummarizerClient;
173
144
 
174
145
  return {
175
- gcEnabled, // For this document
176
- sweepEnabled: sweepAllowed, // For this document (based on current GC Generation option)
177
- tombstoneAutorecoveryEnabled,
178
- shouldRunSweep, // For this session
146
+ gcAllowed, // For this document
147
+ sweepAllowed, // For this document
148
+ sweepEnabled, // For this session
179
149
  runFullGC,
180
150
  testMode,
181
- tombstoneMode,
182
151
  sessionExpiryTimeoutMs,
183
152
  tombstoneTimeoutMs,
184
153
  sweepGracePeriodMs,
@@ -186,9 +155,7 @@ export function generateGCConfigs(
186
155
  persistedGcFeatureMatrix,
187
156
  gcVersionInBaseSnapshot,
188
157
  gcVersionInEffect: getGCVersionInEffect(mc.config),
189
- throwOnInactiveLoad,
190
158
  throwOnTombstoneLoad,
191
- throwOnTombstoneUsage,
192
159
  };
193
160
  }
194
161
 
@@ -37,20 +37,6 @@ export const stableGCVersion: GCVersion = 3;
37
37
  /** The next version of GC Data, to bump to in case we need to regenerate all GC Data across all files. */
38
38
  export const nextGCVersion: GCVersion = 4;
39
39
 
40
- /**
41
- * This undocumented GC Option (on ContainerRuntime Options) allows an app to disable throwing an error when tombstone
42
- * object is loaded (requested), merely logging a message instead.
43
- *
44
- * By default, attempting to load a Tombstoned object will result in an error.
45
- */
46
- export const gcDisableThrowOnTombstoneLoadOptionName = "gcDisableThrowOnTombstoneLoad";
47
-
48
- /**
49
- * This undocumented GC Option (on ContainerRuntime Options) allows an app to enable Sweep for blobs only.
50
- * Only applies if enableGCSweep option is set to true.
51
- */
52
- export const gcDisableDataStoreSweepOptionName = "disableDataStoreSweep";
53
-
54
40
  /**
55
41
  * This undocumented GC Option (on ContainerRuntime Options) allows configuring which documents can have Sweep enabled.
56
42
  * This provides a way to disable both Tombstone Enforcement and Sweep.
@@ -68,19 +54,11 @@ export const gcGenerationOptionName = "gcGeneration";
68
54
  export const gcTestModeKey = "Fluid.GarbageCollection.GCTestMode";
69
55
  /** Config key to expire a session after a set period of time. Defaults to true. */
70
56
  export const runSessionExpiryKey = "Fluid.GarbageCollection.RunSessionExpiry";
71
- /** Config key to disable the tombstone feature, i.e., tombstone information is not read / written into summary. */
72
- export const disableTombstoneKey = "Fluid.GarbageCollection.DisableTombstone";
73
- /** Config key to override throwing an error when tombstone object is loaded (requested). */
74
- export const throwOnTombstoneLoadOverrideKey =
75
- "Fluid.GarbageCollection.ThrowOnTombstoneLoadOverride";
76
- /** Config key to enable throwing an error when tombstone object is used (e.g. outgoing or incoming ops). */
77
- export const throwOnTombstoneUsageKey = "Fluid.GarbageCollection.ThrowOnTombstoneUsage";
57
+ /** Config key to disable throwing an error when tombstone object is loaded (requested). */
58
+ export const disableThrowOnTombstoneLoadKey =
59
+ "Fluid.GarbageCollection.DisableThrowOnTombstoneLoad";
78
60
  /** Config key to enable GC version upgrade. */
79
61
  export const gcVersionUpgradeToV4Key = "Fluid.GarbageCollection.GCVersionUpgradeToV4";
80
- /** Config key to disable GC sweep for datastores. They'll merely be Tombstoned. */
81
- export const disableDatastoreSweepKey = "Fluid.GarbageCollection.DisableDataStoreSweep";
82
- /** Config key to disable auto-recovery mechanism that protects Tombstones that are loaded from being swept (use true) */
83
- export const disableAutoRecoveryKey = "Fluid.GarbageCollection.DisableAutoRecovery";
84
62
 
85
63
  // One day in milliseconds.
86
64
  export const oneDayMs = 1 * 24 * 60 * 60 * 1000;
@@ -339,12 +317,6 @@ export interface IGarbageCollector {
339
317
  readonly shouldRunGC: boolean;
340
318
  /** The count of data stores whose GC state updated since the last summary. */
341
319
  readonly updatedDSCountSinceLastSummary: number;
342
- /** Tells whether tombstone feature is enabled and enforced. */
343
- readonly tombstoneEnforcementAllowed: boolean;
344
- /** Tells whether loading a tombstone object should fail or merely log. */
345
- readonly throwOnTombstoneLoad: boolean;
346
- /** Tells whether using a tombstone object should fail or merely log. */
347
- readonly throwOnTombstoneUsage: boolean;
348
320
  /** Initialize the state from the base snapshot after its creation. */
349
321
  initializeBaseState(): Promise<void>;
350
322
  /** Run garbage collection and update the reference / used state of the system. */
@@ -480,22 +452,17 @@ export interface IGCRuntimeOptions {
480
452
  */
481
453
  export interface IGarbageCollectorConfigs {
482
454
  /**
483
- * Tracks if GC is enabled for this document. GC may not be enabled for old documents created pre-GC.
455
+ * Tracks if GC is allowed for this document. GC may not be allowed for old documents created pre-GC.
456
+ * If GC is allowed for a document, it will always be enabled. It cannot be disabled per session.
484
457
  */
485
- readonly gcEnabled: boolean;
458
+ readonly gcAllowed: boolean;
486
459
  /**
487
- * Tracks if sweep phase is allowed for this document. This is specified during document creation and doesn't change
488
- * throughout its lifetime.
460
+ * Tracks whether sweep phase is allowed for this document. Sweep can be disabled per session via the sweepEnabled
461
+ * flag defined below.
489
462
  */
463
+ readonly sweepAllowed: boolean;
464
+ /** Tracks if sweep phase is enabled to run in this session or not */
490
465
  readonly sweepEnabled: boolean;
491
- /** Is Tombstone AutoRecovery enabled? Useful for preventing the GC "TombstoneLoaded" op, for compatibility reasons */
492
- readonly tombstoneAutorecoveryEnabled: boolean;
493
- /**
494
- * Tracks if sweep phase should run or not, or if it should run only for attachment blobs.
495
- * Even if the sweep phase is allowed for a document (see sweepEnabled), it may be disabled or partially enabled
496
- * for the session, depending on a variety of other configurations present.
497
- */
498
- readonly shouldRunSweep: "YES" | "ONLY_BLOBS" | "NO";
499
466
  /**
500
467
  * If true, bypass optimizations and generate GC data for all nodes irrespective of whether a node changed or not.
501
468
  */
@@ -513,26 +480,14 @@ export interface IGarbageCollectorConfigs {
513
480
  readonly inactiveTimeoutMs: number;
514
481
  /** Tracks whether GC should run in test mode. In this mode, unreferenced objects are deleted immediately. */
515
482
  readonly testMode: boolean;
516
- /**
517
- * Tracks whether GC should run in tombstone mode. In this mode, objects are marked as tombstones as a step along the
518
- * way before they are fully deleted.
519
- * In interactive (non-summarizer) clients, tombstone objects behave as if they are deleted, i.e., access to them
520
- * is not allowed. However, these objects can be accessed after referencing them first. It is used as a "warning"
521
- * step before sweep, where objects wrongly marked as unreferenced can be recovered.
522
- */
523
- readonly tombstoneMode: boolean;
524
483
  /** @see GCFeatureMatrix. */
525
484
  readonly persistedGcFeatureMatrix: GCFeatureMatrix | undefined;
526
485
  /** The version of GC in the base snapshot. */
527
486
  readonly gcVersionInBaseSnapshot: GCVersion | undefined;
528
487
  /** The current version of GC data in the running code */
529
488
  readonly gcVersionInEffect: GCVersion;
530
- /** It is easier for users to diagnose InactiveObject usage if we throw on load, which this option enables */
531
- readonly throwOnInactiveLoad: boolean | undefined;
532
489
  /** If true, throw an error when a tombstone data store is retrieved */
533
490
  readonly throwOnTombstoneLoad: boolean;
534
- /** If true, throw an error when a tombstone data store is used. */
535
- readonly throwOnTombstoneUsage: boolean;
536
491
  }
537
492
 
538
493
  /** The state of node that is unreferenced. */