@fluidframework/container-runtime 2.0.0-internal.6.3.2 → 2.0.0-internal.6.3.4

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 (45) hide show
  1. package/dist/containerRuntime.d.ts.map +1 -1
  2. package/dist/containerRuntime.js +0 -20
  3. package/dist/containerRuntime.js.map +1 -1
  4. package/dist/gc/garbageCollection.d.ts.map +1 -1
  5. package/dist/gc/garbageCollection.js +7 -9
  6. package/dist/gc/garbageCollection.js.map +1 -1
  7. package/dist/gc/gcConfigs.js +1 -1
  8. package/dist/gc/gcConfigs.js.map +1 -1
  9. package/dist/gc/gcDefinitions.d.ts +4 -4
  10. package/dist/gc/gcDefinitions.d.ts.map +1 -1
  11. package/dist/gc/gcDefinitions.js +6 -6
  12. package/dist/gc/gcDefinitions.js.map +1 -1
  13. package/dist/gc/index.d.ts +1 -1
  14. package/dist/gc/index.d.ts.map +1 -1
  15. package/dist/gc/index.js +3 -3
  16. package/dist/gc/index.js.map +1 -1
  17. package/dist/packageVersion.d.ts +1 -1
  18. package/dist/packageVersion.js +1 -1
  19. package/dist/packageVersion.js.map +1 -1
  20. package/lib/containerRuntime.d.ts.map +1 -1
  21. package/lib/containerRuntime.js +0 -20
  22. package/lib/containerRuntime.js.map +1 -1
  23. package/lib/gc/garbageCollection.d.ts.map +1 -1
  24. package/lib/gc/garbageCollection.js +7 -9
  25. package/lib/gc/garbageCollection.js.map +1 -1
  26. package/lib/gc/gcConfigs.js +2 -2
  27. package/lib/gc/gcConfigs.js.map +1 -1
  28. package/lib/gc/gcDefinitions.d.ts +4 -4
  29. package/lib/gc/gcDefinitions.d.ts.map +1 -1
  30. package/lib/gc/gcDefinitions.js +5 -5
  31. package/lib/gc/gcDefinitions.js.map +1 -1
  32. package/lib/gc/index.d.ts +1 -1
  33. package/lib/gc/index.d.ts.map +1 -1
  34. package/lib/gc/index.js +1 -1
  35. package/lib/gc/index.js.map +1 -1
  36. package/lib/packageVersion.d.ts +1 -1
  37. package/lib/packageVersion.js +1 -1
  38. package/lib/packageVersion.js.map +1 -1
  39. package/package.json +15 -15
  40. package/src/containerRuntime.ts +0 -29
  41. package/src/gc/garbageCollection.ts +7 -9
  42. package/src/gc/gcConfigs.ts +3 -3
  43. package/src/gc/gcDefinitions.ts +5 -5
  44. package/src/gc/index.ts +2 -2
  45. package/src/packageVersion.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"garbageCollection.d.ts","sourceRoot":"","sources":["../../src/gc/garbageCollection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"garbageCollection.d.ts","sourceRoot":"","sources":["../../src/gc/garbageCollection.ts"],"names":[],"mappings":"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"}
@@ -169,15 +169,13 @@ class GarbageCollector {
169
169
  const usedRoutes = (0, gcReferenceGraphAlgorithm_1.runGarbageCollection)(gcNodes, ["/"]).referencedNodeIds;
170
170
  return { gcData: { gcNodes }, usedRoutes };
171
171
  });
172
- // Log all the GC options and the state determined by the garbage collector. This is interesting only for the
173
- // summarizer client since it is the only one that runs GC. It also helps keep the telemetry less noisy.
174
- if (this.isSummarizerClient) {
175
- this.mc.logger.sendTelemetryEvent({
176
- eventName: "GarbageCollectorLoaded",
177
- gcConfigs: JSON.stringify(this.configs),
178
- gcOptions: JSON.stringify(createParams.gcOptions),
179
- });
180
- }
172
+ // Log all the GC options and the state determined by the garbage collector.
173
+ // This is useful even for interactive clients since they track unreferenced nodes and log errors.
174
+ this.mc.logger.sendTelemetryEvent({
175
+ eventName: "GarbageCollectorLoaded",
176
+ gcConfigs: JSON.stringify(this.configs),
177
+ gcOptions: JSON.stringify(createParams.gcOptions),
178
+ });
181
179
  }
182
180
  static create(createParams) {
183
181
  return new GarbageCollector(createParams);
@@ -1 +1 @@
1
- {"version":3,"file":"garbageCollection.js","sourceRoot":"","sources":["../../src/gc/garbageCollection.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { LazyPromise, Timer } from \"@fluidframework/core-utils\";\nimport { IRequest, IRequestHeader } from \"@fluidframework/core-interfaces\";\nimport {\n\tgcTreeKey,\n\tIGarbageCollectionData,\n\tIGarbageCollectionDetailsBase,\n\tISummarizeResult,\n\tITelemetryContext,\n} from \"@fluidframework/runtime-definitions\";\nimport { createResponseError, responseToException } from \"@fluidframework/runtime-utils\";\nimport {\n\tcreateChildLogger,\n\tcreateChildMonitoringContext,\n\tDataProcessingError,\n\tITelemetryLoggerExt,\n\tMonitoringContext,\n\tPerformanceEvent,\n} from \"@fluidframework/telemetry-utils\";\n\nimport {\n\tAllowInactiveRequestHeaderKey,\n\tInactiveResponseHeaderKey,\n\tRuntimeHeaders,\n} from \"../containerRuntime\";\nimport { ClientSessionExpiredError } from \"../error\";\nimport { IRefreshSummaryResult } from \"../summary\";\nimport { generateGCConfigs } from \"./gcConfigs\";\nimport {\n\tGCNodeType,\n\tIGarbageCollector,\n\tIGarbageCollectorCreateParams,\n\tIGarbageCollectionRuntime,\n\tIGCResult,\n\tIGCStats,\n\tUnreferencedState,\n\tIGCMetadata,\n\tIGarbageCollectorConfigs,\n} from \"./gcDefinitions\";\nimport { cloneGCData, concatGarbageCollectionData, getGCDataFromSnapshot } from \"./gcHelpers\";\nimport { runGarbageCollection } from \"./gcReferenceGraphAlgorithm\";\nimport { IGarbageCollectionSnapshotData, IGarbageCollectionState } from \"./gcSummaryDefinitions\";\nimport { GCSummaryStateTracker } from \"./gcSummaryStateTracker\";\nimport { UnreferencedStateTracker } from \"./gcUnreferencedStateTracker\";\nimport { GCTelemetryTracker } from \"./gcTelemetry\";\n\n/**\n * The garbage collector for the container runtime. It consolidates the garbage collection functionality and maintains\n * its state across summaries.\n *\n * Node - represented as nodeId, it's a node on the GC graph\n *\n * Outbound Route - a path from one node to another node, think `nodeA` -\\> `nodeB`\n *\n * Graph - all nodes with their respective routes\n *\n * ```\n *\t\t\t GC Graph\n *\n *\t\t\t Node\n *\t\tNodeId = \"datastore1\"\n *\t\t /\t\t\t \\\\\n *\tOutboundRoute OutboundRoute\n *\t\t /\t\t\t\t \\\\\n *\t Node\t\t\t Node\n * NodeId = \"dds1\"\t NodeId = \"dds2\"\n * ```\n */\nexport class GarbageCollector implements IGarbageCollector {\n\tpublic static create(createParams: IGarbageCollectorCreateParams): IGarbageCollector {\n\t\treturn new GarbageCollector(createParams);\n\t}\n\n\tprivate readonly mc: MonitoringContext;\n\n\tprivate readonly configs: IGarbageCollectorConfigs;\n\n\tpublic get shouldRunGC(): boolean {\n\t\treturn this.configs.shouldRunGC;\n\t}\n\n\t// Keeps track of the GC state from the last run.\n\tprivate gcDataFromLastRun: IGarbageCollectionData | undefined;\n\t// Keeps a list of references (edges in the GC graph) between GC runs. Each entry has a node id and a list of\n\t// outbound routes from that node.\n\tprivate readonly newReferencesSinceLastRun: Map<string, string[]> = new Map();\n\t// A list of nodes that have been tombstoned.\n\tprivate tombstones: string[] = [];\n\t// A list of nodes that have been deleted during sweep phase.\n\tprivate deletedNodes: Set<string> = new Set();\n\n\t// Promise when resolved returns the GC data data in the base snapshot.\n\tprivate readonly baseSnapshotDataP: Promise<IGarbageCollectionSnapshotData | undefined>;\n\t// Promise when resolved initializes the GC state from the data in the base snapshot.\n\tprivate readonly initializeGCStateFromBaseSnapshotP: Promise<void>;\n\t// The GC details generated from the base snapshot.\n\tprivate readonly baseGCDetailsP: Promise<IGarbageCollectionDetailsBase>;\n\t// Map of node ids to their unreferenced state tracker.\n\tprivate readonly unreferencedNodesState: Map<string, UnreferencedStateTracker> = new Map();\n\t// The Timer responsible for closing the container when the session has expired\n\tprivate sessionExpiryTimer: Timer | undefined;\n\n\t// The number of times GC has successfully completed on this instance of GarbageCollector.\n\tprivate completedRuns = 0;\n\n\tprivate readonly runtime: IGarbageCollectionRuntime;\n\tprivate readonly isSummarizerClient: boolean;\n\n\tprivate readonly summaryStateTracker: GCSummaryStateTracker;\n\tprivate readonly telemetryTracker: GCTelemetryTracker;\n\n\t/** For a given node path, returns the node's package path. */\n\tprivate readonly getNodePackagePath: (\n\t\tnodePath: string,\n\t) => Promise<readonly string[] | undefined>;\n\t/** Returns the timestamp of the last summary generated for this container. */\n\tprivate readonly getLastSummaryTimestampMs: () => number | undefined;\n\t/** Returns true if connection is active, i.e. it's \"write\" connection and the runtime is connected. */\n\tprivate readonly activeConnection: () => boolean;\n\n\tpublic get summaryStateNeedsReset(): boolean {\n\t\treturn this.summaryStateTracker.doesSummaryStateNeedReset;\n\t}\n\n\t/** Returns the count of data stores whose GC state updated since the last summary. */\n\tpublic get updatedDSCountSinceLastSummary(): number {\n\t\treturn this.summaryStateTracker.updatedDSCountSinceLastSummary;\n\t}\n\n\tprotected constructor(createParams: IGarbageCollectorCreateParams) {\n\t\tthis.runtime = createParams.runtime;\n\t\tthis.isSummarizerClient = createParams.isSummarizerClient;\n\t\tthis.getNodePackagePath = createParams.getNodePackagePath;\n\t\tthis.getLastSummaryTimestampMs = createParams.getLastSummaryTimestampMs;\n\t\tthis.activeConnection = createParams.activeConnection;\n\n\t\tconst baseSnapshot = createParams.baseSnapshot;\n\t\tconst readAndParseBlob = createParams.readAndParseBlob;\n\n\t\tthis.mc = createChildMonitoringContext({\n\t\t\tlogger: createParams.baseLogger,\n\t\t\tnamespace: \"GarbageCollector\",\n\t\t\tproperties: {\n\t\t\t\tall: { completedGCRuns: () => this.completedRuns },\n\t\t\t},\n\t\t});\n\n\t\tthis.configs = generateGCConfigs(this.mc, createParams);\n\n\t\t// If session expiry is enabled, we need to close the container when the session expiry timeout expires.\n\t\tif (this.configs.sessionExpiryTimeoutMs !== undefined) {\n\t\t\t// If Test Override config is set, override Session Expiry timeout.\n\t\t\tconst overrideSessionExpiryTimeoutMs = this.mc.config.getNumber(\n\t\t\t\t\"Fluid.GarbageCollection.TestOverride.SessionExpiryMs\",\n\t\t\t);\n\t\t\tconst timeoutMs = overrideSessionExpiryTimeoutMs ?? this.configs.sessionExpiryTimeoutMs;\n\n\t\t\tthis.sessionExpiryTimer = new Timer(timeoutMs, () => {\n\t\t\t\tthis.runtime.closeFn(\n\t\t\t\t\tnew ClientSessionExpiredError(`Client session expired.`, timeoutMs),\n\t\t\t\t);\n\t\t\t});\n\t\t\tthis.sessionExpiryTimer.start();\n\t\t}\n\n\t\tthis.summaryStateTracker = new GCSummaryStateTracker(\n\t\t\tthis.configs,\n\t\t\tbaseSnapshot?.trees[gcTreeKey] !== undefined /* wasGCRunInBaseSnapshot */,\n\t\t);\n\n\t\tthis.telemetryTracker = new GCTelemetryTracker(\n\t\t\tthis.mc,\n\t\t\tthis.configs,\n\t\t\tthis.isSummarizerClient,\n\t\t\tthis.runtime.gcTombstoneEnforcementAllowed,\n\t\t\tcreateParams.createContainerMetadata,\n\t\t\t(nodeId: string) => this.runtime.getNodeType(nodeId),\n\t\t\t(nodeId: string) => this.unreferencedNodesState.get(nodeId),\n\t\t\tthis.getNodePackagePath,\n\t\t);\n\n\t\t// Get the GC data from the base snapshot. Use LazyPromise because we only want to do this once since it\n\t\t// it involves fetching blobs from storage which is expensive.\n\t\tthis.baseSnapshotDataP = new LazyPromise<IGarbageCollectionSnapshotData | undefined>(\n\t\t\tasync () => {\n\t\t\t\tif (baseSnapshot === undefined) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\t// For newer documents, GC data should be present in the GC tree in the root of the snapshot.\n\t\t\t\t\tconst gcSnapshotTree = baseSnapshot.trees[gcTreeKey];\n\t\t\t\t\tif (gcSnapshotTree === undefined) {\n\t\t\t\t\t\t// back-compat - Older documents get their gc data reset for simplicity as there are few of them\n\t\t\t\t\t\t// incremental gc summary will not work with older gc data as well\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst snapshotData = await getGCDataFromSnapshot(\n\t\t\t\t\t\tgcSnapshotTree,\n\t\t\t\t\t\treadAndParseBlob,\n\t\t\t\t\t);\n\n\t\t\t\t\t// If the GC version in base snapshot does not match the GC version currently in effect, the GC data\n\t\t\t\t\t// in the snapshot cannot be interpreted correctly. Set everything to undefined except for\n\t\t\t\t\t// deletedNodes because irrespective of GC versions, these nodes have been deleted and cannot be\n\t\t\t\t\t// brought back. The deletedNodes info is needed to identify when these nodes are used.\n\t\t\t\t\tif (this.configs.gcVersionInEffect !== this.configs.gcVersionInBaseSnapshot) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tgcState: undefined,\n\t\t\t\t\t\t\ttombstones: undefined,\n\t\t\t\t\t\t\tdeletedNodes: snapshotData.deletedNodes,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn snapshotData;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst dpe = DataProcessingError.wrapIfUnrecognized(\n\t\t\t\t\t\terror,\n\t\t\t\t\t\t\"FailedToInitializeGC\",\n\t\t\t\t\t);\n\t\t\t\t\tdpe.addTelemetryProperties({\n\t\t\t\t\t\tgcConfigs: JSON.stringify(this.configs),\n\t\t\t\t\t});\n\t\t\t\t\tthrow dpe;\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\t/**\n\t\t * Set up the initializer which initializes the GC state from the data in base snapshot. This is done when\n\t\t * connected in write mode or when GC runs the first time. It sets up all unreferenced nodes from the base\n\t\t * GC state and updates their inactive or sweep ready state.\n\t\t */\n\t\tthis.initializeGCStateFromBaseSnapshotP = new LazyPromise<void>(async () => {\n\t\t\t/**\n\t\t\t * If there is no current reference timestamp, skip initialization. We need the current timestamp to track\n\t\t\t * how long objects have been unreferenced and if they can be deleted.\n\t\t\t *\n\t\t\t * Note that the only scenario where there is no reference timestamp is when no ops have ever been processed\n\t\t\t * for this container and it is in read mode. In this scenario, there is no point in running GC anyway\n\t\t\t * because references in the container do not change without any ops, i.e., there is nothing to collect.\n\t\t\t */\n\t\t\tconst currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();\n\t\t\tif (currentReferenceTimestampMs === undefined) {\n\t\t\t\t// Log an event so we can evaluate how often we run into this scenario.\n\t\t\t\tthis.mc.logger.sendErrorEvent({\n\t\t\t\t\teventName: \"GarbageCollectorInitializedWithoutTimestamp\",\n\t\t\t\t\tgcConfigs: JSON.stringify(this.configs),\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t/**\n\t\t\t * The base snapshot data will not be present if the container is loaded from:\n\t\t\t * 1. The first summary created by the detached container.\n\t\t\t * 2. A summary that was generated with GC disabled.\n\t\t\t * 3. A summary that was generated before GC even existed.\n\t\t\t */\n\t\t\tconst baseSnapshotData = await this.baseSnapshotDataP;\n\t\t\tif (baseSnapshotData === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.updateStateFromSnapshotData(baseSnapshotData, currentReferenceTimestampMs);\n\t\t\tthis.summaryStateTracker.initializeBaseState(baseSnapshotData);\n\t\t});\n\n\t\t// Get the GC details from the GC state in the base summary. This is returned in getBaseGCDetails which is\n\t\t// used to initialize the GC state of all the nodes in the container.\n\t\tthis.baseGCDetailsP = new LazyPromise<IGarbageCollectionDetailsBase>(async () => {\n\t\t\tconst baseSnapshotData = await this.baseSnapshotDataP;\n\t\t\tif (baseSnapshotData?.gcState === undefined) {\n\t\t\t\treturn {};\n\t\t\t}\n\n\t\t\tconst gcNodes: { [id: string]: string[] } = {};\n\t\t\tfor (const [nodeId, nodeData] of Object.entries(baseSnapshotData.gcState.gcNodes)) {\n\t\t\t\tgcNodes[nodeId] = Array.from(nodeData.outboundRoutes);\n\t\t\t}\n\t\t\t// Run GC on the nodes in the base summary to get the routes used in each node in the container.\n\t\t\t// This is an optimization for space (vs performance) wherein we don't need to store the used routes of\n\t\t\t// each node in the summary.\n\t\t\tconst usedRoutes = runGarbageCollection(gcNodes, [\"/\"]).referencedNodeIds;\n\n\t\t\treturn { gcData: { gcNodes }, usedRoutes };\n\t\t});\n\n\t\t// Log all the GC options and the state determined by the garbage collector. This is interesting only for the\n\t\t// summarizer client since it is the only one that runs GC. It also helps keep the telemetry less noisy.\n\t\tif (this.isSummarizerClient) {\n\t\t\tthis.mc.logger.sendTelemetryEvent({\n\t\t\t\teventName: \"GarbageCollectorLoaded\",\n\t\t\t\tgcConfigs: JSON.stringify(this.configs),\n\t\t\t\tgcOptions: JSON.stringify(createParams.gcOptions),\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Called during container initialization. Initialize from the tombstone state in the base snapshot. This is done\n\t * during initialization so that deleted or tombstoned objects are marked as such before they are loaded or used.\n\t */\n\tpublic async initializeBaseState(): Promise<void> {\n\t\tconst baseSnapshotData = await this.baseSnapshotDataP;\n\t\t/**\n\t\t * The base snapshot data will not be present if the container is loaded from:\n\t\t * 1. The first summary created by the detached container.\n\t\t * 2. A summary that was generated with GC disabled.\n\t\t * 3. A summary that was generated before GC even existed.\n\t\t */\n\t\tif (baseSnapshotData === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Initialize the deleted nodes from the snapshot. This is done irrespective of whether sweep is enabled or not\n\t\t// to identify deleted nodes' usage.\n\t\tif (baseSnapshotData.deletedNodes !== undefined) {\n\t\t\tthis.deletedNodes = new Set(baseSnapshotData.deletedNodes);\n\t\t}\n\n\t\t// If running in tombstone mode, initialize the tombstone state from the snapshot. Also, notify the runtime of\n\t\t// tombstone routes.\n\t\tif (this.configs.tombstoneMode && baseSnapshotData.tombstones !== undefined) {\n\t\t\t// Create a copy since we are writing from a source we don't control\n\t\t\tthis.tombstones = Array.from(baseSnapshotData.tombstones);\n\t\t\tthis.runtime.updateTombstonedRoutes(this.tombstones);\n\t\t}\n\t}\n\n\t/**\n\t * Update state from the given snapshot data. This is done during load and during refreshing state from a snapshot.\n\t * All current tracking is reset and updated from the data in the snapshot.\n\t * @param snapshotData - The snapshot data to update state from. If this is undefined, all GC state and tracking\n\t * is reset.\n\t * @param currentReferenceTimestampMs - The current reference timestamp for marking unreferenced nodes' unreferenced\n\t * timestamp.\n\t */\n\tprivate updateStateFromSnapshotData(\n\t\tsnapshotData: IGarbageCollectionSnapshotData | undefined,\n\t\tcurrentReferenceTimestampMs: number,\n\t) {\n\t\t/**\n\t\t * Note: \"newReferencesSinceLastRun\" is not reset here. This is done because there may be references since the\n\t\t * snapshot that we are updating state from. For example, this client may have processed ops till seq#1000 and\n\t\t * its refreshing state from a summary that happened at seq#900. In this case, there may be references between\n\t\t * seq#901 and seq#1000 that we don't want to reset.\n\t\t * Unfortunately, there is no way to track the seq# of ops that add references, so we choose to not reset any\n\t\t * references here. This should be fine because, in the worst case, we may end up updating the unreferenced\n\t\t * timestamp of a node which will delay its deletion. Although not ideal, this will only happen in rare\n\t\t * scenarios, so it should be okay.\n\t\t */\n\n\t\t// Clear all existing unreferenced state tracking.\n\t\tfor (const [, nodeStateTracker] of this.unreferencedNodesState) {\n\t\t\tnodeStateTracker.stopTracking();\n\t\t}\n\t\tthis.unreferencedNodesState.clear();\n\n\t\t// If running sweep, the tombstone state represents the list of nodes that have been deleted during sweep.\n\t\t// If running in tombstone mode, the tombstone state represents the list of nodes that have been marked as\n\t\t// tombstones.\n\t\t// If this call is because we are refreshing from a snapshot due to an ack, it is likely that the GC state\n\t\t// in the snapshot is newer than this client's. And so, the deleted / tombstone nodes need to be updated.\n\t\tif (this.configs.shouldRunSweep) {\n\t\t\tconst snapshotDeletedNodes = snapshotData?.deletedNodes\n\t\t\t\t? new Set(snapshotData.deletedNodes)\n\t\t\t\t: undefined;\n\t\t\t// If the snapshot contains deleted nodes that are not yet deleted by this client, ask the runtime to\n\t\t\t// delete them.\n\t\t\tif (snapshotDeletedNodes !== undefined) {\n\t\t\t\tconst newDeletedNodes: string[] = [];\n\t\t\t\tfor (const nodeId of snapshotDeletedNodes) {\n\t\t\t\t\tif (!this.deletedNodes.has(nodeId)) {\n\t\t\t\t\t\tnewDeletedNodes.push(nodeId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (newDeletedNodes.length > 0) {\n\t\t\t\t\t// Call container runtime to delete these nodes and add deleted nodes to this.deletedNodes.\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.configs.tombstoneMode) {\n\t\t\t// The snapshot may contain more or fewer tombstone nodes than this client. Update tombstone state and\n\t\t\t// notify the runtime to update its state as well.\n\t\t\tthis.tombstones = snapshotData?.tombstones ? Array.from(snapshotData.tombstones) : [];\n\t\t\tthis.runtime.updateTombstonedRoutes(this.tombstones);\n\t\t}\n\n\t\t// If there is no snapshot data, it means this snapshot was generated with GC disabled. Unset all GC state.\n\t\tif (snapshotData?.gcState === undefined) {\n\t\t\tthis.gcDataFromLastRun = undefined;\n\t\t\treturn;\n\t\t}\n\n\t\t// Update unreferenced state tracking as per the GC state in the snapshot data and update gcDataFromLastRun\n\t\t// to the GC data from the snapshot data.\n\t\tconst gcNodes: { [id: string]: string[] } = {};\n\t\tfor (const [nodeId, nodeData] of Object.entries(snapshotData.gcState.gcNodes)) {\n\t\t\tif (nodeData.unreferencedTimestampMs !== undefined) {\n\t\t\t\tthis.unreferencedNodesState.set(\n\t\t\t\t\tnodeId,\n\t\t\t\t\tnew UnreferencedStateTracker(\n\t\t\t\t\t\tnodeData.unreferencedTimestampMs,\n\t\t\t\t\t\tthis.configs.inactiveTimeoutMs,\n\t\t\t\t\t\tcurrentReferenceTimestampMs,\n\t\t\t\t\t\tthis.configs.sweepTimeoutMs,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tgcNodes[nodeId] = Array.from(nodeData.outboundRoutes);\n\t\t}\n\t\tthis.gcDataFromLastRun = { gcNodes };\n\t}\n\n\t/**\n\t * Called when the connection state of the runtime changes, i.e., it connects or disconnects. GC subscribes to this\n\t * to initialize the base state for non-summarizer clients so that they can track inactive / sweep ready nodes.\n\t * @param connected - Whether the runtime connected / disconnected.\n\t * @param clientId - The clientId of this runtime.\n\t */\n\tpublic setConnectionState(connected: boolean, clientId?: string | undefined): void {\n\t\t/**\n\t\t * For all clients, initialize the base state when the container becomes active, i.e., it transitions\n\t\t * to \"write\" mode. This will ensure that the container's own join op is processed and there is a recent\n\t\t * reference timestamp that will be used to update the state of unreferenced nodes. Also, all trailing ops which\n\t\t * could affect the GC state will have been processed.\n\t\t *\n\t\t * If GC is up-to-date for the client and the summarizing client, there will be an doubling of both\n\t\t * InactiveObject_Loaded and SweepReady_Loaded errors, as there will be one from the sending client and one from\n\t\t * the receiving summarizer client.\n\t\t *\n\t\t * Ideally, this initialization should only be done for summarizer client. However, we are currently rolling out\n\t\t * sweep in phases and we want to track when inactive and sweep ready objects are used in any client.\n\t\t */\n\t\tif (this.activeConnection() && this.configs.shouldRunGC) {\n\t\t\tthis.initializeGCStateFromBaseSnapshotP.catch((error) => {});\n\t\t}\n\t}\n\n\t/**\n\t * Returns a the GC details generated from the base summary. This is used to initialize the GC state of the nodes\n\t * in the container.\n\t */\n\tpublic async getBaseGCDetails(): Promise<IGarbageCollectionDetailsBase> {\n\t\treturn this.baseGCDetailsP;\n\t}\n\n\t/**\n\t * Runs garbage collection and updates the reference / used state of the nodes in the container.\n\t * @returns stats of the GC run or undefined if GC did not run.\n\t */\n\tpublic async collectGarbage(\n\t\toptions: {\n\t\t\t/** Logger to use for logging GC events */\n\t\t\tlogger?: ITelemetryLoggerExt;\n\t\t\t/** True to run GC sweep phase after the mark phase */\n\t\t\trunSweep?: boolean;\n\t\t\t/** True to generate full GC data */\n\t\t\tfullGC?: boolean;\n\t\t},\n\t\ttelemetryContext?: ITelemetryContext,\n\t): Promise<IGCStats | undefined> {\n\t\tconst fullGC =\n\t\t\toptions.fullGC ??\n\t\t\t(this.configs.runFullGC === true || this.summaryStateTracker.doesSummaryStateNeedReset);\n\n\t\t// Add the options that are used to run GC to the telemetry context.\n\t\ttelemetryContext?.setMultiple(\"fluid_GC\", \"Options\", {\n\t\t\tfullGC,\n\t\t\trunSweep: options.runSweep,\n\t\t});\n\n\t\tconst logger = options.logger\n\t\t\t? createChildLogger({\n\t\t\t\t\tlogger: options.logger,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tall: { completedGCRuns: () => this.completedRuns },\n\t\t\t\t\t},\n\t\t\t })\n\t\t\t: this.mc.logger;\n\n\t\t/**\n\t\t * If there is no current reference timestamp, skip running GC. We need the current timestamp to track\n\t\t * how long objects have been unreferenced and if they should be deleted.\n\t\t *\n\t\t * Note that the only scenario where GC is called and there is no reference timestamp is when no ops have ever\n\t\t * been processed for this container and it is in read mode. In this scenario, there is no point in running GC\n\t\t * anyway because references in the container do not change without any ops, i.e., there is nothing to collect.\n\t\t */\n\t\tconst currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();\n\t\tif (currentReferenceTimestampMs === undefined) {\n\t\t\t// Log an event so we can evaluate how often we run into this scenario.\n\t\t\tlogger.sendErrorEvent({\n\t\t\t\teventName: \"CollectGarbageCalledWithoutTimestamp\",\n\t\t\t\tgcConfigs: JSON.stringify(this.configs),\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\tlogger,\n\t\t\t{ eventName: \"GarbageCollection\" },\n\t\t\tasync (event) => {\n\t\t\t\t/** Pre-GC steps */\n\t\t\t\t// Ensure that state has been initialized from the base snapshot data.\n\t\t\t\tawait this.initializeGCStateFromBaseSnapshotP;\n\t\t\t\t// Let the runtime update its pending state before GC runs.\n\t\t\t\tawait this.runtime.updateStateBeforeGC();\n\n\t\t\t\t/** GC step */\n\t\t\t\tconst gcStats = await this.runGC(fullGC, currentReferenceTimestampMs, logger);\n\t\t\t\tevent.end({ ...gcStats, timestamp: currentReferenceTimestampMs });\n\n\t\t\t\t/** Post-GC steps */\n\t\t\t\t// Log pending unreferenced events such as a node being used after inactive. This is done after GC runs and\n\t\t\t\t// updates its state so that we don't send false positives based on intermediate state. For example, we may get\n\t\t\t\t// reference to an unreferenced node from another unreferenced node which means the node wasn't revived.\n\t\t\t\tawait this.telemetryTracker.logPendingEvents(logger);\n\t\t\t\t// Update the state of summary state tracker from this run's stats.\n\t\t\t\tthis.summaryStateTracker.updateStateFromGCRunStats(gcStats);\n\t\t\t\tthis.newReferencesSinceLastRun.clear();\n\t\t\t\tthis.completedRuns++;\n\n\t\t\t\treturn gcStats;\n\t\t\t},\n\t\t\t{ end: true, cancel: \"error\" },\n\t\t);\n\t}\n\n\t/**\n\t * Runs garbage collection. It does the following:\n\t * 1. It generates / analyzes the runtime's reference graph.\n\t * 2. Generates stats for the GC run based on previous / current GC state.\n\t * 3. Runs Mark phase.\n\t * 4. Runs Sweep phase.\n\t */\n\tprivate async runGC(\n\t\tfullGC: boolean,\n\t\tcurrentReferenceTimestampMs: number,\n\t\tlogger: ITelemetryLoggerExt,\n\t): Promise<IGCStats> {\n\t\t// 1. Generate / analyze the runtime's reference graph.\n\t\t// Get the reference graph (gcData) and run GC algorithm to get referenced / unreferenced nodes.\n\t\tconst gcData = await this.runtime.getGCData(fullGC);\n\t\tconst gcResult = runGarbageCollection(gcData.gcNodes, [\"/\"]);\n\t\t// Get all referenced nodes - References in this run + references between the previous and current runs.\n\t\tconst allReferencedNodeIds =\n\t\t\tthis.findAllNodesReferencedBetweenGCs(gcData, this.gcDataFromLastRun, logger) ??\n\t\t\tgcResult.referencedNodeIds;\n\n\t\t// 2. Generate stats based on the previous / current GC state.\n\t\t// Must happen before running Mark / Sweep phase because previous GC state will be updated in these stages.\n\t\tconst gcStats = this.generateStats(gcResult);\n\n\t\t// 3. Run the Mark phase.\n\t\t// It will mark nodes as referenced / unreferenced and return a list of node ids that are ready to be swept.\n\t\tconst sweepReadyNodeIds = this.runMarkPhase(\n\t\t\tgcResult,\n\t\t\tallReferencedNodeIds,\n\t\t\tcurrentReferenceTimestampMs,\n\t\t);\n\n\t\t// 4. Run the Sweep phase.\n\t\t// It will delete sweep ready nodes and return a list of deleted node ids.\n\t\tconst deletedNodeIds = this.runSweepPhase(\n\t\t\tgcResult,\n\t\t\tsweepReadyNodeIds,\n\t\t\tcurrentReferenceTimestampMs,\n\t\t\tlogger,\n\t\t);\n\n\t\tthis.gcDataFromLastRun = cloneGCData(\n\t\t\tgcData,\n\t\t\t(id: string) => deletedNodeIds.includes(id) /* filter out deleted nodes */,\n\t\t);\n\t\treturn gcStats;\n\t}\n\n\t/**\n\t * Runs the GC Mark phase. It does the following:\n\t * 1. Marks all referenced nodes in this run by clearing tracking for them.\n\t * 2. Marks unreferenced nodes in this run by starting tracking for them.\n\t * 3. Calls the runtime to update nodes that were marked referenced.\n\t *\n\t * @param gcResult - The result of the GC run on the gcData.\n\t * @param allReferencedNodeIds - Nodes referenced in this GC run + referenced between previous and current GC run.\n\t * @param currentReferenceTimestampMs - The timestamp to be used for unreferenced nodes' timestamp.\n\t * @returns - A list of sweep ready nodes, i.e., nodes that ready to be deleted.\n\t */\n\tprivate runMarkPhase(\n\t\tgcResult: IGCResult,\n\t\tallReferencedNodeIds: string[],\n\t\tcurrentReferenceTimestampMs: number,\n\t): string[] {\n\t\t// 1. Marks all referenced nodes by clearing their unreferenced tracker, if any.\n\t\tfor (const nodeId of allReferencedNodeIds) {\n\t\t\tconst nodeStateTracker = this.unreferencedNodesState.get(nodeId);\n\t\t\tif (nodeStateTracker !== undefined) {\n\t\t\t\t// Stop tracking so as to clear out any running timers.\n\t\t\t\tnodeStateTracker.stopTracking();\n\t\t\t\t// Delete the node as we don't need to track it any more.\n\t\t\t\tthis.unreferencedNodesState.delete(nodeId);\n\t\t\t}\n\t\t}\n\n\t\t// 2. Mark unreferenced nodes in this run by starting unreferenced tracking for them.\n\t\tconst sweepReadyNodeIds: string[] = [];\n\t\tfor (const nodeId of gcResult.deletedNodeIds) {\n\t\t\tconst nodeStateTracker = this.unreferencedNodesState.get(nodeId);\n\t\t\tif (nodeStateTracker === undefined) {\n\t\t\t\tthis.unreferencedNodesState.set(\n\t\t\t\t\tnodeId,\n\t\t\t\t\tnew UnreferencedStateTracker(\n\t\t\t\t\t\tcurrentReferenceTimestampMs,\n\t\t\t\t\t\tthis.configs.inactiveTimeoutMs,\n\t\t\t\t\t\tcurrentReferenceTimestampMs,\n\t\t\t\t\t\tthis.configs.sweepTimeoutMs,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// If a node was already unreferenced, update its tracking information. Since the current reference time\n\t\t\t\t// is from the ops seen, this will ensure that we keep updating unreferenced state as time moves forward.\n\t\t\t\tnodeStateTracker.updateTracking(currentReferenceTimestampMs);\n\n\t\t\t\t// If a node is sweep ready, store it so it can be returned.\n\t\t\t\tif (nodeStateTracker.state === UnreferencedState.SweepReady) {\n\t\t\t\t\tsweepReadyNodeIds.push(nodeId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 3. Call the runtime to update referenced nodes in this run.\n\t\tthis.runtime.updateUsedRoutes(gcResult.referencedNodeIds);\n\n\t\treturn sweepReadyNodeIds;\n\t}\n\n\t/**\n\t * Runs the GC Sweep phase. It does the following:\n\t * 1. Calls the runtime to delete nodes that are sweep ready.\n\t * 2. Clears tracking for deleted nodes.\n\t *\n\t * @param gcResult - The result of the GC run on the gcData.\n\t * @param sweepReadyNodes - List of nodes that are sweep ready.\n\t * @param currentReferenceTimestampMs - The timestamp to be used for unreferenced nodes' timestamp.\n\t * @param logger - The logger to be used to log any telemetry.\n\t * @returns - A list of nodes that have been deleted.\n\t */\n\tprivate runSweepPhase(\n\t\tgcResult: IGCResult,\n\t\tsweepReadyNodes: string[],\n\t\tcurrentReferenceTimestampMs: number,\n\t\tlogger: ITelemetryLoggerExt,\n\t): string[] {\n\t\t// Log events for objects that are ready to be deleted by sweep. This will give us data on sweep when\n\t\t// its not enabled.\n\t\tthis.telemetryTracker.logSweepEvents(\n\t\t\tlogger,\n\t\t\tcurrentReferenceTimestampMs,\n\t\t\tthis.unreferencedNodesState,\n\t\t\tthis.completedRuns,\n\t\t\tthis.getLastSummaryTimestampMs(),\n\t\t);\n\n\t\t/**\n\t\t * Currently, there are 3 modes for sweep:\n\t\t * Test mode - Unreferenced nodes are immediately deleted without waiting for them to be sweep ready.\n\t\t * Tombstone mode - Sweep ready modes are marked as tombstones instead of being deleted.\n\t\t * Sweep mode - Sweep ready modes are deleted.\n\t\t *\n\t\t * These modes serve as staging for applications that want to enable sweep by providing an incremental\n\t\t * way to test and validate sweep works as expected.\n\t\t */\n\t\tif (this.configs.testMode) {\n\t\t\t// If we are running in GC test mode, unreferenced nodes (gcResult.deletedNodeIds) are deleted.\n\t\t\tthis.runtime.updateUnusedRoutes(gcResult.deletedNodeIds);\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.configs.tombstoneMode) {\n\t\t\tthis.tombstones = sweepReadyNodes;\n\t\t\t// If we are running in GC tombstone mode, update tombstoned routes. This enables testing scenarios\n\t\t\t// involving access to \"deleted\" data without actually deleting the data from summaries.\n\t\t\tthis.runtime.updateTombstonedRoutes(this.tombstones);\n\t\t\treturn [];\n\t\t}\n\n\t\tif (!this.configs.shouldRunSweep) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// 1. Call the runtime to delete sweep ready nodes. The runtime returns a list of nodes it deleted.\n\t\t// TODO: GC:Validation - validate that removed routes are not double delete and that the child routes of\n\t\t// removed routes are deleted as well.\n\t\tconst deletedNodeIds = this.runtime.deleteSweepReadyNodes(sweepReadyNodes);\n\n\t\t// 2. Clear unreferenced state tracking for deleted nodes.\n\t\tfor (const nodeId of deletedNodeIds) {\n\t\t\tconst nodeStateTracker = this.unreferencedNodesState.get(nodeId);\n\t\t\t// TODO: GC:Validation - assert that the nodeStateTracker is defined\n\t\t\tif (nodeStateTracker !== undefined) {\n\t\t\t\t// Stop tracking so as to clear out any running timers.\n\t\t\t\tnodeStateTracker.stopTracking();\n\t\t\t\t// Delete the node as we don't need to track it any more.\n\t\t\t\tthis.unreferencedNodesState.delete(nodeId);\n\t\t\t}\n\t\t\t// TODO: GC:Validation - assert that the deleted node is not a duplicate\n\t\t\tthis.deletedNodes.add(nodeId);\n\t\t}\n\t\treturn deletedNodeIds;\n\t}\n\n\t/**\n\t * Since GC runs periodically, the GC data that is generated only tells us the state of the world at that point in\n\t * time. There can be nodes that were referenced in between two runs and their unreferenced state needs to be\n\t * updated. For example, in the following scenarios not updating the unreferenced timestamp can lead to deletion of\n\t * these objects while there can be in-memory referenced to it:\n\t * 1. A node transitions from `unreferenced -> referenced -> unreferenced` between two runs. When the reference is\n\t * added, the object may have been accessed and in-memory reference to it added.\n\t * 2. A reference is added from one unreferenced node to one or more unreferenced nodes. Even though the node[s] were\n\t * unreferenced, they could have been accessed and in-memory reference to them added.\n\t *\n\t * This function identifies nodes that were referenced since the last run.\n\t * If these nodes are currently unreferenced, they will be assigned new unreferenced state by the current run.\n\t *\n\t * @returns - a list of all nodes referenced from the last local summary until now.\n\t */\n\tprivate findAllNodesReferencedBetweenGCs(\n\t\tcurrentGCData: IGarbageCollectionData,\n\t\tpreviousGCData: IGarbageCollectionData | undefined,\n\t\tlogger: ITelemetryLoggerExt,\n\t): string[] | undefined {\n\t\t// If we haven't run GC before there is nothing to do.\n\t\t// No previousGCData, means nothing is unreferenced, and there are no reference state trackers to clear\n\t\tif (previousGCData === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t/**\n\t\t * If there are references that were not explicitly notified to GC, log an error because this should never happen.\n\t\t * If it does, this may result in the unreferenced timestamps of these nodes not updated when they were referenced.\n\t\t */\n\t\tthis.telemetryTracker.logIfMissingExplicitReferences(\n\t\t\tcurrentGCData,\n\t\t\tpreviousGCData,\n\t\t\tthis.newReferencesSinceLastRun,\n\t\t\tlogger,\n\t\t);\n\n\t\t// No references were added since the last run so we don't have to update reference states of any unreferenced\n\t\t// nodes. There is no in between state at this point.\n\t\tif (this.newReferencesSinceLastRun.size === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t/**\n\t\t * Generate a super set of the GC data that contains the nodes and edges from last run, plus any new node and\n\t\t * edges that have been added since then. To do this, combine the GC data from the last run and the current\n\t\t * run, and then add the references since last run.\n\t\t *\n\t\t * Note on why we need to combine the data from previous run, current run and all references in between -\n\t\t * 1. We need data from last run because some of its references may have been deleted since then. If those\n\t\t * references added new outbound references before they were deleted, we need to detect them.\n\t\t *\n\t\t * 2. We need new outbound references since last run because some of them may have been deleted later. If those\n\t\t * references added new outbound references before they were deleted, we need to detect them.\n\t\t *\n\t\t * 3. We need data from the current run because currently we may not detect when DDSes are referenced:\n\t\t * - We don't require DDSes handles to be stored in a referenced DDS.\n\t\t * - A new data store may have \"root\" DDSes already created and we don't detect them today.\n\t\t */\n\t\tconst gcDataSuperSet = concatGarbageCollectionData(previousGCData, currentGCData);\n\t\tconst newOutboundRoutesSinceLastRun: string[] = [];\n\t\tthis.newReferencesSinceLastRun.forEach((outboundRoutes: string[], sourceNodeId: string) => {\n\t\t\tif (gcDataSuperSet.gcNodes[sourceNodeId] === undefined) {\n\t\t\t\tgcDataSuperSet.gcNodes[sourceNodeId] = outboundRoutes;\n\t\t\t} else {\n\t\t\t\tgcDataSuperSet.gcNodes[sourceNodeId].push(...outboundRoutes);\n\t\t\t}\n\t\t\tnewOutboundRoutesSinceLastRun.push(...outboundRoutes);\n\t\t});\n\n\t\t/**\n\t\t * Run GC on the above reference graph starting with root and all new outbound routes. This will generate a\n\t\t * list of all nodes that could have been referenced since the last run. If any of these nodes are unreferenced,\n\t\t * unreferenced, stop tracking them and remove from unreferenced list.\n\t\t * Note that some of these nodes may be unreferenced now and if so, the current run will mark them as\n\t\t * unreferenced and add unreferenced state.\n\t\t */\n\t\tconst gcResult = runGarbageCollection(gcDataSuperSet.gcNodes, [\n\t\t\t\"/\",\n\t\t\t...newOutboundRoutesSinceLastRun,\n\t\t]);\n\t\treturn gcResult.referencedNodeIds;\n\t}\n\n\t/**\n\t * Summarizes the GC data and returns it as a summary tree.\n\t * We current write the entire GC state in a single blob. This can be modified later to write multiple\n\t * blobs. All the blob keys should start with `gcBlobPrefix`.\n\t */\n\tpublic summarize(\n\t\tfullTree: boolean,\n\t\ttrackState: boolean,\n\t\ttelemetryContext?: ITelemetryContext,\n\t): ISummarizeResult | undefined {\n\t\tif (!this.configs.shouldRunGC || this.gcDataFromLastRun === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst gcState: IGarbageCollectionState = { gcNodes: {} };\n\t\tfor (const [nodeId, outboundRoutes] of Object.entries(this.gcDataFromLastRun.gcNodes)) {\n\t\t\tgcState.gcNodes[nodeId] = {\n\t\t\t\toutboundRoutes,\n\t\t\t\tunreferencedTimestampMs:\n\t\t\t\t\tthis.unreferencedNodesState.get(nodeId)?.unreferencedTimestampMs,\n\t\t\t};\n\t\t}\n\n\t\treturn this.summaryStateTracker.summarize(\n\t\t\tfullTree,\n\t\t\ttrackState,\n\t\t\tgcState,\n\t\t\tthis.deletedNodes,\n\t\t\tthis.tombstones,\n\t\t);\n\t}\n\n\tpublic getMetadata(): IGCMetadata {\n\t\treturn {\n\t\t\t/**\n\t\t\t * If GC is enabled, the GC data is written using the GC version in effect and that is the gcFeature that goes\n\t\t\t * into the metadata blob. If GC is disabled, the gcFeature is 0.\n\t\t\t */\n\t\t\tgcFeature: this.configs.gcEnabled ? this.configs.gcVersionInEffect : 0,\n\t\t\tgcFeatureMatrix: this.configs.persistedGcFeatureMatrix,\n\t\t\tsessionExpiryTimeoutMs: this.configs.sessionExpiryTimeoutMs,\n\t\t\tsweepEnabled: false, // DEPRECATED - to be removed\n\t\t\tsweepTimeoutMs: this.configs.sweepTimeoutMs,\n\t\t};\n\t}\n\n\t/**\n\t * Called to refresh the latest summary state. This happens when either a pending summary is acked.\n\t */\n\tpublic async refreshLatestSummary(result: IRefreshSummaryResult): Promise<void> {\n\t\treturn this.summaryStateTracker.refreshLatestSummary(result);\n\t}\n\n\t/**\n\t * Called when a node with the given id is updated. If the node is inactive, log an error.\n\t * @param nodePath - The path of the node that changed.\n\t * @param reason - Whether the node was loaded or changed.\n\t * @param timestampMs - The timestamp when the node changed.\n\t * @param packagePath - The package path of the node. This may not be available if the node hasn't been loaded yet.\n\t * @param requestHeaders - If the node was loaded via request path, the headers in the request.\n\t */\n\tpublic nodeUpdated(\n\t\tnodePath: string,\n\t\treason: \"Loaded\" | \"Changed\",\n\t\ttimestampMs?: number,\n\t\tpackagePath?: readonly string[],\n\t\trequestHeaders?: IRequestHeader,\n\t) {\n\t\tif (!this.configs.shouldRunGC) {\n\t\t\treturn;\n\t\t}\n\n\t\t// This will log if appropriate\n\t\tthis.telemetryTracker.nodeUsed({\n\t\t\tid: nodePath,\n\t\t\tusageType: reason,\n\t\t\tcurrentReferenceTimestampMs:\n\t\t\t\ttimestampMs ?? this.runtime.getCurrentReferenceTimestampMs(),\n\t\t\tpackagePath,\n\t\t\tcompletedGCRuns: this.completedRuns,\n\t\t\tisTombstoned: this.tombstones.includes(nodePath),\n\t\t\tlastSummaryTime: this.getLastSummaryTimestampMs(),\n\t\t\tviaHandle: requestHeaders?.[RuntimeHeaders.viaHandle],\n\t\t});\n\n\t\t// Unless this is a Loaded event, we're done after telemetry tracking\n\t\tif (reason !== \"Loaded\") {\n\t\t\treturn;\n\t\t}\n\n\t\t// We may throw when loading an Inactive object, depending on these preconditions\n\t\tconst shouldThrowOnInactiveLoad =\n\t\t\t!this.isSummarizerClient &&\n\t\t\tthis.configs.throwOnInactiveLoad === true &&\n\t\t\trequestHeaders?.[AllowInactiveRequestHeaderKey] !== true;\n\t\tconst state = this.unreferencedNodesState.get(nodePath)?.state;\n\n\t\tif (shouldThrowOnInactiveLoad && state === \"Inactive\") {\n\t\t\tconst request: IRequest = { url: nodePath };\n\t\t\tconst error = responseToException(\n\t\t\t\tcreateResponseError(404, \"Object is inactive\", request, {\n\t\t\t\t\t[InactiveResponseHeaderKey]: true,\n\t\t\t\t}),\n\t\t\t\trequest,\n\t\t\t);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Called when an outbound reference is added to a node. This is used to identify all nodes that have been\n\t * referenced between summaries so that their unreferenced timestamp can be reset.\n\t *\n\t * @param fromNodePath - The node from which the reference is added.\n\t * @param toNodePath - The node to which the reference is added.\n\t */\n\tpublic addedOutboundReference(fromNodePath: string, toNodePath: string) {\n\t\tif (!this.configs.shouldRunGC) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst outboundRoutes = this.newReferencesSinceLastRun.get(fromNodePath) ?? [];\n\t\toutboundRoutes.push(toNodePath);\n\t\tthis.newReferencesSinceLastRun.set(fromNodePath, outboundRoutes);\n\n\t\tthis.telemetryTracker.nodeUsed({\n\t\t\tid: toNodePath,\n\t\t\tusageType: \"Revived\",\n\t\t\tcurrentReferenceTimestampMs: this.runtime.getCurrentReferenceTimestampMs(),\n\t\t\tpackagePath: undefined,\n\t\t\tcompletedGCRuns: this.completedRuns,\n\t\t\tisTombstoned: this.tombstones.includes(toNodePath),\n\t\t\tlastSummaryTime: this.getLastSummaryTimestampMs(),\n\t\t\tfromId: fromNodePath,\n\t\t});\n\t}\n\n\t/**\n\t * Returns whether a node with the given path has been deleted or not. This can be used by the runtime to identify\n\t * cases where objects are used after they are deleted and throw / log errors accordingly.\n\t */\n\tpublic isNodeDeleted(nodePath: string): boolean {\n\t\treturn this.deletedNodes.has(nodePath);\n\t}\n\n\tpublic dispose(): void {\n\t\tthis.sessionExpiryTimer?.clear();\n\t\tthis.sessionExpiryTimer = undefined;\n\t}\n\n\t/**\n\t * Generates the stats of a garbage collection run from the given results of the run.\n\t * @param gcResult - The result of a GC run.\n\t * @returns the GC stats of the GC run.\n\t */\n\tprivate generateStats(gcResult: IGCResult): IGCStats {\n\t\tconst gcStats: IGCStats = {\n\t\t\tnodeCount: 0,\n\t\t\tdataStoreCount: 0,\n\t\t\tattachmentBlobCount: 0,\n\t\t\tunrefNodeCount: 0,\n\t\t\tunrefDataStoreCount: 0,\n\t\t\tunrefAttachmentBlobCount: 0,\n\t\t\tupdatedNodeCount: 0,\n\t\t\tupdatedDataStoreCount: 0,\n\t\t\tupdatedAttachmentBlobCount: 0,\n\t\t};\n\n\t\tconst updateNodeStats = (nodeId: string, referenced: boolean) => {\n\t\t\tgcStats.nodeCount++;\n\t\t\t// If there is no previous GC data, every node's state is generated and is considered as updated.\n\t\t\t// Otherwise, find out if any node went from referenced to unreferenced or vice-versa.\n\t\t\tconst stateUpdated =\n\t\t\t\tthis.gcDataFromLastRun === undefined ||\n\t\t\t\tthis.unreferencedNodesState.has(nodeId) === referenced;\n\t\t\tif (stateUpdated) {\n\t\t\t\tgcStats.updatedNodeCount++;\n\t\t\t}\n\t\t\tif (!referenced) {\n\t\t\t\tgcStats.unrefNodeCount++;\n\t\t\t}\n\n\t\t\tif (this.runtime.getNodeType(nodeId) === GCNodeType.DataStore) {\n\t\t\t\tgcStats.dataStoreCount++;\n\t\t\t\tif (stateUpdated) {\n\t\t\t\t\tgcStats.updatedDataStoreCount++;\n\t\t\t\t}\n\t\t\t\tif (!referenced) {\n\t\t\t\t\tgcStats.unrefDataStoreCount++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (this.runtime.getNodeType(nodeId) === GCNodeType.Blob) {\n\t\t\t\tgcStats.attachmentBlobCount++;\n\t\t\t\tif (stateUpdated) {\n\t\t\t\t\tgcStats.updatedAttachmentBlobCount++;\n\t\t\t\t}\n\t\t\t\tif (!referenced) {\n\t\t\t\t\tgcStats.unrefAttachmentBlobCount++;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tfor (const nodeId of gcResult.referencedNodeIds) {\n\t\t\tupdateNodeStats(nodeId, true /* referenced */);\n\t\t}\n\n\t\tfor (const nodeId of gcResult.deletedNodeIds) {\n\t\t\tupdateNodeStats(nodeId, false /* referenced */);\n\t\t}\n\n\t\treturn gcStats;\n\t}\n}\n"]}
1
+ {"version":3,"file":"garbageCollection.js","sourceRoot":"","sources":["../../src/gc/garbageCollection.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { LazyPromise, Timer } from \"@fluidframework/core-utils\";\nimport { IRequest, IRequestHeader } from \"@fluidframework/core-interfaces\";\nimport {\n\tgcTreeKey,\n\tIGarbageCollectionData,\n\tIGarbageCollectionDetailsBase,\n\tISummarizeResult,\n\tITelemetryContext,\n} from \"@fluidframework/runtime-definitions\";\nimport { createResponseError, responseToException } from \"@fluidframework/runtime-utils\";\nimport {\n\tcreateChildLogger,\n\tcreateChildMonitoringContext,\n\tDataProcessingError,\n\tITelemetryLoggerExt,\n\tMonitoringContext,\n\tPerformanceEvent,\n} from \"@fluidframework/telemetry-utils\";\n\nimport {\n\tAllowInactiveRequestHeaderKey,\n\tInactiveResponseHeaderKey,\n\tRuntimeHeaders,\n} from \"../containerRuntime\";\nimport { ClientSessionExpiredError } from \"../error\";\nimport { IRefreshSummaryResult } from \"../summary\";\nimport { generateGCConfigs } from \"./gcConfigs\";\nimport {\n\tGCNodeType,\n\tIGarbageCollector,\n\tIGarbageCollectorCreateParams,\n\tIGarbageCollectionRuntime,\n\tIGCResult,\n\tIGCStats,\n\tUnreferencedState,\n\tIGCMetadata,\n\tIGarbageCollectorConfigs,\n} from \"./gcDefinitions\";\nimport { cloneGCData, concatGarbageCollectionData, getGCDataFromSnapshot } from \"./gcHelpers\";\nimport { runGarbageCollection } from \"./gcReferenceGraphAlgorithm\";\nimport { IGarbageCollectionSnapshotData, IGarbageCollectionState } from \"./gcSummaryDefinitions\";\nimport { GCSummaryStateTracker } from \"./gcSummaryStateTracker\";\nimport { UnreferencedStateTracker } from \"./gcUnreferencedStateTracker\";\nimport { GCTelemetryTracker } from \"./gcTelemetry\";\n\n/**\n * The garbage collector for the container runtime. It consolidates the garbage collection functionality and maintains\n * its state across summaries.\n *\n * Node - represented as nodeId, it's a node on the GC graph\n *\n * Outbound Route - a path from one node to another node, think `nodeA` -\\> `nodeB`\n *\n * Graph - all nodes with their respective routes\n *\n * ```\n *\t\t\t GC Graph\n *\n *\t\t\t Node\n *\t\tNodeId = \"datastore1\"\n *\t\t /\t\t\t \\\\\n *\tOutboundRoute OutboundRoute\n *\t\t /\t\t\t\t \\\\\n *\t Node\t\t\t Node\n * NodeId = \"dds1\"\t NodeId = \"dds2\"\n * ```\n */\nexport class GarbageCollector implements IGarbageCollector {\n\tpublic static create(createParams: IGarbageCollectorCreateParams): IGarbageCollector {\n\t\treturn new GarbageCollector(createParams);\n\t}\n\n\tprivate readonly mc: MonitoringContext;\n\n\tprivate readonly configs: IGarbageCollectorConfigs;\n\n\tpublic get shouldRunGC(): boolean {\n\t\treturn this.configs.shouldRunGC;\n\t}\n\n\t// Keeps track of the GC state from the last run.\n\tprivate gcDataFromLastRun: IGarbageCollectionData | undefined;\n\t// Keeps a list of references (edges in the GC graph) between GC runs. Each entry has a node id and a list of\n\t// outbound routes from that node.\n\tprivate readonly newReferencesSinceLastRun: Map<string, string[]> = new Map();\n\t// A list of nodes that have been tombstoned.\n\tprivate tombstones: string[] = [];\n\t// A list of nodes that have been deleted during sweep phase.\n\tprivate deletedNodes: Set<string> = new Set();\n\n\t// Promise when resolved returns the GC data data in the base snapshot.\n\tprivate readonly baseSnapshotDataP: Promise<IGarbageCollectionSnapshotData | undefined>;\n\t// Promise when resolved initializes the GC state from the data in the base snapshot.\n\tprivate readonly initializeGCStateFromBaseSnapshotP: Promise<void>;\n\t// The GC details generated from the base snapshot.\n\tprivate readonly baseGCDetailsP: Promise<IGarbageCollectionDetailsBase>;\n\t// Map of node ids to their unreferenced state tracker.\n\tprivate readonly unreferencedNodesState: Map<string, UnreferencedStateTracker> = new Map();\n\t// The Timer responsible for closing the container when the session has expired\n\tprivate sessionExpiryTimer: Timer | undefined;\n\n\t// The number of times GC has successfully completed on this instance of GarbageCollector.\n\tprivate completedRuns = 0;\n\n\tprivate readonly runtime: IGarbageCollectionRuntime;\n\tprivate readonly isSummarizerClient: boolean;\n\n\tprivate readonly summaryStateTracker: GCSummaryStateTracker;\n\tprivate readonly telemetryTracker: GCTelemetryTracker;\n\n\t/** For a given node path, returns the node's package path. */\n\tprivate readonly getNodePackagePath: (\n\t\tnodePath: string,\n\t) => Promise<readonly string[] | undefined>;\n\t/** Returns the timestamp of the last summary generated for this container. */\n\tprivate readonly getLastSummaryTimestampMs: () => number | undefined;\n\t/** Returns true if connection is active, i.e. it's \"write\" connection and the runtime is connected. */\n\tprivate readonly activeConnection: () => boolean;\n\n\tpublic get summaryStateNeedsReset(): boolean {\n\t\treturn this.summaryStateTracker.doesSummaryStateNeedReset;\n\t}\n\n\t/** Returns the count of data stores whose GC state updated since the last summary. */\n\tpublic get updatedDSCountSinceLastSummary(): number {\n\t\treturn this.summaryStateTracker.updatedDSCountSinceLastSummary;\n\t}\n\n\tprotected constructor(createParams: IGarbageCollectorCreateParams) {\n\t\tthis.runtime = createParams.runtime;\n\t\tthis.isSummarizerClient = createParams.isSummarizerClient;\n\t\tthis.getNodePackagePath = createParams.getNodePackagePath;\n\t\tthis.getLastSummaryTimestampMs = createParams.getLastSummaryTimestampMs;\n\t\tthis.activeConnection = createParams.activeConnection;\n\n\t\tconst baseSnapshot = createParams.baseSnapshot;\n\t\tconst readAndParseBlob = createParams.readAndParseBlob;\n\n\t\tthis.mc = createChildMonitoringContext({\n\t\t\tlogger: createParams.baseLogger,\n\t\t\tnamespace: \"GarbageCollector\",\n\t\t\tproperties: {\n\t\t\t\tall: { completedGCRuns: () => this.completedRuns },\n\t\t\t},\n\t\t});\n\n\t\tthis.configs = generateGCConfigs(this.mc, createParams);\n\n\t\t// If session expiry is enabled, we need to close the container when the session expiry timeout expires.\n\t\tif (this.configs.sessionExpiryTimeoutMs !== undefined) {\n\t\t\t// If Test Override config is set, override Session Expiry timeout.\n\t\t\tconst overrideSessionExpiryTimeoutMs = this.mc.config.getNumber(\n\t\t\t\t\"Fluid.GarbageCollection.TestOverride.SessionExpiryMs\",\n\t\t\t);\n\t\t\tconst timeoutMs = overrideSessionExpiryTimeoutMs ?? this.configs.sessionExpiryTimeoutMs;\n\n\t\t\tthis.sessionExpiryTimer = new Timer(timeoutMs, () => {\n\t\t\t\tthis.runtime.closeFn(\n\t\t\t\t\tnew ClientSessionExpiredError(`Client session expired.`, timeoutMs),\n\t\t\t\t);\n\t\t\t});\n\t\t\tthis.sessionExpiryTimer.start();\n\t\t}\n\n\t\tthis.summaryStateTracker = new GCSummaryStateTracker(\n\t\t\tthis.configs,\n\t\t\tbaseSnapshot?.trees[gcTreeKey] !== undefined /* wasGCRunInBaseSnapshot */,\n\t\t);\n\n\t\tthis.telemetryTracker = new GCTelemetryTracker(\n\t\t\tthis.mc,\n\t\t\tthis.configs,\n\t\t\tthis.isSummarizerClient,\n\t\t\tthis.runtime.gcTombstoneEnforcementAllowed,\n\t\t\tcreateParams.createContainerMetadata,\n\t\t\t(nodeId: string) => this.runtime.getNodeType(nodeId),\n\t\t\t(nodeId: string) => this.unreferencedNodesState.get(nodeId),\n\t\t\tthis.getNodePackagePath,\n\t\t);\n\n\t\t// Get the GC data from the base snapshot. Use LazyPromise because we only want to do this once since it\n\t\t// it involves fetching blobs from storage which is expensive.\n\t\tthis.baseSnapshotDataP = new LazyPromise<IGarbageCollectionSnapshotData | undefined>(\n\t\t\tasync () => {\n\t\t\t\tif (baseSnapshot === undefined) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\t// For newer documents, GC data should be present in the GC tree in the root of the snapshot.\n\t\t\t\t\tconst gcSnapshotTree = baseSnapshot.trees[gcTreeKey];\n\t\t\t\t\tif (gcSnapshotTree === undefined) {\n\t\t\t\t\t\t// back-compat - Older documents get their gc data reset for simplicity as there are few of them\n\t\t\t\t\t\t// incremental gc summary will not work with older gc data as well\n\t\t\t\t\t\treturn undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst snapshotData = await getGCDataFromSnapshot(\n\t\t\t\t\t\tgcSnapshotTree,\n\t\t\t\t\t\treadAndParseBlob,\n\t\t\t\t\t);\n\n\t\t\t\t\t// If the GC version in base snapshot does not match the GC version currently in effect, the GC data\n\t\t\t\t\t// in the snapshot cannot be interpreted correctly. Set everything to undefined except for\n\t\t\t\t\t// deletedNodes because irrespective of GC versions, these nodes have been deleted and cannot be\n\t\t\t\t\t// brought back. The deletedNodes info is needed to identify when these nodes are used.\n\t\t\t\t\tif (this.configs.gcVersionInEffect !== this.configs.gcVersionInBaseSnapshot) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tgcState: undefined,\n\t\t\t\t\t\t\ttombstones: undefined,\n\t\t\t\t\t\t\tdeletedNodes: snapshotData.deletedNodes,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn snapshotData;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst dpe = DataProcessingError.wrapIfUnrecognized(\n\t\t\t\t\t\terror,\n\t\t\t\t\t\t\"FailedToInitializeGC\",\n\t\t\t\t\t);\n\t\t\t\t\tdpe.addTelemetryProperties({\n\t\t\t\t\t\tgcConfigs: JSON.stringify(this.configs),\n\t\t\t\t\t});\n\t\t\t\t\tthrow dpe;\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\n\t\t/**\n\t\t * Set up the initializer which initializes the GC state from the data in base snapshot. This is done when\n\t\t * connected in write mode or when GC runs the first time. It sets up all unreferenced nodes from the base\n\t\t * GC state and updates their inactive or sweep ready state.\n\t\t */\n\t\tthis.initializeGCStateFromBaseSnapshotP = new LazyPromise<void>(async () => {\n\t\t\t/**\n\t\t\t * If there is no current reference timestamp, skip initialization. We need the current timestamp to track\n\t\t\t * how long objects have been unreferenced and if they can be deleted.\n\t\t\t *\n\t\t\t * Note that the only scenario where there is no reference timestamp is when no ops have ever been processed\n\t\t\t * for this container and it is in read mode. In this scenario, there is no point in running GC anyway\n\t\t\t * because references in the container do not change without any ops, i.e., there is nothing to collect.\n\t\t\t */\n\t\t\tconst currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();\n\t\t\tif (currentReferenceTimestampMs === undefined) {\n\t\t\t\t// Log an event so we can evaluate how often we run into this scenario.\n\t\t\t\tthis.mc.logger.sendErrorEvent({\n\t\t\t\t\teventName: \"GarbageCollectorInitializedWithoutTimestamp\",\n\t\t\t\t\tgcConfigs: JSON.stringify(this.configs),\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t/**\n\t\t\t * The base snapshot data will not be present if the container is loaded from:\n\t\t\t * 1. The first summary created by the detached container.\n\t\t\t * 2. A summary that was generated with GC disabled.\n\t\t\t * 3. A summary that was generated before GC even existed.\n\t\t\t */\n\t\t\tconst baseSnapshotData = await this.baseSnapshotDataP;\n\t\t\tif (baseSnapshotData === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.updateStateFromSnapshotData(baseSnapshotData, currentReferenceTimestampMs);\n\t\t\tthis.summaryStateTracker.initializeBaseState(baseSnapshotData);\n\t\t});\n\n\t\t// Get the GC details from the GC state in the base summary. This is returned in getBaseGCDetails which is\n\t\t// used to initialize the GC state of all the nodes in the container.\n\t\tthis.baseGCDetailsP = new LazyPromise<IGarbageCollectionDetailsBase>(async () => {\n\t\t\tconst baseSnapshotData = await this.baseSnapshotDataP;\n\t\t\tif (baseSnapshotData?.gcState === undefined) {\n\t\t\t\treturn {};\n\t\t\t}\n\n\t\t\tconst gcNodes: { [id: string]: string[] } = {};\n\t\t\tfor (const [nodeId, nodeData] of Object.entries(baseSnapshotData.gcState.gcNodes)) {\n\t\t\t\tgcNodes[nodeId] = Array.from(nodeData.outboundRoutes);\n\t\t\t}\n\t\t\t// Run GC on the nodes in the base summary to get the routes used in each node in the container.\n\t\t\t// This is an optimization for space (vs performance) wherein we don't need to store the used routes of\n\t\t\t// each node in the summary.\n\t\t\tconst usedRoutes = runGarbageCollection(gcNodes, [\"/\"]).referencedNodeIds;\n\n\t\t\treturn { gcData: { gcNodes }, usedRoutes };\n\t\t});\n\n\t\t// Log all the GC options and the state determined by the garbage collector.\n\t\t// This is useful even for interactive clients since they track unreferenced nodes and log errors.\n\t\tthis.mc.logger.sendTelemetryEvent({\n\t\t\teventName: \"GarbageCollectorLoaded\",\n\t\t\tgcConfigs: JSON.stringify(this.configs),\n\t\t\tgcOptions: JSON.stringify(createParams.gcOptions),\n\t\t});\n\t}\n\n\t/**\n\t * Called during container initialization. Initialize from the tombstone state in the base snapshot. This is done\n\t * during initialization so that deleted or tombstoned objects are marked as such before they are loaded or used.\n\t */\n\tpublic async initializeBaseState(): Promise<void> {\n\t\tconst baseSnapshotData = await this.baseSnapshotDataP;\n\t\t/**\n\t\t * The base snapshot data will not be present if the container is loaded from:\n\t\t * 1. The first summary created by the detached container.\n\t\t * 2. A summary that was generated with GC disabled.\n\t\t * 3. A summary that was generated before GC even existed.\n\t\t */\n\t\tif (baseSnapshotData === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Initialize the deleted nodes from the snapshot. This is done irrespective of whether sweep is enabled or not\n\t\t// to identify deleted nodes' usage.\n\t\tif (baseSnapshotData.deletedNodes !== undefined) {\n\t\t\tthis.deletedNodes = new Set(baseSnapshotData.deletedNodes);\n\t\t}\n\n\t\t// If running in tombstone mode, initialize the tombstone state from the snapshot. Also, notify the runtime of\n\t\t// tombstone routes.\n\t\tif (this.configs.tombstoneMode && baseSnapshotData.tombstones !== undefined) {\n\t\t\t// Create a copy since we are writing from a source we don't control\n\t\t\tthis.tombstones = Array.from(baseSnapshotData.tombstones);\n\t\t\tthis.runtime.updateTombstonedRoutes(this.tombstones);\n\t\t}\n\t}\n\n\t/**\n\t * Update state from the given snapshot data. This is done during load and during refreshing state from a snapshot.\n\t * All current tracking is reset and updated from the data in the snapshot.\n\t * @param snapshotData - The snapshot data to update state from. If this is undefined, all GC state and tracking\n\t * is reset.\n\t * @param currentReferenceTimestampMs - The current reference timestamp for marking unreferenced nodes' unreferenced\n\t * timestamp.\n\t */\n\tprivate updateStateFromSnapshotData(\n\t\tsnapshotData: IGarbageCollectionSnapshotData | undefined,\n\t\tcurrentReferenceTimestampMs: number,\n\t) {\n\t\t/**\n\t\t * Note: \"newReferencesSinceLastRun\" is not reset here. This is done because there may be references since the\n\t\t * snapshot that we are updating state from. For example, this client may have processed ops till seq#1000 and\n\t\t * its refreshing state from a summary that happened at seq#900. In this case, there may be references between\n\t\t * seq#901 and seq#1000 that we don't want to reset.\n\t\t * Unfortunately, there is no way to track the seq# of ops that add references, so we choose to not reset any\n\t\t * references here. This should be fine because, in the worst case, we may end up updating the unreferenced\n\t\t * timestamp of a node which will delay its deletion. Although not ideal, this will only happen in rare\n\t\t * scenarios, so it should be okay.\n\t\t */\n\n\t\t// Clear all existing unreferenced state tracking.\n\t\tfor (const [, nodeStateTracker] of this.unreferencedNodesState) {\n\t\t\tnodeStateTracker.stopTracking();\n\t\t}\n\t\tthis.unreferencedNodesState.clear();\n\n\t\t// If running sweep, the tombstone state represents the list of nodes that have been deleted during sweep.\n\t\t// If running in tombstone mode, the tombstone state represents the list of nodes that have been marked as\n\t\t// tombstones.\n\t\t// If this call is because we are refreshing from a snapshot due to an ack, it is likely that the GC state\n\t\t// in the snapshot is newer than this client's. And so, the deleted / tombstone nodes need to be updated.\n\t\tif (this.configs.shouldRunSweep) {\n\t\t\tconst snapshotDeletedNodes = snapshotData?.deletedNodes\n\t\t\t\t? new Set(snapshotData.deletedNodes)\n\t\t\t\t: undefined;\n\t\t\t// If the snapshot contains deleted nodes that are not yet deleted by this client, ask the runtime to\n\t\t\t// delete them.\n\t\t\tif (snapshotDeletedNodes !== undefined) {\n\t\t\t\tconst newDeletedNodes: string[] = [];\n\t\t\t\tfor (const nodeId of snapshotDeletedNodes) {\n\t\t\t\t\tif (!this.deletedNodes.has(nodeId)) {\n\t\t\t\t\t\tnewDeletedNodes.push(nodeId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (newDeletedNodes.length > 0) {\n\t\t\t\t\t// Call container runtime to delete these nodes and add deleted nodes to this.deletedNodes.\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.configs.tombstoneMode) {\n\t\t\t// The snapshot may contain more or fewer tombstone nodes than this client. Update tombstone state and\n\t\t\t// notify the runtime to update its state as well.\n\t\t\tthis.tombstones = snapshotData?.tombstones ? Array.from(snapshotData.tombstones) : [];\n\t\t\tthis.runtime.updateTombstonedRoutes(this.tombstones);\n\t\t}\n\n\t\t// If there is no snapshot data, it means this snapshot was generated with GC disabled. Unset all GC state.\n\t\tif (snapshotData?.gcState === undefined) {\n\t\t\tthis.gcDataFromLastRun = undefined;\n\t\t\treturn;\n\t\t}\n\n\t\t// Update unreferenced state tracking as per the GC state in the snapshot data and update gcDataFromLastRun\n\t\t// to the GC data from the snapshot data.\n\t\tconst gcNodes: { [id: string]: string[] } = {};\n\t\tfor (const [nodeId, nodeData] of Object.entries(snapshotData.gcState.gcNodes)) {\n\t\t\tif (nodeData.unreferencedTimestampMs !== undefined) {\n\t\t\t\tthis.unreferencedNodesState.set(\n\t\t\t\t\tnodeId,\n\t\t\t\t\tnew UnreferencedStateTracker(\n\t\t\t\t\t\tnodeData.unreferencedTimestampMs,\n\t\t\t\t\t\tthis.configs.inactiveTimeoutMs,\n\t\t\t\t\t\tcurrentReferenceTimestampMs,\n\t\t\t\t\t\tthis.configs.sweepTimeoutMs,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tgcNodes[nodeId] = Array.from(nodeData.outboundRoutes);\n\t\t}\n\t\tthis.gcDataFromLastRun = { gcNodes };\n\t}\n\n\t/**\n\t * Called when the connection state of the runtime changes, i.e., it connects or disconnects. GC subscribes to this\n\t * to initialize the base state for non-summarizer clients so that they can track inactive / sweep ready nodes.\n\t * @param connected - Whether the runtime connected / disconnected.\n\t * @param clientId - The clientId of this runtime.\n\t */\n\tpublic setConnectionState(connected: boolean, clientId?: string | undefined): void {\n\t\t/**\n\t\t * For all clients, initialize the base state when the container becomes active, i.e., it transitions\n\t\t * to \"write\" mode. This will ensure that the container's own join op is processed and there is a recent\n\t\t * reference timestamp that will be used to update the state of unreferenced nodes. Also, all trailing ops which\n\t\t * could affect the GC state will have been processed.\n\t\t *\n\t\t * If GC is up-to-date for the client and the summarizing client, there will be an doubling of both\n\t\t * InactiveObject_Loaded and SweepReady_Loaded errors, as there will be one from the sending client and one from\n\t\t * the receiving summarizer client.\n\t\t *\n\t\t * Ideally, this initialization should only be done for summarizer client. However, we are currently rolling out\n\t\t * sweep in phases and we want to track when inactive and sweep ready objects are used in any client.\n\t\t */\n\t\tif (this.activeConnection() && this.configs.shouldRunGC) {\n\t\t\tthis.initializeGCStateFromBaseSnapshotP.catch((error) => {});\n\t\t}\n\t}\n\n\t/**\n\t * Returns a the GC details generated from the base summary. This is used to initialize the GC state of the nodes\n\t * in the container.\n\t */\n\tpublic async getBaseGCDetails(): Promise<IGarbageCollectionDetailsBase> {\n\t\treturn this.baseGCDetailsP;\n\t}\n\n\t/**\n\t * Runs garbage collection and updates the reference / used state of the nodes in the container.\n\t * @returns stats of the GC run or undefined if GC did not run.\n\t */\n\tpublic async collectGarbage(\n\t\toptions: {\n\t\t\t/** Logger to use for logging GC events */\n\t\t\tlogger?: ITelemetryLoggerExt;\n\t\t\t/** True to run GC sweep phase after the mark phase */\n\t\t\trunSweep?: boolean;\n\t\t\t/** True to generate full GC data */\n\t\t\tfullGC?: boolean;\n\t\t},\n\t\ttelemetryContext?: ITelemetryContext,\n\t): Promise<IGCStats | undefined> {\n\t\tconst fullGC =\n\t\t\toptions.fullGC ??\n\t\t\t(this.configs.runFullGC === true || this.summaryStateTracker.doesSummaryStateNeedReset);\n\n\t\t// Add the options that are used to run GC to the telemetry context.\n\t\ttelemetryContext?.setMultiple(\"fluid_GC\", \"Options\", {\n\t\t\tfullGC,\n\t\t\trunSweep: options.runSweep,\n\t\t});\n\n\t\tconst logger = options.logger\n\t\t\t? createChildLogger({\n\t\t\t\t\tlogger: options.logger,\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tall: { completedGCRuns: () => this.completedRuns },\n\t\t\t\t\t},\n\t\t\t })\n\t\t\t: this.mc.logger;\n\n\t\t/**\n\t\t * If there is no current reference timestamp, skip running GC. We need the current timestamp to track\n\t\t * how long objects have been unreferenced and if they should be deleted.\n\t\t *\n\t\t * Note that the only scenario where GC is called and there is no reference timestamp is when no ops have ever\n\t\t * been processed for this container and it is in read mode. In this scenario, there is no point in running GC\n\t\t * anyway because references in the container do not change without any ops, i.e., there is nothing to collect.\n\t\t */\n\t\tconst currentReferenceTimestampMs = this.runtime.getCurrentReferenceTimestampMs();\n\t\tif (currentReferenceTimestampMs === undefined) {\n\t\t\t// Log an event so we can evaluate how often we run into this scenario.\n\t\t\tlogger.sendErrorEvent({\n\t\t\t\teventName: \"CollectGarbageCalledWithoutTimestamp\",\n\t\t\t\tgcConfigs: JSON.stringify(this.configs),\n\t\t\t});\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn PerformanceEvent.timedExecAsync(\n\t\t\tlogger,\n\t\t\t{ eventName: \"GarbageCollection\" },\n\t\t\tasync (event) => {\n\t\t\t\t/** Pre-GC steps */\n\t\t\t\t// Ensure that state has been initialized from the base snapshot data.\n\t\t\t\tawait this.initializeGCStateFromBaseSnapshotP;\n\t\t\t\t// Let the runtime update its pending state before GC runs.\n\t\t\t\tawait this.runtime.updateStateBeforeGC();\n\n\t\t\t\t/** GC step */\n\t\t\t\tconst gcStats = await this.runGC(fullGC, currentReferenceTimestampMs, logger);\n\t\t\t\tevent.end({ ...gcStats, timestamp: currentReferenceTimestampMs });\n\n\t\t\t\t/** Post-GC steps */\n\t\t\t\t// Log pending unreferenced events such as a node being used after inactive. This is done after GC runs and\n\t\t\t\t// updates its state so that we don't send false positives based on intermediate state. For example, we may get\n\t\t\t\t// reference to an unreferenced node from another unreferenced node which means the node wasn't revived.\n\t\t\t\tawait this.telemetryTracker.logPendingEvents(logger);\n\t\t\t\t// Update the state of summary state tracker from this run's stats.\n\t\t\t\tthis.summaryStateTracker.updateStateFromGCRunStats(gcStats);\n\t\t\t\tthis.newReferencesSinceLastRun.clear();\n\t\t\t\tthis.completedRuns++;\n\n\t\t\t\treturn gcStats;\n\t\t\t},\n\t\t\t{ end: true, cancel: \"error\" },\n\t\t);\n\t}\n\n\t/**\n\t * Runs garbage collection. It does the following:\n\t * 1. It generates / analyzes the runtime's reference graph.\n\t * 2. Generates stats for the GC run based on previous / current GC state.\n\t * 3. Runs Mark phase.\n\t * 4. Runs Sweep phase.\n\t */\n\tprivate async runGC(\n\t\tfullGC: boolean,\n\t\tcurrentReferenceTimestampMs: number,\n\t\tlogger: ITelemetryLoggerExt,\n\t): Promise<IGCStats> {\n\t\t// 1. Generate / analyze the runtime's reference graph.\n\t\t// Get the reference graph (gcData) and run GC algorithm to get referenced / unreferenced nodes.\n\t\tconst gcData = await this.runtime.getGCData(fullGC);\n\t\tconst gcResult = runGarbageCollection(gcData.gcNodes, [\"/\"]);\n\t\t// Get all referenced nodes - References in this run + references between the previous and current runs.\n\t\tconst allReferencedNodeIds =\n\t\t\tthis.findAllNodesReferencedBetweenGCs(gcData, this.gcDataFromLastRun, logger) ??\n\t\t\tgcResult.referencedNodeIds;\n\n\t\t// 2. Generate stats based on the previous / current GC state.\n\t\t// Must happen before running Mark / Sweep phase because previous GC state will be updated in these stages.\n\t\tconst gcStats = this.generateStats(gcResult);\n\n\t\t// 3. Run the Mark phase.\n\t\t// It will mark nodes as referenced / unreferenced and return a list of node ids that are ready to be swept.\n\t\tconst sweepReadyNodeIds = this.runMarkPhase(\n\t\t\tgcResult,\n\t\t\tallReferencedNodeIds,\n\t\t\tcurrentReferenceTimestampMs,\n\t\t);\n\n\t\t// 4. Run the Sweep phase.\n\t\t// It will delete sweep ready nodes and return a list of deleted node ids.\n\t\tconst deletedNodeIds = this.runSweepPhase(\n\t\t\tgcResult,\n\t\t\tsweepReadyNodeIds,\n\t\t\tcurrentReferenceTimestampMs,\n\t\t\tlogger,\n\t\t);\n\n\t\tthis.gcDataFromLastRun = cloneGCData(\n\t\t\tgcData,\n\t\t\t(id: string) => deletedNodeIds.includes(id) /* filter out deleted nodes */,\n\t\t);\n\t\treturn gcStats;\n\t}\n\n\t/**\n\t * Runs the GC Mark phase. It does the following:\n\t * 1. Marks all referenced nodes in this run by clearing tracking for them.\n\t * 2. Marks unreferenced nodes in this run by starting tracking for them.\n\t * 3. Calls the runtime to update nodes that were marked referenced.\n\t *\n\t * @param gcResult - The result of the GC run on the gcData.\n\t * @param allReferencedNodeIds - Nodes referenced in this GC run + referenced between previous and current GC run.\n\t * @param currentReferenceTimestampMs - The timestamp to be used for unreferenced nodes' timestamp.\n\t * @returns - A list of sweep ready nodes, i.e., nodes that ready to be deleted.\n\t */\n\tprivate runMarkPhase(\n\t\tgcResult: IGCResult,\n\t\tallReferencedNodeIds: string[],\n\t\tcurrentReferenceTimestampMs: number,\n\t): string[] {\n\t\t// 1. Marks all referenced nodes by clearing their unreferenced tracker, if any.\n\t\tfor (const nodeId of allReferencedNodeIds) {\n\t\t\tconst nodeStateTracker = this.unreferencedNodesState.get(nodeId);\n\t\t\tif (nodeStateTracker !== undefined) {\n\t\t\t\t// Stop tracking so as to clear out any running timers.\n\t\t\t\tnodeStateTracker.stopTracking();\n\t\t\t\t// Delete the node as we don't need to track it any more.\n\t\t\t\tthis.unreferencedNodesState.delete(nodeId);\n\t\t\t}\n\t\t}\n\n\t\t// 2. Mark unreferenced nodes in this run by starting unreferenced tracking for them.\n\t\tconst sweepReadyNodeIds: string[] = [];\n\t\tfor (const nodeId of gcResult.deletedNodeIds) {\n\t\t\tconst nodeStateTracker = this.unreferencedNodesState.get(nodeId);\n\t\t\tif (nodeStateTracker === undefined) {\n\t\t\t\tthis.unreferencedNodesState.set(\n\t\t\t\t\tnodeId,\n\t\t\t\t\tnew UnreferencedStateTracker(\n\t\t\t\t\t\tcurrentReferenceTimestampMs,\n\t\t\t\t\t\tthis.configs.inactiveTimeoutMs,\n\t\t\t\t\t\tcurrentReferenceTimestampMs,\n\t\t\t\t\t\tthis.configs.sweepTimeoutMs,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// If a node was already unreferenced, update its tracking information. Since the current reference time\n\t\t\t\t// is from the ops seen, this will ensure that we keep updating unreferenced state as time moves forward.\n\t\t\t\tnodeStateTracker.updateTracking(currentReferenceTimestampMs);\n\n\t\t\t\t// If a node is sweep ready, store it so it can be returned.\n\t\t\t\tif (nodeStateTracker.state === UnreferencedState.SweepReady) {\n\t\t\t\t\tsweepReadyNodeIds.push(nodeId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 3. Call the runtime to update referenced nodes in this run.\n\t\tthis.runtime.updateUsedRoutes(gcResult.referencedNodeIds);\n\n\t\treturn sweepReadyNodeIds;\n\t}\n\n\t/**\n\t * Runs the GC Sweep phase. It does the following:\n\t * 1. Calls the runtime to delete nodes that are sweep ready.\n\t * 2. Clears tracking for deleted nodes.\n\t *\n\t * @param gcResult - The result of the GC run on the gcData.\n\t * @param sweepReadyNodes - List of nodes that are sweep ready.\n\t * @param currentReferenceTimestampMs - The timestamp to be used for unreferenced nodes' timestamp.\n\t * @param logger - The logger to be used to log any telemetry.\n\t * @returns - A list of nodes that have been deleted.\n\t */\n\tprivate runSweepPhase(\n\t\tgcResult: IGCResult,\n\t\tsweepReadyNodes: string[],\n\t\tcurrentReferenceTimestampMs: number,\n\t\tlogger: ITelemetryLoggerExt,\n\t): string[] {\n\t\t// Log events for objects that are ready to be deleted by sweep. This will give us data on sweep when\n\t\t// its not enabled.\n\t\tthis.telemetryTracker.logSweepEvents(\n\t\t\tlogger,\n\t\t\tcurrentReferenceTimestampMs,\n\t\t\tthis.unreferencedNodesState,\n\t\t\tthis.completedRuns,\n\t\t\tthis.getLastSummaryTimestampMs(),\n\t\t);\n\n\t\t/**\n\t\t * Currently, there are 3 modes for sweep:\n\t\t * Test mode - Unreferenced nodes are immediately deleted without waiting for them to be sweep ready.\n\t\t * Tombstone mode - Sweep ready modes are marked as tombstones instead of being deleted.\n\t\t * Sweep mode - Sweep ready modes are deleted.\n\t\t *\n\t\t * These modes serve as staging for applications that want to enable sweep by providing an incremental\n\t\t * way to test and validate sweep works as expected.\n\t\t */\n\t\tif (this.configs.testMode) {\n\t\t\t// If we are running in GC test mode, unreferenced nodes (gcResult.deletedNodeIds) are deleted.\n\t\t\tthis.runtime.updateUnusedRoutes(gcResult.deletedNodeIds);\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.configs.tombstoneMode) {\n\t\t\tthis.tombstones = sweepReadyNodes;\n\t\t\t// If we are running in GC tombstone mode, update tombstoned routes. This enables testing scenarios\n\t\t\t// involving access to \"deleted\" data without actually deleting the data from summaries.\n\t\t\tthis.runtime.updateTombstonedRoutes(this.tombstones);\n\t\t\treturn [];\n\t\t}\n\n\t\tif (!this.configs.shouldRunSweep) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// 1. Call the runtime to delete sweep ready nodes. The runtime returns a list of nodes it deleted.\n\t\t// TODO: GC:Validation - validate that removed routes are not double delete and that the child routes of\n\t\t// removed routes are deleted as well.\n\t\tconst deletedNodeIds = this.runtime.deleteSweepReadyNodes(sweepReadyNodes);\n\n\t\t// 2. Clear unreferenced state tracking for deleted nodes.\n\t\tfor (const nodeId of deletedNodeIds) {\n\t\t\tconst nodeStateTracker = this.unreferencedNodesState.get(nodeId);\n\t\t\t// TODO: GC:Validation - assert that the nodeStateTracker is defined\n\t\t\tif (nodeStateTracker !== undefined) {\n\t\t\t\t// Stop tracking so as to clear out any running timers.\n\t\t\t\tnodeStateTracker.stopTracking();\n\t\t\t\t// Delete the node as we don't need to track it any more.\n\t\t\t\tthis.unreferencedNodesState.delete(nodeId);\n\t\t\t}\n\t\t\t// TODO: GC:Validation - assert that the deleted node is not a duplicate\n\t\t\tthis.deletedNodes.add(nodeId);\n\t\t}\n\t\treturn deletedNodeIds;\n\t}\n\n\t/**\n\t * Since GC runs periodically, the GC data that is generated only tells us the state of the world at that point in\n\t * time. There can be nodes that were referenced in between two runs and their unreferenced state needs to be\n\t * updated. For example, in the following scenarios not updating the unreferenced timestamp can lead to deletion of\n\t * these objects while there can be in-memory referenced to it:\n\t * 1. A node transitions from `unreferenced -> referenced -> unreferenced` between two runs. When the reference is\n\t * added, the object may have been accessed and in-memory reference to it added.\n\t * 2. A reference is added from one unreferenced node to one or more unreferenced nodes. Even though the node[s] were\n\t * unreferenced, they could have been accessed and in-memory reference to them added.\n\t *\n\t * This function identifies nodes that were referenced since the last run.\n\t * If these nodes are currently unreferenced, they will be assigned new unreferenced state by the current run.\n\t *\n\t * @returns - a list of all nodes referenced from the last local summary until now.\n\t */\n\tprivate findAllNodesReferencedBetweenGCs(\n\t\tcurrentGCData: IGarbageCollectionData,\n\t\tpreviousGCData: IGarbageCollectionData | undefined,\n\t\tlogger: ITelemetryLoggerExt,\n\t): string[] | undefined {\n\t\t// If we haven't run GC before there is nothing to do.\n\t\t// No previousGCData, means nothing is unreferenced, and there are no reference state trackers to clear\n\t\tif (previousGCData === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t/**\n\t\t * If there are references that were not explicitly notified to GC, log an error because this should never happen.\n\t\t * If it does, this may result in the unreferenced timestamps of these nodes not updated when they were referenced.\n\t\t */\n\t\tthis.telemetryTracker.logIfMissingExplicitReferences(\n\t\t\tcurrentGCData,\n\t\t\tpreviousGCData,\n\t\t\tthis.newReferencesSinceLastRun,\n\t\t\tlogger,\n\t\t);\n\n\t\t// No references were added since the last run so we don't have to update reference states of any unreferenced\n\t\t// nodes. There is no in between state at this point.\n\t\tif (this.newReferencesSinceLastRun.size === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t/**\n\t\t * Generate a super set of the GC data that contains the nodes and edges from last run, plus any new node and\n\t\t * edges that have been added since then. To do this, combine the GC data from the last run and the current\n\t\t * run, and then add the references since last run.\n\t\t *\n\t\t * Note on why we need to combine the data from previous run, current run and all references in between -\n\t\t * 1. We need data from last run because some of its references may have been deleted since then. If those\n\t\t * references added new outbound references before they were deleted, we need to detect them.\n\t\t *\n\t\t * 2. We need new outbound references since last run because some of them may have been deleted later. If those\n\t\t * references added new outbound references before they were deleted, we need to detect them.\n\t\t *\n\t\t * 3. We need data from the current run because currently we may not detect when DDSes are referenced:\n\t\t * - We don't require DDSes handles to be stored in a referenced DDS.\n\t\t * - A new data store may have \"root\" DDSes already created and we don't detect them today.\n\t\t */\n\t\tconst gcDataSuperSet = concatGarbageCollectionData(previousGCData, currentGCData);\n\t\tconst newOutboundRoutesSinceLastRun: string[] = [];\n\t\tthis.newReferencesSinceLastRun.forEach((outboundRoutes: string[], sourceNodeId: string) => {\n\t\t\tif (gcDataSuperSet.gcNodes[sourceNodeId] === undefined) {\n\t\t\t\tgcDataSuperSet.gcNodes[sourceNodeId] = outboundRoutes;\n\t\t\t} else {\n\t\t\t\tgcDataSuperSet.gcNodes[sourceNodeId].push(...outboundRoutes);\n\t\t\t}\n\t\t\tnewOutboundRoutesSinceLastRun.push(...outboundRoutes);\n\t\t});\n\n\t\t/**\n\t\t * Run GC on the above reference graph starting with root and all new outbound routes. This will generate a\n\t\t * list of all nodes that could have been referenced since the last run. If any of these nodes are unreferenced,\n\t\t * unreferenced, stop tracking them and remove from unreferenced list.\n\t\t * Note that some of these nodes may be unreferenced now and if so, the current run will mark them as\n\t\t * unreferenced and add unreferenced state.\n\t\t */\n\t\tconst gcResult = runGarbageCollection(gcDataSuperSet.gcNodes, [\n\t\t\t\"/\",\n\t\t\t...newOutboundRoutesSinceLastRun,\n\t\t]);\n\t\treturn gcResult.referencedNodeIds;\n\t}\n\n\t/**\n\t * Summarizes the GC data and returns it as a summary tree.\n\t * We current write the entire GC state in a single blob. This can be modified later to write multiple\n\t * blobs. All the blob keys should start with `gcBlobPrefix`.\n\t */\n\tpublic summarize(\n\t\tfullTree: boolean,\n\t\ttrackState: boolean,\n\t\ttelemetryContext?: ITelemetryContext,\n\t): ISummarizeResult | undefined {\n\t\tif (!this.configs.shouldRunGC || this.gcDataFromLastRun === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst gcState: IGarbageCollectionState = { gcNodes: {} };\n\t\tfor (const [nodeId, outboundRoutes] of Object.entries(this.gcDataFromLastRun.gcNodes)) {\n\t\t\tgcState.gcNodes[nodeId] = {\n\t\t\t\toutboundRoutes,\n\t\t\t\tunreferencedTimestampMs:\n\t\t\t\t\tthis.unreferencedNodesState.get(nodeId)?.unreferencedTimestampMs,\n\t\t\t};\n\t\t}\n\n\t\treturn this.summaryStateTracker.summarize(\n\t\t\tfullTree,\n\t\t\ttrackState,\n\t\t\tgcState,\n\t\t\tthis.deletedNodes,\n\t\t\tthis.tombstones,\n\t\t);\n\t}\n\n\tpublic getMetadata(): IGCMetadata {\n\t\treturn {\n\t\t\t/**\n\t\t\t * If GC is enabled, the GC data is written using the GC version in effect and that is the gcFeature that goes\n\t\t\t * into the metadata blob. If GC is disabled, the gcFeature is 0.\n\t\t\t */\n\t\t\tgcFeature: this.configs.gcEnabled ? this.configs.gcVersionInEffect : 0,\n\t\t\tgcFeatureMatrix: this.configs.persistedGcFeatureMatrix,\n\t\t\tsessionExpiryTimeoutMs: this.configs.sessionExpiryTimeoutMs,\n\t\t\tsweepEnabled: false, // DEPRECATED - to be removed\n\t\t\tsweepTimeoutMs: this.configs.sweepTimeoutMs,\n\t\t};\n\t}\n\n\t/**\n\t * Called to refresh the latest summary state. This happens when either a pending summary is acked.\n\t */\n\tpublic async refreshLatestSummary(result: IRefreshSummaryResult): Promise<void> {\n\t\treturn this.summaryStateTracker.refreshLatestSummary(result);\n\t}\n\n\t/**\n\t * Called when a node with the given id is updated. If the node is inactive, log an error.\n\t * @param nodePath - The path of the node that changed.\n\t * @param reason - Whether the node was loaded or changed.\n\t * @param timestampMs - The timestamp when the node changed.\n\t * @param packagePath - The package path of the node. This may not be available if the node hasn't been loaded yet.\n\t * @param requestHeaders - If the node was loaded via request path, the headers in the request.\n\t */\n\tpublic nodeUpdated(\n\t\tnodePath: string,\n\t\treason: \"Loaded\" | \"Changed\",\n\t\ttimestampMs?: number,\n\t\tpackagePath?: readonly string[],\n\t\trequestHeaders?: IRequestHeader,\n\t) {\n\t\tif (!this.configs.shouldRunGC) {\n\t\t\treturn;\n\t\t}\n\n\t\t// This will log if appropriate\n\t\tthis.telemetryTracker.nodeUsed({\n\t\t\tid: nodePath,\n\t\t\tusageType: reason,\n\t\t\tcurrentReferenceTimestampMs:\n\t\t\t\ttimestampMs ?? this.runtime.getCurrentReferenceTimestampMs(),\n\t\t\tpackagePath,\n\t\t\tcompletedGCRuns: this.completedRuns,\n\t\t\tisTombstoned: this.tombstones.includes(nodePath),\n\t\t\tlastSummaryTime: this.getLastSummaryTimestampMs(),\n\t\t\tviaHandle: requestHeaders?.[RuntimeHeaders.viaHandle],\n\t\t});\n\n\t\t// Unless this is a Loaded event, we're done after telemetry tracking\n\t\tif (reason !== \"Loaded\") {\n\t\t\treturn;\n\t\t}\n\n\t\t// We may throw when loading an Inactive object, depending on these preconditions\n\t\tconst shouldThrowOnInactiveLoad =\n\t\t\t!this.isSummarizerClient &&\n\t\t\tthis.configs.throwOnInactiveLoad === true &&\n\t\t\trequestHeaders?.[AllowInactiveRequestHeaderKey] !== true;\n\t\tconst state = this.unreferencedNodesState.get(nodePath)?.state;\n\n\t\tif (shouldThrowOnInactiveLoad && state === \"Inactive\") {\n\t\t\tconst request: IRequest = { url: nodePath };\n\t\t\tconst error = responseToException(\n\t\t\t\tcreateResponseError(404, \"Object is inactive\", request, {\n\t\t\t\t\t[InactiveResponseHeaderKey]: true,\n\t\t\t\t}),\n\t\t\t\trequest,\n\t\t\t);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Called when an outbound reference is added to a node. This is used to identify all nodes that have been\n\t * referenced between summaries so that their unreferenced timestamp can be reset.\n\t *\n\t * @param fromNodePath - The node from which the reference is added.\n\t * @param toNodePath - The node to which the reference is added.\n\t */\n\tpublic addedOutboundReference(fromNodePath: string, toNodePath: string) {\n\t\tif (!this.configs.shouldRunGC) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst outboundRoutes = this.newReferencesSinceLastRun.get(fromNodePath) ?? [];\n\t\toutboundRoutes.push(toNodePath);\n\t\tthis.newReferencesSinceLastRun.set(fromNodePath, outboundRoutes);\n\n\t\tthis.telemetryTracker.nodeUsed({\n\t\t\tid: toNodePath,\n\t\t\tusageType: \"Revived\",\n\t\t\tcurrentReferenceTimestampMs: this.runtime.getCurrentReferenceTimestampMs(),\n\t\t\tpackagePath: undefined,\n\t\t\tcompletedGCRuns: this.completedRuns,\n\t\t\tisTombstoned: this.tombstones.includes(toNodePath),\n\t\t\tlastSummaryTime: this.getLastSummaryTimestampMs(),\n\t\t\tfromId: fromNodePath,\n\t\t});\n\t}\n\n\t/**\n\t * Returns whether a node with the given path has been deleted or not. This can be used by the runtime to identify\n\t * cases where objects are used after they are deleted and throw / log errors accordingly.\n\t */\n\tpublic isNodeDeleted(nodePath: string): boolean {\n\t\treturn this.deletedNodes.has(nodePath);\n\t}\n\n\tpublic dispose(): void {\n\t\tthis.sessionExpiryTimer?.clear();\n\t\tthis.sessionExpiryTimer = undefined;\n\t}\n\n\t/**\n\t * Generates the stats of a garbage collection run from the given results of the run.\n\t * @param gcResult - The result of a GC run.\n\t * @returns the GC stats of the GC run.\n\t */\n\tprivate generateStats(gcResult: IGCResult): IGCStats {\n\t\tconst gcStats: IGCStats = {\n\t\t\tnodeCount: 0,\n\t\t\tdataStoreCount: 0,\n\t\t\tattachmentBlobCount: 0,\n\t\t\tunrefNodeCount: 0,\n\t\t\tunrefDataStoreCount: 0,\n\t\t\tunrefAttachmentBlobCount: 0,\n\t\t\tupdatedNodeCount: 0,\n\t\t\tupdatedDataStoreCount: 0,\n\t\t\tupdatedAttachmentBlobCount: 0,\n\t\t};\n\n\t\tconst updateNodeStats = (nodeId: string, referenced: boolean) => {\n\t\t\tgcStats.nodeCount++;\n\t\t\t// If there is no previous GC data, every node's state is generated and is considered as updated.\n\t\t\t// Otherwise, find out if any node went from referenced to unreferenced or vice-versa.\n\t\t\tconst stateUpdated =\n\t\t\t\tthis.gcDataFromLastRun === undefined ||\n\t\t\t\tthis.unreferencedNodesState.has(nodeId) === referenced;\n\t\t\tif (stateUpdated) {\n\t\t\t\tgcStats.updatedNodeCount++;\n\t\t\t}\n\t\t\tif (!referenced) {\n\t\t\t\tgcStats.unrefNodeCount++;\n\t\t\t}\n\n\t\t\tif (this.runtime.getNodeType(nodeId) === GCNodeType.DataStore) {\n\t\t\t\tgcStats.dataStoreCount++;\n\t\t\t\tif (stateUpdated) {\n\t\t\t\t\tgcStats.updatedDataStoreCount++;\n\t\t\t\t}\n\t\t\t\tif (!referenced) {\n\t\t\t\t\tgcStats.unrefDataStoreCount++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (this.runtime.getNodeType(nodeId) === GCNodeType.Blob) {\n\t\t\t\tgcStats.attachmentBlobCount++;\n\t\t\t\tif (stateUpdated) {\n\t\t\t\t\tgcStats.updatedAttachmentBlobCount++;\n\t\t\t\t}\n\t\t\t\tif (!referenced) {\n\t\t\t\t\tgcStats.unrefAttachmentBlobCount++;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tfor (const nodeId of gcResult.referencedNodeIds) {\n\t\t\tupdateNodeStats(nodeId, true /* referenced */);\n\t\t}\n\n\t\tfor (const nodeId of gcResult.deletedNodeIds) {\n\t\t\tupdateNodeStats(nodeId, false /* referenced */);\n\t\t}\n\n\t\treturn gcStats;\n\t}\n}\n"]}
@@ -68,7 +68,7 @@ function generateGCConfigs(mc, createParams) {
68
68
  // Is sweepEnabled for this document?
69
69
  const sweepEnabled = (0, gcHelpers_1.shouldAllowGcSweep)(persistedGcFeatureMatrix ?? {} /* persistedGenerations */, createParams.gcOptions[gcDefinitions_1.gcSweepGenerationOptionName] /* currentGeneration */);
70
70
  // If version upgrade is not enabled, fall back to the stable GC version.
71
- const gcVersionInEffect = mc.config.getBoolean(gcDefinitions_1.gcVersionUpgradeToV3Key) === true ? gcDefinitions_1.currentGCVersion : gcDefinitions_1.stableGCVersion;
71
+ const gcVersionInEffect = mc.config.getBoolean(gcDefinitions_1.gcVersionUpgradeToV4Key) === true ? gcDefinitions_1.nextGCVersion : gcDefinitions_1.stableGCVersion;
72
72
  // The GC version is up-to-date if the GC version in effect is at least equal to the GC version in base snapshot.
73
73
  // If it is not up-to-date, there is a newer version of GC out there which is more reliable than this. So, GC
74
74
  // should not run as it may produce incorrect / unreliable state.
@@ -1 +1 @@
1
- {"version":3,"file":"gcConfigs.js","sourceRoot":"","sources":["../../src/gc/gcConfigs.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { MonitoringContext, UsageError } from \"@fluidframework/telemetry-utils\";\nimport { IContainerRuntimeMetadata } from \"../summary\";\nimport {\n\tcurrentGCVersion,\n\tdefaultInactiveTimeoutMs,\n\tdefaultSessionExpiryDurationMs,\n\tdisableTombstoneKey,\n\tGCFeatureMatrix,\n\tgcSweepGenerationOptionName,\n\tgcTestModeKey,\n\tgcTombstoneGenerationOptionName,\n\tGCVersion,\n\tgcVersionUpgradeToV3Key,\n\tIGarbageCollectorConfigs,\n\tIGCRuntimeOptions,\n\tmaxSnapshotCacheExpiryMs,\n\toneDayMs,\n\trunGCKey,\n\trunSessionExpiryKey,\n\trunSweepKey,\n\tstableGCVersion,\n} from \"./gcDefinitions\";\nimport { getGCVersion, shouldAllowGcSweep } from \"./gcHelpers\";\n\n/**\n * Generates configurations for the Garbage Collector that it uses to determine what to run and how.\n * @param mc - The monitoring context for reading configs from the config provider.\n * @param createParams - The creation params:\n * gcOptions - The garbage collector runtime options.\n * metadata - The container runtime's createParams.metadata.\n * existing - Whether the container is new or an existing one.\n * @returns The garbage collector configurations.\n */\nexport function generateGCConfigs(\n\tmc: MonitoringContext,\n\tcreateParams: {\n\t\tgcOptions: IGCRuntimeOptions;\n\t\tmetadata: IContainerRuntimeMetadata | undefined;\n\t\texisting: boolean;\n\t},\n): IGarbageCollectorConfigs {\n\tlet gcEnabled: boolean;\n\tlet sessionExpiryTimeoutMs: number | undefined;\n\tlet sweepTimeoutMs: number | undefined;\n\tlet persistedGcFeatureMatrix: GCFeatureMatrix | undefined;\n\tlet gcVersionInBaseSnapshot: GCVersion | undefined;\n\n\t/**\n\t * The following GC state is enabled during container creation and cannot be changed throughout its lifetime:\n\t * 1. Whether running GC mark phase is allowed or not.\n\t * 2. Whether running GC sweep phase is allowed or not.\n\t * 3. Whether GC session expiry is enabled or not.\n\t * For existing containers, we get this information from the createParams.metadata blob of its summary.\n\t */\n\tif (createParams.existing) {\n\t\tgcVersionInBaseSnapshot = getGCVersion(createParams.metadata);\n\t\t// Existing documents which did not have createParams.metadata blob or had GC disabled have version as 0. For all\n\t\t// other existing documents, GC is enabled.\n\t\tgcEnabled = gcVersionInBaseSnapshot > 0;\n\t\tsessionExpiryTimeoutMs = createParams.metadata?.sessionExpiryTimeoutMs;\n\t\tsweepTimeoutMs =\n\t\t\tcreateParams.metadata?.sweepTimeoutMs ?? computeSweepTimeout(sessionExpiryTimeoutMs); // Backfill old documents that didn't persist this\n\t\tpersistedGcFeatureMatrix = createParams.metadata?.gcFeatureMatrix;\n\t} else {\n\t\tconst tombstoneGeneration = createParams.gcOptions[gcTombstoneGenerationOptionName];\n\t\tconst sweepGeneration = createParams.gcOptions[gcSweepGenerationOptionName];\n\n\t\t// Sweep should not be enabled (via sweepGeneration value) without enabling GC mark phase.\n\t\tif (sweepGeneration !== undefined && createParams.gcOptions.gcAllowed === false) {\n\t\t\tthrow new UsageError(\"GC sweep phase cannot be enabled without enabling GC mark phase\");\n\t\t}\n\n\t\t// This Test Override only applies for new containers\n\t\tconst testOverrideSweepTimeoutMs = mc.config.getNumber(\n\t\t\t\"Fluid.GarbageCollection.TestOverride.SweepTimeoutMs\",\n\t\t);\n\n\t\t// For new documents, GC is enabled by default. It can be explicitly disabled by setting the gcAllowed\n\t\t// flag in GC options to false.\n\t\tgcEnabled = createParams.gcOptions.gcAllowed !== false;\n\n\t\t// Set the Session Expiry if GC is enabled and session expiry flag isn't explicitly set to false.\n\t\tif (gcEnabled && mc.config.getBoolean(runSessionExpiryKey) !== false) {\n\t\t\tsessionExpiryTimeoutMs =\n\t\t\t\tcreateParams.gcOptions.sessionExpiryTimeoutMs ?? defaultSessionExpiryDurationMs;\n\t\t}\n\t\tsweepTimeoutMs = testOverrideSweepTimeoutMs ?? computeSweepTimeout(sessionExpiryTimeoutMs);\n\n\t\tif (tombstoneGeneration !== undefined || sweepGeneration !== undefined) {\n\t\t\tpersistedGcFeatureMatrix = {\n\t\t\t\ttombstoneGeneration,\n\t\t\t\tsweepGeneration,\n\t\t\t};\n\t\t}\n\t}\n\n\t// Is sweepEnabled for this document?\n\tconst sweepEnabled = shouldAllowGcSweep(\n\t\tpersistedGcFeatureMatrix ?? {} /* persistedGenerations */,\n\t\tcreateParams.gcOptions[gcSweepGenerationOptionName] /* currentGeneration */,\n\t);\n\n\t// If version upgrade is not enabled, fall back to the stable GC version.\n\tconst gcVersionInEffect =\n\t\tmc.config.getBoolean(gcVersionUpgradeToV3Key) === true ? currentGCVersion : stableGCVersion;\n\n\t// The GC version is up-to-date if the GC version in effect is at least equal to the GC version in base snapshot.\n\t// If it is not up-to-date, there is a newer version of GC out there which is more reliable than this. So, GC\n\t// should not run as it may produce incorrect / unreliable state.\n\tconst isGCVersionUpToDate =\n\t\tgcVersionInBaseSnapshot === undefined || gcVersionInEffect >= gcVersionInBaseSnapshot;\n\n\t/**\n\t * Whether GC should run or not. The following conditions have to be met to run sweep:\n\t * 1. GC should be enabled for this container.\n\t * 2. GC should not be disabled via disableGC GC option.\n\t * 3. The current GC version should be greater of equal to the GC version in the base snapshot.\n\t * These conditions can be overridden via runGCKey feature flag.\n\t */\n\tconst shouldRunGC =\n\t\tmc.config.getBoolean(runGCKey) ??\n\t\t(gcEnabled && !createParams.gcOptions.disableGC && isGCVersionUpToDate);\n\n\t/**\n\t * Whether sweep should run or not. The following conditions have to be met to run sweep:\n\t *\n\t * 1. Overall GC or mark phase must be enabled (this.configs.shouldRunGC).\n\t * 2. Sweep timeout should be available. Without this, we wouldn't know when an object should be deleted.\n\t * 3. The driver must implement the policy limiting the age of snapshots used for loading. Otherwise\n\t * the Sweep Timeout calculation is not valid. We use the persisted value to ensure consistency over time.\n\t * 4. Sweep should be enabled for this container. This can be overridden via runSweep\n\t * feature flag.\n\t */\n\tconst shouldRunSweep =\n\t\tshouldRunGC &&\n\t\tsweepTimeoutMs !== undefined &&\n\t\t(mc.config.getBoolean(runSweepKey) ?? sweepEnabled);\n\n\t// Override inactive timeout if test config or gc options to override it is set.\n\tconst inactiveTimeoutMs =\n\t\tmc.config.getNumber(\"Fluid.GarbageCollection.TestOverride.InactiveTimeoutMs\") ??\n\t\tcreateParams.gcOptions.inactiveTimeoutMs ??\n\t\tdefaultInactiveTimeoutMs;\n\n\t// Inactive timeout must be greater than sweep timeout since a node goes from active -> inactive -> sweep ready.\n\tif (sweepTimeoutMs !== undefined && inactiveTimeoutMs > sweepTimeoutMs) {\n\t\tthrow new UsageError(\"inactive timeout should not be greater than the sweep timeout\");\n\t}\n\n\tconst throwOnInactiveLoad: boolean | undefined = createParams.gcOptions.throwOnInactiveLoad;\n\n\t// Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.\n\tconst testMode =\n\t\tmc.config.getBoolean(gcTestModeKey) ?? createParams.gcOptions.runGCInTestMode === true;\n\t// Whether we are running in tombstone mode. This is enabled by default if sweep won't run. It can be disabled\n\t// via feature flags.\n\tconst tombstoneMode = !shouldRunSweep && mc.config.getBoolean(disableTombstoneKey) !== true;\n\tconst runFullGC = createParams.gcOptions.runFullGC;\n\n\treturn {\n\t\tgcEnabled,\n\t\tsweepEnabled,\n\t\tshouldRunGC,\n\t\tshouldRunSweep,\n\t\trunFullGC,\n\t\ttestMode,\n\t\ttombstoneMode,\n\t\tsessionExpiryTimeoutMs,\n\t\tsweepTimeoutMs,\n\t\tinactiveTimeoutMs,\n\t\tthrowOnInactiveLoad,\n\t\tpersistedGcFeatureMatrix,\n\t\tgcVersionInBaseSnapshot,\n\t\tgcVersionInEffect,\n\t};\n}\n\n/**\n * Sweep timeout is the time after which unreferenced content can be swept.\n * Sweep timeout = session expiry timeout + snapshot cache expiry timeout + one day buffer.\n *\n * The snapshot cache expiry timeout cannot be known precisely but the upper bound is 5 days.\n * The buffer is added to account for any clock skew or other edge cases.\n * We use server timestamps throughout so the skew should be minimal but make it 1 day to be safe.\n */\nfunction computeSweepTimeout(sessionExpiryTimeoutMs: number | undefined): number | undefined {\n\tconst bufferMs = oneDayMs;\n\treturn sessionExpiryTimeoutMs && sessionExpiryTimeoutMs + maxSnapshotCacheExpiryMs + bufferMs;\n}\n"]}
1
+ {"version":3,"file":"gcConfigs.js","sourceRoot":"","sources":["../../src/gc/gcConfigs.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { MonitoringContext, UsageError } from \"@fluidframework/telemetry-utils\";\nimport { IContainerRuntimeMetadata } from \"../summary\";\nimport {\n\tnextGCVersion,\n\tdefaultInactiveTimeoutMs,\n\tdefaultSessionExpiryDurationMs,\n\tdisableTombstoneKey,\n\tGCFeatureMatrix,\n\tgcSweepGenerationOptionName,\n\tgcTestModeKey,\n\tgcTombstoneGenerationOptionName,\n\tGCVersion,\n\tgcVersionUpgradeToV4Key,\n\tIGarbageCollectorConfigs,\n\tIGCRuntimeOptions,\n\tmaxSnapshotCacheExpiryMs,\n\toneDayMs,\n\trunGCKey,\n\trunSessionExpiryKey,\n\trunSweepKey,\n\tstableGCVersion,\n} from \"./gcDefinitions\";\nimport { getGCVersion, shouldAllowGcSweep } from \"./gcHelpers\";\n\n/**\n * Generates configurations for the Garbage Collector that it uses to determine what to run and how.\n * @param mc - The monitoring context for reading configs from the config provider.\n * @param createParams - The creation params:\n * gcOptions - The garbage collector runtime options.\n * metadata - The container runtime's createParams.metadata.\n * existing - Whether the container is new or an existing one.\n * @returns The garbage collector configurations.\n */\nexport function generateGCConfigs(\n\tmc: MonitoringContext,\n\tcreateParams: {\n\t\tgcOptions: IGCRuntimeOptions;\n\t\tmetadata: IContainerRuntimeMetadata | undefined;\n\t\texisting: boolean;\n\t},\n): IGarbageCollectorConfigs {\n\tlet gcEnabled: boolean;\n\tlet sessionExpiryTimeoutMs: number | undefined;\n\tlet sweepTimeoutMs: number | undefined;\n\tlet persistedGcFeatureMatrix: GCFeatureMatrix | undefined;\n\tlet gcVersionInBaseSnapshot: GCVersion | undefined;\n\n\t/**\n\t * The following GC state is enabled during container creation and cannot be changed throughout its lifetime:\n\t * 1. Whether running GC mark phase is allowed or not.\n\t * 2. Whether running GC sweep phase is allowed or not.\n\t * 3. Whether GC session expiry is enabled or not.\n\t * For existing containers, we get this information from the createParams.metadata blob of its summary.\n\t */\n\tif (createParams.existing) {\n\t\tgcVersionInBaseSnapshot = getGCVersion(createParams.metadata);\n\t\t// Existing documents which did not have createParams.metadata blob or had GC disabled have version as 0. For all\n\t\t// other existing documents, GC is enabled.\n\t\tgcEnabled = gcVersionInBaseSnapshot > 0;\n\t\tsessionExpiryTimeoutMs = createParams.metadata?.sessionExpiryTimeoutMs;\n\t\tsweepTimeoutMs =\n\t\t\tcreateParams.metadata?.sweepTimeoutMs ?? computeSweepTimeout(sessionExpiryTimeoutMs); // Backfill old documents that didn't persist this\n\t\tpersistedGcFeatureMatrix = createParams.metadata?.gcFeatureMatrix;\n\t} else {\n\t\tconst tombstoneGeneration = createParams.gcOptions[gcTombstoneGenerationOptionName];\n\t\tconst sweepGeneration = createParams.gcOptions[gcSweepGenerationOptionName];\n\n\t\t// Sweep should not be enabled (via sweepGeneration value) without enabling GC mark phase.\n\t\tif (sweepGeneration !== undefined && createParams.gcOptions.gcAllowed === false) {\n\t\t\tthrow new UsageError(\"GC sweep phase cannot be enabled without enabling GC mark phase\");\n\t\t}\n\n\t\t// This Test Override only applies for new containers\n\t\tconst testOverrideSweepTimeoutMs = mc.config.getNumber(\n\t\t\t\"Fluid.GarbageCollection.TestOverride.SweepTimeoutMs\",\n\t\t);\n\n\t\t// For new documents, GC is enabled by default. It can be explicitly disabled by setting the gcAllowed\n\t\t// flag in GC options to false.\n\t\tgcEnabled = createParams.gcOptions.gcAllowed !== false;\n\n\t\t// Set the Session Expiry if GC is enabled and session expiry flag isn't explicitly set to false.\n\t\tif (gcEnabled && mc.config.getBoolean(runSessionExpiryKey) !== false) {\n\t\t\tsessionExpiryTimeoutMs =\n\t\t\t\tcreateParams.gcOptions.sessionExpiryTimeoutMs ?? defaultSessionExpiryDurationMs;\n\t\t}\n\t\tsweepTimeoutMs = testOverrideSweepTimeoutMs ?? computeSweepTimeout(sessionExpiryTimeoutMs);\n\n\t\tif (tombstoneGeneration !== undefined || sweepGeneration !== undefined) {\n\t\t\tpersistedGcFeatureMatrix = {\n\t\t\t\ttombstoneGeneration,\n\t\t\t\tsweepGeneration,\n\t\t\t};\n\t\t}\n\t}\n\n\t// Is sweepEnabled for this document?\n\tconst sweepEnabled = shouldAllowGcSweep(\n\t\tpersistedGcFeatureMatrix ?? {} /* persistedGenerations */,\n\t\tcreateParams.gcOptions[gcSweepGenerationOptionName] /* currentGeneration */,\n\t);\n\n\t// If version upgrade is not enabled, fall back to the stable GC version.\n\tconst gcVersionInEffect =\n\t\tmc.config.getBoolean(gcVersionUpgradeToV4Key) === true ? nextGCVersion : stableGCVersion;\n\n\t// The GC version is up-to-date if the GC version in effect is at least equal to the GC version in base snapshot.\n\t// If it is not up-to-date, there is a newer version of GC out there which is more reliable than this. So, GC\n\t// should not run as it may produce incorrect / unreliable state.\n\tconst isGCVersionUpToDate =\n\t\tgcVersionInBaseSnapshot === undefined || gcVersionInEffect >= gcVersionInBaseSnapshot;\n\n\t/**\n\t * Whether GC should run or not. The following conditions have to be met to run sweep:\n\t * 1. GC should be enabled for this container.\n\t * 2. GC should not be disabled via disableGC GC option.\n\t * 3. The current GC version should be greater of equal to the GC version in the base snapshot.\n\t * These conditions can be overridden via runGCKey feature flag.\n\t */\n\tconst shouldRunGC =\n\t\tmc.config.getBoolean(runGCKey) ??\n\t\t(gcEnabled && !createParams.gcOptions.disableGC && isGCVersionUpToDate);\n\n\t/**\n\t * Whether sweep should run or not. The following conditions have to be met to run sweep:\n\t *\n\t * 1. Overall GC or mark phase must be enabled (this.configs.shouldRunGC).\n\t * 2. Sweep timeout should be available. Without this, we wouldn't know when an object should be deleted.\n\t * 3. The driver must implement the policy limiting the age of snapshots used for loading. Otherwise\n\t * the Sweep Timeout calculation is not valid. We use the persisted value to ensure consistency over time.\n\t * 4. Sweep should be enabled for this container. This can be overridden via runSweep\n\t * feature flag.\n\t */\n\tconst shouldRunSweep =\n\t\tshouldRunGC &&\n\t\tsweepTimeoutMs !== undefined &&\n\t\t(mc.config.getBoolean(runSweepKey) ?? sweepEnabled);\n\n\t// Override inactive timeout if test config or gc options to override it is set.\n\tconst inactiveTimeoutMs =\n\t\tmc.config.getNumber(\"Fluid.GarbageCollection.TestOverride.InactiveTimeoutMs\") ??\n\t\tcreateParams.gcOptions.inactiveTimeoutMs ??\n\t\tdefaultInactiveTimeoutMs;\n\n\t// Inactive timeout must be greater than sweep timeout since a node goes from active -> inactive -> sweep ready.\n\tif (sweepTimeoutMs !== undefined && inactiveTimeoutMs > sweepTimeoutMs) {\n\t\tthrow new UsageError(\"inactive timeout should not be greater than the sweep timeout\");\n\t}\n\n\tconst throwOnInactiveLoad: boolean | undefined = createParams.gcOptions.throwOnInactiveLoad;\n\n\t// Whether we are running in test mode. In this mode, unreferenced nodes are immediately deleted.\n\tconst testMode =\n\t\tmc.config.getBoolean(gcTestModeKey) ?? createParams.gcOptions.runGCInTestMode === true;\n\t// Whether we are running in tombstone mode. This is enabled by default if sweep won't run. It can be disabled\n\t// via feature flags.\n\tconst tombstoneMode = !shouldRunSweep && mc.config.getBoolean(disableTombstoneKey) !== true;\n\tconst runFullGC = createParams.gcOptions.runFullGC;\n\n\treturn {\n\t\tgcEnabled,\n\t\tsweepEnabled,\n\t\tshouldRunGC,\n\t\tshouldRunSweep,\n\t\trunFullGC,\n\t\ttestMode,\n\t\ttombstoneMode,\n\t\tsessionExpiryTimeoutMs,\n\t\tsweepTimeoutMs,\n\t\tinactiveTimeoutMs,\n\t\tthrowOnInactiveLoad,\n\t\tpersistedGcFeatureMatrix,\n\t\tgcVersionInBaseSnapshot,\n\t\tgcVersionInEffect,\n\t};\n}\n\n/**\n * Sweep timeout is the time after which unreferenced content can be swept.\n * Sweep timeout = session expiry timeout + snapshot cache expiry timeout + one day buffer.\n *\n * The snapshot cache expiry timeout cannot be known precisely but the upper bound is 5 days.\n * The buffer is added to account for any clock skew or other edge cases.\n * We use server timestamps throughout so the skew should be minimal but make it 1 day to be safe.\n */\nfunction computeSweepTimeout(sessionExpiryTimeoutMs: number | undefined): number | undefined {\n\tconst bufferMs = oneDayMs;\n\treturn sessionExpiryTimeoutMs && sessionExpiryTimeoutMs + maxSnapshotCacheExpiryMs + bufferMs;\n}\n"]}
@@ -10,10 +10,10 @@ import { ReadAndParseBlob } from "@fluidframework/runtime-utils";
10
10
  import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
11
11
  import { IContainerRuntimeMetadata, ICreateContainerMetadata, IRefreshSummaryResult } from "../summary";
12
12
  export declare type GCVersion = number;
13
- /** The stable version of garbage collection in production. */
13
+ /** The stable/default version of GC Data */
14
14
  export declare const stableGCVersion: GCVersion;
15
- /** The current version of garbage collection. */
16
- export declare const currentGCVersion: GCVersion;
15
+ /** The next version of GC Data, to bump to in case we need to regenerate all GC Data across all files. */
16
+ export declare const nextGCVersion: GCVersion;
17
17
  /**
18
18
  * This undocumented GC Option (on ContainerRuntime Options) allows an app to disable enforcing GC on old documents by incrementing this value
19
19
  *
@@ -37,7 +37,7 @@ export declare const disableSweepLogKey = "Fluid.GarbageCollection.DisableSweepL
37
37
  export declare const disableTombstoneKey = "Fluid.GarbageCollection.DisableTombstone";
38
38
  export declare const throwOnTombstoneLoadKey = "Fluid.GarbageCollection.ThrowOnTombstoneLoad";
39
39
  export declare const throwOnTombstoneUsageKey = "Fluid.GarbageCollection.ThrowOnTombstoneUsage";
40
- export declare const gcVersionUpgradeToV3Key = "Fluid.GarbageCollection.GCVersionUpgradeToV3";
40
+ export declare const gcVersionUpgradeToV4Key = "Fluid.GarbageCollection.GCVersionUpgradeToV4";
41
41
  export declare const sweepDatastoresKey = "Fluid.GarbageCollection.Test.SweepDataStores";
42
42
  export declare const sweepAttachmentBlobsKey = "Fluid.GarbageCollection.Test.SweepAttachmentBlobs";
43
43
  export declare const oneDayMs: number;
@@ -1 +1 @@
1
- {"version":3,"file":"gcDefinitions.d.ts","sourceRoot":"","sources":["../../src/gc/gcDefinitions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gcDefinitions.d.ts","sourceRoot":"","sources":["../../src/gc/gcDefinitions.ts"],"names":[],"mappings":"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"}
@@ -4,11 +4,11 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.UnreferencedState = exports.GCNodeType = exports.defaultSessionExpiryDurationMs = exports.defaultInactiveTimeoutMs = exports.maxSnapshotCacheExpiryMs = exports.oneDayMs = exports.sweepAttachmentBlobsKey = exports.sweepDatastoresKey = exports.gcVersionUpgradeToV3Key = exports.throwOnTombstoneUsageKey = exports.throwOnTombstoneLoadKey = exports.disableTombstoneKey = exports.disableSweepLogKey = exports.runSessionExpiryKey = exports.gcTestModeKey = exports.runSweepKey = exports.runGCKey = exports.gcSweepGenerationOptionName = exports.gcTombstoneGenerationOptionName = exports.currentGCVersion = exports.stableGCVersion = void 0;
8
- /** The stable version of garbage collection in production. */
9
- exports.stableGCVersion = 2;
10
- /** The current version of garbage collection. */
11
- exports.currentGCVersion = 3;
7
+ exports.UnreferencedState = exports.GCNodeType = exports.defaultSessionExpiryDurationMs = exports.defaultInactiveTimeoutMs = exports.maxSnapshotCacheExpiryMs = exports.oneDayMs = exports.sweepAttachmentBlobsKey = exports.sweepDatastoresKey = exports.gcVersionUpgradeToV4Key = exports.throwOnTombstoneUsageKey = exports.throwOnTombstoneLoadKey = exports.disableTombstoneKey = exports.disableSweepLogKey = exports.runSessionExpiryKey = exports.gcTestModeKey = exports.runSweepKey = exports.runGCKey = exports.gcSweepGenerationOptionName = exports.gcTombstoneGenerationOptionName = exports.nextGCVersion = exports.stableGCVersion = void 0;
8
+ /** The stable/default version of GC Data */
9
+ exports.stableGCVersion = 3;
10
+ /** The next version of GC Data, to bump to in case we need to regenerate all GC Data across all files. */
11
+ exports.nextGCVersion = 4;
12
12
  /**
13
13
  * This undocumented GC Option (on ContainerRuntime Options) allows an app to disable enforcing GC on old documents by incrementing this value
14
14
  *
@@ -41,7 +41,7 @@ exports.throwOnTombstoneLoadKey = "Fluid.GarbageCollection.ThrowOnTombstoneLoad"
41
41
  // Feature gate to enable throwing an error when tombstone object is used (e.g. outgoing or incoming ops).
42
42
  exports.throwOnTombstoneUsageKey = "Fluid.GarbageCollection.ThrowOnTombstoneUsage";
43
43
  // Feature gate to enable GC version upgrade.
44
- exports.gcVersionUpgradeToV3Key = "Fluid.GarbageCollection.GCVersionUpgradeToV3";
44
+ exports.gcVersionUpgradeToV4Key = "Fluid.GarbageCollection.GCVersionUpgradeToV4";
45
45
  // Feature gate to enable GC sweep for datastores.
46
46
  // TODO: Remove Test from the flag when we are confident to turn on sweep
47
47
  exports.sweepDatastoresKey = "Fluid.GarbageCollection.Test.SweepDataStores";
@@ -1 +1 @@
1
- {"version":3,"file":"gcDefinitions.js","sourceRoot":"","sources":["../../src/gc/gcDefinitions.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAqBH,8DAA8D;AACjD,QAAA,eAAe,GAAc,CAAC,CAAC;AAC5C,iDAAiD;AACpC,QAAA,gBAAgB,GAAc,CAAC,CAAC;AAE7C;;;;;GAKG;AACU,QAAA,+BAA+B,GAAG,uBAAuB,CAAC;AACvE;;;;;;GAMG;AACU,QAAA,2BAA2B,GAAG,mBAAmB,CAAC;AAE/D,wCAAwC;AAC3B,QAAA,QAAQ,GAAG,+BAA+B,CAAC;AACxD,8CAA8C;AACjC,QAAA,WAAW,GAAG,kCAAkC,CAAC;AAC9D,kDAAkD;AACrC,QAAA,aAAa,GAAG,oCAAoC,CAAC;AAClE,mEAAmE;AACtD,QAAA,mBAAmB,GAAG,0CAA0C,CAAC;AAC9E,6CAA6C;AAChC,QAAA,kBAAkB,GAAG,yCAAyC,CAAC;AAC5E,qHAAqH;AACxG,QAAA,mBAAmB,GAAG,0CAA0C,CAAC;AAC9E,wFAAwF;AAC3E,QAAA,uBAAuB,GAAG,8CAA8C,CAAC;AACtF,0GAA0G;AAC7F,QAAA,wBAAwB,GAAG,+CAA+C,CAAC;AACxF,6CAA6C;AAChC,QAAA,uBAAuB,GAAG,8CAA8C,CAAC;AACtF,kDAAkD;AAClD,yEAAyE;AAC5D,QAAA,kBAAkB,GAAG,8CAA8C,CAAC;AACjF,wDAAwD;AAC3C,QAAA,uBAAuB,GAAG,mDAAmD,CAAC;AAE3F,2BAA2B;AACd,QAAA,QAAQ,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhD;;;;;GAKG;AACU,QAAA,wBAAwB,GAAG,CAAC,GAAG,gBAAQ,CAAC;AAExC,QAAA,wBAAwB,GAAG,CAAC,GAAG,gBAAQ,CAAC,CAAC,SAAS;AAClD,QAAA,8BAA8B,GAAG,EAAE,GAAG,gBAAQ,CAAC,CAAC,UAAU;AA4EvE,uDAAuD;AAC1C,QAAA,UAAU,GAAG;IACzB,kCAAkC;IAClC,SAAS,EAAE,WAAW;IACtB,8DAA8D;IAC9D,YAAY,EAAE,cAAc;IAC5B,6EAA6E;IAC7E,IAAI,EAAE,MAAM;IACZ,+DAA+D;IAC/D,KAAK,EAAE,OAAO;CACd,CAAC;AAuMF,8CAA8C;AACjC,QAAA,iBAAiB,GAAG;IAChC,gEAAgE;IAChE,MAAM,EAAE,QAAQ;IAChB,mEAAmE;IACnE,QAAQ,EAAE,UAAU;IACpB,0DAA0D;IAC1D,UAAU,EAAE,YAAY;CACf,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ICriticalContainerError } from \"@fluidframework/container-definitions\";\nimport { IRequestHeader } from \"@fluidframework/core-interfaces\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport {\n\tIGarbageCollectionData,\n\tIGarbageCollectionDetailsBase,\n\tISummarizeResult,\n\tITelemetryContext,\n} from \"@fluidframework/runtime-definitions\";\nimport { ReadAndParseBlob } from \"@fluidframework/runtime-utils\";\nimport { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport {\n\tIContainerRuntimeMetadata,\n\tICreateContainerMetadata,\n\tIRefreshSummaryResult,\n} from \"../summary\";\n\nexport type GCVersion = number;\n\n/** The stable version of garbage collection in production. */\nexport const stableGCVersion: GCVersion = 2;\n/** The current version of garbage collection. */\nexport const currentGCVersion: GCVersion = 3;\n\n/**\n * This undocumented GC Option (on ContainerRuntime Options) allows an app to disable enforcing GC on old documents by incrementing this value\n *\n * If unset, GC Tombstone phase will operate as otherwise configured\n * Otherwise, only enforce GC Tombstone if the passed in value matches the persisted value\n */\nexport const gcTombstoneGenerationOptionName = \"gcTombstoneGeneration\";\n/**\n * This GC Option (on ContainerRuntime Options) allows an app to disable GC Sweep on old documents by incrementing this value.\n *\n * If unset altogether, Sweep will be disabled.\n * If 0 is passed in, Sweep will be enabled for any document with gcSweepGeneration OR gcTombstoneGeneration as 0.\n * If any other number is passed in, Sweep will be enabled only for documents with the same value persisted.\n */\nexport const gcSweepGenerationOptionName = \"gcSweepGeneration\";\n\n// Feature gate key to turn GC on / off.\nexport const runGCKey = \"Fluid.GarbageCollection.RunGC\";\n// Feature gate key to turn GC sweep on / off.\nexport const runSweepKey = \"Fluid.GarbageCollection.RunSweep\";\n// Feature gate key to turn GC test mode on / off.\nexport const gcTestModeKey = \"Fluid.GarbageCollection.GCTestMode\";\n// Feature gate key to expire a session after a set period of time.\nexport const runSessionExpiryKey = \"Fluid.GarbageCollection.RunSessionExpiry\";\n// Feature gate key to turn GC sweep log off.\nexport const disableSweepLogKey = \"Fluid.GarbageCollection.DisableSweepLog\";\n// Feature gate key to disable the tombstone feature, i.e., tombstone information is not read / written into summary.\nexport const disableTombstoneKey = \"Fluid.GarbageCollection.DisableTombstone\";\n// Feature gate to enable throwing an error when tombstone object is loaded (requested).\nexport const throwOnTombstoneLoadKey = \"Fluid.GarbageCollection.ThrowOnTombstoneLoad\";\n// Feature gate to enable throwing an error when tombstone object is used (e.g. outgoing or incoming ops).\nexport const throwOnTombstoneUsageKey = \"Fluid.GarbageCollection.ThrowOnTombstoneUsage\";\n// Feature gate to enable GC version upgrade.\nexport const gcVersionUpgradeToV3Key = \"Fluid.GarbageCollection.GCVersionUpgradeToV3\";\n// Feature gate to enable GC sweep for datastores.\n// TODO: Remove Test from the flag when we are confident to turn on sweep\nexport const sweepDatastoresKey = \"Fluid.GarbageCollection.Test.SweepDataStores\";\n// Feature gate to enable GC sweep for attachment blobs.\nexport const sweepAttachmentBlobsKey = \"Fluid.GarbageCollection.Test.SweepAttachmentBlobs\";\n\n// One day in milliseconds.\nexport const oneDayMs = 1 * 24 * 60 * 60 * 1000;\n\n/**\n * The maximum snapshot cache expiry in the driver. This is used to calculate the sweep timeout.\n * Sweep timeout = session expiry timeout + snapshot cache expiry timeout + a buffer.\n * The snapshot cache expiry timeout cannot be known precisely but the upper bound is 5 days, i.e., any snapshot\n * in cache will be invalidated before 5 days.\n */\nexport const maxSnapshotCacheExpiryMs = 5 * oneDayMs;\n\nexport const defaultInactiveTimeoutMs = 7 * oneDayMs; // 7 days\nexport const defaultSessionExpiryDurationMs = 30 * oneDayMs; // 30 days\n\n/** @see IGCMetadata.gcFeatureMatrix */\nexport interface GCFeatureMatrix {\n\t/**\n\t * The Tombstone Generation value in effect when this file was created.\n\t * Gives a way for an app to disqualify old files from GC Tombstone enforcement.\n\t * Provided via Container Runtime Options.\n\t */\n\ttombstoneGeneration?: number;\n\t/**\n\t * The Sweep Generation value in effect when this file was created.\n\t * Gives a way for an app to disqualify old files from GC Sweep.\n\t * Provided via Container Runtime Options.\n\t */\n\tsweepGeneration?: number;\n}\n\nexport interface IGCMetadata {\n\t/**\n\t * The version of the GC code that was run to generate the GC data that is written in the summary.\n\t * If the persisted value doesn't match the current value in the code, saved GC data will be discarded and regenerated from scratch.\n\t * Also, used to determine whether GC is enabled for this container or not:\n\t * - A value of 0 or undefined means GC is disabled.\n\t * - A value greater than 0 means GC is enabled.\n\t */\n\treadonly gcFeature?: GCVersion;\n\n\t/**\n\t * A collection of different numerical \"Generations\" for different features,\n\t * used to determine feature availability over time.\n\t * This info may come from multiple sources (FF code, config service, app via Container Runtime Options),\n\t * and pertains to aspects of the document that may be fixed for its lifetime.\n\t *\n\t * For each dimension, if the persisted value doesn't match the currently provided value,\n\t * then this file does not support the corresponding feature as currently implemented.\n\t *\n\t * Guidance is that if no value is provided at runtime, it should result in the current default behavior.\n\t */\n\treadonly gcFeatureMatrix?: GCFeatureMatrix;\n\t/**\n\t * @deprecated - @see GCFeatureMatrix.sweepGeneration\n\t *\n\t * Tells whether the GC sweep phase is enabled for this container.\n\t * - True means sweep phase is enabled.\n\t * - False means sweep phase is disabled. If GC is disabled as per gcFeature, sweep is also disabled.\n\t */\n\treadonly sweepEnabled?: boolean;\n\t/** If this is present, the session for this container will expire after this time and the container will close */\n\treadonly sessionExpiryTimeoutMs?: number;\n\t/** How long to wait after an object is unreferenced before deleting it via GC Sweep */\n\treadonly sweepTimeoutMs?: number;\n}\n\n/** The statistics of the system state after a garbage collection run. */\nexport interface IGCStats {\n\t/** The number of nodes in the container. */\n\tnodeCount: number;\n\t/** The number of data stores in the container. */\n\tdataStoreCount: number;\n\t/** The number of attachment blobs in the container. */\n\tattachmentBlobCount: number;\n\t/** The number of unreferenced nodes in the container. */\n\tunrefNodeCount: number;\n\t/** The number of unreferenced data stores in the container. */\n\tunrefDataStoreCount: number;\n\t/** The number of unreferenced attachment blobs in the container. */\n\tunrefAttachmentBlobCount: number;\n\t/** The number of nodes whose reference state updated since last GC run. */\n\tupdatedNodeCount: number;\n\t/** The number of data stores whose reference state updated since last GC run. */\n\tupdatedDataStoreCount: number;\n\t/** The number of attachment blobs whose reference state updated since last GC run. */\n\tupdatedAttachmentBlobCount: number;\n}\n\n/** The types of GC nodes in the GC reference graph. */\nexport const GCNodeType = {\n\t// Nodes that are for data stores.\n\tDataStore: \"DataStore\",\n\t// Nodes that are within a data store. For example, DDS nodes.\n\tSubDataStore: \"SubDataStore\",\n\t// Nodes that are for attachment blobs, i.e., blobs uploaded via BlobManager.\n\tBlob: \"Blob\",\n\t// Nodes that are neither of the above. For example, root node.\n\tOther: \"Other\",\n};\nexport type GCNodeType = typeof GCNodeType[keyof typeof GCNodeType];\n\n/**\n * Defines the APIs for the runtime object to be passed to the garbage collector.\n */\nexport interface IGarbageCollectionRuntime {\n\t/** Before GC runs, called to notify the runtime to update any pending GC state. */\n\tupdateStateBeforeGC(): Promise<void>;\n\t/** Returns the garbage collection data of the runtime. */\n\tgetGCData(fullGC?: boolean): Promise<IGarbageCollectionData>;\n\t/** After GC has run, called to notify the runtime of routes that are used in it. */\n\tupdateUsedRoutes(usedRoutes: string[]): void;\n\t/** After GC has run, called to notify the runtime of routes that are unused in it. */\n\tupdateUnusedRoutes(unusedRoutes: string[]): void;\n\t/**\n\t * After GC has run and identified nodes that are sweep ready, called to delete the sweep ready nodes. The runtime\n\t * should return the routes of nodes that were deleted.\n\t * @param sweepReadyRoutes - The routes of nodes that are sweep ready and should be deleted.\n\t */\n\tdeleteSweepReadyNodes(sweepReadyRoutes: string[]): string[];\n\t/** Called to notify the runtime of routes that are tombstones. */\n\tupdateTombstonedRoutes(tombstoneRoutes: string[]): void;\n\t/** Returns a referenced timestamp to be used to track unreferenced nodes. */\n\tgetCurrentReferenceTimestampMs(): number | undefined;\n\t/** Returns the type of the GC node. */\n\tgetNodeType(nodePath: string): GCNodeType;\n\t/** Called when the runtime should close because of an error. */\n\tcloseFn: (error?: ICriticalContainerError) => void;\n\t/** If false, loading or using a Tombstoned object should merely log, not fail */\n\tgcTombstoneEnforcementAllowed: boolean;\n}\n\n/** Defines the contract for the garbage collector. */\nexport interface IGarbageCollector {\n\t/** Tells whether GC should run or not. */\n\treadonly shouldRunGC: boolean;\n\t/** Tells whether the GC state in summary needs to be reset in the next summary. */\n\treadonly summaryStateNeedsReset: boolean;\n\t/** The count of data stores whose GC state updated since the last summary. */\n\treadonly updatedDSCountSinceLastSummary: number;\n\t/** Initialize the state from the base snapshot after its creation. */\n\tinitializeBaseState(): Promise<void>;\n\t/** Run garbage collection and update the reference / used state of the system. */\n\tcollectGarbage(\n\t\toptions: {\n\t\t\tlogger?: ITelemetryLoggerExt;\n\t\t\trunSweep?: boolean;\n\t\t\tfullGC?: boolean;\n\t\t},\n\t\ttelemetryContext?: ITelemetryContext,\n\t): Promise<IGCStats | undefined>;\n\t/** Summarizes the GC data and returns it as a summary tree. */\n\tsummarize(\n\t\tfullTree: boolean,\n\t\ttrackState: boolean,\n\t\ttelemetryContext?: ITelemetryContext,\n\t): ISummarizeResult | undefined;\n\t/** Returns the garbage collector specific metadata to be written into the summary. */\n\tgetMetadata(): IGCMetadata;\n\t/** Returns the GC details generated from the base snapshot. */\n\tgetBaseGCDetails(): Promise<IGarbageCollectionDetailsBase>;\n\t/** Called when the latest summary of the system has been refreshed. */\n\trefreshLatestSummary(result: IRefreshSummaryResult): Promise<void>;\n\t/** Called when a node is updated. Used to detect and log when an inactive node is changed or loaded. */\n\tnodeUpdated(\n\t\tnodePath: string,\n\t\treason: \"Loaded\" | \"Changed\",\n\t\ttimestampMs?: number,\n\t\tpackagePath?: readonly string[],\n\t\trequestHeaders?: IRequestHeader,\n\t): void;\n\t/** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */\n\taddedOutboundReference(fromNodePath: string, toNodePath: string): void;\n\t/** Returns true if this node has been deleted by GC during sweep phase. */\n\tisNodeDeleted(nodePath: string): boolean;\n\tsetConnectionState(connected: boolean, clientId?: string): void;\n\tdispose(): void;\n}\n\n/** Parameters necessary for creating a GarbageCollector. */\nexport interface IGarbageCollectorCreateParams {\n\treadonly runtime: IGarbageCollectionRuntime;\n\treadonly gcOptions: IGCRuntimeOptions;\n\treadonly baseLogger: ITelemetryLoggerExt;\n\treadonly existing: boolean;\n\treadonly metadata: IContainerRuntimeMetadata | undefined;\n\treadonly createContainerMetadata: ICreateContainerMetadata;\n\treadonly baseSnapshot: ISnapshotTree | undefined;\n\treadonly isSummarizerClient: boolean;\n\treadonly getNodePackagePath: (nodePath: string) => Promise<readonly string[] | undefined>;\n\treadonly getLastSummaryTimestampMs: () => number | undefined;\n\treadonly readAndParseBlob: ReadAndParseBlob;\n\treadonly activeConnection: () => boolean;\n}\n\nexport interface IGCRuntimeOptions {\n\t/**\n\t * Flag that if true, will enable running garbage collection (GC) for a new container.\n\t *\n\t * GC has mark phase and sweep phase. In mark phase, unreferenced objects are identified\n\t * and marked as such in the summary. This option enables the mark phase.\n\t * In sweep phase, unreferenced objects are eventually deleted from the container if they meet certain conditions.\n\t * Sweep phase can be enabled via the \"sweepAllowed\" option.\n\t *\n\t * Note: This setting is persisted in the container's summary and cannot be changed.\n\t */\n\tgcAllowed?: boolean;\n\n\t/**\n\t * @deprecated - @see gcSweepGenerationOptionName and @see GCFeatureMatrix.sweepGeneration\n\t *\n\t * Flag that if true, enables GC's sweep phase for a new container.\n\t *\n\t * This will allow GC to eventually delete unreferenced objects from the container.\n\t * This flag should only be set to true if \"gcAllowed\" is true.\n\t *\n\t * Note: This setting is persisted in the container's summary and cannot be changed.\n\t */\n\tsweepAllowed?: boolean;\n\n\t/**\n\t * Flag that if true, will disable garbage collection for the session.\n\t * Can be used to disable running GC on containers where it is allowed via the gcAllowed option.\n\t */\n\tdisableGC?: boolean;\n\n\t/**\n\t * Flag that will bypass optimizations and generate GC data for all nodes irrespective of whether a node\n\t * changed or not.\n\t */\n\trunFullGC?: boolean;\n\n\t/**\n\t * Maximum session duration for a new container. If not present, a default value will be used.\n\t *\n\t * Note: This setting is persisted in the container's summary and cannot be changed.\n\t */\n\tsessionExpiryTimeoutMs?: number;\n\n\t/**\n\t * Allows additional GC options to be passed.\n\t */\n\t[key: string]: any;\n}\n\n/**\n * The configurations for Garbage Collector that determines what runs and how.\n */\nexport interface IGarbageCollectorConfigs {\n\t/**\n\t * Tracks if GC is enabled for this document. This is specified during document creation and doesn't change\n\t * throughout its lifetime.\n\t */\n\treadonly gcEnabled: boolean;\n\t/**\n\t * Tracks if sweep phase is enabled for this document. This is specified during document creation and doesn't change\n\t * throughout its lifetime.\n\t */\n\treadonly sweepEnabled: boolean;\n\t/**\n\t * Tracks if GC should run or not. Even if GC is enabled for a document (see gcEnabled), it can be explicitly\n\t * disabled via runtime options or feature flags.\n\t */\n\treadonly shouldRunGC: boolean;\n\t/**\n\t * Tracks if sweep phase should run or not. Even if the sweep phase is enabled for a document (see sweepEnabled), it\n\t * can be explicitly disabled via feature flags. It also won't run if session expiry is not enabled.\n\t */\n\treadonly shouldRunSweep: boolean;\n\t/**\n\t * If true, bypass optimizations and generate GC data for all nodes irrespective of whether a node changed or not.\n\t */\n\treadonly runFullGC: boolean | undefined;\n\t/** The time in ms to expire a session for a client for gc. */\n\treadonly sessionExpiryTimeoutMs: number | undefined;\n\t/** The time after which an unreferenced node is ready to be swept. */\n\treadonly sweepTimeoutMs: number | undefined;\n\t/** The time after which an unreferenced node is inactive. */\n\treadonly inactiveTimeoutMs: number;\n\t/** It is easier for users to diagnose InactiveObject usage if we throw on load, which this option enables */\n\treadonly throwOnInactiveLoad: boolean | undefined;\n\t/** Tracks whether GC should run in test mode. In this mode, unreferenced objects are deleted immediately. */\n\treadonly testMode: boolean;\n\t/**\n\t * Tracks whether GC should run in tombstone mode. In this mode, sweep ready objects are marked as tombstones.\n\t * In interactive (non-summarizer) clients, tombstone objects behave as if they are deleted, i.e., access to them\n\t * is not allowed. However, these objects can be accessed after referencing them first. It is used as a staging\n\t * step for sweep where accidental sweep ready objects can be recovered.\n\t */\n\treadonly tombstoneMode: boolean;\n\t/** @see GCFeatureMatrix. */\n\treadonly persistedGcFeatureMatrix: GCFeatureMatrix | undefined;\n\t/** The version of GC in the base snapshot. */\n\treadonly gcVersionInBaseSnapshot: GCVersion | undefined;\n\t/** The current version of GC data in the running code */\n\treadonly gcVersionInEffect: GCVersion;\n}\n\n/** The state of node that is unreferenced. */\nexport const UnreferencedState = {\n\t/** The node is active, i.e., it can become referenced again. */\n\tActive: \"Active\",\n\t/** The node is inactive, i.e., it should not become referenced. */\n\tInactive: \"Inactive\",\n\t/** The node is ready to be deleted by the sweep phase. */\n\tSweepReady: \"SweepReady\",\n} as const;\nexport type UnreferencedState = typeof UnreferencedState[keyof typeof UnreferencedState];\n\n/**\n * Represents the result of a GC run.\n */\nexport interface IGCResult {\n\t/** The ids of nodes that are referenced in the referenced graph */\n\treferencedNodeIds: string[];\n\t/** The ids of nodes that are not-referenced or deleted in the referenced graph */\n\tdeletedNodeIds: string[];\n}\n"]}
1
+ {"version":3,"file":"gcDefinitions.js","sourceRoot":"","sources":["../../src/gc/gcDefinitions.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAqBH,4CAA4C;AAC/B,QAAA,eAAe,GAAc,CAAC,CAAC;AAC5C,0GAA0G;AAC7F,QAAA,aAAa,GAAc,CAAC,CAAC;AAE1C;;;;;GAKG;AACU,QAAA,+BAA+B,GAAG,uBAAuB,CAAC;AACvE;;;;;;GAMG;AACU,QAAA,2BAA2B,GAAG,mBAAmB,CAAC;AAE/D,wCAAwC;AAC3B,QAAA,QAAQ,GAAG,+BAA+B,CAAC;AACxD,8CAA8C;AACjC,QAAA,WAAW,GAAG,kCAAkC,CAAC;AAC9D,kDAAkD;AACrC,QAAA,aAAa,GAAG,oCAAoC,CAAC;AAClE,mEAAmE;AACtD,QAAA,mBAAmB,GAAG,0CAA0C,CAAC;AAC9E,6CAA6C;AAChC,QAAA,kBAAkB,GAAG,yCAAyC,CAAC;AAC5E,qHAAqH;AACxG,QAAA,mBAAmB,GAAG,0CAA0C,CAAC;AAC9E,wFAAwF;AAC3E,QAAA,uBAAuB,GAAG,8CAA8C,CAAC;AACtF,0GAA0G;AAC7F,QAAA,wBAAwB,GAAG,+CAA+C,CAAC;AACxF,6CAA6C;AAChC,QAAA,uBAAuB,GAAG,8CAA8C,CAAC;AACtF,kDAAkD;AAClD,yEAAyE;AAC5D,QAAA,kBAAkB,GAAG,8CAA8C,CAAC;AACjF,wDAAwD;AAC3C,QAAA,uBAAuB,GAAG,mDAAmD,CAAC;AAE3F,2BAA2B;AACd,QAAA,QAAQ,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhD;;;;;GAKG;AACU,QAAA,wBAAwB,GAAG,CAAC,GAAG,gBAAQ,CAAC;AAExC,QAAA,wBAAwB,GAAG,CAAC,GAAG,gBAAQ,CAAC,CAAC,SAAS;AAClD,QAAA,8BAA8B,GAAG,EAAE,GAAG,gBAAQ,CAAC,CAAC,UAAU;AA4EvE,uDAAuD;AAC1C,QAAA,UAAU,GAAG;IACzB,kCAAkC;IAClC,SAAS,EAAE,WAAW;IACtB,8DAA8D;IAC9D,YAAY,EAAE,cAAc;IAC5B,6EAA6E;IAC7E,IAAI,EAAE,MAAM;IACZ,+DAA+D;IAC/D,KAAK,EAAE,OAAO;CACd,CAAC;AAuMF,8CAA8C;AACjC,QAAA,iBAAiB,GAAG;IAChC,gEAAgE;IAChE,MAAM,EAAE,QAAQ;IAChB,mEAAmE;IACnE,QAAQ,EAAE,UAAU;IACpB,0DAA0D;IAC1D,UAAU,EAAE,YAAY;CACf,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ICriticalContainerError } from \"@fluidframework/container-definitions\";\nimport { IRequestHeader } from \"@fluidframework/core-interfaces\";\nimport { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\nimport {\n\tIGarbageCollectionData,\n\tIGarbageCollectionDetailsBase,\n\tISummarizeResult,\n\tITelemetryContext,\n} from \"@fluidframework/runtime-definitions\";\nimport { ReadAndParseBlob } from \"@fluidframework/runtime-utils\";\nimport { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils\";\nimport {\n\tIContainerRuntimeMetadata,\n\tICreateContainerMetadata,\n\tIRefreshSummaryResult,\n} from \"../summary\";\n\nexport type GCVersion = number;\n\n/** The stable/default version of GC Data */\nexport const stableGCVersion: GCVersion = 3;\n/** The next version of GC Data, to bump to in case we need to regenerate all GC Data across all files. */\nexport const nextGCVersion: GCVersion = 4;\n\n/**\n * This undocumented GC Option (on ContainerRuntime Options) allows an app to disable enforcing GC on old documents by incrementing this value\n *\n * If unset, GC Tombstone phase will operate as otherwise configured\n * Otherwise, only enforce GC Tombstone if the passed in value matches the persisted value\n */\nexport const gcTombstoneGenerationOptionName = \"gcTombstoneGeneration\";\n/**\n * This GC Option (on ContainerRuntime Options) allows an app to disable GC Sweep on old documents by incrementing this value.\n *\n * If unset altogether, Sweep will be disabled.\n * If 0 is passed in, Sweep will be enabled for any document with gcSweepGeneration OR gcTombstoneGeneration as 0.\n * If any other number is passed in, Sweep will be enabled only for documents with the same value persisted.\n */\nexport const gcSweepGenerationOptionName = \"gcSweepGeneration\";\n\n// Feature gate key to turn GC on / off.\nexport const runGCKey = \"Fluid.GarbageCollection.RunGC\";\n// Feature gate key to turn GC sweep on / off.\nexport const runSweepKey = \"Fluid.GarbageCollection.RunSweep\";\n// Feature gate key to turn GC test mode on / off.\nexport const gcTestModeKey = \"Fluid.GarbageCollection.GCTestMode\";\n// Feature gate key to expire a session after a set period of time.\nexport const runSessionExpiryKey = \"Fluid.GarbageCollection.RunSessionExpiry\";\n// Feature gate key to turn GC sweep log off.\nexport const disableSweepLogKey = \"Fluid.GarbageCollection.DisableSweepLog\";\n// Feature gate key to disable the tombstone feature, i.e., tombstone information is not read / written into summary.\nexport const disableTombstoneKey = \"Fluid.GarbageCollection.DisableTombstone\";\n// Feature gate to enable throwing an error when tombstone object is loaded (requested).\nexport const throwOnTombstoneLoadKey = \"Fluid.GarbageCollection.ThrowOnTombstoneLoad\";\n// Feature gate to enable throwing an error when tombstone object is used (e.g. outgoing or incoming ops).\nexport const throwOnTombstoneUsageKey = \"Fluid.GarbageCollection.ThrowOnTombstoneUsage\";\n// Feature gate to enable GC version upgrade.\nexport const gcVersionUpgradeToV4Key = \"Fluid.GarbageCollection.GCVersionUpgradeToV4\";\n// Feature gate to enable GC sweep for datastores.\n// TODO: Remove Test from the flag when we are confident to turn on sweep\nexport const sweepDatastoresKey = \"Fluid.GarbageCollection.Test.SweepDataStores\";\n// Feature gate to enable GC sweep for attachment blobs.\nexport const sweepAttachmentBlobsKey = \"Fluid.GarbageCollection.Test.SweepAttachmentBlobs\";\n\n// One day in milliseconds.\nexport const oneDayMs = 1 * 24 * 60 * 60 * 1000;\n\n/**\n * The maximum snapshot cache expiry in the driver. This is used to calculate the sweep timeout.\n * Sweep timeout = session expiry timeout + snapshot cache expiry timeout + a buffer.\n * The snapshot cache expiry timeout cannot be known precisely but the upper bound is 5 days, i.e., any snapshot\n * in cache will be invalidated before 5 days.\n */\nexport const maxSnapshotCacheExpiryMs = 5 * oneDayMs;\n\nexport const defaultInactiveTimeoutMs = 7 * oneDayMs; // 7 days\nexport const defaultSessionExpiryDurationMs = 30 * oneDayMs; // 30 days\n\n/** @see IGCMetadata.gcFeatureMatrix */\nexport interface GCFeatureMatrix {\n\t/**\n\t * The Tombstone Generation value in effect when this file was created.\n\t * Gives a way for an app to disqualify old files from GC Tombstone enforcement.\n\t * Provided via Container Runtime Options.\n\t */\n\ttombstoneGeneration?: number;\n\t/**\n\t * The Sweep Generation value in effect when this file was created.\n\t * Gives a way for an app to disqualify old files from GC Sweep.\n\t * Provided via Container Runtime Options.\n\t */\n\tsweepGeneration?: number;\n}\n\nexport interface IGCMetadata {\n\t/**\n\t * The version of the GC code that was run to generate the GC data that is written in the summary.\n\t * If the persisted value doesn't match the current value in the code, saved GC data will be discarded and regenerated from scratch.\n\t * Also, used to determine whether GC is enabled for this container or not:\n\t * - A value of 0 or undefined means GC is disabled.\n\t * - A value greater than 0 means GC is enabled.\n\t */\n\treadonly gcFeature?: GCVersion;\n\n\t/**\n\t * A collection of different numerical \"Generations\" for different features,\n\t * used to determine feature availability over time.\n\t * This info may come from multiple sources (FF code, config service, app via Container Runtime Options),\n\t * and pertains to aspects of the document that may be fixed for its lifetime.\n\t *\n\t * For each dimension, if the persisted value doesn't match the currently provided value,\n\t * then this file does not support the corresponding feature as currently implemented.\n\t *\n\t * Guidance is that if no value is provided at runtime, it should result in the current default behavior.\n\t */\n\treadonly gcFeatureMatrix?: GCFeatureMatrix;\n\t/**\n\t * @deprecated - @see GCFeatureMatrix.sweepGeneration\n\t *\n\t * Tells whether the GC sweep phase is enabled for this container.\n\t * - True means sweep phase is enabled.\n\t * - False means sweep phase is disabled. If GC is disabled as per gcFeature, sweep is also disabled.\n\t */\n\treadonly sweepEnabled?: boolean;\n\t/** If this is present, the session for this container will expire after this time and the container will close */\n\treadonly sessionExpiryTimeoutMs?: number;\n\t/** How long to wait after an object is unreferenced before deleting it via GC Sweep */\n\treadonly sweepTimeoutMs?: number;\n}\n\n/** The statistics of the system state after a garbage collection run. */\nexport interface IGCStats {\n\t/** The number of nodes in the container. */\n\tnodeCount: number;\n\t/** The number of data stores in the container. */\n\tdataStoreCount: number;\n\t/** The number of attachment blobs in the container. */\n\tattachmentBlobCount: number;\n\t/** The number of unreferenced nodes in the container. */\n\tunrefNodeCount: number;\n\t/** The number of unreferenced data stores in the container. */\n\tunrefDataStoreCount: number;\n\t/** The number of unreferenced attachment blobs in the container. */\n\tunrefAttachmentBlobCount: number;\n\t/** The number of nodes whose reference state updated since last GC run. */\n\tupdatedNodeCount: number;\n\t/** The number of data stores whose reference state updated since last GC run. */\n\tupdatedDataStoreCount: number;\n\t/** The number of attachment blobs whose reference state updated since last GC run. */\n\tupdatedAttachmentBlobCount: number;\n}\n\n/** The types of GC nodes in the GC reference graph. */\nexport const GCNodeType = {\n\t// Nodes that are for data stores.\n\tDataStore: \"DataStore\",\n\t// Nodes that are within a data store. For example, DDS nodes.\n\tSubDataStore: \"SubDataStore\",\n\t// Nodes that are for attachment blobs, i.e., blobs uploaded via BlobManager.\n\tBlob: \"Blob\",\n\t// Nodes that are neither of the above. For example, root node.\n\tOther: \"Other\",\n};\nexport type GCNodeType = typeof GCNodeType[keyof typeof GCNodeType];\n\n/**\n * Defines the APIs for the runtime object to be passed to the garbage collector.\n */\nexport interface IGarbageCollectionRuntime {\n\t/** Before GC runs, called to notify the runtime to update any pending GC state. */\n\tupdateStateBeforeGC(): Promise<void>;\n\t/** Returns the garbage collection data of the runtime. */\n\tgetGCData(fullGC?: boolean): Promise<IGarbageCollectionData>;\n\t/** After GC has run, called to notify the runtime of routes that are used in it. */\n\tupdateUsedRoutes(usedRoutes: string[]): void;\n\t/** After GC has run, called to notify the runtime of routes that are unused in it. */\n\tupdateUnusedRoutes(unusedRoutes: string[]): void;\n\t/**\n\t * After GC has run and identified nodes that are sweep ready, called to delete the sweep ready nodes. The runtime\n\t * should return the routes of nodes that were deleted.\n\t * @param sweepReadyRoutes - The routes of nodes that are sweep ready and should be deleted.\n\t */\n\tdeleteSweepReadyNodes(sweepReadyRoutes: string[]): string[];\n\t/** Called to notify the runtime of routes that are tombstones. */\n\tupdateTombstonedRoutes(tombstoneRoutes: string[]): void;\n\t/** Returns a referenced timestamp to be used to track unreferenced nodes. */\n\tgetCurrentReferenceTimestampMs(): number | undefined;\n\t/** Returns the type of the GC node. */\n\tgetNodeType(nodePath: string): GCNodeType;\n\t/** Called when the runtime should close because of an error. */\n\tcloseFn: (error?: ICriticalContainerError) => void;\n\t/** If false, loading or using a Tombstoned object should merely log, not fail */\n\tgcTombstoneEnforcementAllowed: boolean;\n}\n\n/** Defines the contract for the garbage collector. */\nexport interface IGarbageCollector {\n\t/** Tells whether GC should run or not. */\n\treadonly shouldRunGC: boolean;\n\t/** Tells whether the GC state in summary needs to be reset in the next summary. */\n\treadonly summaryStateNeedsReset: boolean;\n\t/** The count of data stores whose GC state updated since the last summary. */\n\treadonly updatedDSCountSinceLastSummary: number;\n\t/** Initialize the state from the base snapshot after its creation. */\n\tinitializeBaseState(): Promise<void>;\n\t/** Run garbage collection and update the reference / used state of the system. */\n\tcollectGarbage(\n\t\toptions: {\n\t\t\tlogger?: ITelemetryLoggerExt;\n\t\t\trunSweep?: boolean;\n\t\t\tfullGC?: boolean;\n\t\t},\n\t\ttelemetryContext?: ITelemetryContext,\n\t): Promise<IGCStats | undefined>;\n\t/** Summarizes the GC data and returns it as a summary tree. */\n\tsummarize(\n\t\tfullTree: boolean,\n\t\ttrackState: boolean,\n\t\ttelemetryContext?: ITelemetryContext,\n\t): ISummarizeResult | undefined;\n\t/** Returns the garbage collector specific metadata to be written into the summary. */\n\tgetMetadata(): IGCMetadata;\n\t/** Returns the GC details generated from the base snapshot. */\n\tgetBaseGCDetails(): Promise<IGarbageCollectionDetailsBase>;\n\t/** Called when the latest summary of the system has been refreshed. */\n\trefreshLatestSummary(result: IRefreshSummaryResult): Promise<void>;\n\t/** Called when a node is updated. Used to detect and log when an inactive node is changed or loaded. */\n\tnodeUpdated(\n\t\tnodePath: string,\n\t\treason: \"Loaded\" | \"Changed\",\n\t\ttimestampMs?: number,\n\t\tpackagePath?: readonly string[],\n\t\trequestHeaders?: IRequestHeader,\n\t): void;\n\t/** Called when a reference is added to a node. Used to identify nodes that were referenced between summaries. */\n\taddedOutboundReference(fromNodePath: string, toNodePath: string): void;\n\t/** Returns true if this node has been deleted by GC during sweep phase. */\n\tisNodeDeleted(nodePath: string): boolean;\n\tsetConnectionState(connected: boolean, clientId?: string): void;\n\tdispose(): void;\n}\n\n/** Parameters necessary for creating a GarbageCollector. */\nexport interface IGarbageCollectorCreateParams {\n\treadonly runtime: IGarbageCollectionRuntime;\n\treadonly gcOptions: IGCRuntimeOptions;\n\treadonly baseLogger: ITelemetryLoggerExt;\n\treadonly existing: boolean;\n\treadonly metadata: IContainerRuntimeMetadata | undefined;\n\treadonly createContainerMetadata: ICreateContainerMetadata;\n\treadonly baseSnapshot: ISnapshotTree | undefined;\n\treadonly isSummarizerClient: boolean;\n\treadonly getNodePackagePath: (nodePath: string) => Promise<readonly string[] | undefined>;\n\treadonly getLastSummaryTimestampMs: () => number | undefined;\n\treadonly readAndParseBlob: ReadAndParseBlob;\n\treadonly activeConnection: () => boolean;\n}\n\nexport interface IGCRuntimeOptions {\n\t/**\n\t * Flag that if true, will enable running garbage collection (GC) for a new container.\n\t *\n\t * GC has mark phase and sweep phase. In mark phase, unreferenced objects are identified\n\t * and marked as such in the summary. This option enables the mark phase.\n\t * In sweep phase, unreferenced objects are eventually deleted from the container if they meet certain conditions.\n\t * Sweep phase can be enabled via the \"sweepAllowed\" option.\n\t *\n\t * Note: This setting is persisted in the container's summary and cannot be changed.\n\t */\n\tgcAllowed?: boolean;\n\n\t/**\n\t * @deprecated - @see gcSweepGenerationOptionName and @see GCFeatureMatrix.sweepGeneration\n\t *\n\t * Flag that if true, enables GC's sweep phase for a new container.\n\t *\n\t * This will allow GC to eventually delete unreferenced objects from the container.\n\t * This flag should only be set to true if \"gcAllowed\" is true.\n\t *\n\t * Note: This setting is persisted in the container's summary and cannot be changed.\n\t */\n\tsweepAllowed?: boolean;\n\n\t/**\n\t * Flag that if true, will disable garbage collection for the session.\n\t * Can be used to disable running GC on containers where it is allowed via the gcAllowed option.\n\t */\n\tdisableGC?: boolean;\n\n\t/**\n\t * Flag that will bypass optimizations and generate GC data for all nodes irrespective of whether a node\n\t * changed or not.\n\t */\n\trunFullGC?: boolean;\n\n\t/**\n\t * Maximum session duration for a new container. If not present, a default value will be used.\n\t *\n\t * Note: This setting is persisted in the container's summary and cannot be changed.\n\t */\n\tsessionExpiryTimeoutMs?: number;\n\n\t/**\n\t * Allows additional GC options to be passed.\n\t */\n\t[key: string]: any;\n}\n\n/**\n * The configurations for Garbage Collector that determines what runs and how.\n */\nexport interface IGarbageCollectorConfigs {\n\t/**\n\t * Tracks if GC is enabled for this document. This is specified during document creation and doesn't change\n\t * throughout its lifetime.\n\t */\n\treadonly gcEnabled: boolean;\n\t/**\n\t * Tracks if sweep phase is enabled for this document. This is specified during document creation and doesn't change\n\t * throughout its lifetime.\n\t */\n\treadonly sweepEnabled: boolean;\n\t/**\n\t * Tracks if GC should run or not. Even if GC is enabled for a document (see gcEnabled), it can be explicitly\n\t * disabled via runtime options or feature flags.\n\t */\n\treadonly shouldRunGC: boolean;\n\t/**\n\t * Tracks if sweep phase should run or not. Even if the sweep phase is enabled for a document (see sweepEnabled), it\n\t * can be explicitly disabled via feature flags. It also won't run if session expiry is not enabled.\n\t */\n\treadonly shouldRunSweep: boolean;\n\t/**\n\t * If true, bypass optimizations and generate GC data for all nodes irrespective of whether a node changed or not.\n\t */\n\treadonly runFullGC: boolean | undefined;\n\t/** The time in ms to expire a session for a client for gc. */\n\treadonly sessionExpiryTimeoutMs: number | undefined;\n\t/** The time after which an unreferenced node is ready to be swept. */\n\treadonly sweepTimeoutMs: number | undefined;\n\t/** The time after which an unreferenced node is inactive. */\n\treadonly inactiveTimeoutMs: number;\n\t/** It is easier for users to diagnose InactiveObject usage if we throw on load, which this option enables */\n\treadonly throwOnInactiveLoad: boolean | undefined;\n\t/** Tracks whether GC should run in test mode. In this mode, unreferenced objects are deleted immediately. */\n\treadonly testMode: boolean;\n\t/**\n\t * Tracks whether GC should run in tombstone mode. In this mode, sweep ready objects are marked as tombstones.\n\t * In interactive (non-summarizer) clients, tombstone objects behave as if they are deleted, i.e., access to them\n\t * is not allowed. However, these objects can be accessed after referencing them first. It is used as a staging\n\t * step for sweep where accidental sweep ready objects can be recovered.\n\t */\n\treadonly tombstoneMode: boolean;\n\t/** @see GCFeatureMatrix. */\n\treadonly persistedGcFeatureMatrix: GCFeatureMatrix | undefined;\n\t/** The version of GC in the base snapshot. */\n\treadonly gcVersionInBaseSnapshot: GCVersion | undefined;\n\t/** The current version of GC data in the running code */\n\treadonly gcVersionInEffect: GCVersion;\n}\n\n/** The state of node that is unreferenced. */\nexport const UnreferencedState = {\n\t/** The node is active, i.e., it can become referenced again. */\n\tActive: \"Active\",\n\t/** The node is inactive, i.e., it should not become referenced. */\n\tInactive: \"Inactive\",\n\t/** The node is ready to be deleted by the sweep phase. */\n\tSweepReady: \"SweepReady\",\n} as const;\nexport type UnreferencedState = typeof UnreferencedState[keyof typeof UnreferencedState];\n\n/**\n * Represents the result of a GC run.\n */\nexport interface IGCResult {\n\t/** The ids of nodes that are referenced in the referenced graph */\n\treferencedNodeIds: string[];\n\t/** The ids of nodes that are not-referenced or deleted in the referenced graph */\n\tdeletedNodeIds: string[];\n}\n"]}