@fluidframework/container-runtime 0.59.2001 → 0.59.3000

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 (143) hide show
  1. package/.eslintrc.js +0 -1
  2. package/dist/batchTracker.js +1 -1
  3. package/dist/batchTracker.js.map +1 -1
  4. package/dist/blobManager.d.ts +8 -1
  5. package/dist/blobManager.d.ts.map +1 -1
  6. package/dist/blobManager.js +27 -17
  7. package/dist/blobManager.js.map +1 -1
  8. package/dist/connectionTelemetry.js +8 -8
  9. package/dist/connectionTelemetry.js.map +1 -1
  10. package/dist/containerHandleContext.js +1 -1
  11. package/dist/containerHandleContext.js.map +1 -1
  12. package/dist/containerRuntime.d.ts +27 -17
  13. package/dist/containerRuntime.d.ts.map +1 -1
  14. package/dist/containerRuntime.js +152 -176
  15. package/dist/containerRuntime.js.map +1 -1
  16. package/dist/dataStore.js +1 -1
  17. package/dist/dataStore.js.map +1 -1
  18. package/dist/dataStoreContext.d.ts.map +1 -1
  19. package/dist/dataStoreContext.js +44 -44
  20. package/dist/dataStoreContext.js.map +1 -1
  21. package/dist/dataStoreContexts.d.ts +2 -2
  22. package/dist/dataStoreContexts.d.ts.map +1 -1
  23. package/dist/dataStoreContexts.js +8 -8
  24. package/dist/dataStoreContexts.js.map +1 -1
  25. package/dist/dataStores.d.ts +6 -4
  26. package/dist/dataStores.d.ts.map +1 -1
  27. package/dist/dataStores.js +50 -37
  28. package/dist/dataStores.js.map +1 -1
  29. package/dist/garbageCollection.d.ts +23 -23
  30. package/dist/garbageCollection.d.ts.map +1 -1
  31. package/dist/garbageCollection.js +81 -50
  32. package/dist/garbageCollection.js.map +1 -1
  33. package/dist/opTelemetry.js +1 -1
  34. package/dist/opTelemetry.js.map +1 -1
  35. package/dist/orderedClientElection.d.ts.map +1 -1
  36. package/dist/orderedClientElection.js +2 -2
  37. package/dist/orderedClientElection.js.map +1 -1
  38. package/dist/packageVersion.d.ts +1 -1
  39. package/dist/packageVersion.js +1 -1
  40. package/dist/packageVersion.js.map +1 -1
  41. package/dist/pendingStateManager.js +17 -17
  42. package/dist/pendingStateManager.js.map +1 -1
  43. package/dist/runWhileConnectedCoordinator.js +1 -1
  44. package/dist/runWhileConnectedCoordinator.js.map +1 -1
  45. package/dist/runningSummarizer.d.ts.map +1 -1
  46. package/dist/runningSummarizer.js +7 -6
  47. package/dist/runningSummarizer.js.map +1 -1
  48. package/dist/summarizer.d.ts.map +1 -1
  49. package/dist/summarizer.js +4 -3
  50. package/dist/summarizer.js.map +1 -1
  51. package/dist/summarizerClientElection.js.map +1 -1
  52. package/dist/summarizerHeuristics.d.ts +1 -1
  53. package/dist/summarizerHeuristics.d.ts.map +1 -1
  54. package/dist/summarizerHeuristics.js +1 -1
  55. package/dist/summarizerHeuristics.js.map +1 -1
  56. package/dist/summarizerTypes.d.ts +4 -2
  57. package/dist/summarizerTypes.d.ts.map +1 -1
  58. package/dist/summarizerTypes.js.map +1 -1
  59. package/dist/summaryCollection.js +2 -2
  60. package/dist/summaryCollection.js.map +1 -1
  61. package/dist/summaryFormat.d.ts +37 -11
  62. package/dist/summaryFormat.d.ts.map +1 -1
  63. package/dist/summaryFormat.js +12 -4
  64. package/dist/summaryFormat.js.map +1 -1
  65. package/dist/summaryGenerator.d.ts.map +1 -1
  66. package/dist/summaryGenerator.js +6 -4
  67. package/dist/summaryGenerator.js.map +1 -1
  68. package/dist/summaryManager.js +5 -5
  69. package/dist/summaryManager.js.map +1 -1
  70. package/dist/throttler.js +2 -2
  71. package/dist/throttler.js.map +1 -1
  72. package/lib/blobManager.d.ts +8 -1
  73. package/lib/blobManager.d.ts.map +1 -1
  74. package/lib/blobManager.js +19 -9
  75. package/lib/blobManager.js.map +1 -1
  76. package/lib/containerRuntime.d.ts +27 -17
  77. package/lib/containerRuntime.d.ts.map +1 -1
  78. package/lib/containerRuntime.js +71 -95
  79. package/lib/containerRuntime.js.map +1 -1
  80. package/lib/dataStore.js.map +1 -1
  81. package/lib/dataStoreContext.d.ts.map +1 -1
  82. package/lib/dataStoreContext.js.map +1 -1
  83. package/lib/dataStoreContexts.d.ts +2 -2
  84. package/lib/dataStoreContexts.d.ts.map +1 -1
  85. package/lib/dataStoreContexts.js +2 -2
  86. package/lib/dataStoreContexts.js.map +1 -1
  87. package/lib/dataStores.d.ts +6 -4
  88. package/lib/dataStores.d.ts.map +1 -1
  89. package/lib/dataStores.js +27 -14
  90. package/lib/dataStores.js.map +1 -1
  91. package/lib/garbageCollection.d.ts +23 -23
  92. package/lib/garbageCollection.d.ts.map +1 -1
  93. package/lib/garbageCollection.js +68 -37
  94. package/lib/garbageCollection.js.map +1 -1
  95. package/lib/opTelemetry.js.map +1 -1
  96. package/lib/orderedClientElection.d.ts.map +1 -1
  97. package/lib/orderedClientElection.js.map +1 -1
  98. package/lib/packageVersion.d.ts +1 -1
  99. package/lib/packageVersion.js +1 -1
  100. package/lib/packageVersion.js.map +1 -1
  101. package/lib/pendingStateManager.js.map +1 -1
  102. package/lib/runningSummarizer.d.ts.map +1 -1
  103. package/lib/runningSummarizer.js +4 -3
  104. package/lib/runningSummarizer.js.map +1 -1
  105. package/lib/summarizer.d.ts.map +1 -1
  106. package/lib/summarizer.js +1 -0
  107. package/lib/summarizer.js.map +1 -1
  108. package/lib/summarizerClientElection.js.map +1 -1
  109. package/lib/summarizerHeuristics.d.ts +1 -1
  110. package/lib/summarizerHeuristics.d.ts.map +1 -1
  111. package/lib/summarizerHeuristics.js +1 -1
  112. package/lib/summarizerHeuristics.js.map +1 -1
  113. package/lib/summarizerTypes.d.ts +4 -2
  114. package/lib/summarizerTypes.d.ts.map +1 -1
  115. package/lib/summarizerTypes.js.map +1 -1
  116. package/lib/summaryCollection.js.map +1 -1
  117. package/lib/summaryFormat.d.ts +37 -11
  118. package/lib/summaryFormat.d.ts.map +1 -1
  119. package/lib/summaryFormat.js +10 -2
  120. package/lib/summaryFormat.js.map +1 -1
  121. package/lib/summaryGenerator.d.ts.map +1 -1
  122. package/lib/summaryGenerator.js +2 -0
  123. package/lib/summaryGenerator.js.map +1 -1
  124. package/lib/summaryManager.js.map +1 -1
  125. package/lib/throttler.js.map +1 -1
  126. package/package.json +26 -20
  127. package/src/blobManager.ts +23 -11
  128. package/src/containerRuntime.ts +111 -139
  129. package/src/dataStoreContext.ts +8 -11
  130. package/src/dataStoreContexts.ts +5 -5
  131. package/src/dataStores.ts +35 -17
  132. package/src/garbageCollection.ts +100 -57
  133. package/src/orderedClientElection.ts +5 -10
  134. package/src/packageVersion.ts +1 -1
  135. package/src/pendingStateManager.ts +2 -2
  136. package/src/runningSummarizer.ts +8 -9
  137. package/src/summarizer.ts +2 -2
  138. package/src/summarizerHeuristics.ts +1 -1
  139. package/src/summarizerTypes.ts +8 -6
  140. package/src/summaryFormat.ts +38 -11
  141. package/src/summaryGenerator.ts +7 -5
  142. package/src/summaryManager.ts +2 -2
  143. package/src/throttler.ts +1 -1
@@ -29,7 +29,9 @@ const runSweepKey = "Fluid.GarbageCollection.RunSweep";
29
29
  // Feature gate key to write GC data at the root of the summary tree.
30
30
  const writeAtRootKey = "Fluid.GarbageCollection.WriteDataAtRoot";
31
31
  // Feature gate key to expire a session after a set period of time.
32
- const runSessionExpiry = "Fluid.GarbageCollection.RunSessionExpiry";
32
+ const runSessionExpiryKey = "Fluid.GarbageCollection.RunSessionExpiry";
33
+ // Feature gate key to disable expiring session after a set period of time, even if expiry value is present
34
+ const disableSessionExpiryKey = "Fluid.GarbageCollection.DisableSessionExpiry";
33
35
  // Feature gate key to log error messages if GC reference validation fails.
34
36
  const logUnknownOutboundReferencesKey = "Fluid.GarbageCollection.LogUnknownOutboundReferences";
35
37
  const defaultDeleteTimeoutMs = 7 * 24 * 60 * 60 * 1000; // 7 days
@@ -38,9 +40,11 @@ exports.defaultSessionExpiryDurationMs = 30 * 24 * 60 * 60 * 1000; // 30 days
38
40
  exports.GCNodeType = {
39
41
  // Nodes that are for data stores.
40
42
  DataStore: "DataStore",
43
+ // Nodes that are within a data store. For example, DDS nodes.
44
+ SubDataStore: "SubDataStore",
41
45
  // Nodes that are for attachment blobs, i.e., blobs uploaded via BlobManager.
42
46
  Blob: "Blob",
43
- // Nodes that are neither data store not blobs. For example, root node and DDS nodes.
47
+ // Nodes that are neither of the above. For example, root node.
44
48
  Other: "Other",
45
49
  };
46
50
  /**
@@ -94,15 +98,15 @@ class UnreferencedStateTracker {
94
98
  * its state across summaries.
95
99
  *
96
100
  * Node - represented as nodeId, it's a node on the GC graph
97
- * Outbound Route - a path from one node to another node, think `nodeA` -> `nodeB`
101
+ * Outbound Route - a path from one node to another node, think `nodeA` -\> `nodeB`
98
102
  * Graph - all nodes with their respective routes
99
103
  * GC Graph
100
104
  *
101
105
  * Node
102
106
  * NodeId = "datastore1"
103
- * / \
107
+ * / \\
104
108
  * OutboundRoute OutboundRoute
105
- * / \
109
+ * / \\
106
110
  * Node Node
107
111
  * NodeId = "dds1" NodeId = "dds2"
108
112
  */
@@ -112,7 +116,7 @@ class GarbageCollector {
112
116
  getNodePackagePath,
113
117
  /** Returns the timestamp of the last summary generated for this container. */
114
118
  getLastSummaryTimestampMs, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata) {
115
- var _a, _b, _c, _d, _e;
119
+ var _a, _b, _c, _d, _e, _f;
116
120
  this.runtime = runtime;
117
121
  this.gcOptions = gcOptions;
118
122
  this.getNodePackagePath = getNodePackagePath;
@@ -144,29 +148,46 @@ class GarbageCollector {
144
148
  this.loggedUnreferencedEvents = new Set();
145
149
  // Queue for unreferenced events that should be logged the next time GC runs.
146
150
  this.pendingEventsQueue = [];
147
- this.mc = telemetry_utils_1.loggerToMonitoringContext(telemetry_utils_1.ChildLogger.create(baseLogger, "GarbageCollector"));
151
+ this.mc = (0, telemetry_utils_1.loggerToMonitoringContext)(telemetry_utils_1.ChildLogger.create(baseLogger, "GarbageCollector"));
148
152
  this.deleteTimeoutMs = (_a = this.gcOptions.deleteTimeoutMs) !== null && _a !== void 0 ? _a : defaultDeleteTimeoutMs;
149
153
  let prevSummaryGCVersion;
150
- // GC can only be enabled during creation. After that, it can never be enabled again. So, for existing
151
- // documents, we get this information from the metadata blob. Similarly the session timeout should be
152
- // consistent across all clients, thus we grab it as well from the metadata blob, and set it once on creation.
154
+ /**
155
+ * The following GC state is enabled during container creation and cannot be changed throughout its lifetime:
156
+ * 1. Whether running GC mark phase is allowed or not.
157
+ * 2. Whether running GC sweep phase is allowed or not.
158
+ * 3. Whether GC session expiry is enabled or not.
159
+ * For existing containers, we get this information from the metadata blob of its summary.
160
+ */
153
161
  if (existing) {
154
- prevSummaryGCVersion = summaryFormat_1.getGCVersion(metadata);
162
+ prevSummaryGCVersion = (0, summaryFormat_1.getGCVersion)(metadata);
155
163
  // Existing documents which did not have metadata blob or had GC disabled have version as 0. For all
156
164
  // other existing documents, GC is enabled.
157
165
  this.gcEnabled = prevSummaryGCVersion > 0;
166
+ this.sweepEnabled = (_b = metadata === null || metadata === void 0 ? void 0 : metadata.sweepEnabled) !== null && _b !== void 0 ? _b : false;
158
167
  this.sessionExpiryTimeoutMs = metadata === null || metadata === void 0 ? void 0 : metadata.sessionExpiryTimeoutMs;
159
168
  }
160
169
  else {
161
- // For new documents, GC has to be explicitly enabled via the gcAllowed flag in GC options.
170
+ // Sweep should not be enabled without enabling GC mark phase. We could silently disable sweep in this
171
+ // scenario but explicitly failing makes it clearer and promotes correct usage.
172
+ if (gcOptions.sweepAllowed && !gcOptions.gcAllowed) {
173
+ throw new container_utils_1.UsageError("GC sweep phase cannot be enabled without enabling GC mark phase");
174
+ }
175
+ // For new documents, GC has to be explicitly enabled via the flags in GC options.
162
176
  this.gcEnabled = gcOptions.gcAllowed === true;
177
+ this.sweepEnabled = gcOptions.sweepAllowed === true;
163
178
  // Set the Session Expiry only if the flag is enabled or the test option is set.
164
- if (this.mc.config.getBoolean(runSessionExpiry) && this.gcEnabled) {
179
+ if (this.mc.config.getBoolean(runSessionExpiryKey) && this.gcEnabled) {
165
180
  this.sessionExpiryTimeoutMs = exports.defaultSessionExpiryDurationMs;
166
181
  }
167
182
  }
168
183
  // If session expiry is enabled, we need to close the container when the timeout expires
169
- if (this.sessionExpiryTimeoutMs !== undefined) {
184
+ if (this.sessionExpiryTimeoutMs !== undefined
185
+ && this.mc.config.getBoolean(disableSessionExpiryKey) !== true) {
186
+ // If Test Override config is set, override Session Expiry timeout
187
+ const overrideSessionExpiryTimeoutMs = this.mc.config.getNumber("Fluid.GarbageCollection.TestOverride.SessionExpiryMs");
188
+ if (overrideSessionExpiryTimeoutMs !== undefined) {
189
+ this.sessionExpiryTimeoutMs = overrideSessionExpiryTimeoutMs;
190
+ }
170
191
  const timeoutMs = this.sessionExpiryTimeoutMs;
171
192
  setLongTimeout(timeoutMs, () => {
172
193
  this.runtime.closeFn(new container_utils_1.ClientSessionExpiredError(`Client session expired.`, timeoutMs));
@@ -177,19 +198,26 @@ class GarbageCollector {
177
198
  // For existing document, the latest summary is the one that we loaded from. So, use its GC version as the
178
199
  // latest tracked GC version. For new documents, we will be writing the first summary with the current version.
179
200
  this.latestSummaryGCVersion = prevSummaryGCVersion !== null && prevSummaryGCVersion !== void 0 ? prevSummaryGCVersion : this.currentGCVersion;
180
- // Whether GC should run or not. Can override with localStorage flag.
181
- this.shouldRunGC = (_b = this.mc.config.getBoolean(runGCKey)) !== null && _b !== void 0 ? _b : (
201
+ /**
202
+ * Whether GC should run or not. The following conditions have to be met to run sweep:
203
+ * 1. GC should be enabled for this container.
204
+ * 2. GC should not be disabled via disableGC GC option.
205
+ * These conditions can be overridden via runGCKey feature flag.
206
+ */
207
+ this.shouldRunGC = (_c = this.mc.config.getBoolean(runGCKey)) !== null && _c !== void 0 ? _c : (
182
208
  // GC must be enabled for the document.
183
209
  this.gcEnabled
184
210
  // GC must not be disabled via GC options.
185
211
  && !gcOptions.disableGC);
186
- // Whether GC sweep phase should run or not. If this is false, only GC mark phase is run. Can override with
187
- // localStorage flag.
188
- this.shouldRunSweep = this.shouldRunGC &&
189
- ((_c = this.mc.config.getBoolean(runSweepKey)) !== null && _c !== void 0 ? _c : gcOptions.runSweep === true)
190
- && this.sessionExpiryTimer !== undefined;
212
+ /**
213
+ * Whether sweep should run or not. The following conditions have to be met to run sweep:
214
+ * 1. Overall GC or mark phase must be enabled (this.shouldRunGC).
215
+ * 2. Session expiry and sweep should be enabled for this container. Without session expiry we cannot safely
216
+ * delete unreferenced objects. This condition (#2) can be overridden via runSweepKey feature flag.
217
+ */
218
+ this.shouldRunSweep = this.shouldRunGC && ((_d = this.mc.config.getBoolean(runSweepKey)) !== null && _d !== void 0 ? _d : (this.sessionExpiryTimeoutMs !== undefined && this.sweepEnabled));
191
219
  // Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.
192
- this.testMode = (_d = this.mc.config.getBoolean(gcTestModeKey)) !== null && _d !== void 0 ? _d : gcOptions.runGCInTestMode === true;
220
+ this.testMode = (_e = this.mc.config.getBoolean(gcTestModeKey)) !== null && _e !== void 0 ? _e : gcOptions.runGCInTestMode === true;
193
221
  /**
194
222
  * Enable resetting initial state once the following issue is resolved:
195
223
  * https://github.com/microsoft/FluidFramework/issues/8878.
@@ -201,7 +229,7 @@ class GarbageCollector {
201
229
  // this.initialStateNeedsReset = gcTreePresent ? !this.shouldRunGC : this.shouldRunGC;
202
230
  // If `writeDataAtRoot` setting is true, write the GC data into the root of the summary tree. We do this so that
203
231
  // the roll out can be staged. Once its rolled out everywhere, we will start writing at root by default.
204
- this._writeDataAtRoot = (_e = this.mc.config.getBoolean(writeAtRootKey)) !== null && _e !== void 0 ? _e : this.gcOptions.writeDataAtRoot === true;
232
+ this._writeDataAtRoot = (_f = this.mc.config.getBoolean(writeAtRootKey)) !== null && _f !== void 0 ? _f : this.gcOptions.writeDataAtRoot === true;
205
233
  // Get the GC state from the GC blob in the base snapshot. Use LazyPromise because we only want to do
206
234
  // this once since it involves fetching blobs from storage which is expensive.
207
235
  const baseSummaryStateP = new common_utils_1.LazyPromise(async () => {
@@ -220,8 +248,8 @@ class GarbageCollector {
220
248
  // consolidate into IGarbageCollectionState format.
221
249
  // Add a node for the root node that is not present in older snapshot format.
222
250
  const gcState = { gcNodes: { "/": { outboundRoutes: [] } } };
223
- const dataStoreSnapshotTree = dataStores_1.getSummaryForDatastores(baseSnapshot, metadata);
224
- common_utils_1.assert(dataStoreSnapshotTree !== undefined, 0x2a8 /* "Expected data store snapshot tree in base snapshot" */);
251
+ const dataStoreSnapshotTree = (0, dataStores_1.getSummaryForDatastores)(baseSnapshot, metadata);
252
+ (0, common_utils_1.assert)(dataStoreSnapshotTree !== undefined, 0x2a8 /* "Expected data store snapshot tree in base snapshot" */);
225
253
  for (const [dsId, dsSnapshotTree] of Object.entries(dataStoreSnapshotTree.trees)) {
226
254
  const blobId = dsSnapshotTree.blobs[runtime_definitions_1.gcBlobKey];
227
255
  if (blobId === undefined) {
@@ -245,7 +273,7 @@ class GarbageCollector {
245
273
  const rootId = id === "/" ? dsRootId : `${dsRootId}${id}`;
246
274
  gcState.gcNodes[rootId] = { outboundRoutes: Array.from(outboundRoutes) };
247
275
  }
248
- common_utils_1.assert(gcState.gcNodes[dsRootId] !== undefined, 0x2a9 /* `GC nodes for data store ${dsId} not in GC blob` */);
276
+ (0, common_utils_1.assert)(gcState.gcNodes[dsRootId] !== undefined, 0x2a9 /* `GC nodes for data store ${dsId} not in GC blob` */);
249
277
  gcState.gcNodes[dsRootId].unreferencedTimestampMs = gcSummaryDetails.unrefTimestamp;
250
278
  }
251
279
  // If there is only one node (root node just added above), either GC is disabled or we are loading from the
@@ -286,8 +314,8 @@ class GarbageCollector {
286
314
  // Run GC on the nodes in the base summary to get the routes used in each node in the container.
287
315
  // This is an optimization for space (vs performance) wherein we don't need to store the used routes of
288
316
  // each node in the summary.
289
- const usedRoutes = garbage_collector_1.runGarbageCollection(gcNodes, ["/"], this.mc.logger).referencedNodeIds;
290
- const baseGCDetailsMap = garbage_collector_1.unpackChildNodesGCDetails({ gcData: { gcNodes }, usedRoutes });
317
+ const usedRoutes = (0, garbage_collector_1.runGarbageCollection)(gcNodes, ["/"], this.mc.logger).referencedNodeIds;
318
+ const baseGCDetailsMap = (0, garbage_collector_1.unpackChildNodesGCDetails)({ gcData: { gcNodes }, usedRoutes });
291
319
  // Currently, the nodes may write the GC data. So, we need to update it's base GC details with the
292
320
  // unreferenced timestamp. Once we start writing the GC data here, we won't need to do this anymore.
293
321
  for (const [nodeId, nodeData] of Object.entries(baseState.gcNodes)) {
@@ -319,14 +347,6 @@ class GarbageCollector {
319
347
  static create(provider, gcOptions, getNodePackagePath, getLastSummaryTimestampMs, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata) {
320
348
  return new GarbageCollector(provider, gcOptions, getNodePackagePath, getLastSummaryTimestampMs, baseSnapshot, readAndParseBlob, baseLogger, existing, metadata);
321
349
  }
322
- /**
323
- * This tracks two things:
324
- * 1. Whether GC is enabled - If this is 0, GC is disabled. If this is greater than 0, GC is enabled.
325
- * 2. If GC is enabled, the version of GC used to generate the GC data written in a summary.
326
- */
327
- get gcSummaryFeatureVersion() {
328
- return this.gcEnabled ? this.currentGCVersion : 0;
329
- }
330
350
  /**
331
351
  * Tells whether the GC state needs to be reset in the next summary. We need to do this if:
332
352
  * 1. GC was enabled and is now disabled. The GC state needs to be removed and everything becomes referenced.
@@ -354,11 +374,11 @@ class GarbageCollector {
354
374
  await this.runtime.updateStateBeforeGC();
355
375
  // Get the runtime's GC data and run GC on the reference graph in it.
356
376
  const gcData = await this.runtime.getGCData(fullGC);
357
- const gcResult = garbage_collector_1.runGarbageCollection(gcData.gcNodes, ["/"], logger);
358
- const gcStats = this.generateStatsAndLogEvents(gcResult);
377
+ const gcResult = (0, garbage_collector_1.runGarbageCollection)(gcData.gcNodes, ["/"], logger);
378
+ const gcStats = this.generateStatsAndLogEvents(gcResult, logger);
359
379
  // Update the state since the last GC run. There can be nodes that were referenced between the last and
360
380
  // the current run. We need to identify than and update their unreferenced state if needed.
361
- this.updateStateSinceLastRun(gcData);
381
+ this.updateStateSinceLastRun(gcData, logger);
362
382
  // Update the current state of the system based on the GC run.
363
383
  const currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();
364
384
  this.updateCurrentState(gcData, gcResult, currentReferenceTimestampMs);
@@ -396,6 +416,17 @@ class GarbageCollector {
396
416
  builder.addBlob(`${exports.gcBlobPrefix}_root`, JSON.stringify(gcState));
397
417
  return builder.getSummaryTree();
398
418
  }
419
+ getMetadata() {
420
+ return {
421
+ /**
422
+ * If GC is enabled, the GC data is written using the current GC version and that is the gcFeature that goes
423
+ * into the metadata blob. If GC is disabled, the gcFeature is 0.
424
+ */
425
+ gcFeature: this.gcEnabled ? this.currentGCVersion : 0,
426
+ sessionExpiryTimeoutMs: this.sessionExpiryTimeoutMs,
427
+ sweepEnabled: this.sweepEnabled,
428
+ };
429
+ }
399
430
  /**
400
431
  * Returns a map of node ids to their base GC details generated from the base summary. This is used by the caller
401
432
  * to initialize the GC state of the nodes.
@@ -469,7 +500,7 @@ class GarbageCollector {
469
500
  const metadataBlobId = snapshot.blobs[summaryFormat_1.metadataBlobName];
470
501
  if (metadataBlobId) {
471
502
  const metadata = await readAndParseBlob(metadataBlobId);
472
- this.latestSummaryGCVersion = summaryFormat_1.getGCVersion(metadata);
503
+ this.latestSummaryGCVersion = (0, summaryFormat_1.getGCVersion)(metadata);
473
504
  }
474
505
  }
475
506
  /**
@@ -482,7 +513,7 @@ class GarbageCollector {
482
513
  * @param currentReferenceTimestampMs - The timestamp to be used for unreferenced nodes' timestamp.
483
514
  */
484
515
  updateCurrentState(gcData, gcResult, currentReferenceTimestampMs) {
485
- this.previousGCDataFromLastRun = garbage_collector_1.cloneGCData(gcData);
516
+ this.previousGCDataFromLastRun = (0, garbage_collector_1.cloneGCData)(gcData);
486
517
  this.newReferencesSinceLastRun.clear();
487
518
  // Iterate through the referenced nodes and stop tracking if they were unreferenced before.
488
519
  for (const nodeId of gcResult.referencedNodeIds) {
@@ -525,7 +556,7 @@ class GarbageCollector {
525
556
  * This function identifies nodes that were referenced since last run and removes their unreferenced state, if any.
526
557
  * If these nodes are currently unreferenced, they will be assigned new unreferenced state by the current run.
527
558
  */
528
- updateStateSinceLastRun(currentGCData) {
559
+ updateStateSinceLastRun(currentGCData, logger) {
529
560
  // If we haven't run GC before there is nothing to do.
530
561
  if (this.previousGCDataFromLastRun === undefined) {
531
562
  return;
@@ -542,7 +573,7 @@ class GarbageCollector {
542
573
  gcNodeId: missingExplicitReference[0],
543
574
  gcRoutes: JSON.stringify(missingExplicitReference[1]),
544
575
  };
545
- this.mc.logger.sendPerformanceEvent(event);
576
+ logger.sendPerformanceEvent(event);
546
577
  });
547
578
  }
548
579
  // No references were added since the last run so we don't have to update reference states of any unreferenced
@@ -565,7 +596,7 @@ class GarbageCollector {
565
596
  * which is tracked by https://github.com/microsoft/FluidFramework/issues/8470.
566
597
  * - A new data store may have "root" DDSs already created and we don't detect them today.
567
598
  */
568
- const gcDataSuperSet = garbage_collector_1.concatGarbageCollectionData(this.previousGCDataFromLastRun, currentGCData);
599
+ const gcDataSuperSet = (0, garbage_collector_1.concatGarbageCollectionData)(this.previousGCDataFromLastRun, currentGCData);
569
600
  this.newReferencesSinceLastRun.forEach((outboundRoutes, sourceNodeId) => {
570
601
  if (gcDataSuperSet.gcNodes[sourceNodeId] === undefined) {
571
602
  gcDataSuperSet.gcNodes[sourceNodeId] = outboundRoutes;
@@ -579,7 +610,7 @@ class GarbageCollector {
579
610
  * unreferenced, stop tracking them and remove from unreferenced list.
580
611
  * Some of these nodes may be unreferenced now and if so, the current run will add unreferenced state for them.
581
612
  */
582
- const gcResult = garbage_collector_1.runGarbageCollection(gcDataSuperSet.gcNodes, ["/"], this.mc.logger);
613
+ const gcResult = (0, garbage_collector_1.runGarbageCollection)(gcDataSuperSet.gcNodes, ["/"], logger);
583
614
  for (const nodeId of gcResult.referencedNodeIds) {
584
615
  const nodeStateTracker = this.unreferencedNodesState.get(nodeId);
585
616
  if (nodeStateTracker !== undefined) {
@@ -604,7 +635,7 @@ class GarbageCollector {
604
635
  * @returns - a list of missing explicit references
605
636
  */
606
637
  findMissingExplicitReferences(currentGCData, previousGCData, explicitReferences) {
607
- common_utils_1.assert(previousGCData !== undefined, 0x2b7);
638
+ (0, common_utils_1.assert)(previousGCData !== undefined, 0x2b7);
608
639
  const currentGraph = Object.entries(currentGCData.gcNodes);
609
640
  const missingExplicitReferences = [];
610
641
  currentGraph.forEach(([nodeId, currentOutboundRoutes]) => {
@@ -637,13 +668,13 @@ class GarbageCollector {
637
668
  * @param gcResult - The result of a GC run.
638
669
  * @returns the GC stats of the GC run.
639
670
  */
640
- generateStatsAndLogEvents(gcResult) {
671
+ generateStatsAndLogEvents(gcResult, logger) {
641
672
  // Log pending events for unreferenced nodes after GC has run. We should have the package data available for
642
673
  // them now since the GC run should have loaded these nodes.
643
674
  let event = this.pendingEventsQueue.shift();
644
675
  while (event !== undefined) {
645
676
  const pkg = this.getNodePackagePath(event.id);
646
- this.mc.logger.sendErrorEvent(Object.assign(Object.assign({}, event), { pkg: pkg ? { value: `/${pkg.join("/")}`, tag: telemetry_utils_1.TelemetryDataTag.PackageData } : undefined }));
677
+ logger.sendErrorEvent(Object.assign(Object.assign({}, event), { pkg: pkg ? { value: `/${pkg.join("/")}`, tag: telemetry_utils_1.TelemetryDataTag.PackageData } : undefined }));
647
678
  event = this.pendingEventsQueue.shift();
648
679
  }
649
680
  const gcStats = {
@@ -750,9 +781,9 @@ async function getGCStateFromSnapshot(gcSnapshotTree, readAndParseBlob) {
750
781
  continue;
751
782
  }
752
783
  const gcState = await readAndParseBlob(blobId);
753
- common_utils_1.assert(gcState !== undefined, 0x2ad /* "GC blob missing from snapshot" */);
784
+ (0, common_utils_1.assert)(gcState !== undefined, 0x2ad /* "GC blob missing from snapshot" */);
754
785
  // Merge the GC state of this blob into the root GC state.
755
- rootGCState = garbage_collector_1.concatGarbageCollectionStates(rootGCState, gcState);
786
+ rootGCState = (0, garbage_collector_1.concatGarbageCollectionStates)(rootGCState, gcState);
756
787
  }
757
788
  return rootGCState;
758
789
  }