@fluidframework/container-runtime 2.0.0-internal.7.1.0 → 2.0.0-internal.7.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/api-report/container-runtime.api.md +2 -1
  2. package/dist/blobManager.d.ts +3 -6
  3. package/dist/blobManager.d.ts.map +1 -1
  4. package/dist/blobManager.js +17 -42
  5. package/dist/blobManager.js.map +1 -1
  6. package/dist/container-runtime-alpha.d.ts +4 -4
  7. package/dist/container-runtime-beta.d.ts +4 -4
  8. package/dist/container-runtime-public.d.ts +4 -4
  9. package/dist/container-runtime.d.ts +4 -4
  10. package/dist/containerRuntime.d.ts +5 -4
  11. package/dist/containerRuntime.d.ts.map +1 -1
  12. package/dist/containerRuntime.js +27 -6
  13. package/dist/containerRuntime.js.map +1 -1
  14. package/dist/dataStoreContext.d.ts +1 -0
  15. package/dist/dataStoreContext.d.ts.map +1 -1
  16. package/dist/dataStoreContext.js +39 -34
  17. package/dist/dataStoreContext.js.map +1 -1
  18. package/dist/dataStores.d.ts +0 -16
  19. package/dist/dataStores.d.ts.map +1 -1
  20. package/dist/dataStores.js +0 -48
  21. package/dist/dataStores.js.map +1 -1
  22. package/dist/gc/garbageCollection.d.ts +12 -3
  23. package/dist/gc/garbageCollection.d.ts.map +1 -1
  24. package/dist/gc/garbageCollection.js +41 -18
  25. package/dist/gc/garbageCollection.js.map +1 -1
  26. package/dist/gc/gcConfigs.d.ts +1 -0
  27. package/dist/gc/gcConfigs.d.ts.map +1 -1
  28. package/dist/gc/gcConfigs.js +12 -2
  29. package/dist/gc/gcConfigs.js.map +1 -1
  30. package/dist/gc/gcDefinitions.d.ts +21 -7
  31. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  32. package/dist/gc/gcDefinitions.js.map +1 -1
  33. package/dist/gc/gcTelemetry.d.ts +12 -6
  34. package/dist/gc/gcTelemetry.d.ts.map +1 -1
  35. package/dist/gc/gcTelemetry.js +74 -42
  36. package/dist/gc/gcTelemetry.js.map +1 -1
  37. package/dist/gc/index.d.ts +2 -2
  38. package/dist/gc/index.d.ts.map +1 -1
  39. package/dist/gc/index.js +1 -5
  40. package/dist/gc/index.js.map +1 -1
  41. package/dist/packageVersion.d.ts +1 -1
  42. package/dist/packageVersion.js +1 -1
  43. package/dist/packageVersion.js.map +1 -1
  44. package/lib/blobManager.d.ts +3 -6
  45. package/lib/blobManager.d.ts.map +1 -1
  46. package/lib/blobManager.js +18 -43
  47. package/lib/blobManager.js.map +1 -1
  48. package/lib/containerRuntime.d.ts +5 -4
  49. package/lib/containerRuntime.d.ts.map +1 -1
  50. package/lib/containerRuntime.js +28 -7
  51. package/lib/containerRuntime.js.map +1 -1
  52. package/lib/dataStoreContext.d.ts +1 -0
  53. package/lib/dataStoreContext.d.ts.map +1 -1
  54. package/lib/dataStoreContext.js +40 -35
  55. package/lib/dataStoreContext.js.map +1 -1
  56. package/lib/dataStores.d.ts +0 -16
  57. package/lib/dataStores.d.ts.map +1 -1
  58. package/lib/dataStores.js +2 -50
  59. package/lib/dataStores.js.map +1 -1
  60. package/lib/gc/garbageCollection.d.ts +12 -3
  61. package/lib/gc/garbageCollection.d.ts.map +1 -1
  62. package/lib/gc/garbageCollection.js +42 -19
  63. package/lib/gc/garbageCollection.js.map +1 -1
  64. package/lib/gc/gcConfigs.d.ts +1 -0
  65. package/lib/gc/gcConfigs.d.ts.map +1 -1
  66. package/lib/gc/gcConfigs.js +14 -4
  67. package/lib/gc/gcConfigs.js.map +1 -1
  68. package/lib/gc/gcDefinitions.d.ts +21 -7
  69. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  70. package/lib/gc/gcDefinitions.js.map +1 -1
  71. package/lib/gc/gcTelemetry.d.ts +12 -6
  72. package/lib/gc/gcTelemetry.d.ts.map +1 -1
  73. package/lib/gc/gcTelemetry.js +74 -42
  74. package/lib/gc/gcTelemetry.js.map +1 -1
  75. package/lib/gc/index.d.ts +2 -2
  76. package/lib/gc/index.d.ts.map +1 -1
  77. package/lib/gc/index.js +2 -2
  78. package/lib/gc/index.js.map +1 -1
  79. package/lib/packageVersion.d.ts +1 -1
  80. package/lib/packageVersion.js +1 -1
  81. package/lib/packageVersion.js.map +1 -1
  82. package/package.json +21 -17
  83. package/src/blobManager.ts +18 -58
  84. package/src/containerRuntime.ts +39 -16
  85. package/src/dataStoreContext.ts +17 -8
  86. package/src/dataStores.ts +2 -80
  87. package/src/gc/garbageCollection.ts +53 -24
  88. package/src/gc/gcConfigs.ts +22 -4
  89. package/src/gc/gcDefinitions.ts +22 -7
  90. package/src/gc/gcTelemetry.ts +103 -56
  91. package/src/gc/index.ts +0 -4
  92. package/src/packageVersion.ts +1 -1
@@ -24,8 +24,10 @@ import {
24
24
  runSessionExpiryKey,
25
25
  runSweepKey,
26
26
  stableGCVersion,
27
+ throwOnTombstoneLoadKey,
28
+ throwOnTombstoneUsageKey,
27
29
  } from "./gcDefinitions";
28
- import { getGCVersion, shouldAllowGcSweep } from "./gcHelpers";
30
+ import { getGCVersion, shouldAllowGcSweep, shouldAllowGcTombstoneEnforcement } from "./gcHelpers";
29
31
 
30
32
  /**
31
33
  * Generates configurations for the Garbage Collector that it uses to determine what to run and how.
@@ -42,6 +44,7 @@ export function generateGCConfigs(
42
44
  gcOptions: IGCRuntimeOptions;
43
45
  metadata: IContainerRuntimeMetadata | undefined;
44
46
  existing: boolean;
47
+ isSummarizerClient: boolean;
45
48
  },
46
49
  ): IGarbageCollectorConfigs {
47
50
  let gcEnabled: boolean;
@@ -152,8 +155,6 @@ export function generateGCConfigs(
152
155
  throw new UsageError("inactive timeout should not be greater than the sweep timeout");
153
156
  }
154
157
 
155
- const throwOnInactiveLoad: boolean | undefined = createParams.gcOptions.throwOnInactiveLoad;
156
-
157
158
  // Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
158
159
  const testMode =
159
160
  mc.config.getBoolean(gcTestModeKey) ?? createParams.gcOptions.runGCInTestMode === true;
@@ -162,6 +163,20 @@ export function generateGCConfigs(
162
163
  const tombstoneMode = !shouldRunSweep && mc.config.getBoolean(disableTombstoneKey) !== true;
163
164
  const runFullGC = createParams.gcOptions.runFullGC;
164
165
 
166
+ const throwOnInactiveLoad: boolean | undefined = createParams.gcOptions.throwOnInactiveLoad;
167
+ const tombstoneEnforcementAllowed = shouldAllowGcTombstoneEnforcement(
168
+ createParams.metadata?.gcFeatureMatrix?.tombstoneGeneration /* persisted */,
169
+ createParams.gcOptions[gcTombstoneGenerationOptionName] /* current */,
170
+ );
171
+ const throwOnTombstoneLoad =
172
+ mc.config.getBoolean(throwOnTombstoneLoadKey) === true &&
173
+ tombstoneEnforcementAllowed &&
174
+ !createParams.isSummarizerClient;
175
+ const throwOnTombstoneUsage =
176
+ mc.config.getBoolean(throwOnTombstoneUsageKey) === true &&
177
+ tombstoneEnforcementAllowed &&
178
+ !createParams.isSummarizerClient;
179
+
165
180
  return {
166
181
  gcEnabled,
167
182
  sweepEnabled,
@@ -173,10 +188,13 @@ export function generateGCConfigs(
173
188
  sessionExpiryTimeoutMs,
174
189
  sweepTimeoutMs,
175
190
  inactiveTimeoutMs,
176
- throwOnInactiveLoad,
177
191
  persistedGcFeatureMatrix,
178
192
  gcVersionInBaseSnapshot,
179
193
  gcVersionInEffect,
194
+ throwOnInactiveLoad,
195
+ tombstoneEnforcementAllowed,
196
+ throwOnTombstoneLoad,
197
+ throwOnTombstoneUsage,
180
198
  };
181
199
  }
182
200
 
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { ICriticalContainerError } from "@fluidframework/container-definitions";
7
- import { IRequestHeader } from "@fluidframework/core-interfaces";
7
+ import { IRequest } from "@fluidframework/core-interfaces";
8
8
  import { ISnapshotTree } from "@fluidframework/protocol-definitions";
9
9
  import {
10
10
  IGarbageCollectionData,
@@ -19,6 +19,7 @@ import {
19
19
  ICreateContainerMetadata,
20
20
  IRefreshSummaryResult,
21
21
  } from "../summary";
22
+ import { RuntimeHeaderData } from "../containerRuntime";
22
23
 
23
24
  export type GCVersion = number;
24
25
 
@@ -193,8 +194,6 @@ export interface IGarbageCollectionRuntime {
193
194
  getNodeType(nodePath: string): GCNodeType;
194
195
  /** Called when the runtime should close because of an error. */
195
196
  closeFn: (error?: ICriticalContainerError) => void;
196
- /** If false, loading or using a Tombstoned object should merely log, not fail */
197
- gcTombstoneEnforcementAllowed: boolean;
198
197
  }
199
198
 
200
199
  /** Defines the contract for the garbage collector. */
@@ -205,6 +204,12 @@ export interface IGarbageCollector {
205
204
  readonly summaryStateNeedsReset: boolean;
206
205
  /** The count of data stores whose GC state updated since the last summary. */
207
206
  readonly updatedDSCountSinceLastSummary: number;
207
+ /** Tells whether tombstone feature is enabled and enforced. */
208
+ readonly tombstoneEnforcementAllowed: boolean;
209
+ /** Tells whether loading a tombstone object should fail or merely log. */
210
+ readonly throwOnTombstoneLoad: boolean;
211
+ /** Tells whether using a tombstone object should fail or merely log. */
212
+ readonly throwOnTombstoneUsage: boolean;
208
213
  /** Initialize the state from the base snapshot after its creation. */
209
214
  initializeBaseState(): Promise<void>;
210
215
  /** Run garbage collection and update the reference / used state of the system. */
@@ -228,13 +233,17 @@ export interface IGarbageCollector {
228
233
  getBaseGCDetails(): Promise<IGarbageCollectionDetailsBase>;
229
234
  /** Called when the latest summary of the system has been refreshed. */
230
235
  refreshLatestSummary(result: IRefreshSummaryResult): Promise<void>;
231
- /** Called when a node is updated. Used to detect and log when an inactive node is changed or loaded. */
236
+ /**
237
+ * Called when a node with the given path is updated. If the node is inactive or tombstoned, this will log an error
238
+ * or throw an error if failing on incorrect usage is configured.
239
+ */
232
240
  nodeUpdated(
233
241
  nodePath: string,
234
242
  reason: "Loaded" | "Changed",
235
243
  timestampMs?: number,
236
244
  packagePath?: readonly string[],
237
- requestHeaders?: IRequestHeader,
245
+ request?: IRequest,
246
+ headerData?: RuntimeHeaderData,
238
247
  ): void;
239
248
  /** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */
240
249
  addedOutboundReference(fromNodePath: string, toNodePath: string): void;
@@ -332,8 +341,6 @@ export interface IGarbageCollectorConfigs {
332
341
  readonly sweepTimeoutMs: number | undefined;
333
342
  /** The time after which an unreferenced node is inactive. */
334
343
  readonly inactiveTimeoutMs: number;
335
- /** It is easier for users to diagnose InactiveObject usage if we throw on load, which this option enables */
336
- readonly throwOnInactiveLoad: boolean | undefined;
337
344
  /** Tracks whether GC should run in test mode. In this mode, unreferenced objects are deleted immediately. */
338
345
  readonly testMode: boolean;
339
346
  /**
@@ -349,6 +356,14 @@ export interface IGarbageCollectorConfigs {
349
356
  readonly gcVersionInBaseSnapshot: GCVersion | undefined;
350
357
  /** The current version of GC data in the running code */
351
358
  readonly gcVersionInEffect: GCVersion;
359
+ /** It is easier for users to diagnose InactiveObject usage if we throw on load, which this option enables */
360
+ readonly throwOnInactiveLoad: boolean | undefined;
361
+ /** If false, loading or using a Tombstoned object should merely log, not fail */
362
+ readonly tombstoneEnforcementAllowed: boolean;
363
+ /** If true, throw an error when a tombstone data store is retrieved */
364
+ readonly throwOnTombstoneLoad: boolean;
365
+ /** If true, throw an error when a tombstone data store is used. */
366
+ readonly throwOnTombstoneUsage: boolean;
352
367
  }
353
368
 
354
369
  /** The state of node that is unreferenced. */
@@ -11,6 +11,7 @@ import {
11
11
  MonitoringContext,
12
12
  tagCodeArtifacts,
13
13
  } from "@fluidframework/telemetry-utils";
14
+ import { RuntimeHeaderData } from "../containerRuntime";
14
15
  import { ICreateContainerMetadata } from "../summary";
15
16
  import {
16
17
  disableSweepLogKey,
@@ -32,7 +33,7 @@ interface ICommonProps {
32
33
  completedGCRuns: number;
33
34
  isTombstoned: boolean;
34
35
  lastSummaryTime?: number;
35
- viaHandle?: boolean;
36
+ headers?: RuntimeHeaderData;
36
37
  }
37
38
 
38
39
  /** The event that is logged when unreferenced node is used after a certain time. */
@@ -80,10 +81,13 @@ export class GCTelemetryTracker {
80
81
  private readonly mc: MonitoringContext,
81
82
  private readonly configs: Pick<
82
83
  IGarbageCollectorConfigs,
83
- "inactiveTimeoutMs" | "sweepTimeoutMs"
84
+ | "inactiveTimeoutMs"
85
+ | "sweepTimeoutMs"
86
+ | "tombstoneEnforcementAllowed"
87
+ | "throwOnTombstoneLoad"
88
+ | "throwOnTombstoneUsage"
84
89
  >,
85
90
  private readonly isSummarizerClient: boolean,
86
- private readonly gcTombstoneEnforcementAllowed: boolean,
87
91
  private readonly createContainerMetadata: ICreateContainerMetadata,
88
92
  private readonly getNodeType: (nodeId: string) => GCNodeType,
89
93
  private readonly getNodeStateTracker: (
@@ -95,12 +99,12 @@ export class GCTelemetryTracker {
95
99
  ) {}
96
100
 
97
101
  /**
98
- * Returns whether an event should be logged for a node that isn't active anymore. Some scenarios where we won't log:
99
- * 1. When a DDS is changed or loaded. The corresponding data store's event will be logged instead.
102
+ * Returns whether an event should be logged for a node that isn't active anymore. This does not apply to
103
+ * tombstoned nodes for which an event is always logged. Some scenarios where we won't log:
104
+ * 1. When a DDS is changed. The corresponding data store's event will be logged instead.
100
105
  * 2. An event is logged only once per container instance per event per node.
101
106
  */
102
107
  private shouldLogNonActiveEvent(
103
- nodeId: string,
104
108
  nodeType: GCNodeType,
105
109
  usageType: NodeUsageType,
106
110
  nodeStateTracker: UnreferencedStateTracker,
@@ -119,6 +123,8 @@ export class GCTelemetryTracker {
119
123
  return false;
120
124
  }
121
125
 
126
+ // Non-tombstone events are logged once per event per node. A unique id is generated by joining
127
+ // node state (inactive / sweep ready), node's id and usage (loaded / changed / revived).
122
128
  if (this.loggedUnreferencedEvents.has(uniqueEventId)) {
123
129
  return false;
124
130
  }
@@ -126,24 +132,61 @@ export class GCTelemetryTracker {
126
132
  }
127
133
 
128
134
  /**
129
- * Called when a node is used. If the node is not active, log an event indicating object is used when its not active.
135
+ * Called when a node is used. If the node is not active or tombstoned, log telemetry indicating object is used
136
+ * when it should not have been.
130
137
  */
131
138
  public nodeUsed(nodeUsageProps: INodeUsageProps) {
132
139
  // If there is no reference timestamp to work with, no ops have been processed after creation. If so, skip
133
140
  // logging as nothing interesting would have happened worth logging.
134
- // If the node is not unreferenced, skip logging.
135
- const nodeStateTracker = this.getNodeStateTracker(nodeUsageProps.id);
136
- if (!nodeStateTracker || nodeUsageProps.currentReferenceTimestampMs === undefined) {
141
+ if (nodeUsageProps.currentReferenceTimestampMs === undefined) {
137
142
  return;
138
143
  }
139
144
 
140
- // We log these events once per event per node. A unique id is generated by joining node state (inactive / sweep ready),
141
- // node's id and usage (loaded / changed / revived).
142
- const uniqueEventId = `${nodeStateTracker.state}-${nodeUsageProps.id}-${nodeUsageProps.usageType}`;
145
+ const nodeStateTracker = this.getNodeStateTracker(nodeUsageProps.id);
143
146
  const nodeType = this.getNodeType(nodeUsageProps.id);
147
+ const {
148
+ usageType,
149
+ currentReferenceTimestampMs,
150
+ packagePath,
151
+ id: untaggedId,
152
+ fromId: untaggedFromId,
153
+ ...propsToLog
154
+ } = nodeUsageProps;
155
+ const unrefEventProps: Omit<IUnreferencedEventProps, "state" | "usageType"> = {
156
+ type: nodeType,
157
+ unrefTime: nodeStateTracker?.unreferencedTimestampMs ?? -1,
158
+ age:
159
+ nodeStateTracker !== undefined
160
+ ? nodeUsageProps.currentReferenceTimestampMs -
161
+ nodeStateTracker.unreferencedTimestampMs
162
+ : -1,
163
+ timeout:
164
+ nodeStateTracker?.state === UnreferencedState.Inactive
165
+ ? this.configs.inactiveTimeoutMs
166
+ : this.configs.sweepTimeoutMs,
167
+ ...tagCodeArtifacts({ id: untaggedId, fromId: untaggedFromId }),
168
+ ...propsToLog,
169
+ ...this.createContainerMetadata,
170
+ };
171
+
172
+ // If the node that is used is tombstoned, log a tombstone telemetry.
173
+ // Note that this is done before checking if "nodeStateTracker" is undefined below because unreferenced
174
+ // tracking may not have yet been enabled. That happens only after the client transitions to write mode.
175
+ if (nodeUsageProps.isTombstoned) {
176
+ this.logTombstoneUsageTelemetry(nodeUsageProps, unrefEventProps, nodeType, usageType);
177
+ }
178
+
179
+ // After logging tombstone telemetry, if the node's unreferenced state is not tracked, there is nothing
180
+ // else to log.
181
+ if (nodeStateTracker === undefined) {
182
+ return;
183
+ }
184
+
185
+ const state = nodeStateTracker.state;
186
+ const uniqueEventId = `${state}-${nodeUsageProps.id}-${nodeUsageProps.usageType}`;
187
+
144
188
  if (
145
189
  !this.shouldLogNonActiveEvent(
146
- nodeUsageProps.id,
147
190
  nodeType,
148
191
  nodeUsageProps.usageType,
149
192
  nodeStateTracker,
@@ -153,42 +196,9 @@ export class GCTelemetryTracker {
153
196
  return;
154
197
  }
155
198
 
156
- // Add the unique event id so that we don't generate a log for this event again in this session..
199
+ // Add the unique event id so that we don't generate a log for this event again in this session.
157
200
  this.loggedUnreferencedEvents.add(uniqueEventId);
158
201
 
159
- const state = nodeStateTracker.state;
160
- const { usageType, currentReferenceTimestampMs, packagePath, id, fromId, ...propsToLog } =
161
- nodeUsageProps;
162
- const eventProps: Omit<IUnreferencedEventProps, "state" | "usageType"> = {
163
- type: nodeType,
164
- unrefTime: nodeStateTracker.unreferencedTimestampMs,
165
- age:
166
- nodeUsageProps.currentReferenceTimestampMs -
167
- nodeStateTracker.unreferencedTimestampMs,
168
- timeout:
169
- state === UnreferencedState.Inactive
170
- ? this.configs.inactiveTimeoutMs
171
- : this.configs.sweepTimeoutMs,
172
- ...tagCodeArtifacts({ id, fromId }),
173
- ...propsToLog,
174
- ...this.createContainerMetadata,
175
- };
176
-
177
- // This will log the following events:
178
- // GC_Tombstone_DataStore_Revived, GC_Tombstone_SubDataStore_Revived, GC_Tombstone_Blob_Revived
179
- if (nodeUsageProps.usageType === "Revived" && nodeUsageProps.isTombstoned) {
180
- sendGCUnexpectedUsageEvent(
181
- this.mc,
182
- {
183
- eventName: `GC_Tombstone_${nodeType}_Revived`,
184
- category: "generic",
185
- ...tagCodeArtifacts({ url: id }),
186
- gcTombstoneEnforcementAllowed: this.gcTombstoneEnforcementAllowed,
187
- },
188
- undefined /* packagePath */,
189
- );
190
- }
191
-
192
202
  // For summarizer client, queue the event so it is logged the next time GC runs if the event is still valid.
193
203
  // For non-summarizer client, log the event now since GC won't run on it. This may result in false positives
194
204
  // but it's a good signal nonetheless and we can consume it with a grain of salt.
@@ -196,7 +206,7 @@ export class GCTelemetryTracker {
196
206
  // SweepReady errors are usages of Objects that will be deleted by GC Sweep!
197
207
  if (this.isSummarizerClient) {
198
208
  this.pendingEventsQueue.push({
199
- ...eventProps,
209
+ ...unrefEventProps,
200
210
  usageType: nodeUsageProps.usageType,
201
211
  state,
202
212
  });
@@ -206,16 +216,15 @@ export class GCTelemetryTracker {
206
216
  // Events generated:
207
217
  // InactiveObject_Loaded, SweepReadyObject_Loaded
208
218
  if (nodeUsageProps.usageType === "Loaded") {
209
- const { id: taggedId, fromId: taggedFromId, ...otherProps } = eventProps;
219
+ const { id, fromId, headers, ...detailedProps } = unrefEventProps;
210
220
  const event = {
211
221
  eventName: `${state}Object_${nodeUsageProps.usageType}`,
212
- pkg: tagCodeArtifacts({ pkg: nodeUsageProps.packagePath?.join("/") }).pkg,
222
+ ...tagCodeArtifacts({ pkg: nodeUsageProps.packagePath?.join("/") }),
213
223
  stack: generateStack(),
214
- id: taggedId,
215
- fromId: taggedFromId,
216
- details: JSON.stringify({
217
- ...otherProps,
218
- }),
224
+ id,
225
+ fromId,
226
+ headers: { ...headers },
227
+ details: detailedProps,
219
228
  };
220
229
 
221
230
  // Do not log the inactive object x events as error events as they are not the best signal for
@@ -229,6 +238,44 @@ export class GCTelemetryTracker {
229
238
  }
230
239
  }
231
240
 
241
+ /**
242
+ * Logs telemetry when a tombstoned object is changed, revived or loaded.
243
+ */
244
+ private logTombstoneUsageTelemetry(
245
+ nodeUsageProps: INodeUsageProps,
246
+ unrefEventProps: Omit<IUnreferencedEventProps, "state" | "usageType">,
247
+ nodeType: GCNodeType,
248
+ usageType: NodeUsageType,
249
+ ) {
250
+ // This will log the following events:
251
+ // GC_Tombstone_DataStore_Requested, GC_Tombstone_DataStore_Changed, GC_Tombstone_DataStore_Revived
252
+ // GC_Tombstone_SubDataStore_Requested, GC_Tombstone_SubDataStore_Changed, GC_Tombstone_SubDataStore_Revived
253
+ // GC_Tombstone_Blob_Requested, GC_Tombstone_Blob_Changed, GC_Tombstone_Blob_Revived
254
+ const { id, fromId, headers, ...detailedProps } = unrefEventProps;
255
+ const eventUsageName = usageType === "Loaded" ? "Requested" : usageType;
256
+ const event = {
257
+ eventName: `GC_Tombstone_${nodeType}_${eventUsageName}`,
258
+ pkg: tagCodeArtifacts({ pkg: nodeUsageProps.packagePath?.join("/") }).pkg,
259
+ stack: generateStack(),
260
+ id,
261
+ fromId,
262
+ headers: { ...headers },
263
+ details: detailedProps,
264
+ gcTombstoneEnforcementAllowed: this.configs.tombstoneEnforcementAllowed,
265
+ };
266
+
267
+ if (
268
+ (usageType === "Loaded" &&
269
+ this.configs.throwOnTombstoneLoad &&
270
+ !headers?.allowTombstone) ||
271
+ (usageType === "Changed" && this.configs.throwOnTombstoneUsage)
272
+ ) {
273
+ this.mc.logger.sendErrorEvent(event);
274
+ } else {
275
+ this.mc.logger.sendTelemetryEvent(event);
276
+ }
277
+ }
278
+
232
279
  /**
233
280
  * Log all new references or outbound routes in the current graph that haven't been explicitly notified to GC.
234
281
  * The principle is that every new reference or outbound route must be notified to GC via the
package/src/gc/index.ts CHANGED
@@ -31,15 +31,11 @@ export {
31
31
  stableGCVersion,
32
32
  disableAttachmentBlobSweepKey,
33
33
  disableDatastoreSweepKey,
34
- throwOnTombstoneLoadKey,
35
- throwOnTombstoneUsageKey,
36
34
  UnreferencedState,
37
35
  } from "./gcDefinitions";
38
36
  export {
39
37
  cloneGCData,
40
38
  concatGarbageCollectionStates,
41
- shouldAllowGcTombstoneEnforcement,
42
- shouldAllowGcSweep,
43
39
  trimLeadingAndTrailingSlashes,
44
40
  unpackChildNodesGCDetails,
45
41
  } from "./gcHelpers";
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/container-runtime";
9
- export const pkgVersion = "2.0.0-internal.7.1.0";
9
+ export const pkgVersion = "2.0.0-internal.7.1.1";